vendor/guzzlehttp/guzzle/src/Middleware.php line 72

Open in your IDE?
  1. <?php
  2. namespace GuzzleHttp;
  3. use GuzzleHttp\Cookie\CookieJarInterface;
  4. use GuzzleHttp\Exception\RequestException;
  5. use GuzzleHttp\Promise as P;
  6. use GuzzleHttp\Promise\PromiseInterface;
  7. use Psr\Http\Message\RequestInterface;
  8. use Psr\Http\Message\ResponseInterface;
  9. use Psr\Log\LoggerInterface;
  10. /**
  11.  * Functions used to create and wrap handlers with handler middleware.
  12.  */
  13. final class Middleware
  14. {
  15.     /**
  16.      * Middleware that adds cookies to requests.
  17.      *
  18.      * The options array must be set to a CookieJarInterface in order to use
  19.      * cookies. This is typically handled for you by a client.
  20.      *
  21.      * @return callable Returns a function that accepts the next handler.
  22.      */
  23.     public static function cookies(): callable
  24.     {
  25.         return static function (callable $handler): callable {
  26.             return static function ($request, array $options) use ($handler) {
  27.                 if (empty($options['cookies'])) {
  28.                     return $handler($request$options);
  29.                 } elseif (!($options['cookies'] instanceof CookieJarInterface)) {
  30.                     throw new \InvalidArgumentException('cookies must be an instance of GuzzleHttp\Cookie\CookieJarInterface');
  31.                 }
  32.                 $cookieJar $options['cookies'];
  33.                 $request $cookieJar->withCookieHeader($request);
  34.                 return $handler($request$options)
  35.                     ->then(
  36.                         static function (ResponseInterface $response) use ($cookieJar$request): ResponseInterface {
  37.                             $cookieJar->extractCookies($request$response);
  38.                             return $response;
  39.                         }
  40.                     );
  41.             };
  42.         };
  43.     }
  44.     /**
  45.      * Middleware that throws exceptions for 4xx or 5xx responses when the
  46.      * "http_errors" request option is set to true.
  47.      *
  48.      * @param BodySummarizerInterface|null $bodySummarizer The body summarizer to use in exception messages.
  49.      *
  50.      * @return callable(callable): callable Returns a function that accepts the next handler.
  51.      */
  52.     public static function httpErrors(BodySummarizerInterface $bodySummarizer null): callable
  53.     {
  54.         return static function (callable $handler) use ($bodySummarizer): callable {
  55.             return static function ($request, array $options) use ($handler$bodySummarizer) {
  56.                 if (empty($options['http_errors'])) {
  57.                     return $handler($request$options);
  58.                 }
  59.                 return $handler($request$options)->then(
  60.                     static function (ResponseInterface $response) use ($request$bodySummarizer) {
  61.                         $code $response->getStatusCode();
  62.                         if ($code 400) {
  63.                             return $response;
  64.                         }
  65.                         throw RequestException::create($request$responsenull, [], $bodySummarizer);
  66.                     }
  67.                 );
  68.             };
  69.         };
  70.     }
  71.     /**
  72.      * Middleware that pushes history data to an ArrayAccess container.
  73.      *
  74.      * @param array|\ArrayAccess<int, array> $container Container to hold the history (by reference).
  75.      *
  76.      * @return callable(callable): callable Returns a function that accepts the next handler.
  77.      *
  78.      * @throws \InvalidArgumentException if container is not an array or ArrayAccess.
  79.      */
  80.     public static function history(&$container): callable
  81.     {
  82.         if (!\is_array($container) && !$container instanceof \ArrayAccess) {
  83.             throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess');
  84.         }
  85.         return static function (callable $handler) use (&$container): callable {
  86.             return static function (RequestInterface $request, array $options) use ($handler, &$container) {
  87.                 return $handler($request$options)->then(
  88.                     static function ($value) use ($request, &$container$options) {
  89.                         $container[] = [
  90.                             'request' => $request,
  91.                             'response' => $value,
  92.                             'error' => null,
  93.                             'options' => $options,
  94.                         ];
  95.                         return $value;
  96.                     },
  97.                     static function ($reason) use ($request, &$container$options) {
  98.                         $container[] = [
  99.                             'request' => $request,
  100.                             'response' => null,
  101.                             'error' => $reason,
  102.                             'options' => $options,
  103.                         ];
  104.                         return P\Create::rejectionFor($reason);
  105.                     }
  106.                 );
  107.             };
  108.         };
  109.     }
  110.     /**
  111.      * Middleware that invokes a callback before and after sending a request.
  112.      *
  113.      * The provided listener cannot modify or alter the response. It simply
  114.      * "taps" into the chain to be notified before returning the promise. The
  115.      * before listener accepts a request and options array, and the after
  116.      * listener accepts a request, options array, and response promise.
  117.      *
  118.      * @param callable $before Function to invoke before forwarding the request.
  119.      * @param callable $after  Function invoked after forwarding.
  120.      *
  121.      * @return callable Returns a function that accepts the next handler.
  122.      */
  123.     public static function tap(callable $before null, callable $after null): callable
  124.     {
  125.         return static function (callable $handler) use ($before$after): callable {
  126.             return static function (RequestInterface $request, array $options) use ($handler$before$after) {
  127.                 if ($before) {
  128.                     $before($request$options);
  129.                 }
  130.                 $response $handler($request$options);
  131.                 if ($after) {
  132.                     $after($request$options$response);
  133.                 }
  134.                 return $response;
  135.             };
  136.         };
  137.     }
  138.     /**
  139.      * Middleware that handles request redirects.
  140.      *
  141.      * @return callable Returns a function that accepts the next handler.
  142.      */
  143.     public static function redirect(): callable
  144.     {
  145.         return static function (callable $handler): RedirectMiddleware {
  146.             return new RedirectMiddleware($handler);
  147.         };
  148.     }
  149.     /**
  150.      * Middleware that retries requests based on the boolean result of
  151.      * invoking the provided "decider" function.
  152.      *
  153.      * If no delay function is provided, a simple implementation of exponential
  154.      * backoff will be utilized.
  155.      *
  156.      * @param callable $decider Function that accepts the number of retries,
  157.      *                          a request, [response], and [exception] and
  158.      *                          returns true if the request is to be retried.
  159.      * @param callable $delay   Function that accepts the number of retries and
  160.      *                          returns the number of milliseconds to delay.
  161.      *
  162.      * @return callable Returns a function that accepts the next handler.
  163.      */
  164.     public static function retry(callable $decider, callable $delay null): callable
  165.     {
  166.         return static function (callable $handler) use ($decider$delay): RetryMiddleware {
  167.             return new RetryMiddleware($decider$handler$delay);
  168.         };
  169.     }
  170.     /**
  171.      * Middleware that logs requests, responses, and errors using a message
  172.      * formatter.
  173.      *
  174.      * @phpstan-param \Psr\Log\LogLevel::* $logLevel  Level at which to log requests.
  175.      *
  176.      * @param LoggerInterface                            $logger    Logs messages.
  177.      * @param MessageFormatterInterface|MessageFormatter $formatter Formatter used to create message strings.
  178.      * @param string                                     $logLevel  Level at which to log requests.
  179.      *
  180.      * @return callable Returns a function that accepts the next handler.
  181.      */
  182.     public static function log(LoggerInterface $logger$formatterstring $logLevel 'info'): callable
  183.     {
  184.         // To be compatible with Guzzle 7.1.x we need to allow users to pass a MessageFormatter
  185.         if (!$formatter instanceof MessageFormatter && !$formatter instanceof MessageFormatterInterface) {
  186.             throw new \LogicException(sprintf('Argument 2 to %s::log() must be of type %s'self::class, MessageFormatterInterface::class));
  187.         }
  188.         return static function (callable $handler) use ($logger$formatter$logLevel): callable {
  189.             return static function (RequestInterface $request, array $options = []) use ($handler$logger$formatter$logLevel) {
  190.                 return $handler($request$options)->then(
  191.                     static function ($response) use ($logger$request$formatter$logLevel): ResponseInterface {
  192.                         $message $formatter->format($request$response);
  193.                         $logger->log($logLevel$message);
  194.                         return $response;
  195.                     },
  196.                     static function ($reason) use ($logger$request$formatter): PromiseInterface {
  197.                         $response $reason instanceof RequestException $reason->getResponse() : null;
  198.                         $message $formatter->format($request$responseP\Create::exceptionFor($reason));
  199.                         $logger->error($message);
  200.                         return P\Create::rejectionFor($reason);
  201.                     }
  202.                 );
  203.             };
  204.         };
  205.     }
  206.     /**
  207.      * This middleware adds a default content-type if possible, a default
  208.      * content-length or transfer-encoding header, and the expect header.
  209.      */
  210.     public static function prepareBody(): callable
  211.     {
  212.         return static function (callable $handler): PrepareBodyMiddleware {
  213.             return new PrepareBodyMiddleware($handler);
  214.         };
  215.     }
  216.     /**
  217.      * Middleware that applies a map function to the request before passing to
  218.      * the next handler.
  219.      *
  220.      * @param callable $fn Function that accepts a RequestInterface and returns
  221.      *                     a RequestInterface.
  222.      */
  223.     public static function mapRequest(callable $fn): callable
  224.     {
  225.         return static function (callable $handler) use ($fn): callable {
  226.             return static function (RequestInterface $request, array $options) use ($handler$fn) {
  227.                 return $handler($fn($request), $options);
  228.             };
  229.         };
  230.     }
  231.     /**
  232.      * Middleware that applies a map function to the resolved promise's
  233.      * response.
  234.      *
  235.      * @param callable $fn Function that accepts a ResponseInterface and
  236.      *                     returns a ResponseInterface.
  237.      */
  238.     public static function mapResponse(callable $fn): callable
  239.     {
  240.         return static function (callable $handler) use ($fn): callable {
  241.             return static function (RequestInterface $request, array $options) use ($handler$fn) {
  242.                 return $handler($request$options)->then($fn);
  243.             };
  244.         };
  245.     }
  246. }