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.

  1. use Psr\Http\Message\RequestInterface;
  2. function my_middleware()
  3. {
  4. return function (callable $handler) {
  5. return function (RequestInterface $request, array $options) use ($handler) {
  6. return $handler($request, $options);
  7. };
  8. };
  9. }

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.

  1. use Psr\Http\Message\RequestInterface;
  2. function add_header($header, $value)
  3. {
  4. return function (callable $handler) use ($header, $value) {
  5. return function (
  6. RequestInterface $request,
  7. array $options
  8. ) use ($handler, $header, $value) {
  9. $request = $request->withHeader($header, $value);
  10. return $handler($request, $options);
  11. };
  12. };
  13. }

Once a middleware has been created, you can add it to a client by either wrapping the handler used by the client or by decorating a handler stack.

  1. use GuzzleHttp\HandlerStack;
  2. use GuzzleHttp\Handler\CurlHandler;
  3. use GuzzleHttp\Client;
  4. $stack = new HandlerStack();
  5. $stack->setHandler(new CurlHandler());
  6. $stack->push(add_header('X-Foo', 'bar'));
  7. $client = new Client(['handler' => $stack]);

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.

  1. use Psr\Http\Message\RequestInterface;
  2. use Psr\Http\Message\ResponseInterface;
  3. use GuzzleHttp\HandlerStack;
  4. use GuzzleHttp\Handler\CurlHandler;
  5. use GuzzleHttp\Client;
  6. function add_response_header($header, $value)
  7. {
  8. return function (callable $handler) use ($header, $value) {
  9. return function (
  10. RequestInterface $request,
  11. array $options
  12. ) use ($handler, $header, $value) {
  13. $promise = $handler($request, $options)
  14. return $promise->then(
  15. function (ResponseInterface $response) use ($header, $value) {
  16. return $response->withHeader($header, $value);
  17. }
  18. );
  19. }
  20. };
  21. }
  22. $stack = new HandlerStack();
  23. $stack->setHandler(new CurlHandler());
  24. $stack->push(add_response_header('X-Foo', 'bar'));
  25. $client = new Client(['handler' => $stack]);

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.

  1. use Psr\Http\Message\RequestInterface;
  2. use GuzzleHttp\HandlerStack;
  3. use GuzzleHttp\Handler\CurlHandler;
  4. use GuzzleHttp\Client;
  5. use GuzzleHttp\Middleware;
  6. $stack = new HandlerStack();
  7. $stack->setHandler(new CurlHandler());
  8. $stack->push(Middleware::mapRequest(function (RequestInterface $request) {
  9. return $request->withHeader('X-Foo', 'bar');
  10. }));
  11. $client = new Client(['handler' => $stack]);

Modifying a response is also much simpler using the GuzzleHttp\Middleware::mapResponse() middleware.

  1. use Psr\Http\Message\ResponseInterface;
  2. use GuzzleHttp\HandlerStack;
  3. use GuzzleHttp\Handler\CurlHandler;
  4. use GuzzleHttp\Client;
  5. use GuzzleHttp\Middleware;
  6. $stack = new HandlerStack();
  7. $stack->setHandler(new CurlHandler());
  8. $stack->push(Middleware::mapResponse(function (ResponseInterface $response) {
  9. return $response->withHeader('X-Foo', 'bar');
  10. }));
  11. $client = new Client(['handler' => $stack]);