mirror of
https://github.com/guzzle/guzzle.git
synced 2025-02-24 01:53:58 +01:00
238 lines
7.2 KiB
ReStructuredText
238 lines
7.2 KiB
ReStructuredText
=======================
|
|
Handlers and Middleware
|
|
=======================
|
|
|
|
Guzzle clients use a handler and middleware system to send HTTP requests.
|
|
|
|
Handlers
|
|
========
|
|
|
|
A handler function accepts a ``Psr\Http\Message\RequestInterface`` and array of
|
|
request options and returns a ``GuzzleHttp\Promise\PromiseInterface`` that is
|
|
fulfilled with a ``Psr\Http\Message\ResponseInterface`` or rejected with an
|
|
exception.
|
|
|
|
You can provide a custom handler to a client using the ``handler`` option of
|
|
a client constructor.
|
|
|
|
.. code-block:: php
|
|
|
|
use GuzzleHttp\Client;
|
|
use GuzzleHttp\Handler\CurlHandler;
|
|
|
|
$client = new Client(['handler' => new CurlHandler()]);
|
|
|
|
The handler of a client is then stored in the handler stack of the client
|
|
(a ``GuzzleHttp\HandlerStack`` object). The handler stack contains the client
|
|
and any middleware that will be composed on the handler.
|
|
|
|
.. code-block:: php
|
|
|
|
$stack = $client->getHandlerStack();
|
|
assert(true === $stack->hasHandler());
|
|
|
|
|
|
Middleware
|
|
==========
|
|
|
|
Middleware augments the functionality of handlers by invoking them in the
|
|
process of generating responses. Middleware is implemented as a higher order
|
|
function that takes the following form.
|
|
|
|
.. code-block:: php
|
|
|
|
function my_middleware()
|
|
{
|
|
return function (callable $handler) {
|
|
return function (RequestInterface $request, array $options) use ($handler) {
|
|
return $handler($request, $options);
|
|
}
|
|
};
|
|
}
|
|
|
|
Middleware functions return a function that accepts the next handler to invoke.
|
|
This returned function then returns another function that acts as a composed
|
|
handler-- it accepts a request and options, and returns a promise that is
|
|
fulfilled with a response. Your composed middleware can modify the request,
|
|
add custom request options, and modify the promise returned by the downstream
|
|
handler.
|
|
|
|
Here's an example of adding a header to each request.
|
|
|
|
.. code-block:: php
|
|
|
|
function add_header($header, $value)
|
|
{
|
|
return function (callable $handler) use ($header, $value) {
|
|
return function (
|
|
RequestInterface $request,
|
|
array $options
|
|
) use ($handler, $header, $value) {
|
|
$request = $request->withHeader($header, $value);
|
|
return $handler($request, $options);
|
|
}
|
|
};
|
|
}
|
|
|
|
Once a middleware has been created, you can add it to a client using the
|
|
client's handler stack.
|
|
|
|
.. code-block:: php
|
|
|
|
$client->getHandlerStack()->push(add_header('X-Foo', 'bar'));
|
|
|
|
Now when you send a request, the client will use a handler composed with your
|
|
added middleware, adding a header to each request.
|
|
|
|
Here's an example of creating a middleware that modifies the response of the
|
|
downstream handler. This example adds a header to the response.
|
|
|
|
.. code-block:: php
|
|
|
|
use Psr7\Http\Message\ResponseInterface;
|
|
|
|
function add_response_header($header, $value)
|
|
{
|
|
return function (callable $handler) use ($header, $value) {
|
|
return function (
|
|
RequestInterface $request,
|
|
array $options
|
|
) use ($handler, $header, $value) {
|
|
$promise = $handler($request, $options)
|
|
return $promise->then(
|
|
function (ResponseInterface $response) use ($header, $value) {
|
|
return $response->withHeader($header, $value);
|
|
}
|
|
);
|
|
}
|
|
};
|
|
}
|
|
|
|
$client->getHandlerStack()->push(add_response_header('X-Foo', 'bar'));
|
|
|
|
Creating a middleware that modifies a request is made much simpler using the
|
|
``GuzzleHttp\Middleware::mapRequest()`` middleware. This middleware accepts
|
|
a function that takes the request argument and returns the request to send.
|
|
|
|
.. code-block:: php
|
|
|
|
use Psr7\Http\Message\RequestInterface;
|
|
|
|
$stack = $client->getHandlerStack();
|
|
|
|
$stack->push(Middleware::mapRequest(function (RequestInterface $request) {
|
|
return $request->withHeader('X-Foo', 'bar');
|
|
}));
|
|
|
|
Modifying a response is also much simpler using the ``GuzzleHttp\Middleware::mapResponse()``
|
|
middleware.
|
|
|
|
.. code-block:: php
|
|
|
|
use Psr7\Http\Message\ResponseInterface;
|
|
|
|
$stack = $client->getHandlerStack();
|
|
|
|
$stack->push(Middleware::mapResponse(function (ResponseInterface $response) {
|
|
return $response->withHeader('X-Foo', 'bar');
|
|
}));
|
|
|
|
|
|
HandlerStack
|
|
============
|
|
|
|
A handler stack represents a stack of middleware to apply to a base handler
|
|
function. You can push middleware to the stack to add to the top of the stack,
|
|
and unshift middleware onto the stack to add to the bottom of the stack. When
|
|
the stack is resolved, the handler is pushed onto the stack. Each value is
|
|
then popped off of the stack, wrapping the previous value popped off of the
|
|
stack.
|
|
|
|
.. code-block:: php
|
|
|
|
$stack = $client->getHandlerStack();
|
|
|
|
$stack->push(Middleware::mapRequest(function ($r) {
|
|
echo 'A';
|
|
return $r;
|
|
});
|
|
|
|
$stack->push(Middleware::mapRequest(function ($r) {
|
|
echo 'B';
|
|
return $r;
|
|
});
|
|
|
|
$stack->push(Middleware::mapRequest(function ($r) {
|
|
echo 'C';
|
|
return $r;
|
|
});
|
|
|
|
$client->get('http://httpbin.org/');
|
|
// echoes 'ABC';
|
|
|
|
$stack->unshift(Middleware::mapRequest(function ($r) {
|
|
echo '0';
|
|
return $r;
|
|
});
|
|
|
|
$client->get('http://httpbin.org/');
|
|
// echoes '0ABC';
|
|
|
|
You can give middleware a name, which allows you to add middleware before
|
|
other named middleware, after other named middleware, or remove middleware
|
|
by name.
|
|
|
|
.. code-block:: php
|
|
|
|
$stack = $client->getHandlerStack();
|
|
|
|
// Add a middleware with a name
|
|
$stack->push(Middleware::mapRequest(function ($r) {
|
|
return $r->withHeader('X-Foo', 'Bar');
|
|
}, 'add_foo');
|
|
|
|
// Add a middleware before a named middleware (unshift before).
|
|
$stack->before('add_foo', Middleware::mapRequest(function ($r) {
|
|
return $r->withHeader('X-Baz', 'Qux');
|
|
}, 'add_baz');
|
|
|
|
// Add a middleware after a named middleware (pushed after).
|
|
$stack->after('add_baz', Middleware::mapRequest(function ($r) {
|
|
return $r->withHeader('X-Lorem', 'Ipsum');
|
|
});
|
|
|
|
// Remove a middleware by name
|
|
$stack->remove('add_foo');
|
|
|
|
Each request created by a client uses a clone of the client's handler stack.
|
|
This means that any middleware added to a client is also added to each request.
|
|
Guzzle will then add some default middlewares to each request based on the
|
|
provided options. You can add positional middleware to the handler stack of a
|
|
request using the :ref:`stack-option` request option.
|
|
|
|
|
|
Creating a Handler
|
|
==================
|
|
|
|
As stated earlier, a handler is a function accepts a
|
|
``Psr\Http\Message\RequestInterface`` and array of request options and returns
|
|
a ``GuzzleHttp\Promise\PromiseInterface`` that is fulfilled with a
|
|
``Psr\Http\Message\ResponseInterface`` or rejected with an exception.
|
|
|
|
A handler is responsible for applying the following :doc:`request-options`.
|
|
These request options are a subset of request options called
|
|
"transfer options".
|
|
|
|
- :ref:`cert-option`
|
|
- :ref:`connect_timeout-option`
|
|
- :ref:`debug-option`
|
|
- :ref:`delay-option`
|
|
- :ref:`decode_content-option`
|
|
- :ref:`expect-option`
|
|
- :ref:`proxy-option`
|
|
- :ref:`sink-option`
|
|
- :ref:`timeout-option`
|
|
- :ref:`ssl_key-option`
|
|
- :ref:`stream-option`
|
|
- :ref:`verify-option`
|