Skip to content

Commit 6a0185d

Browse files
committed
Set extension with multiple accept based on order in parseExtensions, currently with multiple accepted types, no extension is set at all
1 parent 19c94d0 commit 6a0185d

File tree

2 files changed

+39
-7
lines changed

2 files changed

+39
-7
lines changed

lib/Cake/Controller/Component/RequestHandlerComponent.php

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ public function initialize(Controller $controller) {
144144
* Compares the accepted types and configured extensions.
145145
* If there is one common type, that is assigned as the ext/content type
146146
* for the response.
147+
* Type with the highest weight will be set. If the highest weight has more
148+
* then one type matching the extensions, the order in which extensions are specified
149+
* determines which type will be set.
147150
*
148151
* If html is one of the preferred types, no content type will be set, this
149152
* is to avoid issues with browsers that prefer html and several other content types.
@@ -155,13 +158,19 @@ protected function _setExtension() {
155158
if (empty($accept)) {
156159
return;
157160
}
161+
162+
$accepts = $this->response->mapType($this->request->parseAccept());
163+
$preferedTypes = current($accepts);
164+
if (array_intersect($preferedTypes, array('html', 'xhtml'))) {
165+
return null;
166+
}
167+
158168
$extensions = Router::extensions();
159-
$preferred = array_shift($accept);
160-
$preferredTypes = $this->response->mapType($preferred);
161-
if (!in_array('xhtml', $preferredTypes) && !in_array('html', $preferredTypes)) {
162-
$similarTypes = array_intersect($extensions, $preferredTypes);
163-
if (count($similarTypes) === 1) {
164-
$this->ext = array_shift($similarTypes);
169+
foreach ($accepts as $types) {
170+
$ext = array_intersect($extensions, $types);
171+
if ($ext) {
172+
$this->ext = current($ext);
173+
break;
165174
}
166175
}
167176
}

lib/Cake/Test/Case/Controller/Component/RequestHandlerComponentTest.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,10 @@ public function testInitializeNoContentTypeWithSingleAccept() {
229229
}
230230

231231
/**
232-
* Test that ext is not set with multiple accepted content types.
232+
* Test that ext is set to the first listed extension with multiple accepted
233+
* content types.
234+
* Having multiple types accepted with same weight, means the client lets the
235+
* server choose the returned content type.
233236
*
234237
* @return void
235238
*/
@@ -239,7 +242,27 @@ public function testInitializeNoContentTypeWithMultipleAcceptedTypes() {
239242
Router::parseExtensions('xml', 'json');
240243

241244
$this->RequestHandler->initialize($this->Controller);
245+
$this->assertEquals('xml', $this->RequestHandler->ext);
246+
247+
$this->RequestHandler->ext = null;
248+
Router::setExtensions(array('json', 'xml'), false);
249+
250+
$this->RequestHandler->initialize($this->Controller);
251+
$this->assertEquals('json', $this->RequestHandler->ext);
252+
}
253+
254+
/**
255+
* Test that ext is set to type with highest weight
256+
*
257+
* @return void
258+
*/
259+
public function testInitializeContentTypeWithMultipleAcceptedTypes() {
260+
$_SERVER['HTTP_ACCEPT'] = 'text/csv;q=1.0, application/json;q=0.8, application/xml;q=0.7';
242261
$this->assertNull($this->RequestHandler->ext);
262+
Router::parseExtensions('xml', 'json');
263+
264+
$this->RequestHandler->initialize($this->Controller);
265+
$this->assertEquals('json', $this->RequestHandler->ext);
243266
}
244267

245268
/**

0 commit comments

Comments
 (0)