/**
  * Prepare a request to be sent from the Client by adding client specific behaviors and properties to the request.
  *
  * @param RequestInterface $request Request to prepare for the client
  *
  * @return RequestInterface
  */
 protected function prepareRequest(RequestInterface $request)
 {
     $request->setClient($this);
     // Add any curl options to the request
     if ($options = $this->config->get(self::CURL_OPTIONS)) {
         $request->getCurlOptions()->merge(CurlHandle::parseCurlConfig($options));
     }
     // Add request parameters to the request
     if ($options = $this->config->get(self::REQUEST_PARAMS)) {
         $request->getParams()->merge($options);
     }
     // Attach client observers to the request
     $request->setEventDispatcher(clone $this->getEventDispatcher());
     $this->dispatch('client.create_request', array('client' => $this, 'request' => $request));
     return $request;
 }
Example #2
0
protected function visit_ssl_key(RequestInterface $request, $value, $flags)
{
if (is_array($value)) {
$request->getCurlOptions()->set(CURLOPT_SSLKEY, $value[0]);
$request->getCurlOptions()->set(CURLOPT_SSLKEYPASSWD, $value[1]);
} else {
$request->getCurlOptions()->set(CURLOPT_SSLKEY, $value);
}
}
 protected function visit_proxy(RequestInterface $request, $value, $flags)
 {
     $request->getCurlOptions()->set(CURLOPT_PROXY, $value, $flags);
 }
 /**
  * Add proxy parameters to the context if needed
  *
  * @param RequestInterface $request Request
  */
 protected function addProxyOptions(RequestInterface $request)
 {
     if ($proxy = $request->getCurlOptions()->get(CURLOPT_PROXY)) {
         $this->setContextValue('http', 'proxy', $proxy);
     }
 }
Example #5
0
 /**
  * Clone a request while changing the method. Emulates the behavior of
  * {@see Guzzle\Http\Message\Request::clone}, but can change the HTTP method.
  *
  * @param RequestInterface $request Request to clone
  * @param string           $method  Method to set
  *
  * @return RequestInterface
  */
 public function cloneRequestWithMethod(RequestInterface $request, $method)
 {
     // Create the request with the same client if possible
     if ($client = $request->getClient()) {
         $cloned = $request->getClient()->createRequest($method, $request->getUrl(), $request->getHeaders());
     } else {
         $cloned = $this->create($method, $request->getUrl(), $request->getHeaders());
     }
     $cloned->getCurlOptions()->replace($request->getCurlOptions()->getAll());
     $cloned->setEventDispatcher(clone $request->getEventDispatcher());
     // Ensure that that the Content-Length header is not copied if changing to GET or HEAD
     if (!$cloned instanceof EntityEnclosingRequestInterface) {
         $cloned->removeHeader('Content-Length');
     } elseif ($request instanceof EntityEnclosingRequestInterface) {
         $cloned->setBody($request->getBody());
     }
     $cloned->getParams()->replace($request->getParams()->getAll())->remove('curl_handle')->remove('curl_multi');
     return $cloned;
 }
Example #6
0
 /**
  * Prepare a request to be sent from the Client by adding client specific
  * behaviors and properties to the request.
  *
  * @param RequestInterface $request Request to prepare for the client
  *
  * @return RequestInterface
  */
 protected function prepareRequest(RequestInterface $request)
 {
     $request->setClient($this);
     foreach ($this->getConfig()->getAll() as $key => $value) {
         if ($key == 'curl.blacklist') {
             continue;
         }
         // Add any curl options that might in the config to the request
         if (strpos($key, 'curl.') === 0) {
             $curlOption = substr($key, 5);
             // Convert constants represented as string to constant int values
             if (defined($curlOption)) {
                 $value = is_string($value) && defined($value) ? constant($value) : $value;
                 $curlOption = constant($curlOption);
             }
             $request->getCurlOptions()->set($curlOption, $value);
         } elseif (strpos($key, 'params.') === 0) {
             // Add request specific parameters to all requests (prefix with 'params.')
             $request->getParams()->set(substr($key, 7), $value);
         }
     }
     // Attach client observers to the request
     $request->setEventDispatcher(clone $this->getEventDispatcher());
     $this->dispatch('client.create_request', array('client' => $this, 'request' => $request));
     return $request;
 }
Example #7
0
 /**
  * Factory method to create a new curl handle based on an HTTP request.
  *
  * There are some helpful options you can set to enable specific behavior:
  * - debug:    Set to true to enable cURL debug functionality to track the
  *             actual headers sent over the wire.  The
  * - progress: Set to true to enable progress function callbacks. Most
  *             users do not need this, so it has been disabled by default.
  *
  * @param RequestInterface $request Request
  *
  * @return CurlHandle
  */
 public static function factory(RequestInterface $request)
 {
     $mediator = new RequestMediator($request);
     $requestCurlOptions = $request->getCurlOptions();
     $tempContentLength = null;
     $method = $request->getMethod();
     $client = $request->getClient();
     // Array of default cURL options.
     $curlOptions = array(CURLOPT_URL => $request->getUrl(), CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_RETURNTRANSFER => false, CURLOPT_HEADER => false, CURLOPT_USERAGENT => (string) $request->getHeader('User-Agent'), CURLOPT_ENCODING => '', CURLOPT_PORT => $request->getPort(), CURLOPT_HTTPHEADER => array(), CURLOPT_HEADERFUNCTION => array($mediator, 'receiveResponseHeader'), CURLOPT_HTTP_VERSION => $request->getProtocolVersion() === '1.0' ? CURL_HTTP_VERSION_1_0 : CURL_HTTP_VERSION_1_1);
     // Enable the progress function if the 'progress' param was set
     if ($requestCurlOptions->get('progress')) {
         $curlOptions[CURLOPT_PROGRESSFUNCTION] = array($mediator, 'progress');
         $curlOptions[CURLOPT_NOPROGRESS] = false;
     }
     // Enable curl debug information if the 'debug' param was set
     if ($requestCurlOptions->get('debug')) {
         $curlOptions[CURLOPT_STDERR] = fopen('php://temp', 'r+');
         // @codeCoverageIgnoreStart
         if (false === $curlOptions[CURLOPT_STDERR]) {
             throw new RuntimeException('Unable to create a stream for CURLOPT_STDERR');
         }
         // @codeCoverageIgnoreEnd
         $curlOptions[CURLOPT_VERBOSE] = true;
     }
     // HEAD requests need no response body, everything else might
     if ($method != 'HEAD') {
         $curlOptions[CURLOPT_WRITEFUNCTION] = array($mediator, 'writeResponseBody');
     }
     // Account for PHP installations with safe_mode or open_basedir enabled
     // @codeCoverageIgnoreStart
     if (CurlVersion::getInstance()->get('follow_location')) {
         $curlOptions[CURLOPT_FOLLOWLOCATION] = true;
         $curlOptions[CURLOPT_MAXREDIRS] = 5;
     }
     // @codeCoverageIgnoreEnd
     // Specify settings according to the HTTP method
     switch ($method) {
         case 'GET':
             $curlOptions[CURLOPT_HTTPGET] = true;
             break;
         case 'HEAD':
             $curlOptions[CURLOPT_NOBODY] = true;
             break;
         case 'POST':
             $curlOptions[CURLOPT_POST] = true;
             // Special handling for POST specific fields and files
             if (count($request->getPostFiles())) {
                 $fields = $request->getPostFields()->useUrlEncoding(false)->urlEncode();
                 foreach ($request->getPostFiles() as $key => $data) {
                     $prefixKeys = count($data) > 1;
                     foreach ($data as $index => $file) {
                         // Allow multiple files in the same key
                         $fieldKey = $prefixKeys ? "{$key}[{$index}]" : $key;
                         $fields[$fieldKey] = $file->getCurlString();
                     }
                 }
                 $curlOptions[CURLOPT_POSTFIELDS] = $fields;
                 $request->removeHeader('Content-Length');
             } elseif (count($request->getPostFields())) {
                 $curlOptions[CURLOPT_POSTFIELDS] = (string) $request->getPostFields()->useUrlEncoding(true);
                 $request->removeHeader('Content-Length');
             } elseif (!$request->getBody()) {
                 // Need to remove CURLOPT_POST to prevent chunked encoding for an empty POST
                 unset($curlOptions[CURLOPT_POST]);
                 $curlOptions[CURLOPT_CUSTOMREQUEST] = 'POST';
             }
             break;
         case 'PUT':
         case 'PATCH':
         case 'DELETE':
             $curlOptions[CURLOPT_UPLOAD] = true;
             if ($method != 'PUT') {
                 $curlOptions[CURLOPT_CUSTOMREQUEST] = $method;
             }
             // Let cURL handle setting the Content-Length header
             $contentLength = $request->getHeader('Content-Length');
             if ($contentLength !== null) {
                 $contentLength = (int) (string) $contentLength;
                 $curlOptions[CURLOPT_INFILESIZE] = $contentLength;
                 $tempContentLength = $contentLength;
                 $request->removeHeader('Content-Length');
             }
             break;
         default:
             $curlOptions[CURLOPT_CUSTOMREQUEST] = $method;
     }
     // Special handling for requests sending raw data
     if ($request instanceof EntityEnclosingRequestInterface) {
         if ($request->getBody()) {
             // Add a callback for curl to read data to send with the request only if a body was specified
             $curlOptions[CURLOPT_READFUNCTION] = array($mediator, 'readRequestBody');
             // Attempt to seek to the start of the stream
             $request->getBody()->seek(0);
         }
         // If the Expect header is not present, prevent curl from adding it
         if (!$request->hasHeader('Expect')) {
             $curlOptions[CURLOPT_HTTPHEADER][] = 'Expect:';
         }
     }
     // Set custom cURL options
     foreach ($requestCurlOptions as $key => $value) {
         if (is_numeric($key)) {
             $curlOptions[$key] = $value;
         }
     }
     // Check if any headers or cURL options are blacklisted
     if ($client && ($blacklist = $client->getConfig('curl.blacklist'))) {
         foreach ($blacklist as $value) {
             if (strpos($value, 'header.') !== 0) {
                 unset($curlOptions[$value]);
             } else {
                 // Remove headers that may have previously been set but are supposed to be blacklisted
                 $key = substr($value, 7);
                 $request->removeHeader($key);
                 $curlOptions[CURLOPT_HTTPHEADER][] = $key . ':';
             }
         }
     }
     // Add any custom headers to the request. Empty headers will cause curl to not send the header at all.
     foreach ($request->getHeaderLines() as $line) {
         $curlOptions[CURLOPT_HTTPHEADER][] = $line;
     }
     // Apply the options to a new cURL handle.
     $handle = curl_init();
     curl_setopt_array($handle, $curlOptions);
     $request->getParams()->set('curl.last_options', $curlOptions);
     if ($tempContentLength) {
         $request->setHeader('Content-Length', $tempContentLength);
     }
     $handle = new static($handle, $curlOptions);
     $mediator->setCurlHandle($handle);
     return $handle;
 }
 /**
  * Factory method to create a new curl handle based on an HTTP request
  *
  * There are some helpful options you can set to enable specific behavior:
  *    - disabled_wire: This is a performance improvement that will disable
  *         some debugging functionality with cURL.  The functionality
  *         it disabled allows you to see the exact HTTP request sent over
  *         the wire.
  *    - progress: Set to true to enable progress function callbacks. Most
  *         People don't need this, so it has been disabled by default.
  *
  * @param RequestInterface $request Request
  *
  * @return CurlHandle
  */
 public static function factory(RequestInterface $request)
 {
     $handle = curl_init();
     $mediator = new RequestMediator($request);
     $requestCurlOptions = $request->getCurlOptions();
     // Array of default cURL options.
     $curlOptions = array(CURLOPT_URL => $request->getUrl(), CURLOPT_CUSTOMREQUEST => $request->getMethod(), CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_RETURNTRANSFER => false, CURLOPT_HEADER => false, CURLOPT_USERAGENT => (string) $request->getHeader('User-Agent'), CURLOPT_ENCODING => '', CURLOPT_PORT => $request->getPort(), CURLOPT_HTTP_VERSION => $request->getProtocolVersion() === '1.0' ? CURL_HTTP_VERSION_1_0 : CURL_HTTP_VERSION_1_1, CURLOPT_HTTPHEADER => array(), CURLOPT_HEADERFUNCTION => array($mediator, 'receiveResponseHeader'));
     // Enable the progress function if the 'progress' param was set
     if ($requestCurlOptions->get('progress')) {
         $curlOptions[CURLOPT_PROGRESSFUNCTION] = array($mediator, 'progress');
         $curlOptions[CURLOPT_NOPROGRESS] = false;
     }
     // Enable curl debug information if the 'debug' param was set
     if (!$requestCurlOptions->get('disable_wire')) {
         $curlOptions[CURLOPT_STDERR] = fopen('php://temp', 'r+');
         $curlOptions[CURLOPT_VERBOSE] = true;
     }
     // HEAD requests need no response body, everything else might
     if ($request->getMethod() != 'HEAD') {
         $curlOptions[CURLOPT_WRITEFUNCTION] = array($mediator, 'writeResponseBody');
     }
     // Account for PHP installations with safe_mode or open_basedir enabled
     // @codeCoverageIgnoreStart
     if (Guzzle::getCurlInfo('follow_location')) {
         $curlOptions[CURLOPT_FOLLOWLOCATION] = true;
         $curlOptions[CURLOPT_MAXREDIRS] = 5;
     }
     // @codeCoverageIgnoreEnd
     $headers = $request->getHeaders()->getAll();
     // Specify settings according to the HTTP method
     switch ($request->getMethod()) {
         case 'GET':
             $curlOptions[CURLOPT_HTTPGET] = true;
             break;
         case 'HEAD':
             $curlOptions[CURLOPT_NOBODY] = true;
             unset($curlOptions[CURLOPT_WRITEFUNCTION]);
             break;
         case 'POST':
             $curlOptions[CURLOPT_POST] = true;
             break;
         case 'PUT':
         case 'PATCH':
             $curlOptions[CURLOPT_UPLOAD] = true;
             if ($request->hasHeader('Content-Length')) {
                 unset($headers['Content-Length']);
                 $curlOptions[CURLOPT_INFILESIZE] = (int) (string) $request->getHeader('Content-Length');
             }
             break;
     }
     if ($request instanceof EntityEnclosingRequestInterface) {
         // If no body is being sent, always send Content-Length of 0
         if (!$request->getBody() && !count($request->getPostFields())) {
             $headers['Content-Length'] = 0;
             unset($headers['Transfer-Encoding']);
             // Need to remove CURLOPT_UPLOAD to prevent chunked encoding
             unset($curlOptions[CURLOPT_UPLOAD]);
             unset($curlOptions[CURLOPT_POST]);
             // Not reading from a callback when using empty body
             unset($curlOptions[CURLOPT_READFUNCTION]);
         } else {
             // Add a callback for curl to read data to send with the request
             $curlOptions[CURLOPT_READFUNCTION] = array($mediator, 'readRequestBody');
         }
         // If the Expect header is not present, prevent curl from adding it
         if (!$request->hasHeader('Expect')) {
             $curlOptions[CURLOPT_HTTPHEADER][] = 'Expect:';
         }
     }
     // Set custom cURL options
     foreach ($requestCurlOptions as $key => $value) {
         if (is_numeric($key)) {
             $curlOptions[$key] = $value;
         }
     }
     // Check if any headers or cURL options are blacklisted
     $client = $request->getClient();
     if ($client) {
         $blacklist = $client->getConfig('curl.blacklist');
         if ($blacklist) {
             foreach ($blacklist as $value) {
                 if (strpos($value, 'header.') === 0) {
                     $blacklistHeader = substr($value, 7);
                     // Remove headers that may have previously been set
                     // but are supposed to be blacklisted
                     unset($headers[$blacklistHeader]);
                     $headers[$blacklistHeader] = '';
                 } else {
                     unset($curlOptions[$value]);
                 }
             }
         }
     }
     // Add any custom headers to the request. Emtpy headers will cause curl to
     // not send the header at all.
     foreach ($headers as $key => $value) {
         foreach ((array) $value as $val) {
             $curlOptions[CURLOPT_HTTPHEADER][] = trim("{$key}: {$val}");
         }
     }
     // Apply the options to the cURL handle.
     curl_setopt_array($handle, $curlOptions);
     $request->getParams()->set('curl.last_options', $curlOptions);
     return new static($handle, $curlOptions);
 }
Example #9
0
 /**
  * Factory method to create a new curl handle based on an HTTP request.
  *
  * Note that the HTTP request may be modified by this method
  *
  * There are some helpful options you can set to enable specific behavior:
  *
  *    - disabled_wire: This is a performance improvement that will disable
  *                     some debugging functionality with cURL.  The
  *                     functionality it disabled allows you to see the
  *                     exact HTTP request sent over the wire.
  *    - progress:      Set to true to enable progress function callbacks.
  *                     Most people don't need this, so it has been disabled
  *                     by default.
  *
  * @param RequestInterface $request Request
  *
  * @return CurlHandle
  */
 public static function factory(RequestInterface $request)
 {
     $mediator = new RequestMediator($request);
     $requestCurlOptions = $request->getCurlOptions();
     $tempHeaders = array();
     // Array of default cURL options.
     $curlOptions = array(CURLOPT_URL => $request->getUrl(), CURLOPT_CUSTOMREQUEST => $request->getMethod(), CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_RETURNTRANSFER => false, CURLOPT_HEADER => false, CURLOPT_USERAGENT => (string) $request->getHeader('User-Agent'), CURLOPT_ENCODING => '', CURLOPT_PORT => $request->getPort(), CURLOPT_HTTP_VERSION => $request->getProtocolVersion() === '1.0' ? CURL_HTTP_VERSION_1_0 : CURL_HTTP_VERSION_1_1, CURLOPT_HTTPHEADER => array(), CURLOPT_HEADERFUNCTION => array($mediator, 'receiveResponseHeader'));
     // Enable the progress function if the 'progress' param was set
     if ($requestCurlOptions->get('progress')) {
         $curlOptions[CURLOPT_PROGRESSFUNCTION] = array($mediator, 'progress');
         $curlOptions[CURLOPT_NOPROGRESS] = false;
     }
     // Enable curl debug information if the 'debug' param was set
     if (!$requestCurlOptions->get('disable_wire')) {
         $curlOptions[CURLOPT_STDERR] = fopen('php://temp', 'r+');
         $curlOptions[CURLOPT_VERBOSE] = true;
     }
     // HEAD requests need no response body, everything else might
     if ($request->getMethod() != 'HEAD') {
         $curlOptions[CURLOPT_WRITEFUNCTION] = array($mediator, 'writeResponseBody');
     }
     // Account for PHP installations with safe_mode or open_basedir enabled
     // @codeCoverageIgnoreStart
     if (CurlVersion::getInstance()->get('follow_location')) {
         $curlOptions[CURLOPT_FOLLOWLOCATION] = true;
         $curlOptions[CURLOPT_MAXREDIRS] = 5;
     }
     // @codeCoverageIgnoreEnd
     // Specify settings according to the HTTP method
     switch ($request->getMethod()) {
         case 'GET':
             $curlOptions[CURLOPT_HTTPGET] = true;
             break;
         case 'HEAD':
             $curlOptions[CURLOPT_NOBODY] = true;
             break;
         case 'POST':
             $curlOptions[CURLOPT_POST] = true;
             // Special handling for POST specific fields and files
             if (count($request->getPostFiles())) {
                 $curlOptions[CURLOPT_POSTFIELDS] = $request->getPostFields()->getAll();
                 $request->removeHeader('Content-Length');
             } elseif (count($request->getPostFields())) {
                 $curlOptions[CURLOPT_POSTFIELDS] = (string) $request->getPostFields();
                 $request->removeHeader('Content-Length');
             }
             break;
         case 'PUT':
         case 'PATCH':
             $curlOptions[CURLOPT_UPLOAD] = true;
             // Let cURL handle setting the Content-Length header
             $contentLength = $request->getHeader('Content-Length');
             if ($contentLength != null) {
                 $contentLength = (int) (string) $contentLength;
                 $curlOptions[CURLOPT_INFILESIZE] = $contentLength;
                 $tempHeaders['Content-Length'] = $contentLength;
                 $request->removeHeader('Content-Length');
             }
             break;
     }
     // Special handling for requests sending raw data
     if ($request instanceof EntityEnclosingRequestInterface) {
         // Don't modify POST requests using POST fields and files via cURL
         if (!isset($curlOptions[CURLOPT_POSTFIELDS])) {
             if ($request->getBody()) {
                 // Add a callback for curl to read data to send with the request
                 // only if a body was specified
                 $curlOptions[CURLOPT_READFUNCTION] = array($mediator, 'readRequestBody');
             } else {
                 // If no body is being sent, always send Content-Length of 0
                 $request->setHeader('Content-Length', 0);
                 $request->removeHeader('Transfer-Encoding');
                 // Need to remove CURLOPT_UPLOAD to prevent chunked encoding
                 unset($curlOptions[CURLOPT_UPLOAD]);
                 unset($curlOptions[CURLOPT_POST]);
             }
         }
         // If the Expect header is not present, prevent curl from adding it
         if (!$request->hasHeader('Expect')) {
             $curlOptions[CURLOPT_HTTPHEADER][] = 'Expect:';
         }
     }
     // Set custom cURL options
     foreach ($requestCurlOptions as $key => $value) {
         if (is_numeric($key)) {
             $curlOptions[$key] = $value;
         }
     }
     // Check if any headers or cURL options are blacklisted
     $client = $request->getClient();
     if ($client) {
         $blacklist = $client->getConfig('curl.blacklist');
         if ($blacklist) {
             foreach ($blacklist as $value) {
                 if (strpos($value, 'header.') === 0) {
                     // Remove headers that may have previously been set
                     // but are supposed to be blacklisted
                     $key = substr($value, 7);
                     $request->removeHeader($key);
                     $curlOptions[CURLOPT_HTTPHEADER][] = $key . ':';
                 } else {
                     unset($curlOptions[$value]);
                 }
             }
         }
     }
     // Add any custom headers to the request. Emtpy headers will cause curl to
     // not send the header at all.
     foreach ($request->getHeaders() as $headerName => $values) {
         foreach ($values as $value) {
             $curlOptions[CURLOPT_HTTPHEADER][] = trim("{$headerName}: {$value}");
         }
     }
     // Apply the options to a new cURL handle.
     $handle = curl_init();
     curl_setopt_array($handle, $curlOptions);
     $request->getParams()->set('curl.last_options', $curlOptions);
     // Some fields need to be removed from the request in order to properly
     // send a cURL request message.  The fields that were removed for this
     // purpose (e.g. Content-Length) should be aggregated in this array and
     // added back to the request. Does not apply to blacklisted headers.
     foreach ($tempHeaders as $key => $value) {
         $request->setHeader($key, $value);
     }
     return new static($handle, $curlOptions);
 }
 /**
  * Prepare a request to be sent from the Client by adding client specific
  * behaviors and properties to the request.
  *
  * @param RequestInterface $request Request to prepare for the client
  *
  * @return RequestInterface
  */
 protected function prepareRequest(RequestInterface $request)
 {
     $request->setClient($this);
     // Add any curl options to the request
     $request->getCurlOptions()->merge(CurlHandle::parseCurlConfig($this->config));
     foreach ($this->config as $key => $value) {
         if (strpos($key, 'params.') === 0) {
             // Add request specific parameters to all requests (prefix with 'params.')
             $request->getParams()->set(substr($key, 7), $value);
         }
     }
     // Attach client observers to the request
     $request->setEventDispatcher(clone $this->getEventDispatcher());
     $this->dispatch('client.create_request', array('client' => $this, 'request' => $request));
     return $request;
 }
 /**
  * Prepare a request to be sent from the Client by adding client specific behaviors and properties to the request.
  *
  * @param RequestInterface $request Request to prepare for the client
  *
  * @return RequestInterface
  */
 protected function prepareRequest(RequestInterface $request)
 {
     $request->setClient($this);
     // Add any curl options to the request
     if ($options = $this->config->get(self::CURL_OPTIONS)) {
         $request->getCurlOptions()->merge(CurlHandle::parseCurlConfig($options));
     }
     // Add request parameters to the request
     if ($options = $this->config->get(self::REQUEST_PARAMS)) {
         $request->getParams()->merge($options);
     }
     // Attach client observers to the request
     $request->setEventDispatcher(clone $this->getEventDispatcher());
     // Set the User-Agent if one is specified on the client but not explicitly on the request
     if ($this->userAgent && !$request->hasHeader('User-Agent')) {
         $request->setHeader('User-Agent', $this->userAgent);
     }
     $this->dispatch('client.create_request', array('client' => $this, 'request' => $request));
     return $request;
 }
 /**
  * Factory method to create a new curl handle based on an HTTP request.
  *
  * There are some helpful options you can set to enable specific behavior:
  * - debug:    Set to true to enable cURL debug functionality to track the actual headers sent over the wire.
  * - progress: Set to true to enable progress function callbacks.
  *
  * @param RequestInterface $request Request
  *
  * @return CurlHandle
  * @throws RuntimeException
  */
 public static function factory(RequestInterface $request)
 {
     $requestCurlOptions = $request->getCurlOptions();
     $mediator = new RequestMediator($request, $requestCurlOptions->get('emit_io'));
     $tempContentLength = null;
     $method = $request->getMethod();
     $bodyAsString = $requestCurlOptions->get(self::BODY_AS_STRING);
     // Array of default cURL options.
     $curlOptions = array(CURLOPT_URL => $request->getUrl(), CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_RETURNTRANSFER => false, CURLOPT_HEADER => false, CURLOPT_PORT => $request->getPort(), CURLOPT_HTTPHEADER => array(), CURLOPT_HEADERFUNCTION => array($mediator, 'receiveResponseHeader'), CURLOPT_HTTP_VERSION => $request->getProtocolVersion() === '1.0' ? CURL_HTTP_VERSION_1_0 : CURL_HTTP_VERSION_1_1, CURLOPT_SSL_VERIFYPEER => 1, CURLOPT_SSL_VERIFYHOST => 2);
     if (defined('CURLOPT_PROTOCOLS')) {
         // Allow only HTTP and HTTPS protocols
         $curlOptions[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
     }
     // Add CURLOPT_ENCODING if Accept-Encoding header is provided
     if ($acceptEncodingHeader = $request->getHeader('Accept-Encoding')) {
         $curlOptions[CURLOPT_ENCODING] = (string) $acceptEncodingHeader;
         // Let cURL set the Accept-Encoding header, prevents duplicate values
         $request->removeHeader('Accept-Encoding');
     }
     // Enable the progress function if the 'progress' param was set
     if ($requestCurlOptions->get('progress')) {
         $curlOptions[CURLOPT_PROGRESSFUNCTION] = array($mediator, 'progress');
         $curlOptions[CURLOPT_NOPROGRESS] = false;
     }
     // Enable curl debug information if the 'debug' param was set
     if ($requestCurlOptions->get('debug')) {
         $curlOptions[CURLOPT_STDERR] = fopen('php://temp', 'r+');
         // @codeCoverageIgnoreStart
         if (false === $curlOptions[CURLOPT_STDERR]) {
             throw new RuntimeException('Unable to create a stream for CURLOPT_STDERR');
         }
         // @codeCoverageIgnoreEnd
         $curlOptions[CURLOPT_VERBOSE] = true;
     }
     // HEAD requests need no response body, everything else might
     if ($method != 'HEAD') {
         $curlOptions[CURLOPT_WRITEFUNCTION] = array($mediator, 'writeResponseBody');
     }
     // Specify settings according to the HTTP method
     switch ($method) {
         case 'GET':
             $curlOptions[CURLOPT_HTTPGET] = true;
             break;
         case 'HEAD':
             $curlOptions[CURLOPT_NOBODY] = true;
             break;
         case 'POST':
             $curlOptions[CURLOPT_POST] = true;
             // Special handling for POST specific fields and files
             if (count($request->getPostFiles())) {
                 $fields = $request->getPostFields()->useUrlEncoding(false)->urlEncode();
                 foreach ($request->getPostFiles() as $key => $data) {
                     $prefixKeys = count($data) > 1;
                     foreach ($data as $index => $file) {
                         // Allow multiple files in the same key
                         $fieldKey = $prefixKeys ? "{$key}[{$index}]" : $key;
                         $fields[$fieldKey] = $file->getCurlString();
                     }
                 }
                 $curlOptions[CURLOPT_POSTFIELDS] = $fields;
                 $request->removeHeader('Content-Length');
             } elseif (count($request->getPostFields())) {
                 $curlOptions[CURLOPT_POSTFIELDS] = (string) $request->getPostFields()->useUrlEncoding(true);
                 $request->removeHeader('Content-Length');
             } elseif (!$request->getBody()) {
                 // Need to remove CURLOPT_POST to prevent chunked encoding for an empty POST
                 unset($curlOptions[CURLOPT_POST]);
                 $curlOptions[CURLOPT_CUSTOMREQUEST] = 'POST';
             }
             break;
         case 'PUT':
         case 'PATCH':
         case 'DELETE':
         default:
             $curlOptions[CURLOPT_CUSTOMREQUEST] = $method;
             if (!$bodyAsString) {
                 $curlOptions[CURLOPT_UPLOAD] = true;
                 // Let cURL handle setting the Content-Length header
                 if ($tempContentLength = $request->getHeader('Content-Length')) {
                     $tempContentLength = (int) (string) $tempContentLength;
                     $curlOptions[CURLOPT_INFILESIZE] = $tempContentLength;
                 }
             } elseif (!$request->hasHeader('Content-Type')) {
                 // Remove the curl generated Content-Type header if none was set manually
                 $curlOptions[CURLOPT_HTTPHEADER][] = 'Content-Type:';
             }
     }
     // Special handling for requests sending raw data
     if ($request instanceof EntityEnclosingRequestInterface) {
         if ($request->getBody()) {
             if ($bodyAsString) {
                 $curlOptions[CURLOPT_POSTFIELDS] = (string) $request->getBody();
                 // Allow curl to add the Content-Length for us to account for the times when
                 // POST redirects are followed by GET requests
                 if ($tempContentLength = $request->getHeader('Content-Length')) {
                     $tempContentLength = (int) (string) $tempContentLength;
                 }
             } else {
                 // Add a callback for curl to read data to send with the request only if a body was specified
                 $curlOptions[CURLOPT_READFUNCTION] = array($mediator, 'readRequestBody');
                 // Attempt to seek to the start of the stream
                 $request->getBody()->seek(0);
             }
         }
         // If the Expect header is not present, prevent curl from adding it
         if (!$request->hasHeader('Expect')) {
             $curlOptions[CURLOPT_HTTPHEADER][] = 'Expect:';
         }
     }
     // If a Content-Length header was specified but we want to allow curl to set one for us
     if (null !== $tempContentLength) {
         $request->removeHeader('Content-Length');
     }
     // Set custom cURL options
     foreach ($requestCurlOptions->getAll() as $key => $value) {
         if (is_numeric($key)) {
             $curlOptions[$key] = $value;
         }
     }
     // Do not set an Accept header by default
     if (!isset($curlOptions[CURLOPT_ENCODING])) {
         $curlOptions[CURLOPT_HTTPHEADER][] = 'Accept:';
     }
     // Check if any headers or cURL options are blacklisted
     if ($blacklist = $requestCurlOptions->get('blacklist')) {
         foreach ($blacklist as $value) {
             if (strpos($value, 'header.') !== 0) {
                 unset($curlOptions[$value]);
             } else {
                 // Remove headers that may have previously been set but are supposed to be blacklisted
                 $key = substr($value, 7);
                 $request->removeHeader($key);
                 $curlOptions[CURLOPT_HTTPHEADER][] = $key . ':';
             }
         }
     }
     // Add any custom headers to the request. Empty headers will cause curl to not send the header at all.
     foreach ($request->getHeaderLines() as $line) {
         $curlOptions[CURLOPT_HTTPHEADER][] = $line;
     }
     // Apply the options to a new cURL handle.
     $handle = curl_init();
     curl_setopt_array($handle, $curlOptions);
     if ($tempContentLength) {
         $request->setHeader('Content-Length', $tempContentLength);
     }
     $handle = new static($handle, $curlOptions);
     $mediator->setCurlHandle($handle);
     return $handle;
 }
 /**
  * Apply any set default object parameters to a request
  *
  * @param RequestInterface $request Request object to apply to
  */
 protected function applyDefaults(RequestInterface $request)
 {
     if ($this->hasKey('range')) {
         $request->setHeader('Range', $this->get('range'));
         $request->getCurlOptions()->set(CURLOPT_RANGE, $this->get('range'));
     }
     if ($this->hasKey('if_modified_since')) {
         $request->setHeader('If-Modified-Since', $this->get('if_modified_since'));
     }
     if ($this->hasKey('if_unmodified_since')) {
         $request->setHeader('If-Unmodified-Since', $this->get('if_unmodified_since'));
     }
     if ($this->hasKey('if_match')) {
         $request->setHeader('If-Match', $this->get('if_match'));
     }
     if ($this->hasKey('if_none_match')) {
         $request->setHeader('If-None-Match', $this->get('if_none_match'));
     }
     if ($this->hasKey('version_id')) {
         $request->getQuery()->add('versionId', $this->get('version_id'));
     }
 }
 /**
  * Prepare a request to be sent from the Client by adding client specific behaviors and properties to the request.
  *
  * @param RequestInterface $request Request to prepare for the client
  * @param array            $options Options to apply to the request
  *
  * @return RequestInterface
  */
 protected function prepareRequest(RequestInterface $request, array $options = array())
 {
     $request->setClient($this)->setEventDispatcher(clone $this->getEventDispatcher());
     if ($curl = $this->config[self::CURL_OPTIONS]) {
         $request->getCurlOptions()->overwriteWith(CurlHandle::parseCurlConfig($curl));
     }
     if ($params = $this->config[self::REQUEST_PARAMS]) {
         Version::warn('request.params is deprecated. Use request.options to add default request options.');
         $request->getParams()->overwriteWith($params);
     }
     if ($this->userAgent && !$request->hasHeader('User-Agent')) {
         $request->setHeader('User-Agent', $this->userAgent);
     }
     if ($defaults = $this->config[self::REQUEST_OPTIONS]) {
         $this->requestFactory->applyOptions($request, $defaults, RequestFactoryInterface::OPTIONS_AS_DEFAULTS);
     }
     if ($options) {
         $this->requestFactory->applyOptions($request, $options);
     }
     $this->dispatch('client.create_request', array('client' => $this, 'request' => $request));
     return $request;
 }
Example #15
0
 public static function factory(RequestInterface $request)
 {
     $requestCurlOptions = $request->getCurlOptions();
     $mediator = new RequestMediator($request, $requestCurlOptions->get('emit_io'));
     $tempContentLength = null;
     $method = $request->getMethod();
     $bodyAsString = $requestCurlOptions->get(self::BODY_AS_STRING);
     $url = (string) $request->getUrl();
     if (($pos = strpos($url, '#')) !== false) {
         $url = substr($url, 0, $pos);
     }
     $curlOptions = array(CURLOPT_URL => $url, CURLOPT_CONNECTTIMEOUT => 150, CURLOPT_RETURNTRANSFER => false, CURLOPT_HEADER => false, CURLOPT_PORT => $request->getPort(), CURLOPT_HTTPHEADER => array(), CURLOPT_WRITEFUNCTION => array($mediator, 'writeResponseBody'), CURLOPT_HEADERFUNCTION => array($mediator, 'receiveResponseHeader'), CURLOPT_HTTP_VERSION => $request->getProtocolVersion() === '1.0' ? CURL_HTTP_VERSION_1_0 : CURL_HTTP_VERSION_1_1, CURLOPT_SSL_VERIFYPEER => 1, CURLOPT_SSL_VERIFYHOST => 2);
     if (defined('CURLOPT_PROTOCOLS')) {
         $curlOptions[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
     }
     if ($acceptEncodingHeader = $request->getHeader('Accept-Encoding')) {
         $curlOptions[CURLOPT_ENCODING] = (string) $acceptEncodingHeader;
         $request->removeHeader('Accept-Encoding');
     }
     if ($requestCurlOptions->get('debug')) {
         $curlOptions[CURLOPT_STDERR] = fopen('php://temp', 'r+');
         if (false === $curlOptions[CURLOPT_STDERR]) {
             throw new RuntimeException('Unable to create a stream for CURLOPT_STDERR');
         }
         $curlOptions[CURLOPT_VERBOSE] = true;
     }
     if ($method == 'GET') {
         $curlOptions[CURLOPT_HTTPGET] = true;
     } elseif ($method == 'HEAD') {
         $curlOptions[CURLOPT_NOBODY] = true;
         unset($curlOptions[CURLOPT_WRITEFUNCTION]);
     } elseif (!$request instanceof EntityEnclosingRequest) {
         $curlOptions[CURLOPT_CUSTOMREQUEST] = $method;
     } else {
         $curlOptions[CURLOPT_CUSTOMREQUEST] = $method;
         if ($request->getBody()) {
             if ($bodyAsString) {
                 $curlOptions[CURLOPT_POSTFIELDS] = (string) $request->getBody();
                 if ($tempContentLength = $request->getHeader('Content-Length')) {
                     $tempContentLength = (int) (string) $tempContentLength;
                 }
                 if (!$request->hasHeader('Content-Type')) {
                     $curlOptions[CURLOPT_HTTPHEADER][] = 'Content-Type:';
                 }
             } else {
                 $curlOptions[CURLOPT_UPLOAD] = true;
                 if ($tempContentLength = $request->getHeader('Content-Length')) {
                     $tempContentLength = (int) (string) $tempContentLength;
                     $curlOptions[CURLOPT_INFILESIZE] = $tempContentLength;
                 }
                 $curlOptions[CURLOPT_READFUNCTION] = array($mediator, 'readRequestBody');
                 $request->getBody()->seek(0);
             }
         } else {
             $postFields = false;
             if (count($request->getPostFiles())) {
                 $postFields = $request->getPostFields()->useUrlEncoding(false)->urlEncode();
                 foreach ($request->getPostFiles() as $key => $data) {
                     $prefixKeys = count($data) > 1;
                     foreach ($data as $index => $file) {
                         $fieldKey = $prefixKeys ? "{$key}[{$index}]" : $key;
                         $postFields[$fieldKey] = $file->getCurlValue();
                     }
                 }
             } elseif (count($request->getPostFields())) {
                 $postFields = (string) $request->getPostFields()->useUrlEncoding(true);
             }
             if ($postFields !== false) {
                 if ($method == 'POST') {
                     unset($curlOptions[CURLOPT_CUSTOMREQUEST]);
                     $curlOptions[CURLOPT_POST] = true;
                 }
                 $curlOptions[CURLOPT_POSTFIELDS] = $postFields;
                 $request->removeHeader('Content-Length');
             }
         }
         if (!$request->hasHeader('Expect')) {
             $curlOptions[CURLOPT_HTTPHEADER][] = 'Expect:';
         }
     }
     if (null !== $tempContentLength) {
         $request->removeHeader('Content-Length');
     }
     foreach ($requestCurlOptions->toArray() as $key => $value) {
         if (is_numeric($key)) {
             $curlOptions[$key] = $value;
         }
     }
     if (!isset($curlOptions[CURLOPT_ENCODING])) {
         $curlOptions[CURLOPT_HTTPHEADER][] = 'Accept:';
     }
     foreach ($request->getHeaderLines() as $line) {
         $curlOptions[CURLOPT_HTTPHEADER][] = $line;
     }
     if ($tempContentLength) {
         $request->setHeader('Content-Length', $tempContentLength);
     }
     $handle = curl_init();
     if ($requestCurlOptions->get('progress')) {
         $curlOptions[CURLOPT_PROGRESSFUNCTION] = function () use($mediator, $handle) {
             $args = func_get_args();
             $args[] = $handle;
             if (is_resource($args[0])) {
                 array_shift($args);
             }
             call_user_func_array(array($mediator, 'progress'), $args);
         };
         $curlOptions[CURLOPT_NOPROGRESS] = false;
     }
     curl_setopt_array($handle, $curlOptions);
     return new static($handle, $curlOptions);
 }
Example #16
0
 /**
  * Factory method to create a new curl handle based on an HTTP request.
  *
  * There are some helpful options you can set to enable specific behavior:
  * - debug:    Set to true to enable cURL debug functionality to track the actual headers sent over the wire.
  * - progress: Set to true to enable progress function callbacks.
  *
  * @param RequestInterface $request Request
  *
  * @return CurlHandle
  * @throws RuntimeException
  */
 public static function factory(RequestInterface $request)
 {
     $requestCurlOptions = $request->getCurlOptions();
     $mediator = new RequestMediator($request, $requestCurlOptions->get('emit_io'));
     $tempContentLength = null;
     $method = $request->getMethod();
     $bodyAsString = $requestCurlOptions->get(self::BODY_AS_STRING);
     // Prepare url
     $url = (string) $request->getUrl();
     if (($pos = strpos($url, '#')) !== false) {
         // strip fragment from url
         $url = substr($url, 0, $pos);
     }
     // Array of default cURL options.
     $curlOptions = array(CURLOPT_URL => $url, CURLOPT_CONNECTTIMEOUT => 150, CURLOPT_RETURNTRANSFER => false, CURLOPT_HEADER => false, CURLOPT_PORT => $request->getPort(), CURLOPT_HTTPHEADER => array(), CURLOPT_WRITEFUNCTION => array($mediator, 'writeResponseBody'), CURLOPT_HEADERFUNCTION => array($mediator, 'receiveResponseHeader'), CURLOPT_HTTP_VERSION => $request->getProtocolVersion() === '1.0' ? CURL_HTTP_VERSION_1_0 : CURL_HTTP_VERSION_1_1, CURLOPT_SSL_VERIFYPEER => 1, CURLOPT_SSL_VERIFYHOST => 2);
     if (defined('CURLOPT_PROTOCOLS')) {
         // Allow only HTTP and HTTPS protocols
         $curlOptions[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
     }
     // Add CURLOPT_ENCODING if Accept-Encoding header is provided
     if ($acceptEncodingHeader = $request->getHeader('Accept-Encoding')) {
         $curlOptions[CURLOPT_ENCODING] = (string) $acceptEncodingHeader;
         // Let cURL set the Accept-Encoding header, prevents duplicate values
         $request->removeHeader('Accept-Encoding');
     }
     // Enable curl debug information if the 'debug' param was set
     if ($requestCurlOptions->get('debug')) {
         $curlOptions[CURLOPT_STDERR] = fopen('php://temp', 'r+');
         // @codeCoverageIgnoreStart
         if (false === $curlOptions[CURLOPT_STDERR]) {
             throw new RuntimeException('Unable to create a stream for CURLOPT_STDERR');
         }
         // @codeCoverageIgnoreEnd
         $curlOptions[CURLOPT_VERBOSE] = true;
     }
     // Specify settings according to the HTTP method
     if ($method == 'GET') {
         $curlOptions[CURLOPT_HTTPGET] = true;
     } elseif ($method == 'HEAD') {
         $curlOptions[CURLOPT_NOBODY] = true;
         // HEAD requests do not use a write function
         unset($curlOptions[CURLOPT_WRITEFUNCTION]);
     } elseif (!$request instanceof EntityEnclosingRequest) {
         $curlOptions[CURLOPT_CUSTOMREQUEST] = $method;
     } else {
         $curlOptions[CURLOPT_CUSTOMREQUEST] = $method;
         // Handle sending raw bodies in a request
         if ($request->getBody()) {
             // You can send the body as a string using curl's CURLOPT_POSTFIELDS
             if ($bodyAsString) {
                 $curlOptions[CURLOPT_POSTFIELDS] = (string) $request->getBody();
                 // Allow curl to add the Content-Length for us to account for the times when
                 // POST redirects are followed by GET requests
                 if ($tempContentLength = $request->getHeader('Content-Length')) {
                     $tempContentLength = (int) (string) $tempContentLength;
                 }
                 // Remove the curl generated Content-Type header if none was set manually
                 if (!$request->hasHeader('Content-Type')) {
                     $curlOptions[CURLOPT_HTTPHEADER][] = 'Content-Type:';
                 }
             } else {
                 $curlOptions[CURLOPT_UPLOAD] = true;
                 // Let cURL handle setting the Content-Length header
                 if ($tempContentLength = $request->getHeader('Content-Length')) {
                     $tempContentLength = (int) (string) $tempContentLength;
                     $curlOptions[CURLOPT_INFILESIZE] = $tempContentLength;
                 }
                 // Add a callback for curl to read data to send with the request only if a body was specified
                 $curlOptions[CURLOPT_READFUNCTION] = array($mediator, 'readRequestBody');
                 // Attempt to seek to the start of the stream
                 $request->getBody()->seek(0);
             }
         } else {
             // Special handling for POST specific fields and files
             $postFields = false;
             if (count($request->getPostFiles())) {
                 $postFields = $request->getPostFields()->useUrlEncoding(false)->urlEncode();
                 foreach ($request->getPostFiles() as $key => $data) {
                     $prefixKeys = count($data) > 1;
                     foreach ($data as $index => $file) {
                         // Allow multiple files in the same key
                         $fieldKey = $prefixKeys ? "{$key}[{$index}]" : $key;
                         $postFields[$fieldKey] = $file->getCurlValue();
                     }
                 }
             } elseif (count($request->getPostFields())) {
                 $postFields = (string) $request->getPostFields()->useUrlEncoding(true);
             }
             if ($postFields !== false) {
                 if ($method == 'POST') {
                     unset($curlOptions[CURLOPT_CUSTOMREQUEST]);
                     $curlOptions[CURLOPT_POST] = true;
                 }
                 $curlOptions[CURLOPT_POSTFIELDS] = $postFields;
                 $request->removeHeader('Content-Length');
             }
         }
         // If the Expect header is not present, prevent curl from adding it
         if (!$request->hasHeader('Expect')) {
             $curlOptions[CURLOPT_HTTPHEADER][] = 'Expect:';
         }
     }
     // If a Content-Length header was specified but we want to allow curl to set one for us
     if (null !== $tempContentLength) {
         $request->removeHeader('Content-Length');
     }
     // Set custom cURL options
     foreach ($requestCurlOptions->toArray() as $key => $value) {
         if (is_numeric($key)) {
             $curlOptions[$key] = $value;
         }
     }
     // Do not set an Accept header by default
     if (!isset($curlOptions[CURLOPT_ENCODING])) {
         $curlOptions[CURLOPT_HTTPHEADER][] = 'Accept:';
     }
     // Add any custom headers to the request. Empty headers will cause curl to not send the header at all.
     foreach ($request->getHeaderLines() as $line) {
         $curlOptions[CURLOPT_HTTPHEADER][] = $line;
     }
     // Add the content-length header back if it was temporarily removed
     if ($tempContentLength) {
         $request->setHeader('Content-Length', $tempContentLength);
     }
     // Apply the options to a new cURL handle.
     $handle = curl_init();
     // Enable the progress function if the 'progress' param was set
     if ($requestCurlOptions->get('progress')) {
         // Wrap the function in a function that provides the curl handle to the mediator's progress function
         // Using this rather than injecting the handle into the mediator prevents a circular reference
         $curlOptions[CURLOPT_PROGRESSFUNCTION] = function () use($mediator, $handle) {
             $args = func_get_args();
             $args[] = $handle;
             // PHP 5.5 pushed the handle onto the start of the args
             if (is_resource($args[0])) {
                 array_shift($args);
             }
             call_user_func_array(array($mediator, 'progress'), $args);
         };
         $curlOptions[CURLOPT_NOPROGRESS] = false;
     }
     curl_setopt_array($handle, $curlOptions);
     return new static($handle, $curlOptions);
 }
Example #17
0
 /**
  * Applies the specified curl option on a request
  *
  * @param RequestInterface $request request
  *
  * @return void
  */
 protected function applyCurlOptions($request)
 {
     $curl = $request->getCurlOptions();
     foreach ($this->curlOptions as $option => $value) {
         $option = 'CURLOPT_' . strtoupper($option);
         $curl->set(constant($option), $value);
     }
     $curl->set(constant('CURLOPT_CAINFO'), __DIR__ . '/../../Resources/cert/cacert.pem');
 }