Set extension with multiple accept based on order in parseExtensions, currently with multiple accepted types, no extension is set at all

This commit is contained in:
Ceeram 2013-06-27 14:22:49 +02:00
parent 19c94d0211
commit 6a0185d7e6
2 changed files with 39 additions and 7 deletions

View file

@ -144,6 +144,9 @@ class RequestHandlerComponent extends Component {
* Compares the accepted types and configured extensions. * Compares the accepted types and configured extensions.
* If there is one common type, that is assigned as the ext/content type * If there is one common type, that is assigned as the ext/content type
* for the response. * for the response.
* Type with the highest weight will be set. If the highest weight has more
* then one type matching the extensions, the order in which extensions are specified
* determines which type will be set.
* *
* If html is one of the preferred types, no content type will be set, this * If html is one of the preferred types, no content type will be set, this
* is to avoid issues with browsers that prefer html and several other content types. * is to avoid issues with browsers that prefer html and several other content types.
@ -155,13 +158,19 @@ class RequestHandlerComponent extends Component {
if (empty($accept)) { if (empty($accept)) {
return; return;
} }
$accepts = $this->response->mapType($this->request->parseAccept());
$preferedTypes = current($accepts);
if (array_intersect($preferedTypes, array('html', 'xhtml'))) {
return null;
}
$extensions = Router::extensions(); $extensions = Router::extensions();
$preferred = array_shift($accept); foreach ($accepts as $types) {
$preferredTypes = $this->response->mapType($preferred); $ext = array_intersect($extensions, $types);
if (!in_array('xhtml', $preferredTypes) && !in_array('html', $preferredTypes)) { if ($ext) {
$similarTypes = array_intersect($extensions, $preferredTypes); $this->ext = current($ext);
if (count($similarTypes) === 1) { break;
$this->ext = array_shift($similarTypes);
} }
} }
} }

View file

@ -229,7 +229,10 @@ class RequestHandlerComponentTest extends CakeTestCase {
} }
/** /**
* Test that ext is not set with multiple accepted content types. * Test that ext is set to the first listed extension with multiple accepted
* content types.
* Having multiple types accepted with same weight, means the client lets the
* server choose the returned content type.
* *
* @return void * @return void
*/ */
@ -239,7 +242,27 @@ class RequestHandlerComponentTest extends CakeTestCase {
Router::parseExtensions('xml', 'json'); Router::parseExtensions('xml', 'json');
$this->RequestHandler->initialize($this->Controller); $this->RequestHandler->initialize($this->Controller);
$this->assertEquals('xml', $this->RequestHandler->ext);
$this->RequestHandler->ext = null;
Router::setExtensions(array('json', 'xml'), false);
$this->RequestHandler->initialize($this->Controller);
$this->assertEquals('json', $this->RequestHandler->ext);
}
/**
* Test that ext is set to type with highest weight
*
* @return void
*/
public function testInitializeContentTypeWithMultipleAcceptedTypes() {
$_SERVER['HTTP_ACCEPT'] = 'text/csv;q=1.0, application/json;q=0.8, application/xml;q=0.7';
$this->assertNull($this->RequestHandler->ext); $this->assertNull($this->RequestHandler->ext);
Router::parseExtensions('xml', 'json');
$this->RequestHandler->initialize($this->Controller);
$this->assertEquals('json', $this->RequestHandler->ext);
} }
/** /**