Permalink
Browse files

Fixing CakeRequest::accepts() where ;q values on Accept header

were not respected.
Fixes #1940
  • Loading branch information...
1 parent 5df12a2 commit 1a872e6544d382f691365b91e1740c7be9f3129e @markstory markstory committed Aug 27, 2011
Showing with 34 additions and 9 deletions.
  1. +20 −8 lib/Cake/Network/CakeRequest.php
  2. +14 −1 lib/Cake/Test/Case/Network/CakeRequestTest.php
@@ -605,23 +605,35 @@ public function subdomains($tldLength = 1) {
*
* `$this->request->accepts('json');`
*
+ * This method will order the returned content types by the preference values indicated
+ * by the client.
+ *
* @param string $type The content type to check for. Leave null to get all types a client accepts.
* @return mixed Either an array of all the types the client accepts or a boolean if they accept the
* provided type.
*/
public function accepts($type = null) {
- $acceptTypes = explode(',', $this->header('accept'));
- $acceptTypes = array_map('trim', $acceptTypes);
- foreach ($acceptTypes as $i => $accepted) {
- if (strpos($accepted, ';') !== false) {
- list($accepted) = explode(';', $accepted);
- $acceptTypes[$i] = $accepted;
+ $accept = array();
+ $header = explode(',', $this->header('accept'));
+ foreach (array_filter(array_reverse($header)) as $value) {
+ $prefPos = strpos($value, ';');
+ if ($prefPos !== false) {
+ $prefValue = (float) substr($value, strpos($value, '=') + 1);
+ $value = trim(substr($value, 0, $prefPos));
+ } else {
+ $prefValue = 1.0;
+ $value = trim($value);
+ }
+ if ($prefValue) {
+ $accept[$value] = $prefValue;
}
}
+ arsort($accept);
+ $accept = array_keys($accept);
if ($type === null) {
- return $acceptTypes;
+ return $accept;
}
- return in_array($type, $acceptTypes);
+ return in_array($type, $accept);
}
/**
@@ -785,7 +785,7 @@ public function testAccepts() {
$result = $request->accepts();
$expected = array(
- 'text/xml', 'application/xml', 'application/xhtml+xml', 'text/html', 'text/plain', 'image/png'
+ 'text/xml', 'application/xhtml+xml', 'text/html', 'image/png', 'text/plain', 'application/xml'
);
$this->assertEquals($expected, $result, 'Content types differ.');
@@ -813,6 +813,19 @@ public function testAcceptWithWhitespace() {
$this->assertTrue($request->accepts('text/html'));
}
+/**
+ * Content types from accepts() should respect the client's q preference values.
+ *
+ * @return void
+ */
+ public function testAcceptWithQvalueSorting() {
+ $_SERVER['HTTP_ACCEPT'] = 'text/html;q=0.8,application/json;q=0.7,application/xml;q=1.0';
+ $request = new CakeRequest('/', false);
+ $result = $request->accepts();
+ $expected = array('application/xml', 'text/html', 'application/json');
+ $this->assertEquals($expected, $result);
+ }
+
/**
* testBaseUrlAndWebrootWithModRewrite method
*

0 comments on commit 1a872e6

Please sign in to comment.