Permalink
Browse files

FIX Improve recent RestfulService fix for proxies

  • Loading branch information...
1 parent 5c82609 commit b1f03db4fff17127d493d32d13ca2e51d0ece2c8 Hamish Friedlander committed Sep 20, 2013
Showing with 27 additions and 75 deletions.
  1. +20 −22 api/RestfulService.php
  2. +7 −53 tests/api/RestfulServiceTest.php
View
@@ -224,8 +224,11 @@ public function curlRequest($url, $method, $data = null, $headers = null, $curlO
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
if(!ini_get('open_basedir')) curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
- //include headers in the response
- curl_setopt($ch, CURLOPT_HEADER, true);
+
+
+ // Write headers to a temporary file
+ $headerfd = tmpfile();
+ curl_setopt($ch, CURLOPT_WRITEHEADER, $headerfd);
// Add headers
if($this->customHeaders) {
@@ -260,8 +263,13 @@ public function curlRequest($url, $method, $data = null, $headers = null, $curlO
curl_setopt_array($ch, $curlOptions);
// Run request
- $rawResponse = curl_exec($ch);
- $response = $this->extractResponse($ch, $rawResponse);
+ $body = curl_exec($ch);
+
+ rewind($headerfd);
+ $headers = stream_get_contents($headerfd);
+ fclose($headerfd);
+
+ $response = $this->extractResponse($ch, $headers, $body);
curl_close($ch);
return $response;
@@ -308,36 +316,26 @@ protected function getCachePath($cacheData) {
}
/**
- * Build the response from raw data. The response could have multiple redirection
- * and proxy connect headers, so we are only interested in the last header before the body.
+ * Extracts the response body and headers from a full curl response
*
* @param curl_handle $ch The curl handle for the request
* @param string $rawResponse The raw response text
*
* @return RestfulService_Response The response object
*/
- protected function extractResponse($ch, $rawResponse) {
+ protected function extractResponse($ch, $rawHeaders, $rawBody) {
//get the status code
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
//get a curl error if there is one
$curlError = curl_error($ch);
//normalise the status code
if(curl_error($ch) !== '' || $statusCode == 0) $statusCode = 500;
-
- // Parse the headers and body from the response.
- // We cannot rely on CURLINFO_HEADER_SIZE here, it's miscalculated when connecting via
- // a proxy (see http://sourceforge.net/p/curl/bugs/1204/). This is fixed in curl 7.30.0.
- $headerParts = array();
- $parts = explode("\r\n\r\n", $rawResponse);
- while (isset($parts[0])) {
- if (strpos($parts[0], 'HTTP/')===0) $headerParts[] = array_shift($parts);
- else break; // We have reached the body.
- }
- $lastHeader = array_pop($headerParts);
- $body = implode("\r\n\r\n", $parts);
-
- $parsedHeader = $this->parseRawHeaders($lastHeader);
- return new RestfulService_Response($body, $statusCode, $parsedHeader);
+ //parse the headers
+ $parts = array_filter(explode("\r\n\r\n", $rawHeaders));
+ $lastHeaders = array_pop($parts);
+ $headers = $this->parseRawHeaders($lastHeaders);
+ //return the response object
+ return new RestfulService_Response($rawBody, $statusCode, $headers);
}
/**
@@ -198,7 +198,7 @@ public function testHttpHeaderParseing() {
public function testExtractResponseRedirectionAndProxy() {
// This is an example of real raw response for a request via a proxy that gets redirected.
- $rawResponse =
+ $rawHeaders =
"HTTP/1.0 200 Connection established\r\n" .
"\r\n" .
"HTTP/1.1 301 Moved Permanently\r\n" .
@@ -220,8 +220,8 @@ public function testExtractResponseRedirectionAndProxy() {
"X-Frame-Options: SAMEORIGIN\r\n" .
"Cache-Control: no-cache, max-age=0, must-revalidate, no-transform\r\n" .
"Vary: Accept-Encoding\r\n" .
- "\r\n" .
- "<!doctype html></html>";
+ "\r\n"
+ ;
$headerFunction = new ReflectionMethod('RestfulService', 'extractResponse');
$headerFunction->setAccessible(true);
@@ -230,10 +230,10 @@ public function testExtractResponseRedirectionAndProxy() {
$response = $headerFunction->invoke(
new RestfulService(Director::absoluteBaseURL(),0),
$ch,
- $rawResponse
+ $rawHeaders,
+ ''
);
- $this->assertEquals($response->getBody(), '<!doctype html></html>', 'Body is correctly extracted.');
$this->assertEquals(
$response->getHeaders(),
array(
@@ -250,64 +250,18 @@ public function testExtractResponseRedirectionAndProxy() {
);
}
- public function testExtractResponseNewlinesInBody() {
- $rawResponse =
- "HTTP/1.1 200 OK\r\n" .
- "Server: nginx\r\n" .
- "\r\n" .
- "<!doctype html>\r\n" .
- "\r\n" .
- "</html>";
-
- $headerFunction = new ReflectionMethod('RestfulService', 'extractResponse');
- $headerFunction->setAccessible(true);
-
- $ch = curl_init();
- $response = $headerFunction->invoke(
- new RestfulService(Director::absoluteBaseURL(),0),
- $ch,
- $rawResponse
- );
-
- $this->assertEquals($response->getBody(), "<!doctype html>\r\n\r\n</html>", 'Body is correctly extracted.');
- $this->assertEquals($response->getHeaders(), array('Server' => "nginx"), 'Headers are correctly extracted.');
- }
-
- public function testExtractResponseNoBody() {
- // For example a response to HEAD request.
- $rawResponse =
- "HTTP/1.1 200 OK\r\n" .
- "Server: nginx";
-
- $headerFunction = new ReflectionMethod('RestfulService', 'extractResponse');
- $headerFunction->setAccessible(true);
-
- $ch = curl_init();
- $response = $headerFunction->invoke(
- new RestfulService(Director::absoluteBaseURL(),0),
- $ch,
- $rawResponse
- );
-
- $this->assertEquals($response->getBody(), "", 'Body is correctly extracted.');
- $this->assertEquals($response->getHeaders(), array('Server' => "nginx"), 'Headers are correctly extracted.');
- }
-
public function testExtractResponseNoHead() {
- // Malformed response.
- $rawResponse = "I am a malformed response";
-
$headerFunction = new ReflectionMethod('RestfulService', 'extractResponse');
$headerFunction->setAccessible(true);
$ch = curl_init();
$response = $headerFunction->invoke(
new RestfulService(Director::absoluteBaseURL(),0),
$ch,
- $rawResponse
+ '',
+ ''
);
- $this->assertEquals($response->getBody(), "I am a malformed response", 'Body is correctly extracted.');
$this->assertEquals($response->getHeaders(), array(), 'Headers are correctly extracted.');
}
}

0 comments on commit b1f03db

Please sign in to comment.