Skip to content

Commit

Permalink
Updated the HttpSocket to use the new HttpResponse.
Browse files Browse the repository at this point in the history
  • Loading branch information
jrbasso committed Dec 14, 2010
1 parent f45027e commit 60a9d34
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 128 deletions.
99 changes: 33 additions & 66 deletions cake/libs/http_socket.php
Expand Up @@ -19,6 +19,7 @@
*/
App::import('Core', 'CakeSocket');
App::import('Core', 'Router');
App::import('Lib', 'HttpResponse');

/**
* Cake network socket connection class.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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'])) {
Expand Down Expand Up @@ -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'] = '';
Expand Down Expand Up @@ -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;
}

/**
Expand All @@ -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'])) {
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down
110 changes: 48 additions & 62 deletions cake/tests/cases/libs/http_socket.test.php
Expand Up @@ -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);
}
}

/**
Expand Down Expand Up @@ -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>");
}

Expand All @@ -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
*
Expand All @@ -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>');
}

Expand Down Expand Up @@ -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(
Expand All @@ -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>"
)
),
Expand All @@ -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()
)
)
);
Expand All @@ -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) {
Expand All @@ -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
*
Expand Down

0 comments on commit 60a9d34

Please sign in to comment.