Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed the content type default to use uppercase so when the after c… #196

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 49 additions & 18 deletions src/Tonic/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Request
protected $contentType;
protected $data;
protected $accept = array();
protected $acceptParams = array();
protected $acceptLanguage = array();
protected $ifMatch = array();
protected $ifNoneMatch = array();
Expand Down Expand Up @@ -62,7 +63,9 @@ public function __construct($options = array())
$this->contentType = $this->getContentTypeFromEnvironment($options);
$this->data = $this->getDataFromEnvironment($options);

$this->accept = array_unique(array_merge($this->accept, $this->getAcceptArrayFromEnvironment($this->getOption($options, 'accept'))));
$accept = $this->getAcceptArrayFromEnvironment($this->getOption($options, 'accept'), $acceptParams);
$this->acceptParams = $acceptParams;
$this->accept = array_merge($this->accept, $accept);
$this->acceptLanguage = array_unique(array_merge($this->acceptLanguage, $this->getAcceptArrayFromEnvironment($this->getOption($options, 'acceptLanguage'))));

$this->ifMatch = $this->getMatchArrayFromEnvironment($this->getOption($options, 'ifMatch'));
Expand Down Expand Up @@ -175,6 +178,11 @@ public function setAccept($value)
}
}

public function getAcceptParams()
{
return $this->acceptParams;
}

public function getAcceptLanguage()
{
return $this->acceptLanguage;
Expand Down Expand Up @@ -243,7 +251,7 @@ private function getMethodFromEnvironment($options)
$override = strtoupper($this->getHeader('xHttpMethodOverride'));
if ($override && $method == 'POST') {
$method = $override;

} else {
// get override value from URL and use if applicable
if (
Expand All @@ -254,7 +262,7 @@ private function getMethodFromEnvironment($options)
if (preg_match('/![A-Z]+$/', $this->uri, $match, PREG_OFFSET_CAPTURE)) {
$method = strtoupper(substr($this->uri, $match[0][1] + 1));
$this->uri = substr($this->uri, 0, $match[0][1]);

// get override value from _method querystring
} elseif (isset($_GET['_method'])) {
$method = strtoupper($_GET['_method']);
Expand Down Expand Up @@ -326,28 +334,51 @@ private function getURIFromEnvironment($options)
}

/**
* Get accepted content mimetypes from request header
* @param str $acceptString
* Get accepted content mimetypes and accept parameters from request header
* @param str $acceptString accept string
* @param array $params accept parameters
* @return str[]
*/
private function getAcceptArrayFromEnvironment($acceptString)
private function getAcceptArrayFromEnvironment($acceptString, &$acceptParamArray = array())
{
$accept = $acceptArray = array();
foreach (explode(',', strtolower($acceptString)) as $part) {
$parts = preg_split('/\s*;\s*q=/', $part);
if (isset($parts) && isset($parts[1]) && $parts[1]) {
$num = $parts[1] * 10;
} else {
$num = 10;
$accept = $acceptArray = $acceptParam = $acceptParamArray = array();
$parts = preg_split('/\s*,\s*/', strtolower($acceptString));
foreach ($parts as $part) {
if (empty($part)) {
continue;
}
$partParams = preg_split('/\s*;\s*/', $part);
$type = array_shift($partParams);
$num = 10;
$acceptParams = array();
foreach ($partParams as $param) {
$keyValue = preg_split('/\s*=\s*/', $param);
if ($keyValue[0] === 'q') {
if (array_key_exists(1, $keyValue) && is_numeric($keyValue[1]) && (int)$keyValue[1] >= 0
&& (int)$keyValue[1] <= 1) {
$num = $keyValue[1] * 10;
}
} else {
$key = $keyValue[0];
$value = array_key_exists(1, $keyValue) ? $keyValue[1] : null;
$acceptParams[] = $key . '=' . $value;
}
}
// quality of 0 is not acceptable to the client - rfc2616 sec 3.9
if ($num === 0) {
$type = null;
}
if ($parts[0]) {
$accept[$num][] = $parts[0];
if ($type) {
$accept[$num][] = $type;
$acceptParam[$num][] = $acceptParams;
}
}
krsort($accept);
foreach ($accept as $parts) {
foreach ($parts as $part) {
$acceptArray[] = trim($part);
krsort($acceptParam);
foreach ($accept as $i => $parts) {
foreach ($parts as $j => $part) {
$acceptArray[] = $part;
$acceptParamArray[] = $acceptParam[$i][$j];
}
}

Expand Down
71 changes: 52 additions & 19 deletions src/Tonic/Resource.php
Original file line number Diff line number Diff line change
Expand Up @@ -167,17 +167,12 @@ public function exec()
*/
public function options()
{
$options = array();

$resourceMetadata = $this->app->getResourceMetadata($this);

foreach ($resourceMetadata->getMethods() as $method => $methodMetadata) {
$options[] = strtoupper($method);
}

return new Response(200, $options, array(
'Allow' => implode(',', $options)
$options = implode(',', $this->allowedMethods());
$response = new Response(200, $options, array(
'Allow' => $options
));
$response->contentType = 'text/plain';
return $response;
}

/**
Expand Down Expand Up @@ -241,18 +236,48 @@ protected function accepts($mimetype)
/**
* Provides condition mimetype must be in request accept array, returns a number
* based on the priority of the match.
* @param str $mimetype
* @param str $mimetype
* @param str $parameter variable number of key=value parameters to check for in the accept header
* @return int
*/
protected function provides($mimetype)
protected function provides()
{
if (count($this->request->getAccept()) == 0) return 0;
$pos = array_search($mimetype, $this->request->getAccept());
$params = func_get_args();
$mimetype = array_shift($params);

if (count($this->request->getAccept()) == 0) {
return 0;
}
$acceptParams = $this->request->getAcceptParams();
$pos = false;
foreach ($this->request->getAccept() as $i => $acceptMimetype) {
if ($mimetype === $acceptMimetype) {
foreach ($acceptParams[$i] as $acceptParam) {
if (array_search($acceptParam, $params) === false) {
continue 2;
}
}
$pos = $i;
break;
}
}
if ($pos === FALSE) {
if (in_array('*/*', $this->request->getAccept())) {
return 0;
} else {
throw new NotAcceptableException('No matching method for response type "'.join(', ', $this->request->getAccept()).'"');
$responseTypes = array();

foreach ($this->request->getAccept() as $i => $acceptMimetype) {
$responseType = $acceptMimetype;
foreach ($acceptParams[$i] as $acceptParam) {
if (! empty($acceptParam)) {
$responseType .= ';' . $acceptParam;
}
}
$responseTypes[] = $responseType;
}

throw new NotAcceptableException('No matching method for response type "'.join(', ', $responseTypes).'"');
}
} else {
$this->after(function ($response) use ($mimetype) {
Expand Down Expand Up @@ -297,12 +322,20 @@ public function allowedMethods()
{
$metadata = $this->app->getResourceMetadata($this);
$allowedMethods = array();
foreach ($metadata['methods'] as $method => $properties) {
foreach ($properties['method'] as $method) {
$allowedMethods[] = strtoupper($method[0]);
foreach ($metadata->getMethods() as $method => $methodMetadata) {
foreach ($methodMetadata->getConditions() as $key => $values) {
if ($key !== 'method') {
continue;
}
foreach ($values as $value) {
if (in_array($value, $allowedMethods)) {
continue;
}
$allowedMethods[] = $value;
}
}
}
return array_values(array_unique($allowedMethods));
return array_unique($allowedMethods);
}

public function __toString()
Expand Down
2 changes: 1 addition & 1 deletion src/Tonic/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class Response
public
$code = self::NOCONTENT,
$body = null,
$headers = array('content-type' => 'text/html');
$headers = array('Content-Type' => 'text/html');

public function __construct($code = null, $body = null, $headers = array())
{
Expand Down