PluginProbe
Media Cloud Sync / 1.2.6
Media Cloud Sync v1.2.6
1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 All 34 releases
media-cloud-sync / includes / sdk / s3 / GuzzleHttp / RedirectMiddleware.php

RedirectMiddleware.php in Media Cloud Sync 1.2.6, at includes/sdk/s3/GuzzleHttp/RedirectMiddleware.php

183 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Dudlewebs\WPMCS\s3\GuzzleHttp;
4
5 use Dudlewebs\WPMCS\s3\GuzzleHttp\Exception\BadResponseException;
6 use Dudlewebs\WPMCS\s3\GuzzleHttp\Exception\TooManyRedirectsException;
7 use Dudlewebs\WPMCS\s3\GuzzleHttp\Promise\PromiseInterface;
8 use Dudlewebs\WPMCS\s3\GuzzleHttp\Psr7;
9 use Dudlewebs\WPMCS\s3\Psr\Http\Message\RequestInterface;
10 use Dudlewebs\WPMCS\s3\Psr\Http\Message\ResponseInterface;
11 use Dudlewebs\WPMCS\s3\Psr\Http\Message\UriInterface;
12 /**
13 * Request redirect middleware.
14 *
15 * Apply this middleware like other middleware using
16 * {@see \GuzzleHttp\Middleware::redirect()}.
17 */
18 class RedirectMiddleware
19 {
20 const HISTORY_HEADER = 'X-Guzzle-Redirect-History';
21 const STATUS_HISTORY_HEADER = 'X-Guzzle-Redirect-Status-History';
22 public static $defaultSettings = ['max' => 5, 'protocols' => ['http', 'https'], 'strict' => \false, 'referer' => \false, 'track_redirects' => \false];
23 /** @var callable */
24 private $nextHandler;
25 /**
26 * @param callable $nextHandler Next handler to invoke.
27 */
28 public function __construct(callable $nextHandler)
29 {
30 $this->nextHandler = $nextHandler;
31 }
32 /**
33 * @param RequestInterface $request
34 * @param array $options
35 *
36 * @return PromiseInterface
37 */
38 public function __invoke(RequestInterface $request, array $options)
39 {
40 $fn = $this->nextHandler;
41 if (empty($options['allow_redirects'])) {
42 return $fn($request, $options);
43 }
44 if ($options['allow_redirects'] === \true) {
45 $options['allow_redirects'] = self::$defaultSettings;
46 } elseif (!\is_array($options['allow_redirects'])) {
47 throw new \InvalidArgumentException('allow_redirects must be true, false, or array');
48 } else {
49 // Merge the default settings with the provided settings
50 $options['allow_redirects'] += self::$defaultSettings;
51 }
52 if (empty($options['allow_redirects']['max'])) {
53 return $fn($request, $options);
54 }
55 return $fn($request, $options)->then(function (ResponseInterface $response) use($request, $options) {
56 return $this->checkRedirect($request, $options, $response);
57 });
58 }
59 /**
60 * @param RequestInterface $request
61 * @param array $options
62 * @param ResponseInterface $response
63 *
64 * @return ResponseInterface|PromiseInterface
65 */
66 public function checkRedirect(RequestInterface $request, array $options, ResponseInterface $response)
67 {
68 if (\substr($response->getStatusCode(), 0, 1) != '3' || !$response->hasHeader('Location')) {
69 return $response;
70 }
71 $this->guardMax($request, $options);
72 $nextRequest = $this->modifyRequest($request, $options, $response);
73 // If authorization is handled by curl, unset it if URI is cross-origin.
74 if (Psr7\UriComparator::isCrossOrigin($request->getUri(), $nextRequest->getUri()) && \defined('\\CURLOPT_HTTPAUTH')) {
75 unset($options['curl'][\CURLOPT_HTTPAUTH], $options['curl'][\CURLOPT_USERPWD]);
76 }
77 if (isset($options['allow_redirects']['on_redirect'])) {
78 \call_user_func($options['allow_redirects']['on_redirect'], $request, $response, $nextRequest->getUri());
79 }
80 /** @var PromiseInterface|ResponseInterface $promise */
81 $promise = $this($nextRequest, $options);
82 // Add headers to be able to track history of redirects.
83 if (!empty($options['allow_redirects']['track_redirects'])) {
84 return $this->withTracking($promise, (string) $nextRequest->getUri(), $response->getStatusCode());
85 }
86 return $promise;
87 }
88 /**
89 * Enable tracking on promise.
90 *
91 * @return PromiseInterface
92 */
93 private function withTracking(PromiseInterface $promise, $uri, $statusCode)
94 {
95 return $promise->then(function (ResponseInterface $response) use($uri, $statusCode) {
96 // Note that we are pushing to the front of the list as this
97 // would be an earlier response than what is currently present
98 // in the history header.
99 $historyHeader = $response->getHeader(self::HISTORY_HEADER);
100 $statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER);
101 \array_unshift($historyHeader, $uri);
102 \array_unshift($statusHeader, $statusCode);
103 return $response->withHeader(self::HISTORY_HEADER, $historyHeader)->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader);
104 });
105 }
106 /**
107 * Check for too many redirects.
108 *
109 * @return void
110 *
111 * @throws TooManyRedirectsException Too many redirects.
112 */
113 private function guardMax(RequestInterface $request, array &$options)
114 {
115 $current = isset($options['__redirect_count']) ? $options['__redirect_count'] : 0;
116 $options['__redirect_count'] = $current + 1;
117 $max = $options['allow_redirects']['max'];
118 if ($options['__redirect_count'] > $max) {
119 throw new TooManyRedirectsException("Will not follow more than {$max} redirects", $request);
120 }
121 }
122 /**
123 * @param RequestInterface $request
124 * @param array $options
125 * @param ResponseInterface $response
126 *
127 * @return RequestInterface
128 */
129 public function modifyRequest(RequestInterface $request, array $options, ResponseInterface $response)
130 {
131 // Request modifications to apply.
132 $modify = [];
133 $protocols = $options['allow_redirects']['protocols'];
134 // Use a GET request if this is an entity enclosing request and we are
135 // not forcing RFC compliance, but rather emulating what all browsers
136 // would do.
137 $statusCode = $response->getStatusCode();
138 if ($statusCode == 303 || $statusCode <= 302 && !$options['allow_redirects']['strict']) {
139 $modify['method'] = 'GET';
140 $modify['body'] = '';
141 }
142 $uri = self::redirectUri($request, $response, $protocols);
143 if (isset($options['idn_conversion']) && $options['idn_conversion'] !== \false) {
144 $idnOptions = $options['idn_conversion'] === \true ? \IDNA_DEFAULT : $options['idn_conversion'];
145 $uri = Utils::idnUriConvert($uri, $idnOptions);
146 }
147 $modify['uri'] = $uri;
148 Psr7\rewind_body($request);
149 // Add the Referer header if it is told to do so and only
150 // add the header if we are not redirecting from https to http.
151 if ($options['allow_redirects']['referer'] && $modify['uri']->getScheme() === $request->getUri()->getScheme()) {
152 $uri = $request->getUri()->withUserInfo('');
153 $modify['set_headers']['Referer'] = (string) $uri;
154 } else {
155 $modify['remove_headers'][] = 'Referer';
156 }
157 // Remove Authorization and Cookie headers if URI is cross-origin.
158 if (Psr7\UriComparator::isCrossOrigin($request->getUri(), $modify['uri'])) {
159 $modify['remove_headers'][] = 'Authorization';
160 $modify['remove_headers'][] = 'Cookie';
161 }
162 return Psr7\modify_request($request, $modify);
163 }
164 /**
165 * Set the appropriate URL on the request based on the location header.
166 *
167 * @param RequestInterface $request
168 * @param ResponseInterface $response
169 * @param array $protocols
170 *
171 * @return UriInterface
172 */
173 private static function redirectUri(RequestInterface $request, ResponseInterface $response, array $protocols)
174 {
175 $location = Psr7\UriResolver::resolve($request->getUri(), new Psr7\Uri($response->getHeaderLine('Location')));
176 // Ensure that the redirect URI is allowed based on the protocols.
177 if (!\in_array($location->getScheme(), $protocols)) {
178 throw new BadResponseException(\sprintf('Redirect URI, %s, does not use one of the allowed redirect protocols: %s', $location, \implode(', ', $protocols)), $request, $response);
179 }
180 return $location;
181 }
182 }
183