diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a1b739..369a9f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [3.0.3] - 2018-01-08 + +### Changed +- Fixed issue where `Content-type` headers with directives (e.g. `Content-type: application/json; charset=utf-8`) are processed correctly + ## [3.0.2] - 2018-01-03 + +### Changed - Added URI matching tests into `EndpointTestCases`. Updating to this version will result in existing passing tests using said trait being skipped until good and bad URI matches are added into the test case. ## [3.0.1] - 2017-12-01 diff --git a/src/Dispatcher.php b/src/Dispatcher.php index 25fdc2c..ac0b4bb 100644 --- a/src/Dispatcher.php +++ b/src/Dispatcher.php @@ -177,10 +177,17 @@ private function parseInput(): ParsedInput // don't use $_POST because additional content types are supported. // Since PSR-7 doesn't specify parsing the body of most MIME-types, // we'll hand off to our own set of parsers. - $cth = $this->request->getHeader('Content-type'); - if ($cth) { + $header = $this->request->getHeader('Content-type'); + if ($header) { + $directives = explode(';', $header[0]); + if (!count($directives)) { + throw new OutOfBoundsException('Invalid Content-type header', 400); + } + $mediaType = array_shift($directives); + // Future: trim and format directives; e.g. ' charset=utf-8' => + // ['charset' => 'utf-8'] list($parser_class) = (new ClassMapper($this->parser_list)) - ->search($cth[0]); + ->search($mediaType); if (!$parser_class) { throw new OutOfBoundsException('Unsupported Content-type', 400); } diff --git a/tests/DispatcherTest.php b/tests/DispatcherTest.php index 5e593e1..a105f47 100644 --- a/tests/DispatcherTest.php +++ b/tests/DispatcherTest.php @@ -417,6 +417,25 @@ public function testUnsupportedContentTypeReachesErrorHandler() ); } + /** + * @covers ::dispatch + */ + public function testMatchingContentTypeWithDirectives() + { + $contentType = 'application/json; charset=utf-8'; + $req = $this->getMockRequestWithUriPath('/user/5', 'POST'); + $req->expects($this->any()) + ->method('getHeader') + ->with('Content-type') + ->will($this->returnValue([$contentType])); + $response = (new Dispatcher()) + ->setEndpointList($this->getEndpointListForFixture()) + ->setParserList($this->getDefaultParserList()) + ->setRequest($req) + ->dispatch(); + $this->checkResponse($response, 200); + } + /** @covers ::dispatch */ public function testFailedAuthenticationReachesErrorHandler() {