Skip to content
This repository has been archived by the owner on Jan 21, 2020. It is now read-only.

Commit

Permalink
Content-Type matching
Browse files Browse the repository at this point in the history
- Ported final changes from zendframework/zendframework#4950
- Updated ContentTypeFilterListener to use new match() methodology from
  ContentType header
  • Loading branch information
weierophinney committed Aug 12, 2013
1 parent 409f4b9 commit 7f3f135
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 41 deletions.
43 changes: 6 additions & 37 deletions src/ZF/ContentNegotiation/ContentTypeFilterListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,47 +83,16 @@ public function onDispatch(MvcEvent $e)

$headers = $request->getHeaders();
$contentTypeHeader = false;
if ($headers->has('content-type')) {
$contentTypeHeader = $headers->get('content-type');
$value = $contentTypeHeader->getFieldValue();
$value = explode(';', $value, 2);
$contentTypeHeader = array_shift($value);
$contentTypeHeader = strtolower($contentTypeHeader);
}

$matched = false;
if (is_string($this->config[$controllerName])) {
$matched = $this->validateContentType($contentTypeHeader, $this->config[$controllerName]);
} elseif (is_array($this->config[$controllerName])) {
foreach ($this->config[$controllerName] as $whitelistType) {
$matched = $this->validateContentType($contentTypeHeader, $whitelistType);
if ($matched) {
break;
}
}
}

if (!$matched) {
if (!$headers->has('content-type')) {
throw new DomainException('Invalid content-type specified', 415);
}
}

/**
* Validate that the content type received matches that in the whitelist
*
* @param string $received
* @param string $allowed
*/
protected function validateContentType($received, $allowed)
{
if (!$received) {
return false;
}
$contentTypeHeader = $headers->get('content-type');

$matched = $contentTypeHeader->match($this->config[$controllerName]);

if (strtolower($allowed) === $received) {
return true;
if (false === $matched) {
throw new DomainException('Invalid content-type specified', 415);
}

return false;
}
}
4 changes: 3 additions & 1 deletion src/ZF/ContentNegotiation/Header/ContentType.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ public function match($matchAgainst)
$left = $this->getMediaTypeObjectFromString($mediaType);

foreach ($matchAgainst as $matchType) {
$matchType = strtolower($matchType);

if ($mediaType == $matchType) {
return $matchType;
}
Expand Down Expand Up @@ -142,7 +144,7 @@ public function getFieldValue()
*/
public function setMediaType($mediaType)
{
$this->mediaType = $mediaType;
$this->mediaType = strtolower($mediaType);
$this->value = null;
return $this;
}
Expand Down
12 changes: 9 additions & 3 deletions test/ZFTest/ContentNegotiation/ContentTypeFilterListenerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@ class ContentTypeFilterListenerTest extends TestCase
{
public function setUp()
{
$request = new Request();
$headers = $request->getHeaders();
$headers->getPluginClassLoader()->registerPlugin('contenttype', 'ZF\ContentNegotiation\Header\ContentType');

$this->listener = new ContentTypeFilterListener();
$this->event = new MvcEvent();
$this->event->setTarget(new TestAsset\ContentTypeController());
$this->event->setRequest(new Request);
$this->event->setRequest($request);
$this->event->setRouteMatch(new RouteMatch(array(
'controller' => __NAMESPACE__ . '\TestAsset\ContentTypeController',
)));
Expand Down Expand Up @@ -44,10 +48,12 @@ public function testListenerRaisesExceptionIfRequestContentTypeIsNotInController
$contentType = 'application/vnd.zf.v1.foo+json';
$this->listener->setConfig(array(
'ZFTest\ContentNegotiation\TestAsset\ContentTypeController' => array(
'application/json',
'application/xml',
),
));
$this->event->getRequest()->getHeaders()->addHeaderLine('content-type', $contentType);
$request = $this->event->getRequest();
$request->getHeaders()->addHeaderLine('content-type', $contentType);
$request->setContent('<?xml version="1.0"?><foo><bar>baz</bar></foo>');

$this->setExpectedException('ZF\ApiProblem\Exception\DomainException', 'Invalid content-type');
$this->listener->onDispatch($this->event);
Expand Down

0 comments on commit 7f3f135

Please sign in to comment.