Skip to content
Permalink
Browse files

Updated the HttpSocket to use the new HttpResponse.

  • Loading branch information...
jrbasso committed Dec 14, 2010
1 parent f45027e commit 60a9d34027d9ab1d822fb75bcefe2c87bac7e4cf
Showing with 81 additions and 128 deletions.
  1. +33 −66 cake/libs/http_socket.php
  2. +48 −62 cake/tests/cases/libs/http_socket.test.php
@@ -19,6 +19,7 @@
*/
App::import('Core', 'CakeSocket');
App::import('Core', 'Router');
App::import('Lib', 'HttpResponse');
/**
* Cake network socket connection class.
@@ -73,22 +74,7 @@ class HttpSocket extends CakeSocket {
*
* @var array
*/
public $response = array(
'raw' => array(
'status-line' => null,
'header' => null,
'body' => null,
'response' => null
),
'status' => array(
'http-version' => null,
'code' => null,
'reason-phrase' => null
),
'header' => array(),
'body' => '',
'cookies' => array()
);
public $response = null;
/**
* Configuration settings for the HttpSocket and the requests
@@ -238,16 +224,15 @@ public function setContentResource($resource) {
* method and provide a more granular interface.
*
* @param mixed $request Either an URI string, or an array defining host/uri
* @return mixed null on error, reference to request body on success
* @return mixed false on error, HttpResponse on success
*/
public function &request($request = array()) {
public function request($request = array()) {
$this->reset(false);
if (is_string($request)) {
$request = array('uri' => $request);
} elseif (!is_array($request)) {
$return = false;
return $return;
return false;
}
if (!isset($request['uri'])) {
@@ -338,7 +323,7 @@ public function &request($request = array()) {
}
if ($this->quirksMode === false && $this->request['line'] === false) {
return $this->response = false;
return false;
}
$this->request['raw'] = '';
@@ -383,14 +368,14 @@ public function &request($request = array()) {
}
$this->response = $this->_parseResponse($response);
if (!empty($this->response['cookies'])) {
if (!empty($this->response->cookies)) {
if (!isset($this->config['request']['cookies'][$Host])) {
$this->config['request']['cookies'][$Host] = array();
}
$this->config['request']['cookies'][$Host] = array_merge($this->config['request']['cookies'][$Host], $this->response['cookies']);
$this->config['request']['cookies'][$Host] = array_merge($this->config['request']['cookies'][$Host], $this->response->cookies);
}
return $this->response['body'];
return $this->response;
}
/**
@@ -416,7 +401,7 @@ public function &request($request = array()) {
* @param array $request An indexed array with indexes such as 'method' or uri
* @return mixed Result of request, either false on failure or the response to the request.
*/
public function &get($uri = null, $query = array(), $request = array()) {
public function get($uri = null, $query = array(), $request = array()) {
if (!empty($query)) {
$uri = $this->_parseUri($uri);
if (isset($uri['query'])) {
@@ -448,7 +433,7 @@ public function &get($uri = null, $query = array(), $request = array()) {
* @param array $request An indexed array with indexes such as 'method' or uri
* @return mixed Result of request, either false on failure or the response to the request.
*/
public function &post($uri = null, $data = array(), $request = array()) {
public function post($uri = null, $data = array(), $request = array()) {
$request = Set::merge(array('method' => 'POST', 'uri' => $uri, 'body' => $data), $request);
return $this->request($request);
}
@@ -461,7 +446,7 @@ public function &post($uri = null, $data = array(), $request = array()) {
* @param array $request An indexed array with indexes such as 'method' or uri
* @return mixed Result of request
*/
public function &put($uri = null, $data = array(), $request = array()) {
public function put($uri = null, $data = array(), $request = array()) {
$request = Set::merge(array('method' => 'PUT', 'uri' => $uri, 'body' => $data), $request);
return $this->request($request);
}
@@ -474,7 +459,7 @@ public function &put($uri = null, $data = array(), $request = array()) {
* @param array $request An indexed array with indexes such as 'method' or uri
* @return mixed Result of request
*/
public function &delete($uri = null, $data = array(), $request = array()) {
public function delete($uri = null, $data = array(), $request = array()) {
$request = Set::merge(array('method' => 'DELETE', 'uri' => $uri, 'body' => $data), $request);
return $this->request($request);
}
@@ -585,58 +570,40 @@ protected function _setProxy() {
* Parses the given message and breaks it down in parts.
*
* @param string $message Message to parse
* @return array Parsed message (with indexed elements such as raw, status, header, body)
* @return object Parsed message as HttpResponse
*/
protected function _parseResponse($message) {
if (is_array($message)) {
return $message;
} elseif (!is_string($message)) {
return false;
}
static $responseTemplate;
if (empty($responseTemplate)) {
$classVars = get_class_vars(__CLASS__);
$responseTemplate = $classVars['response'];
if (!is_string($message)) {
throw new Exception(__('Invalid response.'));
}
$response = $responseTemplate;
if (!preg_match("/^(.+\r\n)(.*)(?<=\r\n)\r\n/Us", $message, $match)) {
return false;
throw new Exception(__('Invalid HTTP response.'));
}
list($null, $response['raw']['status-line'], $response['raw']['header']) = $match;
$response['raw']['response'] = $message;
$response['raw']['body'] = substr($message, strlen($match[0]));
$response = new HttpResponse();
if (preg_match("/(.+) ([0-9]{3}) (.+)\r\n/DU", $response['raw']['status-line'], $match)) {
$response['status']['http-version'] = $match[1];
$response['status']['code'] = (int)$match[2];
$response['status']['reason-phrase'] = $match[3];
}
list(, $statusLine, $header) = $match;
$response->raw = $message;
$response->body = (string)substr($message, strlen($match[0]));
$response['header'] = $this->_parseHeader($response['raw']['header']);
$transferEncoding = null;
if (isset($response['header']['Transfer-Encoding'])) {
$transferEncoding = $response['header']['Transfer-Encoding'];
if (preg_match("/(.+) ([0-9]{3}) (.+)\r\n/DU", $statusLine, $match)) {
$response->httpVersion = $match[1];
$response->code = $match[2];
$response->reasonPhrase = $match[3];
}
$decoded = $this->_decodeBody($response['raw']['body'], $transferEncoding);
$response['body'] = $decoded['body'];
if (!empty($decoded['header'])) {
$response['header'] = $this->_parseHeader($this->_buildHeader($response['header']) . $this->_buildHeader($decoded['header']));
}
$response->headers = $this->_parseHeader($header);
$transferEncoding = $response->getHeader('Transfer-Encoding');
$decoded = $this->_decodeBody($response->body, $transferEncoding);
$response->body = $decoded['body'];
if (!empty($response['header'])) {
$response['cookies'] = $this->parseCookies($response['header']);
if (!empty($decoded['header'])) {
$response->headers = $this->_parseHeader($this->_buildHeader($response->headers) . $this->_buildHeader($decoded['header']));
}
foreach ($response['raw'] as $field => $val) {
if ($val === '') {
$response['raw'][$field] = null;
}
if (!empty($response->headers)) {
$response->cookies = $this->parseCookies($response->headers);
}
return $response;
@@ -190,6 +190,19 @@ public function EscapeToken($token, $chars = null) {
public function unescapeToken($token, $chars = null) {
return parent::_unescapeToken($token, $chars);
}
/**
* Convenience method for testing protected method
*
* @param string $message
* @return object HttpResponse
*/
protected function _parseResponse($message) {
if (!is_string($message)) {
return false;
}
return parent::_parseResponse($message);
}
}
/**
@@ -596,7 +609,7 @@ public function testRequest2() {
$this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse));
$this->Socket->expects($this->once())->method('write')
->with("GET / HTTP/1.1\r\nHost: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\n\r\n");
$response = $this->Socket->request($request);
$response = (string)$this->Socket->request($request);
$this->assertEquals($response, "<h1>Hello, your lucky number is " . $number . "</h1>");
}
@@ -622,22 +635,6 @@ public function testRequest3() {
$this->assertFalse($this->Socket->connected);
}
/**
* testRequestResultAsReference method
*
* @return void
*/
public function testRequestResultAsReference() {
$request = array('uri' => 'htpp://www.cakephp.org/');
$serverResponse = "HTTP/1.x 200 OK\r\nSet-Cookie: foo=bar\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n<h1>This is a cookie test!</h1>";
$this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse));
$this->Socket->connected = true;
$data =& $this->Socket->request($request);
$this->assertEqual($data, $this->Socket->response['body']);
$data = 'new data';
$this->assertEqual($data, $this->Socket->response['body']);
}
/**
* testRequestWithResource
*
@@ -654,15 +651,15 @@ public function testRequestWithResource() {
$this->skipUnless($f, 'Can not write in TMP directory.');
$this->Socket->setContentResource($f);
$result = $this->Socket->request('http://www.cakephp.org/');
$result = (string)$this->Socket->request('http://www.cakephp.org/');
$this->assertEqual($result, '');
$this->assertEqual($this->Socket->response['header']['Server'], 'CakeHttp Server');
fclose($f);
$this->assertEqual(file_get_contents(TMP . 'download.txt'), '<h1>This is a test!</h1>');
unlink(TMP . 'download.txt');
$this->Socket->setContentResource(false);
$result = $this->Socket->request('http://www.cakephp.org/');
$result = (string)$this->Socket->request('http://www.cakephp.org/');
$this->assertEqual($result, '<h1>This is a test!</h1>');
}
@@ -987,15 +984,6 @@ public function testDelete() {
public function testParseResponse() {
$this->Socket->reset();
$r = $this->Socket->parseResponse(array('foo' => 'bar'));
$this->assertEquals($r, array('foo' => 'bar'));
$r = $this->Socket->parseResponse(true);
$this->assertEquals($r, false);
$r = $this->Socket->parseResponse("HTTP Foo\r\nBar: La");
$this->assertEquals($r, false);
$tests = array(
'simple-request' => array(
'response' => array(
@@ -1004,10 +992,10 @@ public function testParseResponse() {
'body' => "<h1>Hello World</h1>\r\n<p>It's good to be html</p>"
),
'expectations' => array(
'status.http-version' => 'HTTP/1.x',
'status.code' => 200,
'status.reason-phrase' => 'OK',
'header' => $this->Socket->parseHeader("Date: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\n"),
'httpVersion' => 'HTTP/1.x',
'code' => 200,
'reasonPhrase' => 'OK',
'headers' => array('Date' => 'Mon, 16 Apr 2007 04:14:16 GMT', 'Server' => 'CakeHttp Server'),
'body' => "<h1>Hello World</h1>\r\n<p>It's good to be html</p>"
)
),
@@ -1017,34 +1005,8 @@ public function testParseResponse() {
'header' => null
),
'expectations' => array(
'status.code' => 404,
'header' => array()
)
),
'chunked' => array(
'response' => array(
'header' => "Transfer-Encoding: chunked\r\n",
'body' => "19\r\nThis is a chunked message\r\n0\r\n"
),
'expectations' => array(
'body' => "This is a chunked message",
'header' => $this->Socket->parseHeader("Transfer-Encoding: chunked\r\n")
)
),
'enitity-header' => array(
'response' => array(
'body' => "19\r\nThis is a chunked message\r\n0\r\nFoo: Bar\r\n"
),
'expectations' => array(
'header' => $this->Socket->parseHeader("Transfer-Encoding: chunked\r\nFoo: Bar\r\n")
)
),
'enitity-header-combine' => array(
'response' => array(
'header' => "Transfer-Encoding: chunked\r\nFoo: Foobar\r\n"
),
'expectations' => array(
'header' => $this->Socket->parseHeader("Transfer-Encoding: chunked\r\nFoo: Foobar\r\nFoo: Bar\r\n")
'code' => 404,
'headers' => array()
)
)
);
@@ -1059,8 +1021,7 @@ public function testParseResponse() {
$expectations = array_merge($expectations, $test['expectations']);
foreach ($expectations as $property => $expectedVal) {
$val = Set::extract($r, $property);
$this->assertEquals($val, $expectedVal, 'Test "' . $name . '": response.' . $property . ' - %s');
$this->assertEquals($r->{$property}, $expectedVal, 'Test "' . $name . '": response.' . $property . ' - %s');
}
foreach (array('status-line', 'header', 'body', 'response') as $field) {
@@ -1069,6 +1030,31 @@ public function testParseResponse() {
}
}
/**
* data provider function for testInvalidParseResponseData
*
* @return array
*/
public static function invalidParseResponseDataProvider() {
return array(
array(array('foo' => 'bar')),
array(true),
array("HTTP Foo\r\nBar: La"),
array('HTTP/1.1 TEST ERROR')
);
}
/**
* testInvalidParseResponseData
*
* @dataProvider invalidParseResponseDataProvider
* @expectedException Exception
* return void
*/
public function testInvalidParseResponseData($value) {
$this->Socket->parseResponse($value);
}
/**
* testDecodeBody method
*

0 comments on commit 60a9d34

Please sign in to comment.
You can’t perform that action at this time.