public function signRequest(RequestInterface $request, CredentialsInterface $credentials)
 {
     if ($request instanceof EntityEnclosingRequestInterface && $request->getBody()) {
         $request->setHeader('X-Amz-Content-Sha256', EntityBody::getHash($request->getBody(), 'sha256'));
     } else {
         $request->setHeader('X-Amz-Content-Sha256', hash('sha256', ''));
     }
     parent::signRequest($request, $credentials);
 }
 /**
  * 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);
         if ($this->emitIo) {
             $this->request->dispatch('curl.callback.read', array('request' => $this->request, 'read' => $read));
         }
     }
     return !$read ? '' : $read;
 }
Beispiel #3
0
 /**
  * Always add a x-amz-content-sha-256 for data integrity.
  */
 public function signRequest(RequestInterface $request, CredentialsInterface $credentials)
 {
     if ($request instanceof EntityEnclosingRequestInterface && $request->getBody() && !$request->hasHeader('x-amz-content-sha256')) {
         $request->setHeader('X-Amz-Content-Sha256', $this->getPresignedPayload($request));
     }
     parent::signRequest($request, $credentials);
 }
Beispiel #4
0
 /**
  * @param RequestInterface|EntityEnclosingRequestInterface $request
  * @param Credentials $credentials
  */
 public function signRequest($request, $credentials)
 {
     $request->setHeader('X-HMB-Signature-Method', self::DEFAULT_METHOD);
     $request->setHeader('X-HMB-Signature-Version', self::DEFAULT_SIGN_VERSION);
     $request->setHeader('X-HMB-TimeStamp', time());
     $contentMd5 = $request instanceof EntityEnclosingRequestInterface ? md5($request->getBody()) : '';
     if ($contentMd5) {
         $request->setHeader('Content-MD5', $contentMd5);
     }
     $sign = array();
     $sign[] = strtoupper($request->getMethod());
     $sign[] = $request->getHost();
     if ($request->getHeader('Content-MD5')) {
         $sign[] = $request->getHeader('Content-MD5');
     }
     if ($request->getHeader('Content-Type')) {
         $sign[] = $request->getHeader('Content-Type');
     }
     $sign[] = $request->getHeader('X-HMB-Signature-Method');
     $sign[] = $request->getHeader('X-HMB-Signature-Version');
     $sign[] = $request->getHeader('X-HMB-TimeStamp');
     if ($request->getHeader('X-HMB-User-Session-Token')) {
         $sign[] = $request->getHeader('X-HMB-User-Session-Token');
     }
     $sign[] = $request->getQuery(true) ? $request->getPath() . '?' . $request->getQuery(true) : $request->getPath();
     $signature = base64_encode(hash_hmac(strtolower($request->getHeader('X-HMB-Signature-Method')), implode("\n", $sign), $credentials->getSecret()));
     $request->setHeader('Authorization', sprintf('%s %s:%s', self::AUTHORIZATION_SCHME, $credentials->getKey(), $signature));
 }
Beispiel #5
0
 /**
  * @param Guzzle\Http\Message\RequestInterface
  * @return Guzzle\Http\Message\Response
  */
 public function handshake(RequestInterface $request)
 {
     $body = $this->sign($request->getHeader('Sec-WebSocket-Key1', true), $request->getHeader('Sec-WebSocket-Key2', true), (string) $request->getBody());
     $headers = array('Upgrade' => 'WebSocket', 'Connection' => 'Upgrade', 'Sec-WebSocket-Origin' => $request->getHeader('Origin', true), 'Sec-WebSocket-Location' => 'ws://' . $request->getHeader('Host', true) . $request->getPath());
     $response = new Response(101, $headers, $body);
     $response->setStatus(101, 'WebSocket Protocol Handshake');
     return $response;
 }
 /**
  * {@inheritdoc}
  */
 protected function getDelay($retries, RequestInterface $request, Response $response = null, HttpException $e = null)
 {
     if ($response && $response->getStatusCode() == 400 && strpos($response->getBody(), self::ERR)) {
         // Check if the request is sending a local file, and if so, clear the stat cache and recalculate the size.
         if ($request instanceof EntityEnclosingRequestInterface) {
             if ($request->getBody()->getWrapper() == 'plainfile') {
                 $filename = $request->getBody()->getUri();
                 // Clear the cache so that we send accurate file sizes
                 clearstatcache(true, $filename);
                 $length = filesize($filename);
                 $request->getBody()->setSize($length);
                 $request->setHeader('Content-Length', $length);
             }
         }
         return true;
     }
 }
 /**
  * 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)
 {
     if (!($body = $this->request->getBody())) {
         return '';
     }
     $read = (string) $body->read($length);
     if ($this->emitIo) {
         $this->request->dispatch('curl.callback.read', array('request' => $this->request, 'read' => $read));
     }
     return $read;
 }
Beispiel #8
0
 /**
  * @param  \Guzzle\Http\Message\RequestInterface $request
  * @return \Guzzle\Http\Message\Response
  * @throws \UnderflowException If there hasn't been enough data received
  */
 public function handshake(RequestInterface $request)
 {
     $body = substr($request->getBody(), 0, 8);
     if (8 !== strlen($body)) {
         throw new \UnderflowException("Not enough data received to issue challenge response");
     }
     $challenge = $this->sign((string) $request->getHeader('Sec-WebSocket-Key1'), (string) $request->getHeader('Sec-WebSocket-Key2'), $body);
     $headers = array('Upgrade' => 'WebSocket', 'Connection' => 'Upgrade', 'Sec-WebSocket-Origin' => (string) $request->getHeader('Origin'), 'Sec-WebSocket-Location' => 'ws://' . (string) $request->getHeader('Host') . $request->getPath());
     $response = new Response(101, $headers, $challenge);
     $response->setStatus(101, 'WebSocket Protocol Handshake');
     return $response;
 }
 public function __construct(ConnectionInterface $conn, RequestInterface $req)
 {
     $body = (string) $req->getBody();
     if (!empty($body)) {
         $query = QueryString::fromString($body);
         $fields = $query->getAll();
         foreach ($fields as $field => $value) {
             $req->setPostField($field, $value);
         }
     }
     $this->conn = $conn;
     $this->session = $conn->Session;
     $this->req = $req;
 }
Beispiel #10
0
 /**
  * Sign the Pusher request
  *
  * @link  http://pusher.com/docs/rest_api#authentication
  * @param RequestInterface $request
  * @param Credentials $credentials
  */
 public function signRequest(RequestInterface $request, Credentials $credentials)
 {
     $queryParameters = array('auth_key' => $credentials->getKey(), 'auth_timestamp' => time(), 'auth_version' => self::AUTH_VERSION);
     if ($request instanceof EntityEnclosingRequestInterface) {
         $body = $request->getBody();
         $queryParameters['body_md5'] = $body->getContentLength() ? $body->getContentMd5() : '';
     }
     // The signature algorithm asks that keys are all lowercased
     $queryParameters = array_change_key_case($request->getQuery()->toArray()) + $queryParameters;
     $queryParameters = array_filter($queryParameters);
     ksort($queryParameters);
     $method = strtoupper($request->getMethod());
     $requestPath = $request->getPath();
     $query = urldecode(http_build_query($queryParameters));
     $signature = $this->signString(implode("\n", array($method, $requestPath, $query)), $credentials);
     $queryParameters['auth_signature'] = $signature;
     $request->getQuery()->replace($queryParameters);
 }
Beispiel #11
0
 /**
  * Returns an HTML-formatted string representation of the exception.
  *
  * @return string
  * @internal
  */
 public function __toString()
 {
     $msg = $this->getMessage();
     if (is_object($this->requestObj) && $this->requestObj instanceof \Guzzle\Http\Message\Request) {
         $request = array('url' => $this->requestObj->getUrl(), 'host' => $this->requestObj->getHost(), 'headers' => $this->requestObj->getRawHeaders(), 'query' => (string) $this->requestObj->getQuery());
         if ($this->requestObj instanceof \Guzzle\Http\Message\EntityEnclosingRequestInterface) {
             $request_body = $this->requestObj->getBody();
             $request['content-type'] = $request_body->getContentType();
             $request['content-length'] = $request_body->getContentLength();
             $request['body'] = $request_body->__toString();
         }
         $msg .= "\n\nRequest: <pre>" . htmlspecialchars(print_r($request, true)) . '</pre>';
     }
     if (is_object($this->responseObj) && $this->responseObj instanceof \Guzzle\Http\Message\Response) {
         $response = array('status' => $this->responseObj->getStatusCode(), 'headers' => $this->responseObj->getRawHeaders(), 'body' => $this->responseBody);
         $msg .= "\n\nResponse: <pre>" . htmlspecialchars(print_r($response, true)) . '</pre>';
     }
     return $msg;
 }
Beispiel #12
0
public function cloneRequestWithMethod(RequestInterface $request, $method)
{

 if ($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()->toArray());
$cloned->setEventDispatcher(clone $request->getEventDispatcher());

 if (!($cloned instanceof EntityEnclosingRequestInterface)) {
$cloned->removeHeader('Content-Length');
} elseif ($request instanceof EntityEnclosingRequestInterface) {
$cloned->setBody($request->getBody());
}
$cloned->getParams()->replace($request->getParams()->toArray());
$cloned->dispatch('request.clone', array('request' => $cloned));

return $cloned;
}
 /**
  * Collect & sanitize data about a Guzzle request
  *
  * @param Guzzle\Http\Message\RequestInterface $request
  *
  * @return array
  */
 private function collectRequest(GuzzleRequestInterface $request)
 {
     $body = null;
     if ($request instanceof EntityEnclosingRequestInterface) {
         $body = (string) $request->getBody();
     }
     return array('headers' => $request->getHeaders(), 'method' => $request->getMethod(), 'scheme' => $request->getScheme(), 'host' => $request->getHost(), 'port' => $request->getPort(), 'path' => $request->getPath(), 'query' => $request->getQuery(), 'body' => $body);
 }
 /**
  * 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;
 }
Beispiel #15
0
 /**
  * Perform a http request and return the response
  *
  * @param \Guzzle\Http\Message\RequestInterface $request the request to preform
  * @param bool $async whether or not to perform an async request
  *
  * @return \Guzzle\Http\Message\Response|mixed the response from elastic search
  * @throws \Exception
  */
 public function perform(\Guzzle\Http\Message\RequestInterface $request, $async = false)
 {
     try {
         $profileKey = null;
         if ($this->enableProfiling) {
             $profileKey = __METHOD__ . '(' . $request->getUrl() . ')';
             if ($request instanceof \Guzzle\Http\Message\EntityEnclosingRequest) {
                 $profileKey .= " " . $request->getBody();
             }
             Yii::beginProfile($profileKey);
         }
         $response = $async ? $request->send() : json_decode($request->send()->getBody(true), true);
         Yii::trace("Sent request to '{$request->getUrl()}'", 'application.elastic.connection');
         if ($this->enableProfiling) {
             Yii::endProfile($profileKey);
         }
         return $response;
     } catch (\Guzzle\Http\Exception\BadResponseException $e) {
         $body = $e->getResponse()->getBody(true);
         if (($msg = json_decode($body)) !== null && isset($msg->error)) {
             throw new \CException($msg->error);
         } else {
             throw new \CException($e);
         }
     } catch (\Guzzle\Http\Exception\ClientErrorResponseException $e) {
         throw new \CException($e->getResponse()->getBody(true));
     }
 }
Beispiel #16
0
 /**
  * @link https://github.com/guzzle/guzzle/issues/710
  */
 private function validateResponseWasSet(RequestInterface $request)
 {
     if ($request->getResponse()) {
         return true;
     }
     $body = $request instanceof EntityEnclosingRequestInterface ? $request->getBody() : null;
     if (!$body) {
         $rex = new RequestException('No response was received for a request with no body. This' . ' could mean that you are saturating your network.');
         $rex->setRequest($request);
         $this->removeErroredRequest($request, $rex);
     } elseif (!$body->isSeekable() || !$body->seek(0)) {
         // Nothing we can do with this. Sorry!
         $rex = new RequestException('The connection was unexpectedly closed. The request would' . ' have been retried, but attempting to rewind the' . ' request body failed.');
         $rex->setRequest($request);
         $this->removeErroredRequest($request, $rex);
     } else {
         $this->remove($request);
         // Add the request back to the batch to retry automatically.
         $this->requests[] = $request;
         $this->addHandle($request);
     }
     return false;
 }
Beispiel #17
0
 /**
  * Parse cURL log messages
  *
  * @param RequestInterface $request Request that has a curl handle
  *
  * @return string
  */
 protected function parseCurlLog(RequestInterface $request)
 {
     $message = '';
     $handle = $request->getParams()->get('curl_handle');
     $stderr = $handle->getStderr(true);
     if ($stderr) {
         rewind($stderr);
         while ($line = fgets($stderr)) {
             // * - Debug | < - Downstream | > - Upstream
             if ($line[0] == '*') {
                 if ($this->settings & self::LOG_DEBUG) {
                     $message .= $line;
                 }
             } elseif ($this->settings & self::LOG_HEADERS) {
                 $message .= $line;
             }
             // Add the request body if needed
             if ($this->settings & self::LOG_BODY) {
                 if (trim($line) == '' && $request instanceof EntityEnclosingRequestInterface) {
                     if ($request->getParams()->get('request_wire')) {
                         $message .= (string) $request->getParams()->get('request_wire') . "\r\n";
                     } else {
                         $message .= (string) $request->getBody() . "\r\n";
                     }
                 }
             }
         }
     }
     return $message;
 }
 /**
  * Add body (content) specific options to the context options
  *
  * @param RequestInterface $request
  */
 protected function addBodyOptions(RequestInterface $request)
 {
     // Add the content for the request if needed
     if (!$request instanceof EntityEnclosingRequestInterface) {
         return;
     }
     if (count($request->getPostFields())) {
         $this->setContextValue('http', 'content', (string) $request->getPostFields(), true);
     } elseif ($request->getBody()) {
         $this->setContextValue('http', 'content', (string) $request->getBody(), true);
     }
     // Always ensure a content-length header is sent
     if (isset($this->contextOptions['http']['content'])) {
         $headers = isset($this->contextOptions['http']['header']) ? $this->contextOptions['http']['header'] : array();
         $headers[] = 'Content-Length: ' . strlen($this->contextOptions['http']['content']);
         $this->setContextValue('http', 'header', $headers, true);
     }
 }
Beispiel #19
0
 /**
  * Get the payload part of a signature from a request.
  *
  * @param RequestInterface $request
  *
  * @return string
  */
 protected function getPayload(RequestInterface $request)
 {
     // Calculate the request signature payload
     if ($request->hasHeader('x-amz-content-sha256')) {
         // Handle streaming operations (e.g. Glacier.UploadArchive)
         return (string) $request->getHeader('x-amz-content-sha256');
     }
     if ($request instanceof EntityEnclosingRequestInterface) {
         return hash('sha256', $request->getMethod() == 'POST' && count($request->getPostFields()) ? (string) $request->getPostFields() : (string) $request->getBody());
     }
     return self::DEFAULT_PAYLOAD;
 }
 /**
  * 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);
 }
Beispiel #21
0
 protected function onRequest(ConnectionInterface $from, RequestInterface $request)
 {
     $requestPath = $request->getPath();
     $body = (string) $request->getBody();
     if (!empty($body)) {
         $query = QueryString::fromString($body);
         $fields = $query->getAll();
         $request->addPostFields($fields);
     }
     // TODO: use only $req->acceptLanguage() in Managers
     $_SERVER['HTTP_ACCEPT_LANGUAGE'] = (string) $request->getHeaders()->get('accept-language');
     $routes = array('/' => 'executeUiBooter', '/api' => 'executeApiCall', '/api/group' => 'executeApiCallGroup', '/sbin/apicall.php' => 'executeApiCall', '/sbin/apicallgroup.php' => 'executeApiCallGroup', '/sbin/rawdatacall.php' => 'executeRawDataCall', '#^/([a-zA-Z0-9-_.]+)\\.html$#' => 'executeUiBooter', '#^/(bin|boot|etc|home|tmp|usr|var)/(.*)$#' => 'executeReadFile', '/webos.webapp' => 'executeReadManifest', '/hello' => 'executeSayHello');
     foreach ($routes as $path => $method) {
         $matched = false;
         if (substr($path, 0, 1) == '#') {
             // Regex
             if (preg_match($path, $requestPath, $matches)) {
                 $result = $this->{$method}($from, $request, $matches);
                 $matched = true;
             }
         } else {
             if ($path == $requestPath) {
                 $result = $this->{$method}($from, $request);
                 $matched = true;
             }
         }
         if ($matched) {
             if (empty($result)) {
                 $result = '';
             }
             if ($result instanceof ResponseContent) {
                 $result = $result->generate();
             }
             if ($result instanceof HTTPServerResponse) {
                 if ($result->headersSent()) {
                     // Implicit mode, content already sent
                     if ($result->getHeader('Connection') != 'keep-alive') {
                         $from->close();
                     }
                 } else {
                     $result->send();
                 }
                 return;
             }
             $response = null;
             if (is_string($result)) {
                 $response = new Response(200, array(), (string) $result);
             } else {
                 $response = $result;
             }
             $from->send((string) $response);
             $from->close();
             return;
         }
     }
     $resp = new Response(404, array('Content-Type' => 'text/plain'), '404 Not Found');
     $from->send((string) $resp);
     $from->close();
 }
Beispiel #22
0
 public function signRequest(RequestInterface $request, CredentialsInterface $credentials)
 {
     $timestamp = $this->getTimestamp();
     $longDate = gmdate(DateFormat::ISO8601, $timestamp);
     $shortDate = substr($longDate, 0, 8);
     // Remove any previously set Authorization headers so that retries work
     $request->removeHeader('Authorization');
     // Requires a x-amz-date header or Date
     if ($request->hasHeader('x-amz-date') || !$request->hasHeader('Date')) {
         $request->setHeader('x-amz-date', $longDate);
     } else {
         $request->setHeader('Date', gmdate(DateFormat::RFC1123, $timestamp));
     }
     // Add the security token if one is present
     if ($credentials->getSecurityToken()) {
         $request->setHeader('x-amz-security-token', $credentials->getSecurityToken());
     }
     // Parse the service and region or use one that is explicitly set
     $region = $this->regionName;
     $service = $this->serviceName;
     if (!$region || !$service) {
         $url = Url::factory($request->getUrl());
         $region = $region ?: HostNameUtils::parseRegionName($url);
         $service = $service ?: HostNameUtils::parseServiceName($url);
     }
     $credentialScope = "{$shortDate}/{$region}/{$service}/aws4_request";
     // Calculate the request signature payload
     if ($request->hasHeader('x-amz-content-sha256')) {
         // Handle streaming operations (e.g. Glacier.UploadArchive)
         $payload = $request->getHeader('x-amz-content-sha256');
     } elseif ($request instanceof EntityEnclosingRequestInterface) {
         $payload = hash('sha256', $request->getMethod() == 'POST' && count($request->getPostFields()) ? (string) $request->getPostFields() : (string) $request->getBody());
     } else {
         // Use the default payload if there is no body
         $payload = self::DEFAULT_PAYLOAD;
     }
     $signingContext = $this->createSigningContext($request, $payload);
     $signingContext['string_to_sign'] = "AWS4-HMAC-SHA256\n{$longDate}\n{$credentialScope}\n" . hash('sha256', $signingContext['canonical_request']);
     // Calculate the signing key using a series of derived keys
     $signingKey = $this->getSigningKey($shortDate, $region, $service, $credentials->getSecretKey());
     $signature = hash_hmac('sha256', $signingContext['string_to_sign'], $signingKey);
     $request->setHeader('Authorization', "AWS4-HMAC-SHA256 " . "Credential={$credentials->getAccessKeyId()}/{$credentialScope}, " . "SignedHeaders={$signingContext['signed_headers']}, Signature={$signature}");
     // Add debug information to the request
     $request->getParams()->set('aws.signature', $signingContext);
 }
Beispiel #23
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);
 }
Beispiel #24
0
 private function exec(\Guzzle\Http\Message\RequestInterface $request)
 {
     $start = microtime(true);
     $this->responseCode = 0;
     // Get snapshot of request headers.
     $request_headers = $request->getRawHeaders();
     // Mask authorization for logs.
     $request_headers = preg_replace('!\\nAuthorization: (Basic|Digest) [^\\r\\n]+\\r!i', "\nAuthorization: \$1 [**masked**]\r", $request_headers);
     try {
         $response = $request->send();
     } catch (\Guzzle\Http\Exception\BadResponseException $e) {
         $response = $e->getResponse();
     } catch (\Guzzle\Http\Exception\CurlException $e) {
         // Timeouts etc.
         DebugData::$raw = '';
         DebugData::$code = $e->getErrorNo();
         DebugData::$code_status = $e->getError();
         DebugData::$code_class = 0;
         DebugData::$exception = $e->getMessage();
         DebugData::$opts = array('request_headers' => $request_headers);
         DebugData::$data = null;
         $exception = new ResponseException($e->getError(), $e->getErrorNo(), $request->getUrl(), DebugData::$opts);
         $exception->requestObj = $request;
         // Log Exception
         $headers_array = $request->getHeaders();
         unset($headers_array['Authorization']);
         $headerString = '';
         foreach ($headers_array as $value) {
             $headerString .= $value->getName() . ': ' . $value . " ";
         }
         $log_message = '{code_status} ({code}) Request Details:[ {r_method} {r_resource} {r_scheme} {r_headers} ]';
         $httpScheme = strtoupper(str_replace('https', 'http', $request->getScheme())) . $request->getProtocolVersion();
         $log_params = array('code' => $e->getErrorNo(), 'code_status' => $e->getError(), 'r_method' => $request->getUrl(), 'r_resource' => $request->getRawHeaders(), 'r_scheme' => $httpScheme, 'r_headers' => $headerString);
         self::$logger->emergency($log_message, $log_params);
         throw $exception;
     }
     $this->responseCode = $response->getStatusCode();
     $this->responseText = trim($response->getBody(true));
     $this->responseLength = $response->getContentLength();
     $this->responseMimeType = $response->getContentType();
     $this->responseObj = array();
     $content_type = $response->getContentType();
     $firstChar = substr($this->responseText, 0, 1);
     if (strpos($content_type, '/json') !== false && ($firstChar == '{' || $firstChar == '[')) {
         $response_obj = @json_decode($this->responseText, true);
         if (is_array($response_obj)) {
             $this->responseObj = $response_obj;
         }
     }
     $status = self::getStatusMessage($this->responseCode);
     $code_class = floor($this->responseCode / 100);
     DebugData::$raw = $this->responseText;
     DebugData::$opts = array('request_headers' => $request_headers, 'response_headers' => $response->getRawHeaders());
     if ($request instanceof \Guzzle\Http\Message\EntityEnclosingRequestInterface) {
         DebugData::$opts['request_body'] = (string) $request->getBody();
     }
     DebugData::$opts['request_type'] = class_implements($request);
     DebugData::$data = $this->responseObj;
     DebugData::$code = $this->responseCode;
     DebugData::$code_status = $status;
     DebugData::$code_class = $code_class;
     DebugData::$exception = null;
     DebugData::$time_elapsed = microtime(true) - $start;
     if ($code_class != 2) {
         $uri = $request->getUrl();
         if (!empty($this->responseCode) && isset($this->responseObj['message'])) {
             $message = 'Code: ' . $this->responseCode . '; Message: ' . $this->responseObj['message'];
         } else {
             $message = 'API returned HTTP code of ' . $this->responseCode . ' when fetching from ' . $uri;
         }
         DebugData::$exception = $message;
         $this->debugCallback(DebugData::toArray());
         self::$logger->error($this->responseText);
         // Create better status to show up in logs
         $status .= ': ' . $request->getMethod() . ' ' . $uri;
         if ($request instanceof \Guzzle\Http\Message\EntityEnclosingRequestInterface) {
             $body = $request->getBody();
             if ($body instanceof \Guzzle\Http\EntityBodyInterface) {
                 $status .= ' with Content-Length of ' . $body->getContentLength() . ' and Content-Type of ' . $body->getContentType();
             }
         }
         $exception = new ResponseException($status, $this->responseCode, $uri, DebugData::$opts, $this->responseText);
         $exception->requestObj = $request;
         $exception->responseObj = $response;
         throw $exception;
     }
     $this->debugCallback(DebugData::toArray());
 }
 /**
  * Returns a formatted message
  *
  * @param RequestInterface $request    Request that was sent
  * @param Response         $response   Response that was received
  * @param CurlHandle       $handle     Curl handle associated with the message
  * @param array            $customData Associative array of custom template data
  *
  * @return string
  */
 public function format(RequestInterface $request, Response $response = null, CurlHandle $handle = null, array $customData = array())
 {
     $cache = $customData;
     return preg_replace_callback('/{\\s*([A-Za-z_\\-\\.0-9]+)\\s*}/', function (array $matches) use($request, $response, $handle, &$cache) {
         if (array_key_exists($matches[1], $cache)) {
             return $cache[$matches[1]];
         }
         $result = '';
         switch ($matches[1]) {
             case 'request':
                 $result = (string) $request;
                 break;
             case 'response':
                 $result = (string) $response;
                 break;
             case 'req_body':
                 $result = $request instanceof EntityEnclosingRequestInterface ? (string) $request->getBody() : '';
                 break;
             case 'res_body':
                 $result = $response ? $response->getBody(true) : '';
                 break;
             case 'ts':
                 $result = gmdate('c');
                 break;
             case 'method':
                 $result = $request->getMethod();
                 break;
             case 'url':
                 $result = (string) $request->getUrl();
                 break;
             case 'resource':
                 $result = $request->getResource();
                 break;
             case 'protocol':
                 $result = 'HTTP';
                 break;
             case 'version':
                 $result = $request->getProtocolVersion();
                 break;
             case 'host':
                 $result = $request->getHost();
                 break;
             case 'hostname':
                 $result = gethostname();
                 break;
             case 'port':
                 $result = $request->getPort();
                 break;
             case 'code':
                 $result = $response ? $response->getStatusCode() : '';
                 break;
             case 'phrase':
                 $result = $response ? $response->getReasonPhrase() : '';
                 break;
             case 'connect_time':
                 if ($handle) {
                     $result = $handle->getInfo(CURLINFO_CONNECT_TIME);
                 } elseif ($response) {
                     $result = $response->getInfo('connect_time');
                 }
                 break;
             case 'total_time':
                 if ($handle) {
                     $result = $handle->getInfo(CURLINFO_TOTAL_TIME);
                 } elseif ($response) {
                     $result = $response->getInfo('total_time');
                 }
                 break;
             case 'curl_error':
                 $result = $handle ? $handle->getError() : '';
                 break;
             case 'curl_code':
                 $result = $handle ? $handle->getErrorNo() : '';
                 break;
             case 'curl_stderr':
                 $result = $handle ? $handle->getStderr() : '';
                 break;
             default:
                 if (strpos($matches[1], 'req_header_') === 0) {
                     $result = $request->getHeader(substr($matches[1], 11));
                 } elseif (strpos($matches[1], 'res_header_') === 0) {
                     $result = $response->getHeader(substr($matches[1], 11));
                 }
         }
         $cache[$matches[1]] = $result;
         return $result;
     }, $this->template);
 }
Beispiel #26
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);
 }
 protected function getDelay($retries, RequestInterface $request, Response $response = null, HttpException $e = null)
 {
     if ($response && $request->getMethod() === 'POST' && $request instanceof EntityEnclosingRequestInterface && $response->getStatusCode() == 200 && strpos($request->getBody(), '<CompleteMultipartUpload xmlns') !== false && strpos($response->getBody(), '<CompleteMultipartUploadResult xmlns') === false) {
         return true;
     }
 }
Beispiel #28
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()->toArray());
     $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()->toArray());
     $cloned->dispatch('request.clone', array('request' => $cloned));
     return $cloned;
 }
Beispiel #29
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);
 }
Beispiel #30
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;
 }