source: vendor/guzzlehttp/guzzle/src/Middleware.php@ f9c482b

Last change on this file since f9c482b was f9c482b, checked in by Vlado 222039 <vlado.popovski@…>, 7 days ago

Upload new project files

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