Permalink
Browse files

First pass at disambiguating request/response content type. WARNING: …

…BC break - going forward, usage of the `$type` instance property should be replaced with the `type()` method.
  • Loading branch information...
nateabele authored and gwoo committed Sep 18, 2012
1 parent 9432658 commit 854171dcfd57be515e87f2c346a3ac124b59630d
View
@@ -92,7 +92,7 @@ public function __construct(array $config = array()) {
);
$config += $defaults;
- foreach (array_filter($config) as $key => $value) {
+ foreach (array_intersect_key(array_filter($config), $defaults) as $key => $value) {
$this->{$key} = $value;
}
parent::__construct($config);
View
@@ -551,7 +551,7 @@ public static function path($path, $type, array $options = array()) {
*
* @param object $response A Response object into which the operation will be
* rendered. The content of the render operation will be assigned to the `$body`
- * property of the object, the `'Content-type'` header will be set accordingly, and it
+ * property of the object, the `'Content-Type'` header will be set accordingly, and it
* will be returned.
* @param mixed $data The data (usually an associative array) to be rendered in the response.
* @param array $options Any options specific to the response being rendered, such as type
View
@@ -40,7 +40,7 @@ class Message extends \lithium\net\Message {
*
* @var string
*/
- protected $_type = 'html';
+ protected $_type = null;
/**
* Classes used by `Request`.
@@ -85,6 +85,7 @@ public function __construct(array $config = array()) {
if (strpos($this->host, '/') !== false) {
list($this->host, $this->path) = explode('/', $this->host, 2);
}
+ if ($this->headers);
$this->path = str_replace('//', '/', "/{$this->path}");
$this->protocol = $this->protocol ?: "HTTP/{$this->version}";
}
@@ -131,25 +132,39 @@ public function headers($key = null, $value = null) {
}
/**
- * Sets/Gets the content type
+ * Sets/gets the content type.
*
- * @param string $type a full content type i.e. `'application/json'` or simple name `'json'`
+ * @param string $type A full content type i.e. `'application/json'` or simple name `'json'`
* @return string A simple content type name, i.e. `'html'`, `'xml'`, `'json'`, etc., depending
* on the content type of the request.
*/
public function type($type = null) {
- if ($type == null && $type !== false) {
+ if ($type === false) {
+ unset($this->headers['Content-Type']);
+ $this->_type = null;
+ return;
+ }
+ $media = $this->_classes['media'];
+
+ if (!$type && $this->_type) {
return $this->_type;
}
- if (strpos($type, '/')) {
- $media = $this->_classes['media'];
+ $headers = $this->headers + array('Content-Type' => null);
+ $type = $type ?: $headers['Content-Type'];
+
+ if (!$type) {
+ return;
+ }
+ $header = $type;
+ if (!strpos($type, '/')) {
if (!$data = $media::type($type)) {
- return $this->_type;
+ return false;
}
- $type = is_array($data) ? reset($data) : $data;
+ $header = is_array($data['content']) ? reset($data['content']) : $data['content'];
}
- return $this->_type = $type;
+ $this->headers['Content-Type'] = $header;
+ return ($this->_type = $type);
}
}
View
@@ -233,7 +233,8 @@ public function to($format, array $options = array()) {
if (in_array($options['method'], array('POST', 'PUT', 'PATCH'))) {
$media = $this->_classes['media'];
if ($type = $media::type($this->_type)) {
- $this->headers('Content-Type', $type['content'][0]);
+ $type = is_array($type['content']) ? reset($type['content']) : $type['content'];
+ $this->headers('Content-Type', $type);
}
}
View
@@ -20,13 +20,6 @@ class Response extends \lithium\net\http\Message {
*/
public $status = array('code' => 200, 'message' => 'OK');
- /**
- * Content Type.
- *
- * @var string
- */
- public $type = 'text/html';
-
/**
* Character encoding.
*
@@ -95,7 +88,7 @@ class Response extends \lithium\net\http\Message {
* @param array $config
*/
public function __construct(array $config = array()) {
- $defaults = array('message' => null);
+ $defaults = array('message' => null, 'type' => null);
$config += $defaults;
parent::__construct($config);
}
@@ -114,17 +107,21 @@ protected function _init() {
if (isset($this->headers['Transfer-Encoding'])) {
$this->body = $this->_httpChunkedDecode($this->body);
}
- if (isset($this->headers['Content-Type'])) {
- $pattern = '/([-\w\/\.+]+)(;\s*?charset=(.+))?/i';
- preg_match($pattern, $this->headers['Content-Type'], $match);
+ if ($type = $this->_config['type']) {
+ $this->type($type);
+ }
+ if (!isset($this->headers['Content-Type'])) {
+ return;
+ }
+ $pattern = '/([-\w\/\.+]+)(;\s*?charset=(.+))?/i';
+ preg_match($pattern, $this->headers['Content-Type'], $match);
- if (isset($match[1])) {
- $this->type = trim($match[1]);
- $this->body = $this->_decode($this->body);
- }
- if (isset($match[3])) {
- $this->encoding = strtoupper(trim($match[3]));
- }
+ if (isset($match[1])) {
+ $this->type(trim($match[1]));
+ $this->body = $this->_decode($this->body);
+ }
+ if (isset($match[3])) {
+ $this->encoding = strtoupper(trim($match[3]));
}
}
@@ -136,10 +133,11 @@ protected function _init() {
*/
protected function _decode($body) {
$media = $this->_classes['media'];
- if ($type = $media::type($this->_type)) {
- $body = $media::decode($this->_type, $body) ?: $body;
+
+ if (!$type = $media::type($this->_type)) {
+ return $body;
}
- return $body;
+ return $media::decode($this->_type, $body) ?: $body;
}
/**
@@ -248,8 +246,8 @@ protected function _httpChunkedDecode($body) {
* @return string
*/
public function __toString() {
- if ($this->type != 'text/html' && !isset($this->headers['Content-Type'])) {
- $this->headers['Content-Type'] = $this->type;
+ if ($this->_type != 'text/html' && !isset($this->headers['Content-Type'])) {
+ $this->headers['Content-Type'] = $this->type();
}
$first = "{$this->protocol} {$this->status['code']} {$this->status['message']}";
$response = array($first, join("\r\n", $this->headers()), "", $this->body());
@@ -431,7 +431,7 @@ public function testUnregisteredContentHandler() {
public function testManualContentHandling() {
Media::type('custom', 'text/x-custom');
$response = new Response();
- $response->type = 'custom';
+ $response->type('custom');
Media::render($response, 'Hello, world!', array(
'layout' => false,
@@ -463,7 +463,7 @@ public function testRequestOptionMerging() {
$request->params['foo'] = 'bar';
$response = new Response();
- $response->type = 'custom';
+ $response->type('custom');
Media::render($response, null, compact('request') + array(
'layout' => false,
@@ -494,7 +494,7 @@ public function testRenderWithOptionsMerging() {
$request->params['controller'] = 'pages';
$response = new Response();
- $response->type = 'html';
+ $response->type('html');
$this->expectException('/Template not found/');
Media::render($response, null, compact('request'));
@@ -326,6 +326,21 @@ public function testQueryParamsConstructed() {
$result = $request->queryString(array('param3' => 3));
$this->assertEqual($expected, $result);
}
+
+ public function testKeepDefinedContentTypeHeaderOnPost() {
+ $request = new Request(array(
+ 'method' => 'POST',
+ 'headers' => array('Content-Type' => 'text/x-test')
+ ));
+ $expected = 'Content-Type: text/x-test';
+ $result = $request->headers();
+ $message = "Expected value `{$expected}` not found in result.";
+ $this->assertTrue(in_array($expected, $result), $message);
+
+ $expected = '#Content-Type: text/x-test#';
+ $result = $request->to('string');
+ $this->assertPattern($expected, $result);
+ }
}
?>
Oops, something went wrong.

0 comments on commit 854171d

Please sign in to comment.