Skip to content

Commit

Permalink
Return 415 on unsupported format in request-body
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonSimCity committed Feb 27, 2014
1 parent 5218769 commit 5d7dfc6
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 4 deletions.
3 changes: 3 additions & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ private function addBodyListenerSection(ArrayNodeDefinition $rootNode)
->addDefaultsIfNotSet()
->canBeUnset()
->children()
->booleanNode('throw_exception_on_unsupported_content_type')
->defaultFalse()
->end()
->arrayNode('decoders')
->useAttributeAsKey('name')
->defaultValue(array('json' => 'fos_rest.decoder.json', 'xml' => 'fos_rest.decoder.xml'))
Expand Down
1 change: 1 addition & 0 deletions DependencyInjection/FOSRestExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ public function load(array $configs, ContainerBuilder $container)
if (!empty($config['body_listener'])) {
$loader->load('body_listener.xml');

$container->setParameter($this->getAlias().'.throw_exception_on_unsupported_content_type', $config['body_listener']['throw_exception_on_unsupported_content_type']);
$container->setParameter($this->getAlias().'.decoders', $config['body_listener']['decoders']);
}

Expand Down
16 changes: 15 additions & 1 deletion EventListener/BodyListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;

/**
* This listener handles Request body decoding.
Expand All @@ -28,20 +29,29 @@ class BodyListener
*/
private $decoderProvider;

/**
* @var boolean
*/
private $throwExceptionOnUnsupportedContentType;

/**
* Constructor.
*
* @param DecoderProviderInterface $decoderProvider Provider for fetching decoders
* @param boolean $throwExceptionOnUnsupportedContentType
*/
public function __construct(DecoderProviderInterface $decoderProvider)
public function __construct(DecoderProviderInterface $decoderProvider, $throwExceptionOnUnsupportedContentType = false)
{
$this->decoderProvider = $decoderProvider;
$this->throwExceptionOnUnsupportedContentType = $throwExceptionOnUnsupportedContentType;
}

/**
* Core request handler
*
* @param GetResponseEvent $event The event
* @throws BadRequestHttpException
* @throws UnsupportedMediaTypeHttpException
*/
public function onKernelRequest(GetResponseEvent $event)
{
Expand All @@ -57,6 +67,10 @@ public function onKernelRequest(GetResponseEvent $event)
: $request->getFormat($contentType);

if (!$this->decoderProvider->supports($format)) {
if ($this->throwExceptionOnUnsupportedContentType) {
throw new UnsupportedMediaTypeHttpException("Request body format '$format' not supported");
}

return;
}

Expand Down
1 change: 1 addition & 0 deletions Resources/config/body_listener.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<service id="fos_rest.body_listener" class="%fos_rest.body_listener.class%">
<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="10" />
<argument type="service" id="fos_rest.decoder_provider" />
<argument>%fos_rest.throw_exception_on_unsupported_content_type%</argument>
</service>

</services>
Expand Down
1 change: 1 addition & 0 deletions Resources/doc/configuration-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ fos_rest:
# Prototype
name: []
body_listener:
throw_exception_on_unsupported_content_type: false
decoders:

# Prototype
Expand Down
1 change: 1 addition & 0 deletions Tests/DependencyInjection/FOSRestExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ public function testLoadBodyListenerWithDefaults()

$this->assertTrue($this->container->hasDefinition('fos_rest.body_listener'));
$this->assertParameter($decoders, 'fos_rest.decoders');
$this->assertParameter(false, 'fos_rest.throw_exception_on_unsupported_content_type');
}

public function testDisableFormatListener()
Expand Down
15 changes: 12 additions & 3 deletions Tests/EventListener/BodyListenerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
use Symfony\Component\HttpFoundation\HeaderBag;
use FOS\RestBundle\Decoder\ContainerDecoderProvider;
use FOS\RestBundle\EventListener\BodyListener;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

/**
* Request listener test
Expand All @@ -31,10 +30,11 @@ class BodyListenerTest extends \PHPUnit_Framework_TestCase
* @param string $method a http method (e.g. POST, GET, PUT, ...)
* @param string $contentType the request header content type
* @param array $expectedParameters the http parameters of the updated request
* @param boolean $throwExceptionOnUnsupportedContentType
*
* @dataProvider testOnKernelRequestDataProvider
*/
public function testOnKernelRequest($decode, $request, $method, $contentType, $expectedParameters)
public function testOnKernelRequest($decode, $request, $method, $contentType, $expectedParameters, $throwExceptionOnUnsupportedContentType = false)
{
$decoder = $this->getMockBuilder('FOS\RestBundle\Decoder\DecoderInterface')->disableOriginalConstructor()->getMock();
$decoder->expects($this->any())
Expand All @@ -43,7 +43,7 @@ public function testOnKernelRequest($decode, $request, $method, $contentType, $e

$decoderProvider = new ContainerDecoderProvider(array('json' => 'foo'));

$listener = new BodyListener($decoderProvider);
$listener = new BodyListener($decoderProvider, $throwExceptionOnUnsupportedContentType);

if ($decode) {
$container = $this->getMock('Symfony\Component\DependencyInjection\Container', array('get'));
Expand Down Expand Up @@ -93,4 +93,13 @@ public function testBadRequestExceptionOnMalformedContent()
$this->testOnKernelRequest(true, new Request(array(), array(), array(), array(), array(), array(), 'foo'), 'POST', 'application/json', array());
}

/**
* Test that a unallowed format will cause a UnsupportedMediaTypeHttpException to be thrown
*/
public function testUnsupportedMediaTypeHttpExceptionOnUnsupportedMediaType()
{
$this->setExpectedException('\Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException');
$this->testOnKernelRequest(false, new Request(array(), array(), array(), array(), array(), array(), 'foo'), 'POST', 'application/foo', array(), true);
}

}

0 comments on commit 5d7dfc6

Please sign in to comment.