Handlers and Middleware

Los clientes de Guzzle utilizan un sistema de manejadores y middleware para enviar peticiones HTTP.

Manejadores

Una función manejadora acepta un Psr\Http\Message\RequestInterface y un array de opciones de solicitud y devuelve un GuzzleHttp\Promise\PromiseInterface que se que se cumple con un Psr\Http\Message\ResponseInterface o se rechaza con una excepción.

Puede proporcionar un manejador personalizado a un cliente utilizando la opción handler del un constructor de cliente. Es importante entender que varias opciones de petición de solicitud utilizadas por Guzzle requieren que los middlewares específicos envuelvan el handler utilizado por el cliente. Puedes asegurarte de que el manejador que proporcionas a un cliente utiliza los middlewares por defecto envolviendo el manejador en el GuzzleHttp\HandlerStack::create(callable $handler = null) método estático.

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Handler\CurlHandler;

$handler = new CurlHandler();
$stack = HandlerStack::create($handler); // Wrap w/ middleware
$client = new Client(['handler' => $stack]);

El método create añade manejadores por defecto a la HandlerStack. Cuando el HandlerStack se resuelve, los manejadores se ejecutarán en el siguiente orden:

  1. Envío de solicitud:
  1. http_errors - No op al enviar una solicitud. El código de estado de la respuesta se comprueba en el procesamiento de la respuesta cuando se devuelve una promesa de respuesta hacia arriba la pila.
  2. allow_redirects - No op al enviar una petición. Seguir las redirecciones ocurre cuando una promesa de respuesta está siendo devuelta en la pila.
  3. cookies - Añade cookies a las peticiones.
  4. prepare_body - Se preparará el cuerpo de una petición HTTP (por ejemplo, añadir cabeceras por defecto como Content-Length, Content-Type, etc.).
  5. <enviar solicitud con manejador<
  1. Respuesta de procesamiento:
  1. prepare_body - no op en el procesamiento de la respuesta.
  2. cookies - extrae las cookies de respuesta en el tarro de cookies.
  3. allow_redirects - Sigue las redirecciones.
  4. http_errors - lanza excepciones cuando el código de estado de la respuesta >= 400.

Cuando no se proporciona ningún argumento $handler, GuzzleHttp\HandlerStack::create() elegirá el manejador más apropiado basándose en las extensiones disponibles en su sistema.

Importante

El manejador proporcionado a un cliente determina cómo se aplican las opciones de la solicitud y se utilizan para cada solicitud enviada por un cliente. Por ejemplo, si no se tiene tiene un middleware de cookies asociado a un cliente, entonces establecer el cookies opción de solicitud no tendrá efecto en la solicitud.

Middleware

El middleware aumenta la funcionalidad de los manejadores invocándolos en el proceso de generación de respuestas. El middleware se implementa como una función de orden superior que tiene la siguiente forma.

use Psr\Http\Message\RequestInterface;

function my_middleware()
{
    return function (callable $handler) {
        return function (RequestInterface $request, array $options) use ($handler) {
            return $handler($request, $options);
        };
    };
}

Las funciones del middleware devuelven una función que acepta el siguiente manejador a invocar. Esta función devuelve otra función que actúa como un compuesta: acepta una solicitud y opciones, y devuelve una promesa que se cumple con una respuesta. promesa que se cumple con una respuesta. Tu middleware compuesto puede modificar la petición, añadir opciones de solicitud personalizadas y modificar la promesa devuelta por el gestor de la solicitud.

Este es un ejemplo de cómo añadir una cabecera a cada petición.

use Psr\Http\Message\RequestInterface;

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);
        };
    };
}

Una vez que se ha creado un middleware, se puede añadir a un cliente envolviendo el manejador utilizado por el cliente o decorando una pila de manejadores.

use GuzzleHttp\HandlerStack;
use GuzzleHttp\Handler\CurlHandler;
use GuzzleHttp\Client;

$stack = new HandlerStack();
$stack->setHandler(new CurlHandler());
$stack->push(add_header('X-Foo', 'bar'));
$client = new Client(['handler' => $stack]);

Ahora, cuando envíe una solicitud, el cliente utilizará un manejador compuesto con su middleware añadido, añadiendo una cabecera a cada solicitud.

Este es un ejemplo de creación de un middleware que modifica la respuesta del manejador descendente. Este ejemplo añade una cabecera a la respuesta.

use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Handler\CurlHandler;
use GuzzleHttp\Client;

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);
                }
            );
        };
    };
}

$stack = new HandlerStack();
$stack->setHandler(new CurlHandler());
$stack->push(add_response_header('X-Foo', 'bar'));
$client = new Client(['handler' => $stack]);

La creación de un middleware que modifique una petición es mucho más sencilla utilizando el GuzzleHttp\Middleware::mapRequest() middleware. Este middleware acepta una función que toma el argumento de la petición y devuelve la petición a enviar.

use Psr\Http\Message\RequestInterface;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Handler\CurlHandler;
use GuzzleHttp\Client;
use GuzzleHttp\Middleware;

$stack = new HandlerStack();
$stack->setHandler(new CurlHandler());

$stack->push(Middleware::mapRequest(function (RequestInterface $request) {
    return $request->withHeader('X-Foo', 'bar');
}));

$client = new Client(['handler' => $stack]);

Modificar una respuesta es también mucho más simple usando el GuzzleHttp\Middleware::mapResponse() middleware.

use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Handler\CurlHandler;
use GuzzleHttp\Client;
use GuzzleHttp\Middleware;

$stack = new HandlerStack();
$stack->setHandler(new CurlHandler());

$stack->push(Middleware::mapResponse(function (ResponseInterface $response) {
    return $response->withHeader('X-Foo', 'bar');
}));

$client = new Client(['handler' => $stack]);

HandlerStack

Una pila de manipuladores representa una pila de programas intermedios para aplicar a un manipulador base base. Puedes empujar middleware a la pila para añadirlo a la parte superior de la pila y desalojar middleware a la pila para añadirlo a la parte inferior de la misma. Cuando la pila se resuelve, el manejador es empujado a la pila. Cada valor es Cada valor es sacado de la pila, envolviendo el valor anterior sacado de la pila. pila.

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use GuzzleHttp\Utils;
use Psr\Http\Message\RequestInterface;

$stack = new HandlerStack();
$stack->setHandler(Utils::chooseHandler());

$stack->push(Middleware::mapRequest(function (RequestInterface $r) {
    echo 'A';
    return $r;
}));

$stack->push(Middleware::mapRequest(function (RequestInterface $r) {
    echo 'B';
    return $r;
}));

$stack->push(Middleware::mapRequest(function (RequestInterface $r) {
    echo 'C';
    return $r;
}));

$client->request('GET', 'http://httpbin.org/');
// echoes 'ABC';

$stack->unshift(Middleware::mapRequest(function (RequestInterface $r) {
    echo '0';
    return $r;
}));

$client = new Client(['handler' => $stack]);
$client->request('GET', 'http://httpbin.org/');
// echoes '0ABC';

Se puede dar un nombre al middleware, lo que permite añadirlo antes de otros middleware con nombre, después de otros middleware con nombre, o eliminar middleware por su nombre.

use Psr\Http\Message\RequestInterface;
use GuzzleHttp\Middleware;

// Add a middleware with a name
$stack->push(Middleware::mapRequest(function (RequestInterface $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 (RequestInterface $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 (RequestInterface $r) {
    return $r->withHeader('X-Lorem', 'Ipsum');
}));

// Remove a middleware by name
$stack->remove('add_foo');

Creación de un manipulador

Como ya se ha dicho, un handler es una función que acepta un Psr\Http\Message\RequestInterface y un array de opciones de petición y devuelve un GuzzleHttp\Promise\PromiseInterface que se cumple con un Psr\Http\Message\ResponseInterface o se rechaza con una excepción.

Un gestor es responsable de aplicar las siguientes Opciones de solicitud. Estas opciones de solicitud son un subconjunto de opciones de solicitud denominadas "opciones de transferencia".