Chris@0: withCookieHeader($request); Chris@0: return $handler($request, $options) Chris@13: ->then( Chris@13: function ($response) use ($cookieJar, $request) { Chris@13: $cookieJar->extractCookies($request, $response); Chris@13: return $response; Chris@13: } Chris@0: ); Chris@0: }; Chris@0: }; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Middleware that throws exceptions for 4xx or 5xx responses when the Chris@0: * "http_error" request option is set to true. Chris@0: * Chris@0: * @return callable Returns a function that accepts the next handler. Chris@0: */ Chris@0: public static function httpErrors() Chris@0: { Chris@0: return function (callable $handler) { Chris@0: return function ($request, array $options) use ($handler) { Chris@0: if (empty($options['http_errors'])) { Chris@0: return $handler($request, $options); Chris@0: } Chris@0: return $handler($request, $options)->then( Chris@0: function (ResponseInterface $response) use ($request, $handler) { Chris@0: $code = $response->getStatusCode(); Chris@0: if ($code < 400) { Chris@0: return $response; Chris@0: } Chris@0: throw RequestException::create($request, $response); Chris@0: } Chris@0: ); Chris@0: }; Chris@0: }; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Middleware that pushes history data to an ArrayAccess container. Chris@0: * Chris@13: * @param array|\ArrayAccess $container Container to hold the history (by reference). Chris@0: * Chris@0: * @return callable Returns a function that accepts the next handler. Chris@0: * @throws \InvalidArgumentException if container is not an array or ArrayAccess. Chris@0: */ Chris@0: public static function history(&$container) Chris@0: { Chris@0: if (!is_array($container) && !$container instanceof \ArrayAccess) { Chris@0: throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess'); Chris@0: } Chris@0: Chris@0: return function (callable $handler) use (&$container) { Chris@0: return function ($request, array $options) use ($handler, &$container) { Chris@0: return $handler($request, $options)->then( Chris@0: function ($value) use ($request, &$container, $options) { Chris@0: $container[] = [ Chris@0: 'request' => $request, Chris@0: 'response' => $value, Chris@0: 'error' => null, Chris@0: 'options' => $options Chris@0: ]; Chris@0: return $value; Chris@0: }, Chris@0: function ($reason) use ($request, &$container, $options) { Chris@0: $container[] = [ Chris@0: 'request' => $request, Chris@0: 'response' => null, Chris@0: 'error' => $reason, Chris@0: 'options' => $options Chris@0: ]; Chris@0: return \GuzzleHttp\Promise\rejection_for($reason); Chris@0: } Chris@0: ); Chris@0: }; Chris@0: }; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Middleware that invokes a callback before and after sending a request. Chris@0: * Chris@0: * The provided listener cannot modify or alter the response. It simply Chris@0: * "taps" into the chain to be notified before returning the promise. The Chris@0: * before listener accepts a request and options array, and the after Chris@0: * listener accepts a request, options array, and response promise. Chris@0: * Chris@0: * @param callable $before Function to invoke before forwarding the request. Chris@0: * @param callable $after Function invoked after forwarding. Chris@0: * Chris@0: * @return callable Returns a function that accepts the next handler. Chris@0: */ Chris@0: public static function tap(callable $before = null, callable $after = null) Chris@0: { Chris@0: return function (callable $handler) use ($before, $after) { Chris@0: return function ($request, array $options) use ($handler, $before, $after) { Chris@0: if ($before) { Chris@0: $before($request, $options); Chris@0: } Chris@0: $response = $handler($request, $options); Chris@0: if ($after) { Chris@0: $after($request, $options, $response); Chris@0: } Chris@0: return $response; Chris@0: }; Chris@0: }; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Middleware that handles request redirects. Chris@0: * Chris@0: * @return callable Returns a function that accepts the next handler. Chris@0: */ Chris@0: public static function redirect() Chris@0: { Chris@0: return function (callable $handler) { Chris@0: return new RedirectMiddleware($handler); Chris@0: }; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Middleware that retries requests based on the boolean result of Chris@0: * invoking the provided "decider" function. Chris@0: * Chris@0: * If no delay function is provided, a simple implementation of exponential Chris@0: * backoff will be utilized. Chris@0: * Chris@0: * @param callable $decider Function that accepts the number of retries, Chris@0: * a request, [response], and [exception] and Chris@0: * returns true if the request is to be retried. Chris@0: * @param callable $delay Function that accepts the number of retries and Chris@0: * returns the number of milliseconds to delay. Chris@0: * Chris@0: * @return callable Returns a function that accepts the next handler. Chris@0: */ Chris@0: public static function retry(callable $decider, callable $delay = null) Chris@0: { Chris@0: return function (callable $handler) use ($decider, $delay) { Chris@0: return new RetryMiddleware($decider, $handler, $delay); Chris@0: }; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Middleware that logs requests, responses, and errors using a message Chris@0: * formatter. Chris@0: * Chris@0: * @param LoggerInterface $logger Logs messages. Chris@0: * @param MessageFormatter $formatter Formatter used to create message strings. Chris@0: * @param string $logLevel Level at which to log requests. Chris@0: * Chris@0: * @return callable Returns a function that accepts the next handler. Chris@0: */ Chris@0: public static function log(LoggerInterface $logger, MessageFormatter $formatter, $logLevel = LogLevel::INFO) Chris@0: { Chris@0: return function (callable $handler) use ($logger, $formatter, $logLevel) { Chris@0: return function ($request, array $options) use ($handler, $logger, $formatter, $logLevel) { Chris@0: return $handler($request, $options)->then( Chris@0: function ($response) use ($logger, $request, $formatter, $logLevel) { Chris@0: $message = $formatter->format($request, $response); Chris@0: $logger->log($logLevel, $message); Chris@0: return $response; Chris@0: }, Chris@0: function ($reason) use ($logger, $request, $formatter) { Chris@0: $response = $reason instanceof RequestException Chris@0: ? $reason->getResponse() Chris@0: : null; Chris@0: $message = $formatter->format($request, $response, $reason); Chris@0: $logger->notice($message); Chris@0: return \GuzzleHttp\Promise\rejection_for($reason); Chris@0: } Chris@0: ); Chris@0: }; Chris@0: }; Chris@0: } Chris@0: Chris@0: /** Chris@0: * This middleware adds a default content-type if possible, a default Chris@0: * content-length or transfer-encoding header, and the expect header. Chris@0: * Chris@0: * @return callable Chris@0: */ Chris@0: public static function prepareBody() Chris@0: { Chris@0: return function (callable $handler) { Chris@0: return new PrepareBodyMiddleware($handler); Chris@0: }; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Middleware that applies a map function to the request before passing to Chris@0: * the next handler. Chris@0: * Chris@0: * @param callable $fn Function that accepts a RequestInterface and returns Chris@0: * a RequestInterface. Chris@0: * @return callable Chris@0: */ Chris@0: public static function mapRequest(callable $fn) Chris@0: { Chris@0: return function (callable $handler) use ($fn) { Chris@0: return function ($request, array $options) use ($handler, $fn) { Chris@0: return $handler($fn($request), $options); Chris@0: }; Chris@0: }; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Middleware that applies a map function to the resolved promise's Chris@0: * response. Chris@0: * Chris@0: * @param callable $fn Function that accepts a ResponseInterface and Chris@0: * returns a ResponseInterface. Chris@0: * @return callable Chris@0: */ Chris@0: public static function mapResponse(callable $fn) Chris@0: { Chris@0: return function (callable $handler) use ($fn) { Chris@0: return function ($request, array $options) use ($handler, $fn) { Chris@0: return $handler($request, $options)->then($fn); Chris@0: }; Chris@0: }; Chris@0: } Chris@0: }