Skip to content

Commit

Permalink
Dirty hacky implementation of the type option.
Browse files Browse the repository at this point in the history
Mime types need to be shared either via inheritance or by extracting theminto a separate class. This code is
horrible, but it works.
  • Loading branch information
markstory committed Dec 28, 2012
1 parent f3af8bd commit 6559721
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 0 deletions.
50 changes: 50 additions & 0 deletions lib/Cake/Network/Http/Client.php
Expand Up @@ -24,8 +24,27 @@
*
* ### Doing requests
*
* ### Sending request bodies
*
* By default any POST/PUT/PATCH/DELETE request with $data will
* send their data as `multipart/form-data`.
*
* When sending request bodies you can use the `type` option to
* set the Content-Type for the request:
*
* `$http->get('/users', [], ['type' => 'json']);`
*
* The `type` option sets both the `Content-Type` and `Accept` header, to
* the same mime type. When using `type` you can use either a full mime
* type or an alias. If you need different types in the Accept and Content-Type
* headers you should set them manually and not use `type`
*
* ### Using authentication
*
*
* ### Using proxies
*
*
*/
class Client {

Expand Down Expand Up @@ -268,6 +287,9 @@ protected function _createRequest($method, $url, $data, $options) {
$request->method($method)
->url($url)
->content($data);
if (isset($options['type'])) {
$request->header($this->_typeHeaders($options['type']));
}
if (isset($options['headers'])) {
$request->header($options['headers']);
}
Expand All @@ -278,4 +300,32 @@ protected function _createRequest($method, $url, $data, $options) {
return $request;
}

/**
* Returns headers for Accept/Content-Type based on a short type
* or full mime-type.
*
* @param string $type short type alias or full mimetype.
* @return array Headers to set on the request.
*/
protected function _typeHeaders($type) {
if (strpos($type, '/') !== false) {
return [
'Accept' => $type,
'Content-Type' => $type
];
}
// Hacky as hell but I'll clean it up I promise
$reflection = new \ReflectionClass('Cake\Network\Response');
$properties = $reflection->getDefaultProperties();
if (isset($properties['_mimeTypes'][$type])) {
$mimeTypes = $properties['_mimeTypes'][$type];
$mimeType = is_array($mimeTypes) ? current($mimeTypes) : $mimeTypes;
return [
'Accept' => $mimeType,
'Content-Type' => $mimeType,
];
}
return [];
}

}
46 changes: 46 additions & 0 deletions lib/Cake/Test/TestCase/Network/Http/ClientTest.php
Expand Up @@ -277,4 +277,50 @@ public function testMethodsSimple($method) {
$this->assertSame($result, $response);
}

/**
* Provider for testing the type option.
*
* @return array
*/
public static function typeProvider() {
return [
['application/json', 'application/json'],
['json', 'application/json'],
['xml', 'application/xml'],
['application/xml', 'application/xml'],
];
}

/**
* Test that using the 'type' option sets the correct headers
*
* @dataProvider typeProvider
* @return void
*/
public function testPostWithTypeKey($type, $mime) {
$response = new Response();
$data = 'some data';
$headers = [
'Connection' => 'close',
'User-Agent' => 'CakePHP',
'Content-Type' => $mime,
'Accept' => $mime,
];

$mock = $this->getMock('Cake\Network\Http\Adapter\Stream', ['send']);
$mock->expects($this->once())
->method('send')
->with($this->logicalAnd(
$this->attributeEqualTo('_method', Request::METHOD_POST),
$this->attributeEqualTo('_content', $data),
$this->attributeEqualTo('_headers', $headers)
))
->will($this->returnValue($response));

$http = new Client([
'host' => 'cakephp.org',
'adapter' => $mock
]);
$http->post('/projects/add', $data, ['type' => $type]);
}
}

0 comments on commit 6559721

Please sign in to comment.