mirror of
https://github.com/guzzle/guzzle.git
synced 2025-02-25 02:22:57 +01:00
Trying to flesh out intercepting events
This commit is contained in:
parent
75eca7f10d
commit
ee0756ff06
@ -10,9 +10,9 @@ interface AdapterInterface
|
||||
/**
|
||||
* Transfers one or more HTTP requests and populates responses
|
||||
*
|
||||
* @param array $requests Array of {@see \Guzzle\Http\Message\RequestInterface} objects
|
||||
* @param Transaction $transaction Hash of request to response object with an associated client
|
||||
*
|
||||
* @return Transaction Returns a hash mapping RequestInterface to ResponseInterface objects or AdapterExceptions
|
||||
*/
|
||||
public function send(array $requests);
|
||||
public function send(Transaction $transaction);
|
||||
}
|
||||
|
@ -45,15 +45,15 @@ class CurlAdapter extends AbstractAdapter
|
||||
$this->factory = isset($options['factory']) ? $options['factory'] : CurlFactory::getInstance();
|
||||
}
|
||||
|
||||
public function send(array $requests)
|
||||
public function send(Transaction $transaction)
|
||||
{
|
||||
$context = [
|
||||
'transaction' => new Transaction(),
|
||||
'transaction' => $transaction,
|
||||
'handles' => new \SplObjectStorage(),
|
||||
'multi' => $this->checkoutMultiHandle()
|
||||
];
|
||||
|
||||
foreach ($requests as $request) {
|
||||
foreach ($transaction as $request) {
|
||||
try {
|
||||
$this->prepare($request, $context);
|
||||
} catch (RequestException $e) {
|
||||
@ -69,11 +69,9 @@ class CurlAdapter extends AbstractAdapter
|
||||
|
||||
private function prepare(RequestInterface $request, array $context)
|
||||
{
|
||||
$response = $this->messageFactory->createResponse();
|
||||
$handle = $this->factory->createHandle($request, $response);
|
||||
$handle = $this->factory->createHandle($request, $context['transaction'][$request]);
|
||||
$this->checkCurlResult(curl_multi_add_handle($context['multi'], $handle));
|
||||
$context['handles'][$request] = $handle;
|
||||
$context['transaction'][$request] = $response;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -117,7 +115,6 @@ class CurlAdapter extends AbstractAdapter
|
||||
|
||||
try {
|
||||
$this->isCurlException($request, $curl);
|
||||
// Emit request.sent
|
||||
} catch (RequestException $e) {
|
||||
$context['transaction'][$request] = $e;
|
||||
}
|
||||
|
@ -12,29 +12,27 @@ use Guzzle\Stream\Stream;
|
||||
*/
|
||||
class StreamAdapter extends AbstractAdapter
|
||||
{
|
||||
public function send(array $requests)
|
||||
public function send(Transaction $transaction)
|
||||
{
|
||||
$result = new Transaction();
|
||||
foreach ($requests as $request) {
|
||||
foreach ($transaction as $request) {
|
||||
try {
|
||||
$result[$request] = $this->createResponse($request);
|
||||
$this->createResponse($request, $transaction[$request]);
|
||||
} catch (RequestException $e) {
|
||||
$result[$request] = $e;
|
||||
$transaction[$request] = $e;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
return $transaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RequestInterface $request
|
||||
* @return ResponseInterface
|
||||
* @param RequestInterface $request Request to send
|
||||
* @param ResponseInterface $response Response to populate
|
||||
* @throws \LogicException if you attempt to stream and specify a write_to option
|
||||
*/
|
||||
private function createResponse(RequestInterface $request)
|
||||
private function createResponse(RequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
$stream = $this->createStream($request, $http_response_header);
|
||||
$response = $this->messageFactory->createResponse();
|
||||
|
||||
// Track the response headers of the request
|
||||
if (isset($http_response_header)) {
|
||||
@ -46,8 +44,6 @@ class StreamAdapter extends AbstractAdapter
|
||||
} else{
|
||||
$this->applySaveToBody($request, $response, $stream);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,11 +22,11 @@ class StreamingProxyAdapter implements AdapterInterface
|
||||
$this->streamingAdapter = $streamingAdapter;
|
||||
}
|
||||
|
||||
public function send(array $requests)
|
||||
public function send(Transaction $transaction)
|
||||
{
|
||||
$streaming = $default = array();
|
||||
|
||||
foreach ($requests as $request) {
|
||||
foreach ($transaction as $request) {
|
||||
if ($request->getTransferOptions()['streaming']) {
|
||||
$streaming[] = $request;
|
||||
} else {
|
||||
@ -34,14 +34,25 @@ class StreamingProxyAdapter implements AdapterInterface
|
||||
}
|
||||
}
|
||||
|
||||
if ($default) {
|
||||
$result = $this->defaultAdapter->send($default);
|
||||
if ($streaming) {
|
||||
$result->addAll($this->streamingAdapter->send($streaming));
|
||||
}
|
||||
return $result;
|
||||
} elseif ($streaming) {
|
||||
return $this->streamingAdapter->send($streaming);
|
||||
if (!$streaming) {
|
||||
return $this->defaultAdapter->send($transaction);
|
||||
}
|
||||
|
||||
$streamingTransaction = new Transaction($transaction->getClient());
|
||||
foreach ($streaming as $request) {
|
||||
$streamingTransaction[$request] = $transaction[$request];
|
||||
}
|
||||
|
||||
$this->streamingAdapter->send($streamingTransaction);
|
||||
|
||||
if ($default) {
|
||||
$defaultTransaction = new Transaction($transaction->getClient());
|
||||
foreach ($default as $request) {
|
||||
$defaultTransaction[$request] = $transaction[$request];
|
||||
}
|
||||
$streamingTransaction->addAll($this->defaultAdapter->send($defaultTransaction));
|
||||
}
|
||||
|
||||
return $streamingTransaction;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace Guzzle\Http\Adapter;
|
||||
|
||||
use Guzzle\Http\ClientInterface;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
use Guzzle\Http\Message\ResponseInterface;
|
||||
use Guzzle\Http\Exception\RequestException;
|
||||
@ -11,6 +12,17 @@ use Guzzle\Http\Exception\RequestException;
|
||||
*/
|
||||
class Transaction extends \SplObjectStorage
|
||||
{
|
||||
/** @var ClientInterface */
|
||||
private $client;
|
||||
|
||||
/**
|
||||
* @param ClientInterface $client Client that is used to send the requests
|
||||
*/
|
||||
public function __construct(ClientInterface $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
}
|
||||
|
||||
public function offsetSet($object, $data = null)
|
||||
{
|
||||
if (!($object instanceof RequestInterface)) {
|
||||
@ -89,4 +101,14 @@ class Transaction extends \SplObjectStorage
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the client that sent the requests
|
||||
*
|
||||
* @return ClientInterface
|
||||
*/
|
||||
public function getClient()
|
||||
{
|
||||
return $this->client;
|
||||
}
|
||||
}
|
||||
|
@ -5,13 +5,17 @@ namespace Guzzle\Http;
|
||||
use Guzzle\Common\Collection;
|
||||
use Guzzle\Common\HasDispatcher;
|
||||
use Guzzle\Common\Version;
|
||||
use Guzzle\Http\Event\AfterSendEvent;
|
||||
use Guzzle\Http\Event\BeforeSendEvent;
|
||||
use Guzzle\Http\Adapter\AdapterInterface;
|
||||
use Guzzle\Http\Adapter\StreamAdapter;
|
||||
use Guzzle\Http\Adapter\StreamingProxyAdapter;
|
||||
use Guzzle\Http\Adapter\Curl\CurlAdapter;
|
||||
use Guzzle\Http\Adapter\Transaction;
|
||||
use Guzzle\Http\Exception\AdapterException;
|
||||
use Guzzle\Http\Exception\BatchException;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
use Guzzle\Http\Message\ResponseInterface;
|
||||
use Guzzle\Url\Url;
|
||||
use Guzzle\Url\UriTemplate;
|
||||
use Guzzle\Http\Message\MessageFactory;
|
||||
@ -184,10 +188,17 @@ class Client implements ClientInterface
|
||||
|
||||
public function send(RequestInterface $request)
|
||||
{
|
||||
$transaction = $this->adapter->send(array($request));
|
||||
if (!isset($transaction[$request])) {
|
||||
throw new \LogicException('The client HTTP adapter did not populate a response for the request');
|
||||
} elseif ($transaction[$request] instanceof AdapterException) {
|
||||
$transaction = new Transaction($this);
|
||||
$event = $this->preSend($request);
|
||||
if ($response = $event->getResponse()) {
|
||||
$transaction[$request] = $response;
|
||||
} else {
|
||||
$transaction[$request] = $this->messageFactory->createResponse();
|
||||
$this->adapter->send($transaction);
|
||||
}
|
||||
|
||||
$this->afterSend($request, $transaction);
|
||||
if ($transaction[$request] instanceof \Exception) {
|
||||
throw $transaction[$request];
|
||||
}
|
||||
|
||||
@ -196,7 +207,28 @@ class Client implements ClientInterface
|
||||
|
||||
public function batch(array $requests)
|
||||
{
|
||||
$transaction = $this->adapter->send($requests);
|
||||
$transaction = new Transaction($this);
|
||||
$intercepted = new Transaction($this);
|
||||
|
||||
foreach ($requests as $request) {
|
||||
$event = $this->preSend($request);
|
||||
if ($response = $event->getResponse()) {
|
||||
$intercepted[$request] = $response;
|
||||
} else {
|
||||
$transaction[$request] = $this->messageFactory->createResponse();
|
||||
}
|
||||
}
|
||||
|
||||
if (count($transaction)) {
|
||||
$this->adapter->send($transaction);
|
||||
}
|
||||
|
||||
$transaction->addAll($intercepted);
|
||||
|
||||
foreach ($requests as $request) {
|
||||
$this->afterSend($request, $transaction);
|
||||
}
|
||||
|
||||
if ($transaction->hasExceptions()) {
|
||||
throw new BatchException($transaction, $this);
|
||||
}
|
||||
@ -214,6 +246,41 @@ class Client implements ClientInterface
|
||||
return 'Guzzle/' . Version::VERSION . ' curl/' . curl_version()['version'] . ' PHP/' . PHP_VERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits events before a request is sent
|
||||
*
|
||||
* @param RequestInterface $request Request about to be sent
|
||||
*
|
||||
* @return BeforeSendEvent
|
||||
*/
|
||||
private function preSend(RequestInterface $request)
|
||||
{
|
||||
return $request->getEventDispatcher()->dispatch(
|
||||
'request.before_send',
|
||||
new BeforeSendEvent($request, $this->messageFactory)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs validation and emits events after a request has been sent
|
||||
*
|
||||
* @param RequestInterface $request Request that sent
|
||||
* @param Transaction $transaction Transaction
|
||||
* @throws \LogicException if the transaction loses the request for some reason after the request.after_send event
|
||||
*/
|
||||
private function afterSend(RequestInterface $request, Transaction $transaction)
|
||||
{
|
||||
if (!isset($transaction[$request])) {
|
||||
throw new \LogicException('The request is not associated with the transaction');
|
||||
}
|
||||
|
||||
$event = $request->getEventDispatcher()->dispatch(
|
||||
'request.after_send',
|
||||
new AfterSendEvent($request, $transaction[$request], $this->messageFactory)
|
||||
);
|
||||
$transaction[$request] = $event->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand a URI template
|
||||
*
|
||||
|
54
src/Guzzle/Http/Event/AfterSendEvent.php
Normal file
54
src/Guzzle/Http/Event/AfterSendEvent.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Guzzle\Http\Event;
|
||||
|
||||
use Guzzle\Common\Event;
|
||||
use Guzzle\Http\Message\MessageFactoryInterface;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
use Guzzle\Http\Message\ResponseInterface;
|
||||
|
||||
class AfterSendEvent extends Event
|
||||
{
|
||||
public function __construct(RequestInterface $request, $result, MessageFactoryInterface $factory)
|
||||
{
|
||||
parent::__construct([
|
||||
'request' => $request,
|
||||
'message_factory' => $factory,
|
||||
'result' => $result
|
||||
]);
|
||||
}
|
||||
|
||||
public function getRequest()
|
||||
{
|
||||
return $this['request'];
|
||||
}
|
||||
|
||||
public function getMessageFactory()
|
||||
{
|
||||
return $this['message_factory'];
|
||||
}
|
||||
|
||||
public function setResult($result)
|
||||
{
|
||||
if (!($result instanceof ResponseInterface) && !($result instanceof \Exception)) {
|
||||
throw new \InvalidArgumentException('Result must be a ResponseInterface or Exception object');
|
||||
}
|
||||
|
||||
$this['result'] = $result;
|
||||
}
|
||||
|
||||
public function getResult()
|
||||
{
|
||||
return $this['result'];
|
||||
}
|
||||
|
||||
public function hasResponse()
|
||||
{
|
||||
return $this['result'] instanceof ResponseInterface;
|
||||
}
|
||||
|
||||
public function hasException()
|
||||
{
|
||||
return $this['result'] instanceof \Exception;
|
||||
}
|
||||
}
|
39
src/Guzzle/Http/Event/BeforeSendEvent.php
Normal file
39
src/Guzzle/Http/Event/BeforeSendEvent.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Guzzle\Http\Event;
|
||||
|
||||
use Guzzle\Common\Event;
|
||||
use Guzzle\Http\Message\MessageFactoryInterface;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
use Guzzle\Http\Message\ResponseInterface;
|
||||
|
||||
class BeforeSendEvent extends Event
|
||||
{
|
||||
public function __construct(RequestInterface $request, MessageFactoryInterface $factory)
|
||||
{
|
||||
parent::__construct([
|
||||
'request' => $request,
|
||||
'message_factory' => $factory
|
||||
]);
|
||||
}
|
||||
|
||||
public function getRequest()
|
||||
{
|
||||
return $this['request'];
|
||||
}
|
||||
|
||||
public function getMessageFactory()
|
||||
{
|
||||
return $this['message_factory'];
|
||||
}
|
||||
|
||||
public function getResponse()
|
||||
{
|
||||
return $this['response'];
|
||||
}
|
||||
|
||||
public function setResponse(ResponseInterface $response)
|
||||
{
|
||||
$this['response'] = $response;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user