PluginProbe
Media Cloud Sync / 1.3.11
Media Cloud Sync v1.3.11
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 / Client.php

Client.php in Media Cloud Sync 1.3.11, at includes/sdk/s3/GuzzleHttp/Client.php

403 lines 17.8 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\Cookie\CookieJar;
6 use Dudlewebs\WPMCS\s3\GuzzleHttp\Exception\GuzzleException;
7 use Dudlewebs\WPMCS\s3\GuzzleHttp\Exception\InvalidArgumentException;
8 use Dudlewebs\WPMCS\s3\GuzzleHttp\Promise as P;
9 use Dudlewebs\WPMCS\s3\GuzzleHttp\Promise\PromiseInterface;
10 use Dudlewebs\WPMCS\s3\Psr\Http\Message\RequestInterface;
11 use Dudlewebs\WPMCS\s3\Psr\Http\Message\ResponseInterface;
12 use Dudlewebs\WPMCS\s3\Psr\Http\Message\UriInterface;
13 /**
14 * @final
15 */
16 class Client implements ClientInterface, \Dudlewebs\WPMCS\s3\Psr\Http\Client\ClientInterface
17 {
18 use ClientTrait;
19 /**
20 * @var array Default request options
21 */
22 private $config;
23 /**
24 * Clients accept an array of constructor parameters.
25 *
26 * Here's an example of creating a client using a base_uri and an array of
27 * default request options to apply to each request:
28 *
29 * $client = new Client([
30 * 'base_uri' => 'http://www.foo.com/1.0/',
31 * 'timeout' => 0,
32 * 'allow_redirects' => false,
33 * 'proxy' => '192.168.16.1:10'
34 * ]);
35 *
36 * Client configuration settings include the following options:
37 *
38 * - handler: (callable) Function that transfers HTTP requests over the
39 * wire. The function is called with a Psr7\Http\Message\RequestInterface
40 * and array of transfer options, and must return a
41 * GuzzleHttp\Promise\PromiseInterface that is fulfilled with a
42 * Psr7\Http\Message\ResponseInterface on success.
43 * If no handler is provided, a default handler will be created
44 * that enables all of the request options below by attaching all of the
45 * default middleware to the handler.
46 * - base_uri: (string|UriInterface) Base URI of the client that is merged
47 * into relative URIs. Can be a string or instance of UriInterface.
48 * - **: any request option
49 *
50 * @param array $config Client configuration settings.
51 *
52 * @see RequestOptions for a list of available request options.
53 */
54 public function __construct(array $config = [])
55 {
56 if (!isset($config['handler'])) {
57 $config['handler'] = HandlerStack::create();
58 } elseif (!\is_callable($config['handler'])) {
59 throw new InvalidArgumentException('handler must be a callable');
60 }
61 // Convert the base_uri to a UriInterface
62 if (isset($config['base_uri'])) {
63 $config['base_uri'] = Psr7\Utils::uriFor($config['base_uri']);
64 }
65 $this->configureDefaults($config);
66 }
67 /**
68 * @param string $method
69 * @param array $args
70 *
71 * @return PromiseInterface|ResponseInterface
72 *
73 * @deprecated Client::__call will be removed in guzzlehttp/guzzle:8.0.
74 */
75 public function __call($method, $args)
76 {
77 if (\count($args) < 1) {
78 throw new InvalidArgumentException('Magic request methods require a URI and optional options array');
79 }
80 $uri = $args[0];
81 $opts = $args[1] ?? [];
82 return \substr($method, -5) === 'Async' ? $this->requestAsync(\substr($method, 0, -5), $uri, $opts) : $this->request($method, $uri, $opts);
83 }
84 /**
85 * Asynchronously send an HTTP request.
86 *
87 * @param array $options Request options to apply to the given
88 * request and to the transfer. See \GuzzleHttp\RequestOptions.
89 */
90 public function sendAsync(RequestInterface $request, array $options = []) : PromiseInterface
91 {
92 // Merge the base URI into the request URI if needed.
93 $options = $this->prepareDefaults($options);
94 return $this->transfer($request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')), $options);
95 }
96 /**
97 * Send an HTTP request.
98 *
99 * @param array $options Request options to apply to the given
100 * request and to the transfer. See \GuzzleHttp\RequestOptions.
101 *
102 * @throws GuzzleException
103 */
104 public function send(RequestInterface $request, array $options = []) : ResponseInterface
105 {
106 $options[RequestOptions::SYNCHRONOUS] = \true;
107 return $this->sendAsync($request, $options)->wait();
108 }
109 /**
110 * The HttpClient PSR (PSR-18) specify this method.
111 *
112 * {@inheritDoc}
113 */
114 public function sendRequest(RequestInterface $request) : ResponseInterface
115 {
116 $options[RequestOptions::SYNCHRONOUS] = \true;
117 $options[RequestOptions::ALLOW_REDIRECTS] = \false;
118 $options[RequestOptions::HTTP_ERRORS] = \false;
119 return $this->sendAsync($request, $options)->wait();
120 }
121 /**
122 * Create and send an asynchronous HTTP request.
123 *
124 * Use an absolute path to override the base path of the client, or a
125 * relative path to append to the base path of the client. The URL can
126 * contain the query string as well. Use an array to provide a URL
127 * template and additional variables to use in the URL template expansion.
128 *
129 * @param string $method HTTP method
130 * @param string|UriInterface $uri URI object or string.
131 * @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
132 */
133 public function requestAsync(string $method, $uri = '', array $options = []) : PromiseInterface
134 {
135 $options = $this->prepareDefaults($options);
136 // Remove request modifying parameter because it can be done up-front.
137 $headers = $options['headers'] ?? [];
138 $body = $options['body'] ?? null;
139 $version = $options['version'] ?? '1.1';
140 // Merge the URI into the base URI.
141 $uri = $this->buildUri(Psr7\Utils::uriFor($uri), $options);
142 if (\is_array($body)) {
143 throw $this->invalidBody();
144 }
145 $request = new Psr7\Request($method, $uri, $headers, $body, $version);
146 // Remove the option so that they are not doubly-applied.
147 unset($options['headers'], $options['body'], $options['version']);
148 return $this->transfer($request, $options);
149 }
150 /**
151 * Create and send an HTTP request.
152 *
153 * Use an absolute path to override the base path of the client, or a
154 * relative path to append to the base path of the client. The URL can
155 * contain the query string as well.
156 *
157 * @param string $method HTTP method.
158 * @param string|UriInterface $uri URI object or string.
159 * @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
160 *
161 * @throws GuzzleException
162 */
163 public function request(string $method, $uri = '', array $options = []) : ResponseInterface
164 {
165 $options[RequestOptions::SYNCHRONOUS] = \true;
166 return $this->requestAsync($method, $uri, $options)->wait();
167 }
168 /**
169 * Get a client configuration option.
170 *
171 * These options include default request options of the client, a "handler"
172 * (if utilized by the concrete client), and a "base_uri" if utilized by
173 * the concrete client.
174 *
175 * @param string|null $option The config option to retrieve.
176 *
177 * @return mixed
178 *
179 * @deprecated Client::getConfig will be removed in guzzlehttp/guzzle:8.0.
180 */
181 public function getConfig(?string $option = null)
182 {
183 return $option === null ? $this->config : $this->config[$option] ?? null;
184 }
185 private function buildUri(UriInterface $uri, array $config) : UriInterface
186 {
187 if (isset($config['base_uri'])) {
188 $uri = Psr7\UriResolver::resolve(Psr7\Utils::uriFor($config['base_uri']), $uri);
189 }
190 if (isset($config['idn_conversion']) && $config['idn_conversion'] !== \false) {
191 $idnOptions = $config['idn_conversion'] === \true ? \IDNA_DEFAULT : $config['idn_conversion'];
192 $uri = Utils::idnUriConvert($uri, $idnOptions);
193 }
194 return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri;
195 }
196 /**
197 * Configures the default options for a client.
198 */
199 private function configureDefaults(array $config) : void
200 {
201 $defaults = ['allow_redirects' => RedirectMiddleware::$defaultSettings, 'http_errors' => \true, 'decode_content' => \true, 'verify' => \true, 'cookies' => \false, 'idn_conversion' => \false];
202 // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
203 // We can only trust the HTTP_PROXY environment variable in a CLI
204 // process due to the fact that PHP has no reliable mechanism to
205 // get environment variables that start with "HTTP_".
206 if (\PHP_SAPI === 'cli' && ($proxy = Utils::getenv('HTTP_PROXY'))) {
207 $defaults['proxy']['http'] = $proxy;
208 }
209 if ($proxy = Utils::getenv('HTTPS_PROXY')) {
210 $defaults['proxy']['https'] = $proxy;
211 }
212 if ($noProxy = Utils::getenv('NO_PROXY')) {
213 $cleanedNoProxy = \str_replace(' ', '', $noProxy);
214 $defaults['proxy']['no'] = \explode(',', $cleanedNoProxy);
215 }
216 $this->config = $config + $defaults;
217 if (!empty($config['cookies']) && $config['cookies'] === \true) {
218 $this->config['cookies'] = new CookieJar();
219 }
220 // Add the default user-agent header.
221 if (!isset($this->config['headers'])) {
222 $this->config['headers'] = ['User-Agent' => Utils::defaultUserAgent()];
223 } else {
224 // Add the User-Agent header if one was not already set.
225 foreach (\array_keys($this->config['headers']) as $name) {
226 if (\strtolower($name) === 'user-agent') {
227 return;
228 }
229 }
230 $this->config['headers']['User-Agent'] = Utils::defaultUserAgent();
231 }
232 }
233 /**
234 * Merges default options into the array.
235 *
236 * @param array $options Options to modify by reference
237 */
238 private function prepareDefaults(array $options) : array
239 {
240 $defaults = $this->config;
241 if (!empty($defaults['headers'])) {
242 // Default headers are only added if they are not present.
243 $defaults['_conditional'] = $defaults['headers'];
244 unset($defaults['headers']);
245 }
246 // Special handling for headers is required as they are added as
247 // conditional headers and as headers passed to a request ctor.
248 if (\array_key_exists('headers', $options)) {
249 // Allows default headers to be unset.
250 if ($options['headers'] === null) {
251 $defaults['_conditional'] = [];
252 unset($options['headers']);
253 } elseif (!\is_array($options['headers'])) {
254 throw new InvalidArgumentException('headers must be an array');
255 }
256 }
257 // Shallow merge defaults underneath options.
258 $result = $options + $defaults;
259 // Remove null values.
260 foreach ($result as $k => $v) {
261 if ($v === null) {
262 unset($result[$k]);
263 }
264 }
265 return $result;
266 }
267 /**
268 * Transfers the given request and applies request options.
269 *
270 * The URI of the request is not modified and the request options are used
271 * as-is without merging in default options.
272 *
273 * @param array $options See \GuzzleHttp\RequestOptions.
274 */
275 private function transfer(RequestInterface $request, array $options) : PromiseInterface
276 {
277 $request = $this->applyOptions($request, $options);
278 /** @var HandlerStack $handler */
279 $handler = $options['handler'];
280 try {
281 return P\Create::promiseFor($handler($request, $options));
282 } catch (\Exception $e) {
283 return P\Create::rejectionFor($e);
284 }
285 }
286 /**
287 * Applies the array of request options to a request.
288 */
289 private function applyOptions(RequestInterface $request, array &$options) : RequestInterface
290 {
291 $modify = ['set_headers' => []];
292 if (isset($options['headers'])) {
293 if (\array_keys($options['headers']) === \range(0, \count($options['headers']) - 1)) {
294 throw new InvalidArgumentException('The headers array must have header name as keys.');
295 }
296 $modify['set_headers'] = $options['headers'];
297 unset($options['headers']);
298 }
299 if (isset($options['form_params'])) {
300 if (isset($options['multipart'])) {
301 throw new InvalidArgumentException('You cannot use ' . 'form_params and multipart at the same time. Use the ' . 'form_params option if you want to send application/' . 'x-www-form-urlencoded requests, and the multipart ' . 'option to send multipart/form-data requests.');
302 }
303 $options['body'] = \http_build_query($options['form_params'], '', '&');
304 unset($options['form_params']);
305 // Ensure that we don't have the header in different case and set the new value.
306 $options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']);
307 $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
308 }
309 if (isset($options['multipart'])) {
310 $options['body'] = new Psr7\MultipartStream($options['multipart']);
311 unset($options['multipart']);
312 }
313 if (isset($options['json'])) {
314 $options['body'] = Utils::jsonEncode($options['json']);
315 unset($options['json']);
316 // Ensure that we don't have the header in different case and set the new value.
317 $options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']);
318 $options['_conditional']['Content-Type'] = 'application/json';
319 }
320 if (!empty($options['decode_content']) && $options['decode_content'] !== \true) {
321 // Ensure that we don't have the header in different case and set the new value.
322 $options['_conditional'] = Psr7\Utils::caselessRemove(['Accept-Encoding'], $options['_conditional']);
323 $modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
324 }
325 if (isset($options['body'])) {
326 if (\is_array($options['body'])) {
327 throw $this->invalidBody();
328 }
329 $modify['body'] = Psr7\Utils::streamFor($options['body']);
330 unset($options['body']);
331 }
332 if (!empty($options['auth']) && \is_array($options['auth'])) {
333 $value = $options['auth'];
334 $type = isset($value[2]) ? \strtolower($value[2]) : 'basic';
335 switch ($type) {
336 case 'basic':
337 // Ensure that we don't have the header in different case and set the new value.
338 $modify['set_headers'] = Psr7\Utils::caselessRemove(['Authorization'], $modify['set_headers']);
339 $modify['set_headers']['Authorization'] = 'Basic ' . \base64_encode("{$value[0]}:{$value[1]}");
340 break;
341 case 'digest':
342 // @todo: Do not rely on curl
343 $options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_DIGEST;
344 $options['curl'][\CURLOPT_USERPWD] = "{$value[0]}:{$value[1]}";
345 break;
346 case 'ntlm':
347 $options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_NTLM;
348 $options['curl'][\CURLOPT_USERPWD] = "{$value[0]}:{$value[1]}";
349 break;
350 }
351 }
352 if (isset($options['query'])) {
353 $value = $options['query'];
354 if (\is_array($value)) {
355 $value = \http_build_query($value, '', '&', \PHP_QUERY_RFC3986);
356 }
357 if (!\is_string($value)) {
358 throw new InvalidArgumentException('query must be a string or array');
359 }
360 $modify['query'] = $value;
361 unset($options['query']);
362 }
363 // Ensure that sink is not an invalid value.
364 if (isset($options['sink'])) {
365 // TODO: Add more sink validation?
366 if (\is_bool($options['sink'])) {
367 throw new InvalidArgumentException('sink must not be a boolean');
368 }
369 }
370 if (isset($options['version'])) {
371 $modify['version'] = $options['version'];
372 }
373 $request = Psr7\Utils::modifyRequest($request, $modify);
374 if ($request->getBody() instanceof Psr7\MultipartStream) {
375 // Use a multipart/form-data POST if a Content-Type is not set.
376 // Ensure that we don't have the header in different case and set the new value.
377 $options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']);
378 $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary=' . $request->getBody()->getBoundary();
379 }
380 // Merge in conditional headers if they are not present.
381 if (isset($options['_conditional'])) {
382 // Build up the changes so it's in a single clone of the message.
383 $modify = [];
384 foreach ($options['_conditional'] as $k => $v) {
385 if (!$request->hasHeader($k)) {
386 $modify['set_headers'][$k] = $v;
387 }
388 }
389 $request = Psr7\Utils::modifyRequest($request, $modify);
390 // Don't pass this internal value along to middleware/handlers.
391 unset($options['_conditional']);
392 }
393 return $request;
394 }
395 /**
396 * Return an InvalidArgumentException with pre-set message.
397 */
398 private function invalidBody() : InvalidArgumentException
399 {
400 return new InvalidArgumentException('Passing in the "body" request ' . 'option as an array to send a request is not supported. ' . 'Please use the "form_params" request option to send a ' . 'application/x-www-form-urlencoded request, or the "multipart" ' . 'request option to send a multipart/form-data request.');
401 }
402 }
403