private function createResponseObject(puzzle_message_RequestInterface $request, array $headers, puzzle_adapter_TransactionInterface $transaction, puzzle_stream_StreamInterface $stream) { $parts = explode(' ', array_shift($headers), 3); $options = array('protocol_version' => substr($parts[0], -3)); if (isset($parts[2])) { $options['reason_phrase'] = $parts[2]; } $response = $this->messageFactory->createResponse($parts[1], $this->headersFromLines($headers), null, $options); // Automatically decode responses when instructed. if ($request->getConfig()->get('decode_content')) { switch ($response->getHeader('Content-Encoding')) { case 'gzip': case 'deflate': $stream = new puzzle_stream_InflateStream($stream); break; } } // Drain the stream immediately if 'stream' was not enabled. $config = $request->getConfig(); if (!$config['stream']) { $stream = $this->getSaveToBody($request, $stream); } $response->setBody($stream); $transaction->setResponse($response); puzzle_event_RequestEvents::emitHeaders($transaction); return $response; }
/** * Emits an error event for a request and accounts for the propagation * of an error event being stopped to prevent the exception from being * thrown. * * @param puzzle_adapter_TransactionInterface $transaction * @param Exception $e * @param array $stats * * @throws puzzle_exception_RequestException */ public static function emitError(puzzle_adapter_TransactionInterface $transaction, Exception $e, array $stats = array()) { $request = $transaction->getRequest(); // Convert non-request exception to a wrapped exception if (!$e instanceof puzzle_exception_RequestException) { $e = new puzzle_exception_RequestException($e->getMessage(), $request, null, $e); } // Mark the exception as having been emitted for an error event. This // works in tandem with the emitBefore method to prevent the error // event from being triggered twice for the same exception. $e->emittedError(true); // Dispatch an event and allow interception if (!$request->getEmitter()->emit('error', new puzzle_event_ErrorEvent($transaction, $e, $stats))->isPropagationStopped()) { throw $e; } }
/** * Creates a cURL handle based on a transaction. * * @param puzzle_adapter_TransactionInterface $transaction Holds a request and response * @param puzzle_message_MessageFactoryInterface $messageFactory Used to create responses * @param null|resource $handle Optionally provide a curl handle to modify * * @return resource Returns a prepared cURL handle * @throws puzzle_exception_AdapterException when an option cannot be applied */ public function __invoke(puzzle_adapter_TransactionInterface $transaction, puzzle_message_MessageFactoryInterface $messageFactory, $handle = null) { $request = $transaction->getRequest(); $mediator = new puzzle_adapter_curl_RequestMediator($transaction, $messageFactory); $this->_closure_handleOptions = $this->getDefaultOptions($request, $mediator); $this->applyMethod($request); $this->applyTransferOptions($request, $mediator); $this->applyHeaders($request); unset($this->_closure_handleOptions['_headers']); // Add adapter options from the request's configuration options $config = $request->getConfig(); if ($config = $config['curl']) { $this->_closure_handleOptions = $this->applyCustomCurlOptions($config); } if (!$handle) { $handle = curl_init(); } if (self::$_TEST_MODE && function_exists('puzzle_test_adapter_curl_curl_setopt_array')) { puzzle_test_adapter_curl_curl_setopt_array($handle, $this->_closure_handleOptions); } else { curl_setopt_array($handle, $this->_closure_handleOptions); } return $handle; }
private function validateResponseWasSet(puzzle_adapter_TransactionInterface $transaction, puzzle_adapter_curl_BatchContext $context) { if ($transaction->getResponse()) { return true; } $body = $transaction->getRequest()->getBody(); if (!$body) { // This is weird and should probably never happen. puzzle_event_RequestEvents::emitError($transaction, new puzzle_exception_RequestException('No response was received for a request with no body. This' . ' could mean that you are saturating your network.', $transaction->getRequest())); } elseif (!$body->isSeekable() || !$body->seek(0)) { // Nothing we can do with this. Sorry! puzzle_event_RequestEvents::emitError($transaction, new puzzle_exception_RequestException('The connection was unexpectedly closed. The request would' . ' have been retried, but attempting to rewind the' . ' request body failed. Consider wrapping your request' . ' body in a CachingStream decorator to work around this' . ' issue if necessary.', $transaction->getRequest())); } else { $this->retryFailedConnection($transaction, $context); } return false; }
public function send(puzzle_adapter_TransactionInterface $transaction) { $config = $transaction->getRequest()->getConfig(); return $config['stream'] ? $this->streamingAdapter->send($transaction) : $this->defaultAdapter->send($transaction); }
/** * Get the request object * * @return puzzle_message_RequestInterface */ public function getRequest() { return $this->transaction->getRequest(); }
/** * 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) { return (string) $this->transaction->getRequest()->getBody()->read($length); }