Aggiornato Composer

This commit is contained in:
Paolo A
2024-05-17 12:24:19 +00:00
parent 4ac62108b5
commit ec201d75b2
2238 changed files with 38684 additions and 59785 deletions

View File

@@ -2,6 +2,106 @@
Please refer to [UPGRADING](UPGRADING.md) guide for upgrading to a major version.
## 7.8.1 - 2023-12-03
### Changed
- Updated links in docs to their canonical versions
- Replaced `call_user_func*` with native calls
## 7.8.0 - 2023-08-27
### Added
- Support for PHP 8.3
- Added automatic closing of handles on `CurlFactory` object destruction
## 7.7.1 - 2023-08-27
### Changed
- Remove the need for `AllowDynamicProperties` in `CurlMultiHandler`
## 7.7.0 - 2023-05-21
### Added
- Support `guzzlehttp/promises` v2
## 7.6.1 - 2023-05-15
### Fixed
- Fix `SetCookie::fromString` MaxAge deprecation warning and skip invalid MaxAge values
## 7.6.0 - 2023-05-14
### Added
- Support for setting the minimum TLS version in a unified way
- Apply on request the version set in options parameters
## 7.5.2 - 2023-05-14
### Fixed
- Fixed set cookie constructor validation
- Fixed handling of files with `'0'` body
### Changed
- Corrected docs and default connect timeout value to 300 seconds
## 7.5.1 - 2023-04-17
### Fixed
- Fixed `NO_PROXY` settings so that setting the `proxy` option to `no` overrides the env variable
### Changed
- Adjusted `guzzlehttp/psr7` version constraint to `^1.9.1 || ^2.4.5`
## 7.5.0 - 2022-08-28
### Added
- Support PHP 8.2
- Add request to delay closure params
## 7.4.5 - 2022-06-20
### Fixed
* Fix change in port should be considered a change in origin
* Fix `CURLOPT_HTTPAUTH` option not cleared on change of origin
## 7.4.4 - 2022-06-09
### Fixed
* Fix failure to strip Authorization header on HTTP downgrade
* Fix failure to strip the Cookie header on change in host or HTTP downgrade
## 7.4.3 - 2022-05-25
### Fixed
* Fix cross-domain cookie leakage
## 7.4.2 - 2022-03-20
### Fixed
@@ -10,6 +110,7 @@ Please refer to [UPGRADING](UPGRADING.md) guide for upgrading to a major version
- Reject non-HTTP schemes in StreamHandler
- Set a default ssl.peer_name context in StreamHandler to allow `force_ip_resolve`
## 7.4.1 - 2021-12-06
### Changed
@@ -21,6 +122,7 @@ Please refer to [UPGRADING](UPGRADING.md) guide for upgrading to a major version
- Only close curl handle if it's done [#2950](https://github.com/guzzle/guzzle/pull/2950)
## 7.4.0 - 2021-10-18
### Added
@@ -38,6 +140,7 @@ Please refer to [UPGRADING](UPGRADING.md) guide for upgrading to a major version
- Be more strict with types [#2914](https://github.com/guzzle/guzzle/pull/2914), [#2917](https://github.com/guzzle/guzzle/pull/2917), [#2919](https://github.com/guzzle/guzzle/pull/2919), [#2945](https://github.com/guzzle/guzzle/pull/2945)
## 7.3.0 - 2021-03-23
### Added
@@ -50,6 +153,7 @@ Please refer to [UPGRADING](UPGRADING.md) guide for upgrading to a major version
- Handle exceptions on invalid header consistently between PHP versions and handlers [#2872](https://github.com/guzzle/guzzle/pull/2872)
## 7.2.0 - 2020-10-10
### Added
@@ -72,6 +176,7 @@ Please refer to [UPGRADING](UPGRADING.md) guide for upgrading to a major version
- Using environment variable GUZZLE_CURL_SELECT_TIMEOUT [#2786](https://github.com/guzzle/guzzle/pull/2786)
## 7.1.1 - 2020-09-30
### Fixed
@@ -83,6 +188,7 @@ Please refer to [UPGRADING](UPGRADING.md) guide for upgrading to a major version
- We dont connect curl `sink` on HEAD requests.
- Removed some PHP 5 workarounds
## 7.1.0 - 2020-09-22
### Added
@@ -105,14 +211,17 @@ Please refer to [UPGRADING](UPGRADING.md) guide for upgrading to a major version
- `Utils::defaultCaBundle()`
- `CurlFactory::LOW_CURL_VERSION_NUMBER`
## 7.0.1 - 2020-06-27
* Fix multiply defined functions fatal error [#2699](https://github.com/guzzle/guzzle/pull/2699)
## 7.0.0 - 2020-06-27
No changes since 7.0.0-rc1.
## 7.0.0-rc1 - 2020-06-15
### Changed
@@ -120,6 +229,7 @@ No changes since 7.0.0-rc1.
* Use error level for logging errors in Middleware [#2629](https://github.com/guzzle/guzzle/pull/2629)
* Disabled IDN support by default and require ext-intl to use it [#2675](https://github.com/guzzle/guzzle/pull/2675)
## 7.0.0-beta2 - 2020-05-25
### Added
@@ -145,6 +255,7 @@ No changes since 7.0.0-rc1.
* Pool option `pool_size` [#2528](https://github.com/guzzle/guzzle/pull/2528)
## 7.0.0-beta1 - 2019-12-30
The diff might look very big but 95% of Guzzle users will be able to upgrade without modification.
@@ -178,15 +289,18 @@ Please see [the upgrade document](UPGRADING.md) that describes all BC breaking c
* `uri_template()` and `UriTemplate` [#2440](https://github.com/guzzle/guzzle/pull/2440)
* Request options `save_to` and `exceptions` [#2464](https://github.com/guzzle/guzzle/pull/2464)
## 6.5.2 - 2019-12-23
* idn_to_ascii() fix for old PHP versions [#2489](https://github.com/guzzle/guzzle/pull/2489)
## 6.5.1 - 2019-12-21
* Better defaults for PHP installations with old ICU lib [#2454](https://github.com/guzzle/guzzle/pull/2454)
* IDN support for redirects [#2424](https://github.com/guzzle/guzzle/pull/2424)
## 6.5.0 - 2019-12-07
* Improvement: Added support for reset internal queue in MockHandler. [#2143](https://github.com/guzzle/guzzle/pull/2143)
@@ -196,11 +310,13 @@ Please see [the upgrade document](UPGRADING.md) that describes all BC breaking c
* Fix: Prevent undefined offset when using array for ssl_key options. [#2348](https://github.com/guzzle/guzzle/pull/2348)
* Deprecated `ClientInterface::VERSION`
## 6.4.1 - 2019-10-23
* No `guzzle.phar` was created in 6.4.0 due expired API token. This release will fix that
* Added `parent::__construct()` to `FileCookieJar` and `SessionCookieJar`
## 6.4.0 - 2019-10-23
* Improvement: Improved error messages when using curl < 7.21.2 [#2108](https://github.com/guzzle/guzzle/pull/2108)
@@ -213,6 +329,7 @@ Please see [the upgrade document](UPGRADING.md) that describes all BC breaking c
* Fix: Prevent concurrent writes to file when saving `CookieJar` [#2335](https://github.com/guzzle/guzzle/pull/2335)
* Improvement: Update `MockHandler` so we can test transfer time [#2362](https://github.com/guzzle/guzzle/pull/2362)
## 6.3.3 - 2018-04-22
* Fix: Default headers when decode_content is specified
@@ -254,13 +371,14 @@ Please see [the upgrade document](UPGRADING.md) that describes all BC breaking c
* Bug fix: Fill `CURLOPT_CAPATH` and `CURLOPT_CAINFO` properly [#1684](https://github.com/guzzle/guzzle/pull/1684)
* Improvement: Use `\GuzzleHttp\Promise\rejection_for` function instead of object init [#1827](https://github.com/guzzle/guzzle/pull/1827)
+ Minor code cleanups, documentation fixes and clarifications.
## 6.2.3 - 2017-02-28
* Fix deprecations with guzzle/psr7 version 1.4
## 6.2.2 - 2016-10-08
* Allow to pass nullable Response to delay callable
@@ -268,6 +386,7 @@ Please see [the upgrade document](UPGRADING.md) that describes all BC breaking c
* Fix drain case where content-length is the literal string zero
* Obfuscate in-URL credentials in exceptions
## 6.2.1 - 2016-07-18
* Address HTTP_PROXY security vulnerability, CVE-2016-5385:
@@ -278,6 +397,7 @@ Please see [the upgrade document](UPGRADING.md) that describes all BC breaking c
a server does not honor `Connection: close`.
* Ignore URI fragment when sending requests.
## 6.2.0 - 2016-03-21
* Feature: added `GuzzleHttp\json_encode` and `GuzzleHttp\json_decode`.
@@ -297,6 +417,7 @@ Please see [the upgrade document](UPGRADING.md) that describes all BC breaking c
* Bug fix: provide an empty string to `http_build_query` for HHVM workaround.
https://github.com/guzzle/guzzle/pull/1367
## 6.1.1 - 2015-11-22
* Bug fix: Proxy::wrapSync() now correctly proxies to the appropriate handler
@@ -312,6 +433,7 @@ Please see [the upgrade document](UPGRADING.md) that describes all BC breaking c
* Bug fix: fixed regression where MockHandler was not using `sink`.
https://github.com/guzzle/guzzle/pull/1292
## 6.1.0 - 2015-09-08
* Feature: Added the `on_stats` request option to provide access to transfer
@@ -346,6 +468,7 @@ Please see [the upgrade document](UPGRADING.md) that describes all BC breaking c
* Bug fix: Adding a Content-Length to PHP stream wrapper requests if not set.
https://github.com/guzzle/guzzle/pull/1189
## 6.0.2 - 2015-07-04
* Fixed a memory leak in the curl handlers in which references to callbacks
@@ -363,6 +486,7 @@ Please see [the upgrade document](UPGRADING.md) that describes all BC breaking c
* Functions are now conditionally required using an additional level of
indirection to help with global Composer installations.
## 6.0.1 - 2015-05-27
* Fixed a bug with serializing the `query` request option where the `&`
@@ -371,6 +495,7 @@ Please see [the upgrade document](UPGRADING.md) that describes all BC breaking c
use `form_params` or `multipart` instead.
* Various doc fixes.
## 6.0.0 - 2015-05-26
* See the UPGRADING.md document for more information.
@@ -395,6 +520,7 @@ Please see [the upgrade document](UPGRADING.md) that describes all BC breaking c
* `$maxHandles` has been removed from CurlMultiHandler.
* `MultipartPostBody` is now part of the `guzzlehttp/psr7` package.
## 5.3.0 - 2015-05-19
* Mock now supports `save_to`
@@ -405,6 +531,7 @@ Please see [the upgrade document](UPGRADING.md) that describes all BC breaking c
* Marked `GuzzleHttp\Client::getDefaultUserAgent` as deprecated.
* URL scheme is now always lowercased.
## 6.0.0-beta.1
* Requires PHP >= 5.5
@@ -457,6 +584,7 @@ Please see [the upgrade document](UPGRADING.md) that describes all BC breaking c
* `GuzzleHttp\QueryParser` has been replaced with the
`GuzzleHttp\Psr7\parse_query`.
## 5.2.0 - 2015-01-27
* Added `AppliesHeadersInterface` to make applying headers to a request based
@@ -467,6 +595,7 @@ Please see [the upgrade document](UPGRADING.md) that describes all BC breaking c
RingBridge.
* Added a guard in the Pool class to not use recursion for request retries.
## 5.1.0 - 2014-12-19
* Pool class no longer uses recursion when a request is intercepted.
@@ -487,6 +616,7 @@ Please see [the upgrade document](UPGRADING.md) that describes all BC breaking c
* Exceptions thrown in the `end` event are now correctly wrapped with Guzzle
specific exceptions if necessary.
## 5.0.3 - 2014-11-03
This change updates query strings so that they are treated as un-encoded values
@@ -501,6 +631,7 @@ string that should not be parsed or encoded (unless a call to getQuery() is
subsequently made, forcing the query-string to be converted into a Query
object).
## 5.0.2 - 2014-10-30
* Added a trailing `\r\n` to multipart/form-data payloads. See
@@ -520,7 +651,9 @@ object).
* Note: This has been changed in 5.0.3 to now encode query string values by
default unless the `rawString` argument is provided when setting the query
string on a URL: Now allowing many more characters to be present in the
query string without being percent encoded. See https://tools.ietf.org/html/rfc3986#appendix-A
query string without being percent encoded. See
https://datatracker.ietf.org/doc/html/rfc3986#appendix-A
## 5.0.1 - 2014-10-16
@@ -533,6 +666,7 @@ Bugfix release.
* Fixed an issue where transfer statistics were not being populated in the
RingBridge. https://github.com/guzzle/guzzle/issues/866
## 5.0.0 - 2014-10-12
Adding support for non-blocking responses and some minor API cleanup.
@@ -614,6 +748,7 @@ interfaces.
argument. They now accept an associative array of options, including the
"size" key and "metadata" key which can be used to provide custom metadata.
## 4.2.2 - 2014-09-08
* Fixed a memory leak in the CurlAdapter when reusing cURL handles.
@@ -1056,7 +1191,7 @@ interfaces.
## 3.4.0 - 2013-04-11
* Bug fix: URLs are now resolved correctly based on https://tools.ietf.org/html/rfc3986#section-5.2. #289
* Bug fix: URLs are now resolved correctly based on https://datatracker.ietf.org/doc/html/rfc3986#section-5.2. #289
* Bug fix: Absolute URLs with a path in a service description will now properly override the base URL. #289
* Bug fix: Parsing a query string with a single PHP array value will now result in an array. #263
* Bug fix: Better normalization of the User-Agent header to prevent duplicate headers. #264.

View File

@@ -3,7 +3,7 @@
# Guzzle, PHP HTTP client
[![Latest Version](https://img.shields.io/github/release/guzzle/guzzle.svg?style=flat-square)](https://github.com/guzzle/guzzle/releases)
[![Build Status](https://img.shields.io/github/workflow/status/guzzle/guzzle/CI?label=ci%20build&style=flat-square)](https://github.com/guzzle/guzzle/actions?query=workflow%3ACI)
[![Build Status](https://img.shields.io/github/actions/workflow/status/guzzle/guzzle/ci.yml?label=ci%20build&style=flat-square)](https://github.com/guzzle/guzzle/actions?query=workflow%3ACI)
[![Total Downloads](https://img.shields.io/packagist/dt/guzzlehttp/guzzle.svg?style=flat-square)](https://packagist.org/packages/guzzlehttp/guzzle)
Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and
@@ -42,9 +42,9 @@ $promise->wait();
We use GitHub issues only to discuss bugs and new features. For support please refer to:
- [Documentation](http://guzzlephp.org/)
- [Stack Overflow](http://stackoverflow.com/questions/tagged/guzzle)
- [#guzzle](https://app.slack.com/client/T0D2S9JCT/CE6UAAKL4) channel on [PHP-HTTP Slack](http://slack.httplug.io/)
- [Documentation](https://docs.guzzlephp.org)
- [Stack Overflow](https://stackoverflow.com/questions/tagged/guzzle)
- [#guzzle](https://app.slack.com/client/T0D2S9JCT/CE6UAAKL4) channel on [PHP-HTTP Slack](https://slack.httplug.io/)
- [Gitter](https://gitter.im/guzzle/guzzle)
@@ -60,23 +60,23 @@ composer require guzzlehttp/guzzle
## Version Guidance
| Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 | PHP Version |
|---------|------------|---------------------|--------------|---------------------|---------------------|-------|-------------|
| 3.x | EOL | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No | >= 5.3.3 |
| 4.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A | No | >= 5.4 |
| 5.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No | >= 5.4 |
| 6.x | Security fixes | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes | >= 5.5 |
| 7.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v7][guzzle-7-repo] | [v7][guzzle-7-docs] | Yes | >= 7.2 |
| Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 | PHP Version |
|---------|---------------------|---------------------|--------------|---------------------|---------------------|-------|--------------|
| 3.x | EOL | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No | >=5.3.3,<7.0 |
| 4.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A | No | >=5.4,<7.0 |
| 5.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No | >=5.4,<7.4 |
| 6.x | Security fixes only | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes | >=5.5,<8.0 |
| 7.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v7][guzzle-7-repo] | [v7][guzzle-7-docs] | Yes | >=7.2.5,<8.4 |
[guzzle-3-repo]: https://github.com/guzzle/guzzle3
[guzzle-4-repo]: https://github.com/guzzle/guzzle/tree/4.x
[guzzle-5-repo]: https://github.com/guzzle/guzzle/tree/5.3
[guzzle-6-repo]: https://github.com/guzzle/guzzle/tree/6.5
[guzzle-7-repo]: https://github.com/guzzle/guzzle
[guzzle-3-docs]: http://guzzle3.readthedocs.org
[guzzle-5-docs]: http://docs.guzzlephp.org/en/5.3/
[guzzle-6-docs]: http://docs.guzzlephp.org/en/6.5/
[guzzle-7-docs]: http://docs.guzzlephp.org/en/latest/
[guzzle-3-docs]: https://guzzle3.readthedocs.io/
[guzzle-5-docs]: https://docs.guzzlephp.org/en/5.3/
[guzzle-6-docs]: https://docs.guzzlephp.org/en/6.5/
[guzzle-7-docs]: https://docs.guzzlephp.org/en/latest/
## Security

View File

@@ -27,7 +27,7 @@ Please make sure:
- Function `GuzzleHttp\Exception\RequestException::getResponseBodySummary` is removed.
Use `\GuzzleHttp\Psr7\get_message_body_summary` as an alternative.
- Function `GuzzleHttp\Cookie\CookieJar::getCookieValue` is removed.
- Request option `exception` is removed. Please use `http_errors`.
- Request option `exceptions` is removed. Please use `http_errors`.
- Request option `save_to` is removed. Please use `sink`.
- Pool option `pool_size` is removed. Please use `concurrency`.
- We now look for environment variables in the `$_SERVER` super global, due to thread safety issues with `getenv`. We continue to fallback to `getenv` in CLI environments, for maximum compatibility.
@@ -189,11 +189,11 @@ $client = new GuzzleHttp\Client(['handler' => $handler]);
## POST Requests
This version added the [`form_params`](http://guzzle.readthedocs.org/en/latest/request-options.html#form_params)
This version added the [`form_params`](https://docs.guzzlephp.org/en/latest/request-options.html#form_params)
and `multipart` request options. `form_params` is an associative array of
strings or array of strings and is used to serialize an
`application/x-www-form-urlencoded` POST request. The
[`multipart`](http://guzzle.readthedocs.org/en/latest/request-options.html#multipart)
[`multipart`](https://docs.guzzlephp.org/en/latest/request-options.html#multipart)
option is now used to send a multipart/form-data POST request.
`GuzzleHttp\Post\PostFile` has been removed. Use the `multipart` option to add
@@ -209,7 +209,7 @@ The `base_url` option has been renamed to `base_uri`.
## Rewritten Adapter Layer
Guzzle now uses [RingPHP](http://ringphp.readthedocs.org/en/latest) to send
Guzzle now uses [RingPHP](https://ringphp.readthedocs.org/en/latest) to send
HTTP requests. The `adapter` option in a `GuzzleHttp\Client` constructor
is still supported, but it has now been renamed to `handler`. Instead of
passing a `GuzzleHttp\Adapter\AdapterInterface`, you must now pass a PHP
@@ -575,7 +575,7 @@ You can intercept a request and inject a response using the `intercept()` event
of a `GuzzleHttp\Event\BeforeEvent`, `GuzzleHttp\Event\CompleteEvent`, and
`GuzzleHttp\Event\ErrorEvent` event.
See: http://docs.guzzlephp.org/en/latest/events.html
See: https://docs.guzzlephp.org/en/latest/events.html
## Inflection
@@ -668,9 +668,9 @@ in separate repositories:
The service description layer of Guzzle has moved into two separate packages:
- http://github.com/guzzle/command Provides a high level abstraction over web
- https://github.com/guzzle/command Provides a high level abstraction over web
services by representing web service operations using commands.
- http://github.com/guzzle/guzzle-services Provides an implementation of
- https://github.com/guzzle/guzzle-services Provides an implementation of
guzzle/command that provides request serialization and response parsing using
Guzzle service descriptions.
@@ -870,7 +870,7 @@ HeaderInterface (e.g. toArray(), getAll(), etc.).
3.3 to 3.4
----------
Base URLs of a client now follow the rules of https://tools.ietf.org/html/rfc3986#section-5.2.2 when merging URLs.
Base URLs of a client now follow the rules of https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.2 when merging URLs.
3.2 to 3.3
----------

View File

@@ -53,8 +53,8 @@
"require": {
"php": "^7.2.5 || ^8.0",
"ext-json": "*",
"guzzlehttp/promises": "^1.5",
"guzzlehttp/psr7": "^1.8.3 || ^2.1",
"guzzlehttp/promises": "^1.5.3 || ^2.0.1",
"guzzlehttp/psr7": "^1.9.1 || ^2.5.1",
"psr/http-client": "^1.0",
"symfony/deprecation-contracts": "^2.2 || ^3.0"
},
@@ -63,9 +63,10 @@
},
"require-dev": {
"ext-curl": "*",
"bamarni/composer-bin-plugin": "^1.4.1",
"php-http/client-integration-tests": "^3.0",
"phpunit/phpunit": "^8.5.5 || ^9.3.5",
"bamarni/composer-bin-plugin": "^1.8.2",
"php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999",
"php-http/message-factory": "^1.1",
"phpunit/phpunit": "^8.5.36 || ^9.6.15",
"psr/log": "^1.1 || ^2.0 || ^3.0"
},
"suggest": {
@@ -81,8 +82,9 @@
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-master": "7.4-dev"
"bamarni-bin": {
"bin-links": true,
"forward-command": false
}
},
"autoload": {

View File

@@ -120,13 +120,14 @@ class Client implements ClientInterface, \Psr\Http\Client\ClientInterface
public function send(RequestInterface $request, array $options = []): ResponseInterface
{
$options[RequestOptions::SYNCHRONOUS] = true;
return $this->sendAsync($request, $options)->wait();
}
/**
* The HttpClient PSR (PSR-18) specify this method.
*
* @inheritDoc
* {@inheritDoc}
*/
public function sendRequest(RequestInterface $request): ResponseInterface
{
@@ -184,6 +185,7 @@ class Client implements ClientInterface, \Psr\Http\Client\ClientInterface
public function request(string $method, $uri = '', array $options = []): ResponseInterface
{
$options[RequestOptions::SYNCHRONOUS] = true;
return $this->requestAsync($method, $uri, $options)->wait();
}
@@ -200,7 +202,7 @@ class Client implements ClientInterface, \Psr\Http\Client\ClientInterface
*
* @deprecated Client::getConfig will be removed in guzzlehttp/guzzle:8.0.
*/
public function getConfig(?string $option = null)
public function getConfig(string $option = null)
{
return $option === null
? $this->config
@@ -228,11 +230,11 @@ class Client implements ClientInterface, \Psr\Http\Client\ClientInterface
{
$defaults = [
'allow_redirects' => RedirectMiddleware::$defaultSettings,
'http_errors' => true,
'decode_content' => true,
'verify' => true,
'cookies' => false,
'idn_conversion' => false,
'http_errors' => true,
'decode_content' => true,
'verify' => true,
'cookies' => false,
'idn_conversion' => false,
];
// Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
@@ -354,10 +356,10 @@ class Client implements ClientInterface, \Psr\Http\Client\ClientInterface
if (isset($options['form_params'])) {
if (isset($options['multipart'])) {
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.');
.'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.');
}
$options['body'] = \http_build_query($options['form_params'], '', '&');
unset($options['form_params']);
@@ -403,7 +405,7 @@ class Client implements ClientInterface, \Psr\Http\Client\ClientInterface
// Ensure that we don't have the header in different case and set the new value.
$modify['set_headers'] = Psr7\Utils::caselessRemove(['Authorization'], $modify['set_headers']);
$modify['set_headers']['Authorization'] = 'Basic '
. \base64_encode("$value[0]:$value[1]");
.\base64_encode("$value[0]:$value[1]");
break;
case 'digest':
// @todo: Do not rely on curl
@@ -437,13 +439,17 @@ class Client implements ClientInterface, \Psr\Http\Client\ClientInterface
}
}
if (isset($options['version'])) {
$modify['version'] = $options['version'];
}
$request = Psr7\Utils::modifyRequest($request, $modify);
if ($request->getBody() instanceof Psr7\MultipartStream) {
// Use a multipart/form-data POST if a Content-Type is not set.
// Ensure that we don't have the header in different case and set the new value.
$options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']);
$options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
. $request->getBody()->getBoundary();
.$request->getBody()->getBoundary();
}
// Merge in conditional headers if they are not present.
@@ -469,9 +475,9 @@ class Client implements ClientInterface, \Psr\Http\Client\ClientInterface
private function invalidBody(): InvalidArgumentException
{
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.');
.'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.');
}
}

View File

@@ -80,5 +80,5 @@ interface ClientInterface
*
* @deprecated ClientInterface::getConfig will be removed in guzzlehttp/guzzle:8.0.
*/
public function getConfig(?string $option = null);
public function getConfig(string $option = null);
}

View File

@@ -50,10 +50,10 @@ class CookieJar implements CookieJarInterface
$cookieJar = new self();
foreach ($cookies as $name => $value) {
$cookieJar->setCookie(new SetCookie([
'Domain' => $domain,
'Name' => $name,
'Value' => $value,
'Discard' => true
'Domain' => $domain,
'Name' => $name,
'Value' => $value,
'Discard' => true,
]));
}
@@ -96,9 +96,6 @@ class CookieJar implements CookieJarInterface
return null;
}
/**
* @inheritDoc
*/
public function toArray(): array
{
return \array_map(static function (SetCookie $cookie): array {
@@ -106,13 +103,11 @@ class CookieJar implements CookieJarInterface
}, $this->getIterator()->getArrayCopy());
}
/**
* @inheritDoc
*/
public function clear(?string $domain = null, ?string $path = null, ?string $name = null): void
public function clear(string $domain = null, string $path = null, string $name = null): void
{
if (!$domain) {
$this->cookies = [];
return;
} elseif (!$path) {
$this->cookies = \array_filter(
@@ -125,25 +120,22 @@ class CookieJar implements CookieJarInterface
$this->cookies = \array_filter(
$this->cookies,
static function (SetCookie $cookie) use ($path, $domain): bool {
return !($cookie->matchesPath($path) &&
$cookie->matchesDomain($domain));
return !($cookie->matchesPath($path)
&& $cookie->matchesDomain($domain));
}
);
} else {
$this->cookies = \array_filter(
$this->cookies,
static function (SetCookie $cookie) use ($path, $domain, $name) {
return !($cookie->getName() == $name &&
$cookie->matchesPath($path) &&
$cookie->matchesDomain($domain));
return !($cookie->getName() == $name
&& $cookie->matchesPath($path)
&& $cookie->matchesDomain($domain));
}
);
}
}
/**
* @inheritDoc
*/
public function clearSessionCookies(): void
{
$this->cookies = \array_filter(
@@ -154,9 +146,6 @@ class CookieJar implements CookieJarInterface
);
}
/**
* @inheritDoc
*/
public function setCookie(SetCookie $cookie): bool
{
// If the name string is empty (but not 0), ignore the set-cookie
@@ -170,20 +159,20 @@ class CookieJar implements CookieJarInterface
$result = $cookie->validate();
if ($result !== true) {
if ($this->strictMode) {
throw new \RuntimeException('Invalid cookie: ' . $result);
throw new \RuntimeException('Invalid cookie: '.$result);
}
$this->removeCookieIfEmpty($cookie);
return false;
}
// Resolve conflicts with previously set cookies
foreach ($this->cookies as $i => $c) {
// Two cookies are identical, when their path, and domain are
// identical.
if ($c->getPath() != $cookie->getPath() ||
$c->getDomain() != $cookie->getDomain() ||
$c->getName() != $cookie->getName()
if ($c->getPath() != $cookie->getPath()
|| $c->getDomain() != $cookie->getDomain()
|| $c->getName() != $cookie->getName()
) {
continue;
}
@@ -241,6 +230,11 @@ class CookieJar implements CookieJarInterface
if (0 !== \strpos($sc->getPath(), '/')) {
$sc->setPath($this->getCookiePathFromRequest($request));
}
if (!$sc->matchesDomain($request->getUri()->getHost())) {
continue;
}
// Note: At this point `$sc->getDomain()` being a public suffix should
// be rejected, but we don't want to pull in the full PSL dependency.
$this->setCookie($sc);
}
}
@@ -249,7 +243,7 @@ class CookieJar implements CookieJarInterface
/**
* Computes cookie path following RFC 6265 section 5.1.4
*
* @link https://tools.ietf.org/html/rfc6265#section-5.1.4
* @see https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.4
*/
private function getCookiePathFromRequest(RequestInterface $request): string
{
@@ -280,13 +274,13 @@ class CookieJar implements CookieJarInterface
$path = $uri->getPath() ?: '/';
foreach ($this->cookies as $cookie) {
if ($cookie->matchesPath($path) &&
$cookie->matchesDomain($host) &&
!$cookie->isExpired() &&
(!$cookie->getSecure() || $scheme === 'https')
if ($cookie->matchesPath($path)
&& $cookie->matchesDomain($host)
&& !$cookie->isExpired()
&& (!$cookie->getSecure() || $scheme === 'https')
) {
$values[] = $cookie->getName() . '='
. $cookie->getValue();
$values[] = $cookie->getName().'='
.$cookie->getValue();
}
}

View File

@@ -13,7 +13,8 @@ use Psr\Http\Message\ResponseInterface;
* necessary. Subclasses are also responsible for storing and retrieving
* cookies from a file, database, etc.
*
* @link https://docs.python.org/2/library/cookielib.html Inspiration
* @see https://docs.python.org/2/library/cookielib.html Inspiration
*
* @extends \IteratorAggregate<SetCookie>
*/
interface CookieJarInterface extends \Countable, \IteratorAggregate
@@ -61,7 +62,7 @@ interface CookieJarInterface extends \Countable, \IteratorAggregate
* @param string|null $path Clears cookies matching a domain and path
* @param string|null $name Clears cookies matching a domain, path, and name
*/
public function clear(?string $domain = null, ?string $path = null, ?string $name = null): void;
public function clear(string $domain = null, string $path = null, string $name = null): void;
/**
* Discard all sessions cookies.

View File

@@ -71,7 +71,7 @@ class SessionCookieJar extends CookieJar
$this->setCookie(new SetCookie($cookie));
}
} elseif (\strlen($data)) {
throw new \RuntimeException("Invalid cookie data");
throw new \RuntimeException('Invalid cookie data');
}
}
}

View File

@@ -11,15 +11,15 @@ class SetCookie
* @var array
*/
private static $defaults = [
'Name' => null,
'Value' => null,
'Domain' => null,
'Path' => '/',
'Max-Age' => null,
'Expires' => null,
'Secure' => false,
'Discard' => false,
'HttpOnly' => false
'Name' => null,
'Value' => null,
'Domain' => null,
'Path' => '/',
'Max-Age' => null,
'Expires' => null,
'Secure' => false,
'Discard' => false,
'HttpOnly' => false,
];
/**
@@ -58,7 +58,13 @@ class SetCookie
} else {
foreach (\array_keys(self::$defaults) as $search) {
if (!\strcasecmp($search, $key)) {
$data[$search] = $value;
if ($search === 'Max-Age') {
if (is_numeric($value)) {
$data[$search] = (int) $value;
}
} else {
$data[$search] = $value;
}
continue 2;
}
}
@@ -74,13 +80,49 @@ class SetCookie
*/
public function __construct(array $data = [])
{
/** @var array|null $replaced will be null in case of replace error */
$replaced = \array_replace(self::$defaults, $data);
if ($replaced === null) {
throw new \InvalidArgumentException('Unable to replace the default values for the Cookie.');
$this->data = self::$defaults;
if (isset($data['Name'])) {
$this->setName($data['Name']);
}
if (isset($data['Value'])) {
$this->setValue($data['Value']);
}
if (isset($data['Domain'])) {
$this->setDomain($data['Domain']);
}
if (isset($data['Path'])) {
$this->setPath($data['Path']);
}
if (isset($data['Max-Age'])) {
$this->setMaxAge($data['Max-Age']);
}
if (isset($data['Expires'])) {
$this->setExpires($data['Expires']);
}
if (isset($data['Secure'])) {
$this->setSecure($data['Secure']);
}
if (isset($data['Discard'])) {
$this->setDiscard($data['Discard']);
}
if (isset($data['HttpOnly'])) {
$this->setHttpOnly($data['HttpOnly']);
}
// Set the remaining values that don't have extra validation logic
foreach (array_diff(array_keys($data), array_keys(self::$defaults)) as $key) {
$this->data[$key] = $data[$key];
}
$this->data = $replaced;
// Extract the Expires value and turn it into a UNIX timestamp if needed
if (!$this->getExpires() && $this->getMaxAge()) {
// Calculate the Expires date
@@ -92,13 +134,13 @@ class SetCookie
public function __toString()
{
$str = $this->data['Name'] . '=' . ($this->data['Value'] ?? '') . '; ';
$str = $this->data['Name'].'='.($this->data['Value'] ?? '').'; ';
foreach ($this->data as $k => $v) {
if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== false) {
if ($k === 'Expires') {
$str .= 'Expires=' . \gmdate('D, d M Y H:i:s \G\M\T', $v) . '; ';
$str .= 'Expires='.\gmdate('D, d M Y H:i:s \G\M\T', $v).'; ';
} else {
$str .= ($v === true ? $k : "{$k}={$v}") . '; ';
$str .= ($v === true ? $k : "{$k}={$v}").'; ';
}
}
}
@@ -378,21 +420,23 @@ class SetCookie
}
// Remove the leading '.' as per spec in RFC 6265.
// https://tools.ietf.org/html/rfc6265#section-5.2.3
$cookieDomain = \ltrim($cookieDomain, '.');
// https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.3
$cookieDomain = \ltrim(\strtolower($cookieDomain), '.');
$domain = \strtolower($domain);
// Domain not set or exact match.
if (!$cookieDomain || !\strcasecmp($domain, $cookieDomain)) {
if ('' === $cookieDomain || $domain === $cookieDomain) {
return true;
}
// Matching the subdomain according to RFC 6265.
// https://tools.ietf.org/html/rfc6265#section-5.1.3
// https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.3
if (\filter_var($domain, \FILTER_VALIDATE_IP)) {
return false;
}
return (bool) \preg_match('/\.' . \preg_quote($cookieDomain, '/') . '$/', $domain);
return (bool) \preg_match('/\.'.\preg_quote($cookieDomain, '/').'$/', $domain);
}
/**
@@ -421,8 +465,8 @@ class SetCookie
$name
)) {
return 'Cookie name must not contain invalid characters: ASCII '
. 'Control characters (0-31;127), space, tab and the '
. 'following characters: ()<>@,;:\"/?={}';
.'Control characters (0-31;127), space, tab and the '
.'following characters: ()<>@,;:\"/?={}';
}
// Value must not be null. 0 and empty string are valid. Empty strings

View File

@@ -51,7 +51,7 @@ class CurlFactory implements CurlFactoryInterface
unset($options['curl']['body_as_string']);
}
$easy = new EasyHandle;
$easy = new EasyHandle();
$easy->request = $request;
$easy->options = $options;
$conf = $this->getDefaultConf($easy);
@@ -161,11 +161,11 @@ class CurlFactory implements CurlFactoryInterface
private static function createRejection(EasyHandle $easy, array $ctx): PromiseInterface
{
static $connectionErrors = [
\CURLE_OPERATION_TIMEOUTED => true,
\CURLE_OPERATION_TIMEOUTED => true,
\CURLE_COULDNT_RESOLVE_HOST => true,
\CURLE_COULDNT_CONNECT => true,
\CURLE_SSL_CONNECT_ERROR => true,
\CURLE_GOT_NOTHING => true,
\CURLE_COULDNT_CONNECT => true,
\CURLE_SSL_CONNECT_ERROR => true,
\CURLE_GOT_NOTHING => true,
];
if ($easy->createResponseException) {
@@ -219,12 +219,12 @@ class CurlFactory implements CurlFactoryInterface
private function getDefaultConf(EasyHandle $easy): array
{
$conf = [
'_headers' => $easy->request->getHeaders(),
\CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(),
\CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''),
'_headers' => $easy->request->getHeaders(),
\CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(),
\CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''),
\CURLOPT_RETURNTRANSFER => false,
\CURLOPT_HEADER => false,
\CURLOPT_CONNECTTIMEOUT => 150,
\CURLOPT_HEADER => false,
\CURLOPT_CONNECTTIMEOUT => 300,
];
if (\defined('CURLOPT_PROTOCOLS')) {
@@ -250,12 +250,13 @@ class CurlFactory implements CurlFactoryInterface
if ($size === null || $size > 0) {
$this->applyBody($easy->request, $easy->options, $conf);
return;
}
$method = $easy->request->getMethod();
if ($method === 'PUT' || $method === 'POST') {
// See https://tools.ietf.org/html/rfc7230#section-3.3.2
// See https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2
if (!$easy->request->hasHeader('Content-Length')) {
$conf[\CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
}
@@ -341,6 +342,7 @@ class CurlFactory implements CurlFactoryInterface
foreach (\array_keys($options['_headers']) as $key) {
if (!\strcasecmp($key, $name)) {
unset($options['_headers'][$key]);
return;
}
}
@@ -365,11 +367,11 @@ class CurlFactory implements CurlFactoryInterface
// If it's a directory or a link to a directory use CURLOPT_CAPATH.
// If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO.
if (
\is_dir($options['verify']) ||
(
\is_link($options['verify']) === true &&
($verifyLink = \readlink($options['verify'])) !== false &&
\is_dir($verifyLink)
\is_dir($options['verify'])
|| (
\is_link($options['verify']) === true
&& ($verifyLink = \readlink($options['verify'])) !== false
&& \is_dir($verifyLink)
)
) {
$conf[\CURLOPT_CAPATH] = $options['verify'];
@@ -443,13 +445,41 @@ class CurlFactory implements CurlFactoryInterface
$scheme = $easy->request->getUri()->getScheme();
if (isset($options['proxy'][$scheme])) {
$host = $easy->request->getUri()->getHost();
if (!isset($options['proxy']['no']) || !Utils::isHostInNoProxy($host, $options['proxy']['no'])) {
if (isset($options['proxy']['no']) && Utils::isHostInNoProxy($host, $options['proxy']['no'])) {
unset($conf[\CURLOPT_PROXY]);
} else {
$conf[\CURLOPT_PROXY] = $options['proxy'][$scheme];
}
}
}
}
if (isset($options['crypto_method'])) {
if (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method']) {
if (!defined('CURL_SSLVERSION_TLSv1_0')) {
throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.0 not supported by your version of cURL');
}
$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_0;
} elseif (\STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method']) {
if (!defined('CURL_SSLVERSION_TLSv1_1')) {
throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.1 not supported by your version of cURL');
}
$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_1;
} elseif (\STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']) {
if (!defined('CURL_SSLVERSION_TLSv1_2')) {
throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.2 not supported by your version of cURL');
}
$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_2;
} elseif (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $options['crypto_method']) {
if (!defined('CURL_SSLVERSION_TLSv1_3')) {
throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL');
}
$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_3;
} else {
throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided');
}
}
if (isset($options['cert'])) {
$cert = $options['cert'];
if (\is_array($cert)) {
@@ -459,8 +489,8 @@ class CurlFactory implements CurlFactoryInterface
if (!\file_exists($cert)) {
throw new \InvalidArgumentException("SSL certificate not found: {$cert}");
}
# OpenSSL (versions 0.9.3 and later) also support "P12" for PKCS#12-encoded files.
# see https://curl.se/libcurl/c/CURLOPT_SSLCERTTYPE.html
// OpenSSL (versions 0.9.3 and later) also support "P12" for PKCS#12-encoded files.
// see https://curl.se/libcurl/c/CURLOPT_SSLCERTTYPE.html
$ext = pathinfo($cert, \PATHINFO_EXTENSION);
if (preg_match('#^(der|p12)$#i', $ext)) {
$conf[\CURLOPT_SSLCERTTYPE] = strtoupper($ext);
@@ -523,9 +553,10 @@ class CurlFactory implements CurlFactoryInterface
}
} catch (\RuntimeException $e) {
$ctx['error'] = 'The connection unexpectedly failed without '
. 'providing an error. The request would have been retried, '
. 'but attempting to rewind the request body failed. '
. 'Exception: ' . $e;
.'providing an error. The request would have been retried, '
.'but attempting to rewind the request body failed. '
.'Exception: '.$e;
return self::createRejection($easy, $ctx);
}
@@ -534,14 +565,15 @@ class CurlFactory implements CurlFactoryInterface
$easy->options['_curl_retries'] = 1;
} elseif ($easy->options['_curl_retries'] == 2) {
$ctx['error'] = 'The cURL request was retried 3 times '
. 'and did not succeed. The most likely reason for the failure '
. 'is that cURL was unable to rewind the body of the request '
. 'and subsequent retries resulted in the same error. Turn on '
. 'the debug option to see what went wrong. See '
. 'https://bugs.php.net/bug.php?id=47204 for more information.';
.'and did not succeed. The most likely reason for the failure '
.'is that cURL was unable to rewind the body of the request '
.'and subsequent retries resulted in the same error. Turn on '
.'the debug option to see what went wrong. See '
.'https://bugs.php.net/bug.php?id=47204 for more information.';
return self::createRejection($easy, $ctx);
} else {
$easy->options['_curl_retries']++;
++$easy->options['_curl_retries'];
}
return $handler($easy->request, $easy->options);
@@ -571,6 +603,7 @@ class CurlFactory implements CurlFactoryInterface
$easy->createResponse();
} catch (\Exception $e) {
$easy->createResponseException = $e;
return -1;
}
if ($onHeaders !== null) {
@@ -580,6 +613,7 @@ class CurlFactory implements CurlFactoryInterface
// Associate the exception with the handle and trigger
// a curl header write error by returning 0.
$easy->onHeadersException = $e;
return -1;
}
}
@@ -589,7 +623,16 @@ class CurlFactory implements CurlFactoryInterface
} else {
$easy->headers[] = $value;
}
return \strlen($h);
};
}
public function __destruct()
{
foreach ($this->handles as $id => $handle) {
\curl_close($handle);
unset($this->handles[$id]);
}
}
}

View File

@@ -15,8 +15,6 @@ use Psr\Http\Message\RequestInterface;
* associative array of curl option constants mapping to values in the
* **curl** key of the provided request options.
*
* @property resource|\CurlMultiHandle $_mh Internal use only. Lazy loaded multi-handle.
*
* @final
*/
class CurlMultiHandler
@@ -55,6 +53,9 @@ class CurlMultiHandler
*/
private $options = [];
/** @var resource|\CurlMultiHandle */
private $_mh;
/**
* This handler accepts the following options:
*
@@ -78,6 +79,10 @@ class CurlMultiHandler
}
$this->options = $options['options'] ?? [];
// unsetting the property forces the first access to go through
// __get().
unset($this->_mh);
}
/**
@@ -163,7 +168,8 @@ class CurlMultiHandler
\usleep(250);
}
while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM);
while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) {
}
$this->processMessages();
}

View File

@@ -106,7 +106,7 @@ final class EasyHandle
*/
public function __get($name)
{
$msg = $name === 'handle' ? 'The EasyHandle has been released' : 'Invalid property: ' . $name;
$msg = $name === 'handle' ? 'The EasyHandle has been released' : 'Invalid property: '.$name;
throw new \BadMethodCallException($msg);
}
}

View File

@@ -14,9 +14,9 @@ final class HeaderProcessor
*
* @param string[] $headers
*
* @throws \RuntimeException
*
* @return array{0:string, 1:int, 2:?string, 3:array}
*
* @throws \RuntimeException
*/
public static function parseHeaders(array $headers): array
{

View File

@@ -138,6 +138,7 @@ class MockHandler implements \Countable
if ($this->onRejected) {
($this->onRejected)($reason);
}
return P\Create::rejectionFor($reason);
}
);
@@ -159,7 +160,7 @@ class MockHandler implements \Countable
) {
$this->queue[] = $value;
} else {
throw new \TypeError('Expected a Response, Promise, Throwable or callable. Found ' . Utils::describeType($value));
throw new \TypeError('Expected a Response, Promise, Throwable or callable. Found '.Utils::describeType($value));
}
}
}

View File

@@ -67,7 +67,7 @@ class StreamHandler
if (false !== \strpos($message, 'getaddrinfo') // DNS lookup failed
|| false !== \strpos($message, 'Connection refused')
|| false !== \strpos($message, "couldn't connect to host") // error on HHVM
|| false !== \strpos($message, "connection attempt failed")
|| false !== \strpos($message, 'connection attempt failed')
) {
$e = new ConnectException($e->getMessage(), $request, $e);
} else {
@@ -231,9 +231,10 @@ class StreamHandler
\set_error_handler(static function ($_, $msg, $file, $line) use (&$errors): bool {
$errors[] = [
'message' => $msg,
'file' => $file,
'line' => $line
'file' => $file,
'line' => $line,
];
return true;
});
@@ -247,7 +248,7 @@ class StreamHandler
$message = 'Error creating resource: ';
foreach ($errors as $err) {
foreach ($err as $key => $value) {
$message .= "[$key] $value" . \PHP_EOL;
$message .= "[$key] $value".\PHP_EOL;
}
}
throw new \RuntimeException(\trim($message));
@@ -350,6 +351,7 @@ class StreamHandler
if (false === $records || !isset($records[0]['ip'])) {
throw new ConnectException(\sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request);
}
return $uri->withHost($records[0]['ip']);
}
if ('v6' === $options['force_ip_resolve']) {
@@ -357,7 +359,8 @@ class StreamHandler
if (false === $records || !isset($records[0]['ipv6'])) {
throw new ConnectException(\sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request);
}
return $uri->withHost('[' . $records[0]['ipv6'] . ']');
return $uri->withHost('['.$records[0]['ipv6'].']');
}
}
@@ -375,11 +378,11 @@ class StreamHandler
$context = [
'http' => [
'method' => $request->getMethod(),
'header' => $headers,
'method' => $request->getMethod(),
'header' => $headers,
'protocol_version' => $request->getProtocolVersion(),
'ignore_errors' => true,
'follow_location' => 0,
'ignore_errors' => true,
'follow_location' => 0,
],
'ssl' => [
'peer_name' => $request->getUri()->getHost(),
@@ -388,7 +391,7 @@ class StreamHandler
$body = (string) $request->getBody();
if (!empty($body)) {
if ('' !== $body) {
$context['http']['content'] = $body;
// Prevent the HTTP handler from adding a Content-Type header.
if (!$request->hasHeader('Content-Type')) {
@@ -472,6 +475,25 @@ class StreamHandler
}
}
/**
* @param mixed $value as passed via Request transfer options.
*/
private function add_crypto_method(RequestInterface $request, array &$options, $value, array &$params): void
{
if (
$value === \STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT
|| $value === \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT
|| $value === \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
|| (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && $value === \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT)
) {
$options['http']['crypto_method'] = $value;
return;
}
throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided');
}
/**
* @param mixed $value as passed via Request transfer options.
*/
@@ -542,27 +564,27 @@ class StreamHandler
}
static $map = [
\STREAM_NOTIFY_CONNECT => 'CONNECT',
\STREAM_NOTIFY_CONNECT => 'CONNECT',
\STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED',
\STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT',
\STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS',
\STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS',
\STREAM_NOTIFY_REDIRECTED => 'REDIRECTED',
\STREAM_NOTIFY_PROGRESS => 'PROGRESS',
\STREAM_NOTIFY_FAILURE => 'FAILURE',
\STREAM_NOTIFY_COMPLETED => 'COMPLETED',
\STREAM_NOTIFY_RESOLVE => 'RESOLVE',
\STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT',
\STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS',
\STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS',
\STREAM_NOTIFY_REDIRECTED => 'REDIRECTED',
\STREAM_NOTIFY_PROGRESS => 'PROGRESS',
\STREAM_NOTIFY_FAILURE => 'FAILURE',
\STREAM_NOTIFY_COMPLETED => 'COMPLETED',
\STREAM_NOTIFY_RESOLVE => 'RESOLVE',
];
static $args = ['severity', 'message', 'message_code', 'bytes_transferred', 'bytes_max'];
$value = Utils::debugResource($value);
$ident = $request->getMethod() . ' ' . $request->getUri()->withFragment('');
$ident = $request->getMethod().' '.$request->getUri()->withFragment('');
self::addNotification(
$params,
static function (int $code, ...$passed) use ($ident, $value, $map, $args): void {
\fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
foreach (\array_filter($passed) as $i => $v) {
\fwrite($value, $args[$i] . ': "' . $v . '" ');
\fwrite($value, $args[$i].': "'.$v.'" ');
}
\fwrite($value, "\n");
}
@@ -577,7 +599,7 @@ class StreamHandler
} else {
$params['notification'] = self::callArray([
$params['notification'],
$notify
$notify,
]);
}
}

View File

@@ -44,7 +44,7 @@ class HandlerStack
* handler is provided, the best handler for your
* system will be utilized.
*/
public static function create(?callable $handler = null): self
public static function create(callable $handler = null): self
{
$stack = new self($handler ?: Utils::chooseHandler());
$stack->push(Middleware::httpErrors(), 'http_errors');
@@ -86,14 +86,14 @@ class HandlerStack
$stack = [];
if ($this->handler !== null) {
$stack[] = "0) Handler: " . $this->debugCallable($this->handler);
$stack[] = '0) Handler: '.$this->debugCallable($this->handler);
}
$result = '';
foreach (\array_reverse($this->stack) as $tuple) {
$depth++;
++$depth;
$str = "{$depth}) Name: '{$tuple[1]}', ";
$str .= "Function: " . $this->debugCallable($tuple[0]);
$str .= 'Function: '.$this->debugCallable($tuple[0]);
$result = "> {$str}\n{$result}";
$stack[] = $str;
}
@@ -122,7 +122,7 @@ class HandlerStack
*/
public function hasHandler(): bool
{
return $this->handler !== null ;
return $this->handler !== null;
}
/**
@@ -131,7 +131,7 @@ class HandlerStack
* @param callable(callable): callable $middleware Middleware function
* @param string $name Name to register for this middleware.
*/
public function unshift(callable $middleware, ?string $name = null): void
public function unshift(callable $middleware, string $name = null): void
{
\array_unshift($this->stack, [$middleware, $name]);
$this->cached = null;
@@ -266,10 +266,10 @@ class HandlerStack
if (\is_array($fn)) {
return \is_string($fn[0])
? "callable({$fn[0]}::{$fn[1]})"
: "callable(['" . \get_class($fn[0]) . "', '{$fn[1]}'])";
: "callable(['".\get_class($fn[0])."', '{$fn[1]}'])";
}
/** @var object $fn */
return 'callable(' . \spl_object_hash($fn) . ')';
return 'callable('.\spl_object_hash($fn).')';
}
}

View File

@@ -40,11 +40,11 @@ class MessageFormatter implements MessageFormatterInterface
/**
* Apache Common Log Format.
*
* @link https://httpd.apache.org/docs/2.4/logs.html#common
* @see https://httpd.apache.org/docs/2.4/logs.html#common
*
* @var string
*/
public const CLF = "{hostname} {req_header_User-Agent} - [{date_common_log}] \"{method} {target} HTTP/{version}\" {code} {res_header_Content-Length}";
public const CLF = '{hostname} {req_header_User-Agent} - [{date_common_log}] "{method} {target} HTTP/{version}" {code} {res_header_Content-Length}';
public const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
public const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
@@ -68,7 +68,7 @@ class MessageFormatter implements MessageFormatterInterface
* @param ResponseInterface|null $response Response that was received
* @param \Throwable|null $error Exception that was received
*/
public function format(RequestInterface $request, ?ResponseInterface $response = null, ?\Throwable $error = null): string
public function format(RequestInterface $request, ResponseInterface $response = null, \Throwable $error = null): string
{
$cache = [];
@@ -90,9 +90,9 @@ class MessageFormatter implements MessageFormatterInterface
break;
case 'req_headers':
$result = \trim($request->getMethod()
. ' ' . $request->getRequestTarget())
. ' HTTP/' . $request->getProtocolVersion() . "\r\n"
. $this->headers($request);
.' '.$request->getRequestTarget())
.' HTTP/'.$request->getProtocolVersion()."\r\n"
.$this->headers($request);
break;
case 'res_headers':
$result = $response ?
@@ -101,7 +101,7 @@ class MessageFormatter implements MessageFormatterInterface
$response->getProtocolVersion(),
$response->getStatusCode(),
$response->getReasonPhrase()
) . "\r\n" . $this->headers($response)
)."\r\n".$this->headers($response)
: 'NULL';
break;
case 'req_body':
@@ -177,6 +177,7 @@ class MessageFormatter implements MessageFormatterInterface
}
$cache[$matches[1]] = $result;
return $result;
},
$this->template
@@ -190,7 +191,7 @@ class MessageFormatter implements MessageFormatterInterface
{
$result = '';
foreach ($message->getHeaders() as $name => $values) {
$result .= $name . ': ' . \implode(', ', $values) . "\r\n";
$result .= $name.': '.\implode(', ', $values)."\r\n";
}
return \trim($result);

View File

@@ -14,5 +14,5 @@ interface MessageFormatterInterface
* @param ResponseInterface|null $response Response that was received
* @param \Throwable|null $error Exception that was received
*/
public function format(RequestInterface $request, ?ResponseInterface $response = null, ?\Throwable $error = null): string;
public function format(RequestInterface $request, ResponseInterface $response = null, \Throwable $error = null): string;
}

View File

@@ -34,10 +34,12 @@ final class Middleware
}
$cookieJar = $options['cookies'];
$request = $cookieJar->withCookieHeader($request);
return $handler($request, $options)
->then(
static function (ResponseInterface $response) use ($cookieJar, $request): ResponseInterface {
$cookieJar->extractCookies($request, $response);
return $response;
}
);
@@ -60,6 +62,7 @@ final class Middleware
if (empty($options['http_errors'])) {
return $handler($request, $options);
}
return $handler($request, $options)->then(
static function (ResponseInterface $response) use ($request, $bodySummarizer) {
$code = $response->getStatusCode();
@@ -93,20 +96,22 @@ final class Middleware
return $handler($request, $options)->then(
static function ($value) use ($request, &$container, $options) {
$container[] = [
'request' => $request,
'request' => $request,
'response' => $value,
'error' => null,
'options' => $options
'error' => null,
'options' => $options,
];
return $value;
},
static function ($reason) use ($request, &$container, $options) {
$container[] = [
'request' => $request,
'request' => $request,
'response' => null,
'error' => $reason,
'options' => $options
'error' => $reason,
'options' => $options,
];
return P\Create::rejectionFor($reason);
}
);
@@ -138,6 +143,7 @@ final class Middleware
if ($after) {
$after($request, $options, $response);
}
return $response;
};
};
@@ -202,12 +208,14 @@ final class Middleware
static function ($response) use ($logger, $request, $formatter, $logLevel): ResponseInterface {
$message = $formatter->format($request, $response);
$logger->log($logLevel, $message);
return $response;
},
static function ($reason) use ($logger, $request, $formatter): PromiseInterface {
$response = $reason instanceof RequestException ? $reason->getResponse() : null;
$message = $formatter->format($request, $response, P\Create::exceptionFor($reason));
$logger->error($message);
return P\Create::rejectionFor($reason);
}
);

View File

@@ -84,6 +84,7 @@ class PrepareBodyMiddleware
// The expect header is unconditionally enabled
if ($expect === true) {
$modify['set_headers']['Expect'] = '100-Continue';
return;
}

View File

@@ -27,10 +27,10 @@ class RedirectMiddleware
* @var array
*/
public static $defaultSettings = [
'max' => 5,
'protocols' => ['http', 'https'],
'strict' => false,
'referer' => false,
'max' => 5,
'protocols' => ['http', 'https'],
'strict' => false,
'referer' => false,
'track_redirects' => false,
];
@@ -88,10 +88,8 @@ class RedirectMiddleware
$this->guardMax($request, $response, $options);
$nextRequest = $this->modifyRequest($request, $options, $response);
// If authorization is handled by curl, unset it if host is different.
if ($request->getUri()->getHost() !== $nextRequest->getUri()->getHost()
&& defined('\CURLOPT_HTTPAUTH')
) {
// If authorization is handled by curl, unset it if URI is cross-origin.
if (Psr7\UriComparator::isCrossOrigin($request->getUri(), $nextRequest->getUri()) && defined('\CURLOPT_HTTPAUTH')) {
unset(
$options['curl'][\CURLOPT_HTTPAUTH],
$options['curl'][\CURLOPT_USERPWD]
@@ -142,7 +140,7 @@ class RedirectMiddleware
}
/**
* Check for too many redirects
* Check for too many redirects.
*
* @throws TooManyRedirectsException Too many redirects.
*/
@@ -168,8 +166,8 @@ class RedirectMiddleware
// not forcing RFC compliance, but rather emulating what all browsers
// would do.
$statusCode = $response->getStatusCode();
if ($statusCode == 303 ||
($statusCode <= 302 && !$options['allow_redirects']['strict'])
if ($statusCode == 303
|| ($statusCode <= 302 && !$options['allow_redirects']['strict'])
) {
$safeMethods = ['GET', 'HEAD', 'OPTIONS'];
$requestMethod = $request->getMethod();
@@ -178,7 +176,7 @@ class RedirectMiddleware
$modify['body'] = '';
}
$uri = $this->redirectUri($request, $response, $protocols);
$uri = self::redirectUri($request, $response, $protocols);
if (isset($options['idn_conversion']) && ($options['idn_conversion'] !== false)) {
$idnOptions = ($options['idn_conversion'] === true) ? \IDNA_DEFAULT : $options['idn_conversion'];
$uri = Utils::idnUriConvert($uri, $idnOptions);
@@ -198,19 +196,23 @@ class RedirectMiddleware
$modify['remove_headers'][] = 'Referer';
}
// Remove Authorization header if host is different.
if ($request->getUri()->getHost() !== $modify['uri']->getHost()) {
// Remove Authorization and Cookie headers if URI is cross-origin.
if (Psr7\UriComparator::isCrossOrigin($request->getUri(), $modify['uri'])) {
$modify['remove_headers'][] = 'Authorization';
$modify['remove_headers'][] = 'Cookie';
}
return Psr7\Utils::modifyRequest($request, $modify);
}
/**
* Set the appropriate URL on the request based on the location header
* Set the appropriate URL on the request based on the location header.
*/
private function redirectUri(RequestInterface $request, ResponseInterface $response, array $protocols): UriInterface
{
private static function redirectUri(
RequestInterface $request,
ResponseInterface $response,
array $protocols
): UriInterface {
$location = Psr7\UriResolver::resolve(
$request->getUri(),
new Psr7\Uri($response->getHeaderLine('Location'))

View File

@@ -5,9 +5,7 @@ namespace GuzzleHttp;
/**
* This class contains a list of built-in Guzzle request options.
*
* More documentation for each option can be found at http://guzzlephp.org/.
*
* @link http://docs.guzzlephp.org/en/v6/request-options.html
* @see https://docs.guzzlephp.org/en/latest/request-options.html
*/
final class RequestOptions
{
@@ -70,10 +68,22 @@ final class RequestOptions
/**
* connect_timeout: (float, default=0) Float describing the number of
* seconds to wait while trying to connect to a server. Use 0 to wait
* indefinitely (the default behavior).
* 300 seconds (the default behavior).
*/
public const CONNECT_TIMEOUT = 'connect_timeout';
/**
* crypto_method: (int) A value describing the minimum TLS protocol
* version to use.
*
* This setting must be set to one of the
* ``STREAM_CRYPTO_METHOD_TLS*_CLIENT`` constants. PHP 7.4 or higher is
* required in order to use TLS 1.3, and cURL 7.34.0 or higher is required
* in order to specify a crypto method, with cURL 7.52.0 or higher being
* required to use TLS 1.3.
*/
public const CRYPTO_METHOD = 'crypto_method';
/**
* debug: (bool|resource) Set to true or set to a PHP stream returned by
* fopen() enable debug output with the HTTP handler used to send a

View File

@@ -44,7 +44,7 @@ class RetryMiddleware
{
$this->decider = $decider;
$this->nextHandler = $nextHandler;
$this->delay = $delay ?: __CLASS__ . '::exponentialDelay';
$this->delay = $delay ?: __CLASS__.'::exponentialDelay';
}
/**
@@ -54,7 +54,7 @@ class RetryMiddleware
*/
public static function exponentialDelay(int $retries): int
{
return (int) \pow(2, $retries - 1) * 1000;
return (int) 2 ** ($retries - 1) * 1000;
}
public function __invoke(RequestInterface $request, array $options): PromiseInterface
@@ -64,6 +64,7 @@ class RetryMiddleware
}
$fn = $this->nextHandler;
return $fn($request, $options)
->then(
$this->onFulfilled($request, $options),
@@ -85,6 +86,7 @@ class RetryMiddleware
)) {
return $value;
}
return $this->doRetry($request, $options, $value);
};
}
@@ -103,13 +105,14 @@ class RetryMiddleware
)) {
return P\Create::rejectionFor($reason);
}
return $this->doRetry($req, $options);
};
}
private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null): PromiseInterface
{
$options['delay'] = ($this->delay)(++$options['retries'], $response);
$options['delay'] = ($this->delay)(++$options['retries'], $response, $request);
return $this($request, $options);
}

View File

@@ -46,8 +46,8 @@ final class TransferStats
*/
public function __construct(
RequestInterface $request,
?ResponseInterface $response = null,
?float $transferTime = null,
ResponseInterface $response = null,
float $transferTime = null,
$handlerErrorData = null,
array $handlerStats = []
) {

View File

@@ -23,9 +23,9 @@ final class Utils
{
switch (\gettype($input)) {
case 'object':
return 'object(' . \get_class($input) . ')';
return 'object('.\get_class($input).')';
case 'array':
return 'array(' . \count($input) . ')';
return 'array('.\count($input).')';
default:
\ob_start();
\var_dump($input);
@@ -79,19 +79,22 @@ final class Utils
*
* The returned handler is not wrapped by any default middlewares.
*
* @throws \RuntimeException if no viable Handler is available.
*
* @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the best handler for the given system.
*
* @throws \RuntimeException if no viable Handler is available.
*/
public static function chooseHandler(): callable
{
$handler = null;
if (\function_exists('curl_multi_exec') && \function_exists('curl_exec')) {
$handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler());
} elseif (\function_exists('curl_exec')) {
$handler = new CurlHandler();
} elseif (\function_exists('curl_multi_exec')) {
$handler = new CurlMultiHandler();
if (\defined('CURLOPT_CUSTOMREQUEST')) {
if (\function_exists('curl_multi_exec') && \function_exists('curl_exec')) {
$handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler());
} elseif (\function_exists('curl_exec')) {
$handler = new CurlHandler();
} elseif (\function_exists('curl_multi_exec')) {
$handler = new CurlMultiHandler();
}
}
if (\ini_get('allow_url_fopen')) {
@@ -173,14 +176,13 @@ No system CA bundle could be found in any of the the common system locations.
PHP versions earlier than 5.6 are not properly configured to use the system's
CA bundle by default. In order to verify peer certificates, you will need to
supply the path on disk to a certificate bundle to the 'verify' request
option: http://docs.guzzlephp.org/en/latest/clients.html#verify. If you do not
need a specific certificate bundle, then Mozilla provides a commonly used CA
bundle which can be downloaded here (provided by the maintainer of cURL):
https://curl.haxx.se/ca/cacert.pem. Once
you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP
ini setting to point to the path to the file, allowing you to omit the 'verify'
request option. See https://curl.haxx.se/docs/sslcerts.html for more
information.
option: https://docs.guzzlephp.org/en/latest/request-options.html#verify. If
you do not need a specific certificate bundle, then Mozilla provides a commonly
used CA bundle which can be downloaded here (provided by the maintainer of
cURL): https://curl.haxx.se/ca/cacert.pem. Once you have a CA bundle available
on disk, you can set the 'openssl.cafile' PHP ini setting to point to the path
to the file, allowing you to omit the 'verify' request option. See
https://curl.haxx.se/docs/sslcerts.html for more information.
EOT
);
}
@@ -244,8 +246,8 @@ EOT
}
// Special match if the area when prefixed with ".". Remove any
// existing leading "." and add a new leading ".".
$area = '.' . \ltrim($area, '.');
if (\substr($host, -(\strlen($area))) === $area) {
$area = '.'.\ltrim($area, '.');
if (\substr($host, -\strlen($area)) === $area) {
return true;
}
}
@@ -266,13 +268,13 @@ EOT
*
* @throws InvalidArgumentException if the JSON cannot be decoded.
*
* @link https://www.php.net/manual/en/function.json-decode.php
* @see https://www.php.net/manual/en/function.json-decode.php
*/
public static function jsonDecode(string $json, bool $assoc = false, int $depth = 512, int $options = 0)
{
$data = \json_decode($json, $assoc, $depth, $options);
if (\JSON_ERROR_NONE !== \json_last_error()) {
throw new InvalidArgumentException('json_decode error: ' . \json_last_error_msg());
throw new InvalidArgumentException('json_decode error: '.\json_last_error_msg());
}
return $data;
@@ -287,13 +289,13 @@ EOT
*
* @throws InvalidArgumentException if the JSON cannot be encoded.
*
* @link https://www.php.net/manual/en/function.json-encode.php
* @see https://www.php.net/manual/en/function.json-encode.php
*/
public static function jsonEncode($value, int $options = 0, int $depth = 512): string
{
$json = \json_encode($value, $options, $depth);
if (\JSON_ERROR_NONE !== \json_last_error()) {
throw new InvalidArgumentException('json_encode error: ' . \json_last_error_msg());
throw new InvalidArgumentException('json_encode error: '.\json_last_error_msg());
}
/** @var string */
@@ -338,7 +340,7 @@ EOT
$errorMessage = 'IDN conversion failed';
if ($errors) {
$errorMessage .= ' (errors: ' . implode(', ', $errors) . ')';
$errorMessage .= ' (errors: '.implode(', ', $errors).')';
}
throw new InvalidArgumentException($errorMessage);

View File

@@ -50,10 +50,10 @@ function debug_resource($value = null)
*
* The returned handler is not wrapped by any default middlewares.
*
* @throws \RuntimeException if no viable Handler is available.
*
* @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the best handler for the given system.
*
* @throws \RuntimeException if no viable Handler is available.
*
* @deprecated choose_handler will be removed in guzzlehttp/guzzle:8.0. Use Utils::chooseHandler instead.
*/
function choose_handler(): callable
@@ -141,7 +141,7 @@ function is_host_in_noproxy(string $host, array $noProxyArray): bool
*
* @throws Exception\InvalidArgumentException if the JSON cannot be decoded.
*
* @link https://www.php.net/manual/en/function.json-decode.php
* @see https://www.php.net/manual/en/function.json-decode.php
* @deprecated json_decode will be removed in guzzlehttp/guzzle:8.0. Use Utils::jsonDecode instead.
*/
function json_decode(string $json, bool $assoc = false, int $depth = 512, int $options = 0)
@@ -158,7 +158,7 @@ function json_decode(string $json, bool $assoc = false, int $depth = 512, int $o
*
* @throws Exception\InvalidArgumentException if the JSON cannot be encoded.
*
* @link https://www.php.net/manual/en/function.json-encode.php
* @see https://www.php.net/manual/en/function.json-encode.php
* @deprecated json_encode will be removed in guzzlehttp/guzzle:8.0. Use Utils::jsonEncode instead.
*/
function json_encode($value, int $options = 0, int $depth = 512): string

View File

@@ -2,5 +2,5 @@
// Don't redefine the functions if included multiple times.
if (!\function_exists('GuzzleHttp\describe_type')) {
require __DIR__ . '/functions.php';
require __DIR__.'/functions.php';
}