Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[Http] Adding a mediator object between curl and requests. This shoul…

…d speed up curl requests due to reduction in anonymous function creation. [Http] Using a factory method when creating bad response exceptions. Adding ClientErrorResponseException and ServerErrorResponseException. [Http] Removing curl specific protocal version code from RequestInterace and pushing it to the curl namespace [Http] Renaming parseUrlUtf8 to parseUrl and fixing a typo
  • Loading branch information...
commit 6926d832c8b48fb46fbbb6c6b20910328292dcf0 1 parent cf82fa4
@mtdowling mtdowling authored
View
40 Curl/CurlHandle.php
@@ -20,7 +20,7 @@ class CurlHandle
protected $options;
/**
- * @var resouce Curl resource handle
+ * @var resource Curl resource handle
*/
protected $handle;
@@ -39,6 +39,8 @@ class CurlHandle
public static function factory(RequestInterface $request)
{
$handle = curl_init();
+ $mediator = new RequestMediator($request);
+ $protocolVersion = $request->getProtocolVersion() === '1.0' ? CURL_HTTP_VERSION_1_0 : CURL_HTTP_VERSION_1_1;
// Array of default cURL options.
$curlOptions = array(
@@ -50,34 +52,18 @@ public static function factory(RequestInterface $request)
CURLOPT_USERAGENT => (string) $request->getHeader('User-Agent'),
CURLOPT_ENCODING => '', // Supports all encodings
CURLOPT_PORT => $request->getPort(),
- CURLOPT_HTTP_VERSION => $request->getProtocolVersion(true),
+ CURLOPT_HTTP_VERSION => $protocolVersion,
CURLOPT_NOPROGRESS => false,
CURLOPT_STDERR => fopen('php://temp', 'r+'),
CURLOPT_VERBOSE => true,
CURLOPT_HTTPHEADER => array(),
- CURLOPT_HEADERFUNCTION => function($curl, $header) use ($request) {
- return $request->receiveResponseHeader($header);
- },
- CURLOPT_PROGRESSFUNCTION => function($downloadSize, $downloaded, $uploadSize, $uploaded) use ($request) {
- $request->dispatch('curl.callback.progress', array(
- 'request' => $request,
- 'download_size' => $downloadSize,
- 'downloaded' => $downloaded,
- 'upload_size' => $uploadSize,
- 'uploaded' => $uploaded
- ));
- }
+ CURLOPT_HEADERFUNCTION => array($mediator, 'receiveResponseHeader'),
+ CURLOPT_PROGRESSFUNCTION => array($mediator, 'progress')
);
// HEAD requests need no response body, everything else might
if ($request->getMethod() != 'HEAD') {
- $curlOptions[CURLOPT_WRITEFUNCTION] = function($curl, $write) use ($request) {
- $request->dispatch('curl.callback.write', array(
- 'request' => $request,
- 'write' => $write
- ));
- return $request->getResponse()->getBody()->write($write);
- };
+ $curlOptions[CURLOPT_WRITEFUNCTION] = array($mediator, 'writeResponseBody');
}
// Account for PHP installations with safe_mode or open_basedir enabled
@@ -126,17 +112,7 @@ public static function factory(RequestInterface $request)
unset($curlOptions[CURLOPT_READFUNCTION]);
} else {
// Add a callback for curl to read data to send with the request
- $curlOptions[CURLOPT_READFUNCTION] = function($ch, $fd, $length) use ($request) {
- $read = '';
- if ($request->getBody()) {
- $read = $request->getBody()->read($length);
- $request->dispatch('curl.callback.read', array(
- 'request' => $request,
- 'read' => $read
- ));
- }
- return !$read ? '' : $read;
- };
+ $curlOptions[CURLOPT_READFUNCTION] = array($mediator, 'readRequestBody');
}
// If the Expect header is not present, prevent curl from adding it
View
98 Curl/RequestMediator.php
@@ -0,0 +1,98 @@
+<?php
+
+namespace Guzzle\Http\Curl;
+
+use Guzzle\Http\Message\RequestInterface;
+
+/**
+ * Mediator between curl handles and request objects
+ */
+class RequestMediator
+{
+ /**
+ * @var RequestInterface
+ */
+ protected $request;
+
+ /**
+ * @param RequestInterface $request Request to mediate
+ */
+ public function __construct(RequestInterface $request)
+ {
+ $this->request = $request;
+ }
+
+ /**
+ * Receive a response header from curl
+ *
+ * @param resource $curl Curl handle
+ * @param string $header Received header
+ *
+ * @return int
+ */
+ public function receiveResponseHeader ($curl, $header)
+ {
+ return $this->request->receiveResponseHeader($header);
+ }
+
+ /**
+ * Received a progress notification
+ *
+ * @param int $downloadSize Total download size
+ * @param int $downloaded Amount of bytes downloaded
+ * @param int $uploadSize Total upload size
+ * @param int $uploaded Amount of bytes uploaded
+ */
+ public function progress($downloadSize, $downloaded, $uploadSize, $uploaded)
+ {
+ $this->request->dispatch('curl.callback.progress', array(
+ 'request' => $this->request,
+ 'download_size' => $downloadSize,
+ 'downloaded' => $downloaded,
+ 'upload_size' => $uploadSize,
+ 'uploaded' => $uploaded
+ ));
+ }
+
+ /**
+ * Write data to the response body of a request
+ *
+ * @param resource $curl Curl handle
+ * @param string $write Data that was received
+ *
+ * @return int
+ */
+ public function writeResponseBody($curl, $write)
+ {
+ $this->request->dispatch('curl.callback.write', array(
+ 'request' => $this->request,
+ 'write' => $write
+ ));
+
+ return $this->request->getResponse()->getBody()->write($write);
+ }
+
+ /**
+ * Read data from the request body and send it to curl
+ *
+ * @param resource $ch Curl handle
+ * @param resource $fd File descriptor
+ * @param int $length Amount of data to read
+ *
+ * @return string
+ */
+ public function readRequestBody($ch, $fd, $length)
+ {
+ $read = '';
+
+ if ($this->request->getBody()) {
+ $read = $this->request->getBody()->read($length);
+ $this->request->dispatch('curl.callback.read', array(
+ 'request' => $this->request,
+ 'read' => $read
+ ));
+ }
+
+ return !$read ? '' : $read;
+ }
+}
View
38 Exception/BadResponseException.php
@@ -2,6 +2,7 @@
namespace Guzzle\Http\Exception;
+use Guzzle\Http\Message\RequestInterface;
use Guzzle\Http\Message\Response;
/**
@@ -15,6 +16,43 @@ class BadResponseException extends RequestException
private $response;
/**
+ * Factory method to create a new response exception based on the response code.
+ *
+ * @param RequestInterface $request Request
+ * @param Response $response Response received
+ *
+ * @return BadResponseException
+ */
+ public static function factory(RequestInterface $request, Response $response)
+ {
+ if ($response->isClientError()) {
+ $label = 'Client error response';
+ $class = __NAMESPACE__ . '\\ClientErrorResponseException';
+ } else if ($response->isServerError()) {
+ $label = 'Server error response';
+ $class = __NAMESPACE__ . '\\ServerErrorResponseException';
+ } else {
+ $label = 'Unsuccessful response';
+ $class = __CLASS__;
+ $e = new self();
+ }
+
+ $message = $label . PHP_EOL . implode(PHP_EOL, array(
+ '[status code] ' . $response->getStatusCode(),
+ '[reason phrase] ' . $response->getReasonPhrase(),
+ '[url] ' . $request->getUrl(),
+ '[request] ' . (string) $request,
+ '[response] ' . (string) $response
+ ));
+
+ $e = new $class($message);
+ $e->setResponse($response);
+ $e->setRequest($request);
+
+ return $e;
+ }
+
+ /**
* Set the response that caused the exception
*
* @param Response $response Response to set
View
8 Exception/ClientErrorResponseException.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Guzzle\Http\Exception;
+
+/**
+ * Exception when a client error is encountered (4xx codes)
+ */
+class ClientErrorResponseException extends BadResponseException {}
View
8 Exception/ServerErrorResponseException.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Guzzle\Http\Exception;
+
+/**
+ * Exception when a server error is encountered (5xx codes)
+ */
+class ServerErrorResponseException extends BadResponseException {}
View
25 Message/Request.php
@@ -192,20 +192,13 @@ public function __toString()
*/
public static function onRequestError(Event $event)
{
- $e = new BadResponseException('Unsuccessful response | ' . implode(' | ', array(
- '[status code] ' . $event['response']->getStatusCode(),
- '[reason phrase] ' . $event['response']->getReasonPhrase(),
- '[url] ' . $event['request']->getUrl(),
- '[request] ' . (string) $event['request'],
- '[response] ' . (string) $event['response']
- )));
- $e->setResponse($event['response']);
- $e->setRequest($event['request']);
+ $e = BadResponseException::factory($event['request'], $event['response']);
$event['request']->dispatch('request.exception', array(
'request' => $event['request'],
'response' => $event['response'],
'exception' => $e
));
+
throw $e;
}
@@ -384,19 +377,11 @@ public function setHost($host)
/**
* Get the HTTP protocol version of the request
*
- * @param bool $curlValue (optional) Set to TRUE to retrieve the cURL value
- * for the HTTP protocol version
- *
- * @return string|int
+ * @return string
*/
- public function getProtocolVersion($curlValue = false)
+ public function getProtocolVersion()
{
- if (!$curlValue) {
- return $this->protocolVersion;
- } else {
- return $this->protocolVersion === '1.0'
- ? CURL_HTTP_VERSION_1_0 : CURL_HTTP_VERSION_1_1;
- }
+ return $this->protocolVersion;
}
/**
View
7 Message/RequestInterface.php
@@ -142,12 +142,9 @@ function setHost($host);
/**
* Get the HTTP protocol version of the request
*
- * @param bool $curlValue (optional) Set to TRUE to retrieve the cURL value
- * for the HTTP protocol version
- *
- * @return string|int
+ * @return string
*/
- function getProtocolVersion($curlValue = false);
+ function getProtocolVersion();
/**
* Set the HTTP protocol version of the request (e.g. 1.1 or 1.0)
View
10 Url.php
@@ -30,7 +30,7 @@ class Url
*/
public static function factory($url)
{
- $parts = (array) self::parseUrlUtf8($url);
+ $parts = (array) self::parseUrl($url);
$parts['scheme'] = isset($parts['scheme']) ? $parts['scheme'] : null;
$parts['host'] = isset($parts['host']) ? $parts['host'] : null;
$parts['path'] = isset($parts['path']) ? $parts['path'] : null;
@@ -50,14 +50,14 @@ public static function factory($url)
}
/**
- * Parse a URL using special handling for UTF-8 characters in the query
- * string if needed
+ * Parse a URL using special handling for a subset of UTF-8 characters in
+ * the query string if needed.
*
* @param string $url URL to parse
*
* @return array
*/
- public static function parseUrlUtf8($url)
+ public static function parseUrl($url)
{
$parts = parse_url($url);
@@ -98,7 +98,7 @@ public static function parseQuery($query)
}
/**
- * Buld a URL from parse_url parts. The generated URL will be a relative
+ * Build a URL from parse_url parts. The generated URL will be a relative
* URL if a scheme or host are not provided.
*
* @param array $parts Array of parse_url parts
Please sign in to comment.
Something went wrong with that request. Please try again.