MDL-83404 core: Bump Guzzle and related libraries
GuzzleHttp/Guzzle to 7.9.2 GuzzleHttp/Promises to 2.0.4 GuzzleHttp/PSR7 to 2.7.0. kevinrob/guzzle-cache-middleware to 6.0.0
This commit is contained in:
@@ -3,6 +3,37 @@
|
||||
Please refer to [UPGRADING](UPGRADING.md) guide for upgrading to a major version.
|
||||
|
||||
|
||||
## 7.9.2 - 2024-07-24
|
||||
|
||||
### Fixed
|
||||
|
||||
- Adjusted handler selection to use cURL if its version is 7.21.2 or higher, rather than 7.34.0
|
||||
|
||||
|
||||
## 7.9.1 - 2024-07-19
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix TLS 1.3 check for HTTP/2 requests
|
||||
|
||||
|
||||
## 7.9.0 - 2024-07-18
|
||||
|
||||
### Changed
|
||||
|
||||
- Improve protocol version checks to provide feedback around unsupported protocols
|
||||
- Only select the cURL handler by default if 7.34.0 or higher is linked
|
||||
- Improved `CurlMultiHandler` to avoid busy wait if possible
|
||||
- Dropped support for EOL `guzzlehttp/psr7` v1
|
||||
- Improved URI user info redaction in errors
|
||||
|
||||
## 7.8.2 - 2024-07-18
|
||||
|
||||
### Added
|
||||
|
||||
- Support for PHP 8.4
|
||||
|
||||
|
||||
## 7.8.1 - 2023-12-03
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -62,11 +62,11 @@ composer require guzzlehttp/guzzle
|
||||
|
||||
| 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 |
|
||||
| 3.x | EOL (2016-10-31) | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No | >=5.3.3,<7.0 |
|
||||
| 4.x | EOL (2016-10-31) | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A | No | >=5.4,<7.0 |
|
||||
| 5.x | EOL (2019-10-31) | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No | >=5.4,<7.4 |
|
||||
| 6.x | EOL (2023-10-31) | `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.5 |
|
||||
|
||||
[guzzle-3-repo]: https://github.com/guzzle/guzzle3
|
||||
[guzzle-4-repo]: https://github.com/guzzle/guzzle/tree/4.x
|
||||
|
||||
@@ -6,7 +6,7 @@ Guzzle Upgrade Guide
|
||||
|
||||
In order to take advantage of the new features of PHP, Guzzle dropped the support
|
||||
of PHP 5. The minimum supported PHP version is now PHP 7.2. Type hints and return
|
||||
types for functions and methods have been added wherever possible.
|
||||
types for functions and methods have been added wherever possible.
|
||||
|
||||
Please make sure:
|
||||
- You are calling a function or a method with the correct type.
|
||||
@@ -16,7 +16,7 @@ Please make sure:
|
||||
|
||||
- Class `GuzzleHttp\UriTemplate` is removed.
|
||||
- Class `GuzzleHttp\Exception\SeekException` is removed.
|
||||
- Classes `GuzzleHttp\Exception\BadResponseException`, `GuzzleHttp\Exception\ClientException`,
|
||||
- Classes `GuzzleHttp\Exception\BadResponseException`, `GuzzleHttp\Exception\ClientException`,
|
||||
`GuzzleHttp\Exception\ServerException` can no longer be initialized with an empty
|
||||
Response as argument.
|
||||
- Class `GuzzleHttp\Exception\ConnectException` now extends `GuzzleHttp\Exception\TransferException`
|
||||
@@ -32,7 +32,7 @@ Please make sure:
|
||||
- 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.
|
||||
- The `get`, `head`, `put`, `post`, `patch`, `delete`, `getAsync`, `headAsync`, `putAsync`, `postAsync`, `patchAsync`, and `deleteAsync` methods are now implemented as genuine methods on `GuzzleHttp\Client`, with strong typing. The original `__call` implementation remains unchanged for now, for maximum backwards compatibility, but won't be invoked under normal operation.
|
||||
- The `log` middleware will log the errors with level `error` instead of `notice`
|
||||
- The `log` middleware will log the errors with level `error` instead of `notice`
|
||||
- Support for international domain names (IDN) is now disabled by default, and enabling it requires installing ext-intl, linked against a modern version of the C library (ICU 4.6 or higher).
|
||||
|
||||
#### Native functions calls
|
||||
|
||||
@@ -50,11 +50,39 @@
|
||||
"homepage": "https://github.com/Tobion"
|
||||
}
|
||||
],
|
||||
"repositories": [
|
||||
{
|
||||
"type": "package",
|
||||
"package": {
|
||||
"name": "guzzle/client-integration-tests",
|
||||
"version": "v3.0.2",
|
||||
"dist": {
|
||||
"url": "https://codeload.github.com/guzzle/client-integration-tests/zip/2c025848417c1135031fdf9c728ee53d0a7ceaee",
|
||||
"type": "zip"
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2.5 || ^8.0",
|
||||
"phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.11",
|
||||
"php-http/message": "^1.0 || ^2.0",
|
||||
"guzzlehttp/psr7": "^1.7 || ^2.0",
|
||||
"th3n3rd/cartesian-product": "^0.3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Http\\Client\\Tests\\": "src/"
|
||||
}
|
||||
},
|
||||
"bin": [
|
||||
"bin/http_test_server"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.2.5 || ^8.0",
|
||||
"ext-json": "*",
|
||||
"guzzlehttp/promises": "^1.5.3 || ^2.0.1",
|
||||
"guzzlehttp/psr7": "^1.9.1 || ^2.5.1",
|
||||
"guzzlehttp/promises": "^1.5.3 || ^2.0.3",
|
||||
"guzzlehttp/psr7": "^2.7.0",
|
||||
"psr/http-client": "^1.0",
|
||||
"symfony/deprecation-contracts": "^2.2 || ^3.0"
|
||||
},
|
||||
@@ -64,9 +92,9 @@
|
||||
"require-dev": {
|
||||
"ext-curl": "*",
|
||||
"bamarni/composer-bin-plugin": "^1.8.2",
|
||||
"php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999",
|
||||
"guzzle/client-integration-tests": "3.0.2",
|
||||
"php-http/message-factory": "^1.1",
|
||||
"phpunit/phpunit": "^8.5.36 || ^9.6.15",
|
||||
"phpunit/phpunit": "^8.5.39 || ^9.6.20",
|
||||
"psr/log": "^1.1 || ^2.0 || ^3.0"
|
||||
},
|
||||
"suggest": {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
See instructions in lib/guzzlehttp/readme_moodle.md
|
||||
@@ -11,7 +11,7 @@ final class BodySummarizer implements BodySummarizerInterface
|
||||
*/
|
||||
private $truncateAt;
|
||||
|
||||
public function __construct(int $truncateAt = null)
|
||||
public function __construct(?int $truncateAt = null)
|
||||
{
|
||||
$this->truncateAt = $truncateAt;
|
||||
}
|
||||
@@ -22,7 +22,7 @@ final class BodySummarizer implements BodySummarizerInterface
|
||||
public function summarize(MessageInterface $message): ?string
|
||||
{
|
||||
return $this->truncateAt === null
|
||||
? \GuzzleHttp\Psr7\Message::bodySummary($message)
|
||||
: \GuzzleHttp\Psr7\Message::bodySummary($message, $this->truncateAt);
|
||||
? Psr7\Message::bodySummary($message)
|
||||
: Psr7\Message::bodySummary($message, $this->truncateAt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ class Client implements ClientInterface, \Psr\Http\Client\ClientInterface
|
||||
*
|
||||
* @param array $config Client configuration settings.
|
||||
*
|
||||
* @see \GuzzleHttp\RequestOptions for a list of available request options.
|
||||
* @see RequestOptions for a list of available request options.
|
||||
*/
|
||||
public function __construct(array $config = [])
|
||||
{
|
||||
@@ -202,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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ class CookieJar implements CookieJarInterface
|
||||
}, $this->getIterator()->getArrayCopy());
|
||||
}
|
||||
|
||||
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 = [];
|
||||
|
||||
@@ -62,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.
|
||||
|
||||
@@ -14,7 +14,7 @@ class BadResponseException extends RequestException
|
||||
string $message,
|
||||
RequestInterface $request,
|
||||
ResponseInterface $response,
|
||||
\Throwable $previous = null,
|
||||
?\Throwable $previous = null,
|
||||
array $handlerContext = []
|
||||
) {
|
||||
parent::__construct($message, $request, $response, $previous, $handlerContext);
|
||||
|
||||
@@ -25,7 +25,7 @@ class ConnectException extends TransferException implements NetworkExceptionInte
|
||||
public function __construct(
|
||||
string $message,
|
||||
RequestInterface $request,
|
||||
\Throwable $previous = null,
|
||||
?\Throwable $previous = null,
|
||||
array $handlerContext = []
|
||||
) {
|
||||
parent::__construct($message, 0, $previous);
|
||||
|
||||
@@ -7,7 +7,6 @@ use GuzzleHttp\BodySummarizerInterface;
|
||||
use Psr\Http\Client\RequestExceptionInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
/**
|
||||
* HTTP Request exception
|
||||
@@ -32,8 +31,8 @@ class RequestException extends TransferException implements RequestExceptionInte
|
||||
public function __construct(
|
||||
string $message,
|
||||
RequestInterface $request,
|
||||
ResponseInterface $response = null,
|
||||
\Throwable $previous = null,
|
||||
?ResponseInterface $response = null,
|
||||
?\Throwable $previous = null,
|
||||
array $handlerContext = []
|
||||
) {
|
||||
// Set the code of the exception if the response is set and not future.
|
||||
@@ -63,10 +62,10 @@ class RequestException extends TransferException implements RequestExceptionInte
|
||||
*/
|
||||
public static function create(
|
||||
RequestInterface $request,
|
||||
ResponseInterface $response = null,
|
||||
\Throwable $previous = null,
|
||||
?ResponseInterface $response = null,
|
||||
?\Throwable $previous = null,
|
||||
array $handlerContext = [],
|
||||
BodySummarizerInterface $bodySummarizer = null
|
||||
?BodySummarizerInterface $bodySummarizer = null
|
||||
): self {
|
||||
if (!$response) {
|
||||
return new self(
|
||||
@@ -90,8 +89,7 @@ class RequestException extends TransferException implements RequestExceptionInte
|
||||
$className = __CLASS__;
|
||||
}
|
||||
|
||||
$uri = $request->getUri();
|
||||
$uri = static::obfuscateUri($uri);
|
||||
$uri = \GuzzleHttp\Psr7\Utils::redactUserInfo($request->getUri());
|
||||
|
||||
// Client Error: `GET /` resulted in a `404 Not Found` response:
|
||||
// <html> ... (truncated)
|
||||
@@ -113,20 +111,6 @@ class RequestException extends TransferException implements RequestExceptionInte
|
||||
return new $className($message, $request, $response, $previous, $handlerContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obfuscates URI if there is a username and a password present
|
||||
*/
|
||||
private static function obfuscateUri(UriInterface $uri): UriInterface
|
||||
{
|
||||
$userInfo = $uri->getUserInfo();
|
||||
|
||||
if (false !== ($pos = \strpos($userInfo, ':'))) {
|
||||
return $uri->withUserInfo(\substr($userInfo, 0, $pos), '***');
|
||||
}
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the request that caused the exception
|
||||
*/
|
||||
|
||||
@@ -11,6 +11,7 @@ use GuzzleHttp\Psr7\LazyOpenStream;
|
||||
use GuzzleHttp\TransferStats;
|
||||
use GuzzleHttp\Utils;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
/**
|
||||
* Creates curl resources from a request
|
||||
@@ -46,6 +47,16 @@ class CurlFactory implements CurlFactoryInterface
|
||||
|
||||
public function create(RequestInterface $request, array $options): EasyHandle
|
||||
{
|
||||
$protocolVersion = $request->getProtocolVersion();
|
||||
|
||||
if ('2' === $protocolVersion || '2.0' === $protocolVersion) {
|
||||
if (!self::supportsHttp2()) {
|
||||
throw new ConnectException('HTTP/2 is supported by the cURL handler, however libcurl is built without HTTP/2 support.', $request);
|
||||
}
|
||||
} elseif ('1.0' !== $protocolVersion && '1.1' !== $protocolVersion) {
|
||||
throw new ConnectException(sprintf('HTTP/%s is not supported by the cURL handler.', $protocolVersion), $request);
|
||||
}
|
||||
|
||||
if (isset($options['curl']['body_as_string'])) {
|
||||
$options['_body_as_string'] = $options['curl']['body_as_string'];
|
||||
unset($options['curl']['body_as_string']);
|
||||
@@ -72,6 +83,42 @@ class CurlFactory implements CurlFactoryInterface
|
||||
return $easy;
|
||||
}
|
||||
|
||||
private static function supportsHttp2(): bool
|
||||
{
|
||||
static $supportsHttp2 = null;
|
||||
|
||||
if (null === $supportsHttp2) {
|
||||
$supportsHttp2 = self::supportsTls12()
|
||||
&& defined('CURL_VERSION_HTTP2')
|
||||
&& (\CURL_VERSION_HTTP2 & \curl_version()['features']);
|
||||
}
|
||||
|
||||
return $supportsHttp2;
|
||||
}
|
||||
|
||||
private static function supportsTls12(): bool
|
||||
{
|
||||
static $supportsTls12 = null;
|
||||
|
||||
if (null === $supportsTls12) {
|
||||
$supportsTls12 = \CURL_SSLVERSION_TLSv1_2 & \curl_version()['features'];
|
||||
}
|
||||
|
||||
return $supportsTls12;
|
||||
}
|
||||
|
||||
private static function supportsTls13(): bool
|
||||
{
|
||||
static $supportsTls13 = null;
|
||||
|
||||
if (null === $supportsTls13) {
|
||||
$supportsTls13 = defined('CURL_SSLVERSION_TLSv1_3')
|
||||
&& (\CURL_SSLVERSION_TLSv1_3 & \curl_version()['features']);
|
||||
}
|
||||
|
||||
return $supportsTls13;
|
||||
}
|
||||
|
||||
public function release(EasyHandle $easy): void
|
||||
{
|
||||
$resource = $easy->handle;
|
||||
@@ -147,7 +194,7 @@ class CurlFactory implements CurlFactoryInterface
|
||||
'error' => \curl_error($easy->handle),
|
||||
'appconnect_time' => \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME),
|
||||
] + \curl_getinfo($easy->handle);
|
||||
$ctx[self::CURL_VERSION_STR] = \curl_version()['version'];
|
||||
$ctx[self::CURL_VERSION_STR] = self::getCurlVersion();
|
||||
$factory->release($easy);
|
||||
|
||||
// Retry when nothing is present or when curl failed to rewind.
|
||||
@@ -158,6 +205,17 @@ class CurlFactory implements CurlFactoryInterface
|
||||
return self::createRejection($easy, $ctx);
|
||||
}
|
||||
|
||||
private static function getCurlVersion(): string
|
||||
{
|
||||
static $curlVersion = null;
|
||||
|
||||
if (null === $curlVersion) {
|
||||
$curlVersion = \curl_version()['version'];
|
||||
}
|
||||
|
||||
return $curlVersion;
|
||||
}
|
||||
|
||||
private static function createRejection(EasyHandle $easy, array $ctx): PromiseInterface
|
||||
{
|
||||
static $connectionErrors = [
|
||||
@@ -194,15 +252,22 @@ class CurlFactory implements CurlFactoryInterface
|
||||
);
|
||||
}
|
||||
|
||||
$uri = $easy->request->getUri();
|
||||
|
||||
$sanitizedError = self::sanitizeCurlError($ctx['error'] ?? '', $uri);
|
||||
|
||||
$message = \sprintf(
|
||||
'cURL error %s: %s (%s)',
|
||||
$ctx['errno'],
|
||||
$ctx['error'],
|
||||
$sanitizedError,
|
||||
'see https://curl.haxx.se/libcurl/c/libcurl-errors.html'
|
||||
);
|
||||
$uriString = (string) $easy->request->getUri();
|
||||
if ($uriString !== '' && false === \strpos($ctx['error'], $uriString)) {
|
||||
$message .= \sprintf(' for %s', $uriString);
|
||||
|
||||
if ('' !== $sanitizedError) {
|
||||
$redactedUriString = \GuzzleHttp\Psr7\Utils::redactUserInfo($uri)->__toString();
|
||||
if ($redactedUriString !== '' && false === \strpos($sanitizedError, $redactedUriString)) {
|
||||
$message .= \sprintf(' for %s', $redactedUriString);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a connection exception if it was a specific error code.
|
||||
@@ -213,6 +278,24 @@ class CurlFactory implements CurlFactoryInterface
|
||||
return P\Create::rejectionFor($error);
|
||||
}
|
||||
|
||||
private static function sanitizeCurlError(string $error, UriInterface $uri): string
|
||||
{
|
||||
if ('' === $error) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$baseUri = $uri->withQuery('')->withFragment('');
|
||||
$baseUriString = $baseUri->__toString();
|
||||
|
||||
if ('' === $baseUriString) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$redactedUriString = \GuzzleHttp\Psr7\Utils::redactUserInfo($baseUri)->__toString();
|
||||
|
||||
return str_replace($baseUriString, $redactedUriString, $error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int|string, mixed>
|
||||
*/
|
||||
@@ -232,10 +315,11 @@ class CurlFactory implements CurlFactoryInterface
|
||||
}
|
||||
|
||||
$version = $easy->request->getProtocolVersion();
|
||||
if ($version == 1.1) {
|
||||
$conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1;
|
||||
} elseif ($version == 2.0) {
|
||||
|
||||
if ('2' === $version || '2.0' === $version) {
|
||||
$conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0;
|
||||
} elseif ('1.1' === $version) {
|
||||
$conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1;
|
||||
} else {
|
||||
$conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0;
|
||||
}
|
||||
@@ -390,8 +474,10 @@ class CurlFactory implements CurlFactoryInterface
|
||||
// The empty string enables all available decoders and implicitly
|
||||
// sets a matching 'Accept-Encoding' header.
|
||||
$conf[\CURLOPT_ENCODING] = '';
|
||||
// But as the user did not specify any acceptable encodings we need
|
||||
// to overwrite this implicit header with an empty one.
|
||||
// But as the user did not specify any encoding preference,
|
||||
// let's leave it up to server by preventing curl from sending
|
||||
// the header, which will be interpreted as 'Accept-Encoding: *'.
|
||||
// https://www.rfc-editor.org/rfc/rfc9110#field.accept-encoding
|
||||
$conf[\CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
|
||||
}
|
||||
}
|
||||
@@ -455,23 +541,35 @@ class CurlFactory implements CurlFactoryInterface
|
||||
}
|
||||
|
||||
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');
|
||||
$protocolVersion = $easy->request->getProtocolVersion();
|
||||
|
||||
// If HTTP/2, upgrade TLS 1.0 and 1.1 to 1.2
|
||||
if ('2' === $protocolVersion || '2.0' === $protocolVersion) {
|
||||
if (
|
||||
\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method']
|
||||
|| \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method']
|
||||
|| \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']
|
||||
) {
|
||||
$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 (!self::supportsTls13()) {
|
||||
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');
|
||||
}
|
||||
} elseif (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method']) {
|
||||
$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')) {
|
||||
if (!self::supportsTls12()) {
|
||||
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')) {
|
||||
if (!self::supportsTls13()) {
|
||||
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;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace GuzzleHttp\Handler;
|
||||
|
||||
use Closure;
|
||||
use GuzzleHttp\Promise as P;
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
use GuzzleHttp\Promise\PromiseInterface;
|
||||
@@ -159,6 +160,9 @@ class CurlMultiHandler
|
||||
}
|
||||
}
|
||||
|
||||
// Run curl_multi_exec in the queue to enable other async tasks to run
|
||||
P\Utils::queue()->add(Closure::fromCallable([$this, 'tickInQueue']));
|
||||
|
||||
// Step through the task queue which may add additional requests.
|
||||
P\Utils::queue()->run();
|
||||
|
||||
@@ -169,11 +173,24 @@ class CurlMultiHandler
|
||||
}
|
||||
|
||||
while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) {
|
||||
// Prevent busy looping for slow HTTP requests.
|
||||
\curl_multi_select($this->_mh, $this->selectTimeout);
|
||||
}
|
||||
|
||||
$this->processMessages();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs \curl_multi_exec() inside the event loop, to prevent busy looping
|
||||
*/
|
||||
private function tickInQueue(): void
|
||||
{
|
||||
if (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) {
|
||||
\curl_multi_select($this->_mh, 0);
|
||||
P\Utils::queue()->add(Closure::fromCallable([$this, 'tickInQueue']));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs until all outstanding connections have completed.
|
||||
*/
|
||||
|
||||
@@ -52,21 +52,21 @@ class MockHandler implements \Countable
|
||||
* @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled.
|
||||
* @param callable|null $onRejected Callback to invoke when the return value is rejected.
|
||||
*/
|
||||
public static function createWithMiddleware(array $queue = null, callable $onFulfilled = null, callable $onRejected = null): HandlerStack
|
||||
public static function createWithMiddleware(?array $queue = null, ?callable $onFulfilled = null, ?callable $onRejected = null): HandlerStack
|
||||
{
|
||||
return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
|
||||
}
|
||||
|
||||
/**
|
||||
* The passed in value must be an array of
|
||||
* {@see \Psr\Http\Message\ResponseInterface} objects, Exceptions,
|
||||
* {@see ResponseInterface} objects, Exceptions,
|
||||
* callables, or Promises.
|
||||
*
|
||||
* @param array<int, mixed>|null $queue The parameters to be passed to the append function, as an indexed array.
|
||||
* @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled.
|
||||
* @param callable|null $onRejected Callback to invoke when the return value is rejected.
|
||||
*/
|
||||
public function __construct(array $queue = null, callable $onFulfilled = null, callable $onRejected = null)
|
||||
public function __construct(?array $queue = null, ?callable $onFulfilled = null, ?callable $onRejected = null)
|
||||
{
|
||||
$this->onFulfilled = $onFulfilled;
|
||||
$this->onRejected = $onRejected;
|
||||
@@ -200,7 +200,7 @@ class MockHandler implements \Countable
|
||||
private function invokeStats(
|
||||
RequestInterface $request,
|
||||
array $options,
|
||||
ResponseInterface $response = null,
|
||||
?ResponseInterface $response = null,
|
||||
$reason = null
|
||||
): void {
|
||||
if (isset($options['on_stats'])) {
|
||||
|
||||
@@ -40,6 +40,12 @@ class StreamHandler
|
||||
\usleep($options['delay'] * 1000);
|
||||
}
|
||||
|
||||
$protocolVersion = $request->getProtocolVersion();
|
||||
|
||||
if ('1.0' !== $protocolVersion && '1.1' !== $protocolVersion) {
|
||||
throw new ConnectException(sprintf('HTTP/%s is not supported by the stream handler.', $protocolVersion), $request);
|
||||
}
|
||||
|
||||
$startTime = isset($options['on_stats']) ? Utils::currentTime() : null;
|
||||
|
||||
try {
|
||||
@@ -83,8 +89,8 @@ class StreamHandler
|
||||
array $options,
|
||||
RequestInterface $request,
|
||||
?float $startTime,
|
||||
ResponseInterface $response = null,
|
||||
\Throwable $error = null
|
||||
?ResponseInterface $response = null,
|
||||
?\Throwable $error = null
|
||||
): void {
|
||||
if (isset($options['on_stats'])) {
|
||||
$stats = new TransferStats($request, $response, Utils::currentTime() - $startTime, $error, []);
|
||||
@@ -273,7 +279,7 @@ class StreamHandler
|
||||
|
||||
// HTTP/1.1 streams using the PHP stream wrapper require a
|
||||
// Connection: close header
|
||||
if ($request->getProtocolVersion() == '1.1'
|
||||
if ($request->getProtocolVersion() === '1.1'
|
||||
&& !$request->hasHeader('Connection')
|
||||
) {
|
||||
$request = $request->withHeader('Connection', 'close');
|
||||
|
||||
@@ -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');
|
||||
@@ -58,7 +58,7 @@ class HandlerStack
|
||||
/**
|
||||
* @param (callable(RequestInterface, array): PromiseInterface)|null $handler Underlying HTTP handler.
|
||||
*/
|
||||
public function __construct(callable $handler = null)
|
||||
public function __construct(?callable $handler = null)
|
||||
{
|
||||
$this->handler = $handler;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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 = [];
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ final class Middleware
|
||||
*
|
||||
* @return callable(callable): callable Returns a function that accepts the next handler.
|
||||
*/
|
||||
public static function httpErrors(BodySummarizerInterface $bodySummarizer = null): callable
|
||||
public static function httpErrors(?BodySummarizerInterface $bodySummarizer = null): callable
|
||||
{
|
||||
return static function (callable $handler) use ($bodySummarizer): callable {
|
||||
return static function ($request, array $options) use ($handler, $bodySummarizer) {
|
||||
@@ -132,7 +132,7 @@ final class Middleware
|
||||
*
|
||||
* @return callable Returns a function that accepts the next handler.
|
||||
*/
|
||||
public static function tap(callable $before = null, callable $after = null): callable
|
||||
public static function tap(?callable $before = null, ?callable $after = null): callable
|
||||
{
|
||||
return static function (callable $handler) use ($before, $after): callable {
|
||||
return static function (RequestInterface $request, array $options) use ($handler, $before, $after) {
|
||||
@@ -176,7 +176,7 @@ final class Middleware
|
||||
*
|
||||
* @return callable Returns a function that accepts the next handler.
|
||||
*/
|
||||
public static function retry(callable $decider, callable $delay = null): callable
|
||||
public static function retry(callable $decider, ?callable $delay = null): callable
|
||||
{
|
||||
return static function (callable $handler) use ($decider, $delay): RetryMiddleware {
|
||||
return new RetryMiddleware($decider, $handler, $delay);
|
||||
|
||||
@@ -76,8 +76,8 @@ class PrepareBodyMiddleware
|
||||
|
||||
$expect = $options['expect'] ?? null;
|
||||
|
||||
// Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0
|
||||
if ($expect === false || $request->getProtocolVersion() < 1.1) {
|
||||
// Return if disabled or using HTTP/1.0
|
||||
if ($expect === false || $request->getProtocolVersion() === '1.0') {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ final class RequestOptions
|
||||
* Specifies whether or not cookies are used in a request or what cookie
|
||||
* jar to use or what cookies to send. This option only works if your
|
||||
* handler has the `cookie` middleware. Valid values are `false` and
|
||||
* an instance of {@see \GuzzleHttp\Cookie\CookieJarInterface}.
|
||||
* an instance of {@see Cookie\CookieJarInterface}.
|
||||
*/
|
||||
public const COOKIES = 'cookies';
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ class RetryMiddleware
|
||||
* and returns the number of
|
||||
* milliseconds to delay.
|
||||
*/
|
||||
public function __construct(callable $decider, callable $nextHandler, callable $delay = null)
|
||||
public function __construct(callable $decider, callable $nextHandler, ?callable $delay = null)
|
||||
{
|
||||
$this->decider = $decider;
|
||||
$this->nextHandler = $nextHandler;
|
||||
@@ -110,7 +110,7 @@ class RetryMiddleware
|
||||
};
|
||||
}
|
||||
|
||||
private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null): PromiseInterface
|
||||
private function doRetry(RequestInterface $request, array $options, ?ResponseInterface $response = null): PromiseInterface
|
||||
{
|
||||
$options['delay'] = ($this->delay)(++$options['retries'], $response, $request);
|
||||
|
||||
|
||||
@@ -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 = []
|
||||
) {
|
||||
|
||||
@@ -71,7 +71,7 @@ final class Utils
|
||||
return \STDOUT;
|
||||
}
|
||||
|
||||
return \GuzzleHttp\Psr7\Utils::tryFopen('php://output', 'w');
|
||||
return Psr7\Utils::tryFopen('php://output', 'w');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,7 +87,7 @@ final class Utils
|
||||
{
|
||||
$handler = null;
|
||||
|
||||
if (\defined('CURLOPT_CUSTOMREQUEST')) {
|
||||
if (\defined('CURLOPT_CUSTOMREQUEST') && \function_exists('curl_version') && version_compare(curl_version()['version'], '7.21.2') >= 0) {
|
||||
if (\function_exists('curl_multi_exec') && \function_exists('curl_exec')) {
|
||||
$handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler());
|
||||
} elseif (\function_exists('curl_exec')) {
|
||||
|
||||
@@ -288,9 +288,12 @@ With this example:
|
||||
See [Guzzle Cache](https://www.drupal.org/project/guzzle_cache) module.
|
||||
|
||||
# Links that talk about the project
|
||||
- [Speeding Up APIs/Apps/Smart Toasters with HTTP Response Caching](https://apisyouwonthate.com/blog/speeding-up-apis-apps-smart-toasters-with-http-response-caching)
|
||||
- [Caching HTTP-Requests with Guzzle 6 and PSR-6](http://a.kabachnik.info/caching-http-requests-with-guzzle-6-and-psr-6.html)
|
||||
|
||||
# Buy me a coffee
|
||||
If you like this project, you can [buy me a coffee](https://buymeacoffee.com/kevinrob)! (or a beer 😉)
|
||||
[<img src="bmc_qr.png" width="200">](https://buymeacoffee.com/kevinrob)
|
||||
|
||||
# Development
|
||||
|
||||
## Docker quick start
|
||||
|
||||
@@ -13,20 +13,20 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.2.0",
|
||||
"guzzlehttp/guzzle": "^6.0 || ^7.0",
|
||||
"guzzlehttp/promises": "^1.4 || ^2.0",
|
||||
"guzzlehttp/psr7": "^1.7.0 || ^2.0.0"
|
||||
"php": ">=8.1",
|
||||
"guzzlehttp/guzzle": "^7.9.2",
|
||||
"guzzlehttp/promises": "^2.0.3",
|
||||
"guzzlehttp/psr7": "^2.7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.5.15 || ^9.5",
|
||||
"phpunit/phpunit": "^9.6.21",
|
||||
"doctrine/cache": "^1.10",
|
||||
"league/flysystem": "^2.5",
|
||||
"psr/cache": "^1.0",
|
||||
"cache/array-adapter": "^0.4 || ^0.5 || ^1.0",
|
||||
"illuminate/cache": "^5.0",
|
||||
"cache/simple-cache-bridge": "^0.1 || ^1.0",
|
||||
"symfony/phpunit-bridge": "^4.4 || ^5.0",
|
||||
"symfony/phpunit-bridge": "^7.1.4",
|
||||
"symfony/cache": "^4.4 || ^5.0"
|
||||
},
|
||||
"autoload": {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
See instructions in lib/guzzlehttp/readme_moodle.md
|
||||
@@ -57,8 +57,8 @@ class CacheEntry implements \Serializable
|
||||
RequestInterface $request,
|
||||
ResponseInterface $response,
|
||||
\DateTime $staleAt,
|
||||
\DateTime $staleIfErrorTo = null,
|
||||
\DateTime $staleWhileRevalidateTo = null
|
||||
?\DateTime $staleIfErrorTo = null,
|
||||
?\DateTime $staleWhileRevalidateTo = null
|
||||
) {
|
||||
$this->dateCreated = new \DateTime();
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ class CacheMiddleware
|
||||
/**
|
||||
* @param CacheStrategyInterface|null $cacheStrategy
|
||||
*/
|
||||
public function __construct(CacheStrategyInterface $cacheStrategy = null)
|
||||
public function __construct(?CacheStrategyInterface $cacheStrategy = null)
|
||||
{
|
||||
$this->cacheStorage = $cacheStrategy !== null ? $cacheStrategy : new PrivateCacheStrategy();
|
||||
|
||||
@@ -131,14 +131,14 @@ class CacheMiddleware
|
||||
$response = $this->invalidateCache($request, $response);
|
||||
}
|
||||
|
||||
return $response->withHeader(self::HEADER_CACHE_INFO, self::HEADER_CACHE_MISS);
|
||||
return $response->withHeader(static::HEADER_CACHE_INFO, static::HEADER_CACHE_MISS);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if ($request->hasHeader(self::HEADER_RE_VALIDATION)) {
|
||||
if ($request->hasHeader(static::HEADER_RE_VALIDATION)) {
|
||||
// It's a re-validation request, so bypass the cache!
|
||||
return $handler($request->withoutHeader(self::HEADER_RE_VALIDATION), $options);
|
||||
return $handler($request->withoutHeader(static::HEADER_RE_VALIDATION), $options);
|
||||
}
|
||||
|
||||
// Retrieve information from request (Cache-Control)
|
||||
@@ -162,14 +162,14 @@ class CacheMiddleware
|
||||
) {
|
||||
// Cache HIT!
|
||||
return new FulfilledPromise(
|
||||
$cacheEntry->getResponse()->withHeader(self::HEADER_CACHE_INFO, self::HEADER_CACHE_HIT)
|
||||
$cacheEntry->getResponse()->withHeader(static::HEADER_CACHE_INFO, static::HEADER_CACHE_HIT)
|
||||
);
|
||||
} elseif ($staleResponse
|
||||
|| ($maxStaleCache !== null && $cacheEntry->getStaleAge() <= $maxStaleCache)
|
||||
) {
|
||||
// Staled cache!
|
||||
return new FulfilledPromise(
|
||||
$cacheEntry->getResponse()->withHeader(self::HEADER_CACHE_INFO, self::HEADER_CACHE_HIT)
|
||||
$cacheEntry->getResponse()->withHeader(static::HEADER_CACHE_INFO, static::HEADER_CACHE_HIT)
|
||||
);
|
||||
} elseif ($cacheEntry->hasValidationInformation() && !$onlyFromCache) {
|
||||
// Re-validation header
|
||||
@@ -180,7 +180,7 @@ class CacheMiddleware
|
||||
|
||||
return new FulfilledPromise(
|
||||
$cacheEntry->getResponse()
|
||||
->withHeader(self::HEADER_CACHE_INFO, self::HEADER_CACHE_STALE)
|
||||
->withHeader(static::HEADER_CACHE_INFO, static::HEADER_CACHE_STALE)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -215,7 +215,7 @@ class CacheMiddleware
|
||||
/** @var ResponseInterface $response */
|
||||
$response = $response
|
||||
->withStatus($cacheEntry->getResponse()->getStatusCode())
|
||||
->withHeader(self::HEADER_CACHE_INFO, self::HEADER_CACHE_HIT);
|
||||
->withHeader(static::HEADER_CACHE_INFO, static::HEADER_CACHE_HIT);
|
||||
$response = $response->withBody($cacheEntry->getResponse()->getBody());
|
||||
|
||||
// Merge headers of the "304 Not Modified" and the cache entry
|
||||
@@ -224,14 +224,14 @@ class CacheMiddleware
|
||||
* @var string[] $headerValue
|
||||
*/
|
||||
foreach ($cacheEntry->getOriginalResponse()->getHeaders() as $headerName => $headerValue) {
|
||||
if (!$response->hasHeader($headerName) && $headerName !== self::HEADER_CACHE_INFO) {
|
||||
if (!$response->hasHeader($headerName) && $headerName !== static::HEADER_CACHE_INFO) {
|
||||
$response = $response->withHeader($headerName, $headerValue);
|
||||
}
|
||||
}
|
||||
|
||||
$update = true;
|
||||
} else {
|
||||
$response = $response->withHeader(self::HEADER_CACHE_INFO, self::HEADER_CACHE_MISS);
|
||||
$response = $response->withHeader(static::HEADER_CACHE_INFO, static::HEADER_CACHE_MISS);
|
||||
}
|
||||
|
||||
return static::addToCache($this->cacheStorage, $request, $response, $update);
|
||||
@@ -299,7 +299,7 @@ class CacheMiddleware
|
||||
// Add the promise for revalidate
|
||||
if ($this->client !== null) {
|
||||
/** @var RequestInterface $request */
|
||||
$request = $request->withHeader(self::HEADER_RE_VALIDATION, '1');
|
||||
$request = $request->withHeader(static::HEADER_RE_VALIDATION, '1');
|
||||
$this->waitingRevalidate[] = $this->client
|
||||
->sendAsync($request)
|
||||
->then(function (ResponseInterface $response) use ($request, &$cacheStorage, $cacheEntry) {
|
||||
@@ -335,12 +335,12 @@ class CacheMiddleware
|
||||
*
|
||||
* @return null|ResponseInterface
|
||||
*/
|
||||
protected static function getStaleResponse(CacheEntry $cacheEntry = null)
|
||||
protected static function getStaleResponse(?CacheEntry $cacheEntry = null)
|
||||
{
|
||||
// Return staled cache entry if we can
|
||||
if ($cacheEntry instanceof CacheEntry && $cacheEntry->serveStaleIfError()) {
|
||||
return $cacheEntry->getResponse()
|
||||
->withHeader(self::HEADER_CACHE_INFO, self::HEADER_CACHE_STALE);
|
||||
->withHeader(static::HEADER_CACHE_INFO, static::HEADER_CACHE_STALE);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -352,7 +352,7 @@ class CacheMiddleware
|
||||
*
|
||||
* @return RequestInterface
|
||||
*/
|
||||
protected static function getRequestWithReValidationHeader(RequestInterface $request, CacheEntry $cacheEntry)
|
||||
protected static function getRequestWithReValidationHeader(RequestInterface $request, ?CacheEntry $cacheEntry)
|
||||
{
|
||||
if ($cacheEntry->getResponse()->hasHeader('Last-Modified')) {
|
||||
$request = $request->withHeader(
|
||||
@@ -377,7 +377,7 @@ class CacheMiddleware
|
||||
*
|
||||
* @deprecated Use constructor => `new CacheMiddleware()`
|
||||
*/
|
||||
public static function getMiddleware(CacheStrategyInterface $cacheStorage = null)
|
||||
public static function getMiddleware(?CacheStrategyInterface $cacheStorage = null)
|
||||
{
|
||||
return new self($cacheStorage);
|
||||
}
|
||||
@@ -395,6 +395,6 @@ class CacheMiddleware
|
||||
$this->cacheStorage->delete($request->withMethod($method));
|
||||
}
|
||||
|
||||
return $response->withHeader(self::HEADER_INVALIDATION, true);
|
||||
return $response->withHeader(static::HEADER_INVALIDATION, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,12 @@ class FlysystemStorage implements CacheStorageInterface
|
||||
*/
|
||||
public function save($key, CacheEntry $data)
|
||||
{
|
||||
try {
|
||||
$this->filesystem->write($key, serialize($data));
|
||||
return true;
|
||||
} catch (FilesystemException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,6 +59,7 @@ class FlysystemStorage implements CacheStorageInterface
|
||||
{
|
||||
try {
|
||||
$this->filesystem->delete($key);
|
||||
return true;
|
||||
} catch (FilesystemException $ex) {
|
||||
return true;
|
||||
}
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ class DelegatingCacheStrategy implements CacheStrategyInterface
|
||||
/**
|
||||
* DelegatingCacheStrategy constructor.
|
||||
*/
|
||||
public function __construct(CacheStrategyInterface $defaultCacheStrategy = null)
|
||||
public function __construct(?CacheStrategyInterface $defaultCacheStrategy = null)
|
||||
{
|
||||
$this->defaultCacheStrategy = $defaultCacheStrategy ?: new NullCacheStrategy();
|
||||
}
|
||||
|
||||
@@ -31,14 +31,17 @@ class GreedyCacheStrategy extends PrivateCacheStrategy
|
||||
*/
|
||||
private $varyHeaders;
|
||||
|
||||
public function __construct(CacheStorageInterface $cache = null, $defaultTtl, KeyValueHttpHeader $varyHeaders = null)
|
||||
{
|
||||
public function __construct(
|
||||
?CacheStorageInterface $cache = null,
|
||||
$defaultTtl = 60,
|
||||
?KeyValueHttpHeader $varyHeaders = null,
|
||||
) {
|
||||
$this->defaultTtl = $defaultTtl;
|
||||
$this->varyHeaders = $varyHeaders;
|
||||
parent::__construct($cache);
|
||||
}
|
||||
|
||||
protected function getCacheKey(RequestInterface $request, KeyValueHttpHeader $varyHeaders = null)
|
||||
protected function getCacheKey(RequestInterface $request, ?KeyValueHttpHeader $varyHeaders = null)
|
||||
{
|
||||
if (null === $varyHeaders || $varyHeaders->isEmpty()) {
|
||||
return hash(
|
||||
@@ -95,12 +98,12 @@ class GreedyCacheStrategy extends PrivateCacheStrategy
|
||||
$response = $response->withoutHeader('Etag')->withoutHeader('Last-Modified');
|
||||
|
||||
$ttl = $this->defaultTtl;
|
||||
if ($request->hasHeader(self::HEADER_TTL)) {
|
||||
$ttlHeaderValues = $request->getHeader(self::HEADER_TTL);
|
||||
if ($request->hasHeader(static::HEADER_TTL)) {
|
||||
$ttlHeaderValues = $request->getHeader(static::HEADER_TTL);
|
||||
$ttl = (int)reset($ttlHeaderValues);
|
||||
}
|
||||
|
||||
return new CacheEntry($request->withoutHeader(self::HEADER_TTL), $response, new \DateTime(sprintf('+%d seconds', $ttl)));
|
||||
return new CacheEntry($request->withoutHeader(static::HEADER_TTL), $response, new \DateTime(sprintf('%+d seconds', $ttl)));
|
||||
}
|
||||
|
||||
public function fetch(RequestInterface $request)
|
||||
|
||||
@@ -51,7 +51,7 @@ class PrivateCacheStrategy implements CacheStrategyInterface
|
||||
'max-age',
|
||||
];
|
||||
|
||||
public function __construct(CacheStorageInterface $cache = null)
|
||||
public function __construct(?CacheStorageInterface $cache = null)
|
||||
{
|
||||
$this->storage = $cache !== null ? $cache : new VolatileRuntimeStorage();
|
||||
}
|
||||
@@ -120,7 +120,7 @@ class PrivateCacheStrategy implements CacheStrategyInterface
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getCacheKey(RequestInterface $request, KeyValueHttpHeader $varyHeaders = null)
|
||||
protected function getCacheKey(RequestInterface $request, ?KeyValueHttpHeader $varyHeaders = null)
|
||||
{
|
||||
if (!$varyHeaders) {
|
||||
return hash('sha256', $request->getMethod().$request->getUri());
|
||||
|
||||
@@ -20,7 +20,7 @@ use Psr\Http\Message\ResponseInterface;
|
||||
*/
|
||||
class PublicCacheStrategy extends PrivateCacheStrategy
|
||||
{
|
||||
public function __construct(CacheStorageInterface $cache = null)
|
||||
public function __construct(?CacheStorageInterface $cache = null)
|
||||
{
|
||||
parent::__construct($cache);
|
||||
|
||||
|
||||
@@ -1,6 +1,20 @@
|
||||
# CHANGELOG
|
||||
|
||||
|
||||
## 2.0.4 - 2024-10-17
|
||||
|
||||
### Fixed
|
||||
|
||||
- Once settled, don't allow further rejection of additional promises
|
||||
|
||||
|
||||
## 2.0.3 - 2024-07-18
|
||||
|
||||
### Changed
|
||||
|
||||
- PHP 8.4 support
|
||||
|
||||
|
||||
## 2.0.2 - 2023-12-03
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -38,10 +38,10 @@ composer require guzzlehttp/promises
|
||||
|
||||
## Version Guidance
|
||||
|
||||
| Version | Status | PHP Version |
|
||||
|---------|------------------------|--------------|
|
||||
| 1.x | Bug and security fixes | >=5.5,<8.3 |
|
||||
| 2.x | Latest | >=7.2.5,<8.4 |
|
||||
| Version | Status | PHP Version |
|
||||
|---------|---------------------|--------------|
|
||||
| 1.x | Security fixes only | >=5.5,<8.3 |
|
||||
| 2.x | Latest | >=7.2.5,<8.5 |
|
||||
|
||||
|
||||
## Quick Start
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"bamarni/composer-bin-plugin": "^1.8.2",
|
||||
"phpunit/phpunit": "^8.5.36 || ^9.6.15"
|
||||
"phpunit/phpunit": "^8.5.39 || ^9.6.20"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
See instructions in lib/guzzlehttp/readme_moodle.md
|
||||
@@ -84,8 +84,8 @@ final class Coroutine implements PromiseInterface
|
||||
}
|
||||
|
||||
public function then(
|
||||
callable $onFulfilled = null,
|
||||
callable $onRejected = null
|
||||
?callable $onFulfilled = null,
|
||||
?callable $onRejected = null
|
||||
): PromiseInterface {
|
||||
return $this->result->then($onFulfilled, $onRejected);
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ final class Each
|
||||
*/
|
||||
public static function of(
|
||||
$iterable,
|
||||
callable $onFulfilled = null,
|
||||
callable $onRejected = null
|
||||
?callable $onFulfilled = null,
|
||||
?callable $onRejected = null
|
||||
): PromiseInterface {
|
||||
return (new EachPromise($iterable, [
|
||||
'fulfilled' => $onFulfilled,
|
||||
@@ -46,8 +46,8 @@ final class Each
|
||||
public static function ofLimit(
|
||||
$iterable,
|
||||
$concurrency,
|
||||
callable $onFulfilled = null,
|
||||
callable $onRejected = null
|
||||
?callable $onFulfilled = null,
|
||||
?callable $onRejected = null
|
||||
): PromiseInterface {
|
||||
return (new EachPromise($iterable, [
|
||||
'fulfilled' => $onFulfilled,
|
||||
@@ -67,7 +67,7 @@ final class Each
|
||||
public static function ofLimitAll(
|
||||
$iterable,
|
||||
$concurrency,
|
||||
callable $onFulfilled = null
|
||||
?callable $onFulfilled = null
|
||||
): PromiseInterface {
|
||||
return self::ofLimit(
|
||||
$iterable,
|
||||
|
||||
@@ -31,8 +31,8 @@ class FulfilledPromise implements PromiseInterface
|
||||
}
|
||||
|
||||
public function then(
|
||||
callable $onFulfilled = null,
|
||||
callable $onRejected = null
|
||||
?callable $onFulfilled = null,
|
||||
?callable $onRejected = null
|
||||
): PromiseInterface {
|
||||
// Return itself if there is no onFulfilled function.
|
||||
if (!$onFulfilled) {
|
||||
|
||||
@@ -25,16 +25,16 @@ class Promise implements PromiseInterface
|
||||
* @param callable $cancelFn Fn that when invoked cancels the promise.
|
||||
*/
|
||||
public function __construct(
|
||||
callable $waitFn = null,
|
||||
callable $cancelFn = null
|
||||
?callable $waitFn = null,
|
||||
?callable $cancelFn = null
|
||||
) {
|
||||
$this->waitFn = $waitFn;
|
||||
$this->cancelFn = $cancelFn;
|
||||
}
|
||||
|
||||
public function then(
|
||||
callable $onFulfilled = null,
|
||||
callable $onRejected = null
|
||||
?callable $onFulfilled = null,
|
||||
?callable $onRejected = null
|
||||
): PromiseInterface {
|
||||
if ($this->state === self::PENDING) {
|
||||
$p = new Promise(null, [$this, 'cancel']);
|
||||
|
||||
@@ -27,8 +27,8 @@ interface PromiseInterface
|
||||
* @param callable $onRejected Invoked when the promise is rejected.
|
||||
*/
|
||||
public function then(
|
||||
callable $onFulfilled = null,
|
||||
callable $onRejected = null
|
||||
?callable $onFulfilled = null,
|
||||
?callable $onRejected = null
|
||||
): PromiseInterface;
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,8 +31,8 @@ class RejectedPromise implements PromiseInterface
|
||||
}
|
||||
|
||||
public function then(
|
||||
callable $onFulfilled = null,
|
||||
callable $onRejected = null
|
||||
?callable $onFulfilled = null,
|
||||
?callable $onRejected = null
|
||||
): PromiseInterface {
|
||||
// If there's no onRejected callback then just return self.
|
||||
if (!$onRejected) {
|
||||
|
||||
@@ -18,7 +18,7 @@ class RejectionException extends \RuntimeException
|
||||
* @param mixed $reason Rejection reason.
|
||||
* @param string|null $description Optional description.
|
||||
*/
|
||||
public function __construct($reason, string $description = null)
|
||||
public function __construct($reason, ?string $description = null)
|
||||
{
|
||||
$this->reason = $reason;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ final class Utils
|
||||
*
|
||||
* @param TaskQueueInterface|null $assign Optionally specify a new queue instance.
|
||||
*/
|
||||
public static function queue(TaskQueueInterface $assign = null): TaskQueueInterface
|
||||
public static function queue(?TaskQueueInterface $assign = null): TaskQueueInterface
|
||||
{
|
||||
static $queue;
|
||||
|
||||
@@ -144,7 +144,9 @@ final class Utils
|
||||
$results[$idx] = $value;
|
||||
},
|
||||
function ($reason, $idx, Promise $aggregate): void {
|
||||
$aggregate->reject($reason);
|
||||
if (Is::pending($aggregate)) {
|
||||
$aggregate->reject($reason);
|
||||
}
|
||||
}
|
||||
)->then(function () use (&$results) {
|
||||
ksort($results);
|
||||
|
||||
@@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 2.7.0 - 2024-07-18
|
||||
|
||||
### Added
|
||||
|
||||
- Add `Utils::redactUserInfo()` method
|
||||
- Add ability to encode bools as ints in `Query::build`
|
||||
|
||||
## 2.6.3 - 2024-07-18
|
||||
|
||||
### Fixed
|
||||
|
||||
- Make `StreamWrapper::stream_stat()` return `false` if inner stream's size is `null`
|
||||
|
||||
### Changed
|
||||
|
||||
- PHP 8.4 support
|
||||
|
||||
## 2.6.2 - 2023-12-03
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -24,8 +24,8 @@ composer require guzzlehttp/psr7
|
||||
|
||||
| Version | Status | PHP Version |
|
||||
|---------|---------------------|--------------|
|
||||
| 1.x | Security fixes only | >=5.4,<8.1 |
|
||||
| 2.x | Latest | >=7.2.5,<8.4 |
|
||||
| 1.x | EOL (2024-06-30) | >=5.4,<8.2 |
|
||||
| 2.x | Latest | >=7.2.5,<8.5 |
|
||||
|
||||
|
||||
## AppendStream
|
||||
@@ -436,7 +436,7 @@ will be parsed into `['foo[a]' => '1', 'foo[b]' => '2'])`.
|
||||
|
||||
## `GuzzleHttp\Psr7\Query::build`
|
||||
|
||||
`public static function build(array $params, int|false $encoding = PHP_QUERY_RFC3986): string`
|
||||
`public static function build(array $params, int|false $encoding = PHP_QUERY_RFC3986, bool $treatBoolsAsInts = true): string`
|
||||
|
||||
Build a query string from an array of key value pairs.
|
||||
|
||||
@@ -498,11 +498,18 @@ a message.
|
||||
|
||||
## `GuzzleHttp\Psr7\Utils::readLine`
|
||||
|
||||
`public static function readLine(StreamInterface $stream, int $maxLength = null): string`
|
||||
`public static function readLine(StreamInterface $stream, ?int $maxLength = null): string`
|
||||
|
||||
Read a line from the stream up to the maximum allowed buffer length.
|
||||
|
||||
|
||||
## `GuzzleHttp\Psr7\Utils::redactUserInfo`
|
||||
|
||||
`public static function redactUserInfo(UriInterface $uri): UriInterface`
|
||||
|
||||
Redact the password in the user info part of a URI.
|
||||
|
||||
|
||||
## `GuzzleHttp\Psr7\Utils::streamFor`
|
||||
|
||||
`public static function streamFor(resource|string|null|int|float|bool|StreamInterface|callable|\Iterator $resource = '', array $options = []): StreamInterface`
|
||||
@@ -674,7 +681,7 @@ termed a relative-path reference.
|
||||
|
||||
### `GuzzleHttp\Psr7\Uri::isSameDocumentReference`
|
||||
|
||||
`public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null): bool`
|
||||
`public static function isSameDocumentReference(UriInterface $uri, ?UriInterface $base = null): bool`
|
||||
|
||||
Whether the URI is a same-document reference. A same-document reference refers to a URI that is, aside from its
|
||||
fragment component, identical to the base URI. When no base URI is given, only an empty URI reference
|
||||
|
||||
@@ -61,8 +61,8 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"bamarni/composer-bin-plugin": "^1.8.2",
|
||||
"http-interop/http-factory-tests": "^0.9",
|
||||
"phpunit/phpunit": "^8.5.36 || ^9.6.15"
|
||||
"http-interop/http-factory-tests": "0.9.0",
|
||||
"phpunit/phpunit": "^8.5.39 || ^9.6.20"
|
||||
},
|
||||
"suggest": {
|
||||
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
See instructions in lib/guzzlehttp/readme_moodle.md
|
||||
@@ -33,7 +33,7 @@ final class CachingStream implements StreamInterface
|
||||
*/
|
||||
public function __construct(
|
||||
StreamInterface $stream,
|
||||
StreamInterface $target = null
|
||||
?StreamInterface $target = null
|
||||
) {
|
||||
$this->remoteStream = $stream;
|
||||
$this->stream = $target ?: new Stream(Utils::tryFopen('php://temp', 'r+'));
|
||||
|
||||
@@ -27,10 +27,10 @@ final class HttpFactory implements RequestFactoryInterface, ResponseFactoryInter
|
||||
{
|
||||
public function createUploadedFile(
|
||||
StreamInterface $stream,
|
||||
int $size = null,
|
||||
?int $size = null,
|
||||
int $error = \UPLOAD_ERR_OK,
|
||||
string $clientFilename = null,
|
||||
string $clientMediaType = null
|
||||
?string $clientFilename = null,
|
||||
?string $clientMediaType = null
|
||||
): UploadedFileInterface {
|
||||
if ($size === null) {
|
||||
$size = $stream->getSize();
|
||||
|
||||
@@ -32,7 +32,7 @@ final class MultipartStream implements StreamInterface
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct(array $elements = [], string $boundary = null)
|
||||
public function __construct(array $elements = [], ?string $boundary = null)
|
||||
{
|
||||
$this->boundary = $boundary ?: bin2hex(random_bytes(20));
|
||||
$this->stream = $this->createStream($elements);
|
||||
|
||||
@@ -63,12 +63,15 @@ final class Query
|
||||
* string. This function does not modify the provided keys when an array is
|
||||
* encountered (like `http_build_query()` would).
|
||||
*
|
||||
* @param array $params Query string parameters.
|
||||
* @param int|false $encoding Set to false to not encode, PHP_QUERY_RFC3986
|
||||
* to encode using RFC3986, or PHP_QUERY_RFC1738
|
||||
* to encode using RFC1738.
|
||||
* @param array $params Query string parameters.
|
||||
* @param int|false $encoding Set to false to not encode,
|
||||
* PHP_QUERY_RFC3986 to encode using
|
||||
* RFC3986, or PHP_QUERY_RFC1738 to
|
||||
* encode using RFC1738.
|
||||
* @param bool $treatBoolsAsInts Set to true to encode as 0/1, and
|
||||
* false as false/true.
|
||||
*/
|
||||
public static function build(array $params, $encoding = PHP_QUERY_RFC3986): string
|
||||
public static function build(array $params, $encoding = PHP_QUERY_RFC3986, bool $treatBoolsAsInts = true): string
|
||||
{
|
||||
if (!$params) {
|
||||
return '';
|
||||
@@ -86,12 +89,14 @@ final class Query
|
||||
throw new \InvalidArgumentException('Invalid type');
|
||||
}
|
||||
|
||||
$castBool = $treatBoolsAsInts ? static function ($v) { return (int) $v; } : static function ($v) { return $v ? 'true' : 'false'; };
|
||||
|
||||
$qs = '';
|
||||
foreach ($params as $k => $v) {
|
||||
$k = $encoder((string) $k);
|
||||
if (!is_array($v)) {
|
||||
$qs .= $k;
|
||||
$v = is_bool($v) ? (int) $v : $v;
|
||||
$v = is_bool($v) ? $castBool($v) : $v;
|
||||
if ($v !== null) {
|
||||
$qs .= '='.$encoder((string) $v);
|
||||
}
|
||||
@@ -99,7 +104,7 @@ final class Query
|
||||
} else {
|
||||
foreach ($v as $vv) {
|
||||
$qs .= $k;
|
||||
$vv = is_bool($vv) ? (int) $vv : $vv;
|
||||
$vv = is_bool($vv) ? $castBool($vv) : $vv;
|
||||
if ($vv !== null) {
|
||||
$qs .= '='.$encoder((string) $vv);
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ class Response implements ResponseInterface
|
||||
array $headers = [],
|
||||
$body = null,
|
||||
string $version = '1.1',
|
||||
string $reason = null
|
||||
?string $reason = null
|
||||
) {
|
||||
$this->assertStatusCodeRange($status);
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ final class StreamWrapper
|
||||
}
|
||||
}
|
||||
|
||||
public function stream_open(string $path, string $mode, int $options, string &$opened_path = null): bool
|
||||
public function stream_open(string $path, string $mode, int $options, ?string &$opened_path = null): bool
|
||||
{
|
||||
$options = stream_context_get_options($this->context);
|
||||
|
||||
@@ -136,10 +136,14 @@ final class StreamWrapper
|
||||
* ctime: int,
|
||||
* blksize: int,
|
||||
* blocks: int
|
||||
* }
|
||||
* }|false
|
||||
*/
|
||||
public function stream_stat(): array
|
||||
public function stream_stat()
|
||||
{
|
||||
if ($this->stream->getSize() === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static $modeMap = [
|
||||
'r' => 33060,
|
||||
'rb' => 33060,
|
||||
|
||||
@@ -64,8 +64,8 @@ class UploadedFile implements UploadedFileInterface
|
||||
$streamOrFile,
|
||||
?int $size,
|
||||
int $errorStatus,
|
||||
string $clientFilename = null,
|
||||
string $clientMediaType = null
|
||||
?string $clientFilename = null,
|
||||
?string $clientMediaType = null
|
||||
) {
|
||||
$this->setError($errorStatus);
|
||||
$this->size = $size;
|
||||
|
||||
@@ -279,7 +279,7 @@ class Uri implements UriInterface, \JsonSerializable
|
||||
*
|
||||
* @see https://datatracker.ietf.org/doc/html/rfc3986#section-4.4
|
||||
*/
|
||||
public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null): bool
|
||||
public static function isSameDocumentReference(UriInterface $uri, ?UriInterface $base = null): bool
|
||||
{
|
||||
if ($base !== null) {
|
||||
$uri = UriResolver::resolve($base, $uri);
|
||||
|
||||
@@ -231,7 +231,7 @@ final class Utils
|
||||
* @param StreamInterface $stream Stream to read from
|
||||
* @param int|null $maxLength Maximum buffer length
|
||||
*/
|
||||
public static function readLine(StreamInterface $stream, int $maxLength = null): string
|
||||
public static function readLine(StreamInterface $stream, ?int $maxLength = null): string
|
||||
{
|
||||
$buffer = '';
|
||||
$size = 0;
|
||||
@@ -250,6 +250,20 @@ final class Utils
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redact the password in the user info part of a URI.
|
||||
*/
|
||||
public static function redactUserInfo(UriInterface $uri): UriInterface
|
||||
{
|
||||
$userInfo = $uri->getUserInfo();
|
||||
|
||||
if (false !== ($pos = \strpos($userInfo, ':'))) {
|
||||
return $uri->withUserInfo(\substr($userInfo, 0, $pos), '***');
|
||||
}
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new stream based on the input type.
|
||||
*
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
Instructions to import/update guzzle library into Moodle:
|
||||
|
||||
Update guzzle promises library
|
||||
1. Download the latest guzzle promises library from https://github.com/guzzle/promises
|
||||
2. Copy the src directory to lib/guzzlehttp/promises folder
|
||||
3. Copy the associated files LICENCE, README.md etc. to promises directory
|
||||
Update Guzzle and associated libraries.
|
||||
|
||||
Update guzzle http library
|
||||
1. Download the latest guzzlehttp library from https://github.com/guzzle/guzzle
|
||||
2. Copy the src directory to lib/guzzlehttp/guzzle folder
|
||||
3. Copy the associated files LICENCE, README.md etc. to guzzle directory
|
||||
```
|
||||
installdir=`mktemp -d`
|
||||
cd "$installdir"
|
||||
composer require guzzlehttp/guzzle kevinrob/guzzle-cache-middleware
|
||||
|
||||
Update guzzle psr-7 message implementation library
|
||||
1. Download the latest psr-7 library from https://github.com/guzzle/psr7
|
||||
2. Copy the src directory to lib/guzzlehttp/psr-7 folder
|
||||
3. Copy the associated files LICENCE, README.md etc. to psr-7 directory
|
||||
cd -
|
||||
rm -rf lib/guzzlehttp/guzzle lib/guzzlehttp/psr7 lib/guzzlehttp/promises lib/guzzlehttp/kevinrob/guzzlecache
|
||||
cp -rf "$installdir"/vendor/guzzlehttp/guzzle lib/guzzlehttp/guzzle
|
||||
cp -rf "$installdir"/vendor/guzzlehttp/psr7 lib/guzzlehttp/psr7
|
||||
cp -rf "$installdir"/vendor/guzzlehttp/promises lib/guzzlehttp/promises
|
||||
cp -rf "$installdir"/vendor/kevinrob/guzzle-cache-middleware lib/guzzlehttp/kevinrob/guzzlecache
|
||||
rm -rf lib/guzzlehttp/kevinrob/guzzlecache/*.png
|
||||
|
||||
Update guzzle cache implementation library
|
||||
1. Download the latest Guzzle cache middleware library from https://github.com/Kevinrob/guzzle-cache-middleware
|
||||
2. Copy the src directory to guzzlehttp/kevinrob/guzzlecache folder
|
||||
3. Copy the associated files LICENCE, README.md etc. to guzzlecache directory
|
||||
echo "See instructions in lib/guzzlehttp/readme_moodle.md" > lib/guzzlehttp/guzzle/readme_moodle.txt
|
||||
echo "See instructions in lib/guzzlehttp/readme_moodle.md" > lib/guzzlehttp/promises/readme_moodle.txt
|
||||
echo "See instructions in lib/guzzlehttp/readme_moodle.md" > lib/guzzlehttp/psr7/readme_moodle.txt
|
||||
echo "See instructions in lib/guzzlehttp/readme_moodle.md" > lib/guzzlehttp/kevinrob/guzzlecache/readme_moodle.txt
|
||||
git add lib/guzzlehttp/guzzle lib/guzzlehttp/psr7 lib/guzzlehttp/promises
|
||||
```
|
||||
|
||||
Now update `lib/thirdpartylibs.xml`
|
||||
|
||||
@@ -701,7 +701,7 @@ All rights reserved.</copyright>
|
||||
<location>guzzlehttp/guzzle</location>
|
||||
<name>GuzzleHttp/Guzzle</name>
|
||||
<description>Guzzle is a PHP HTTP client library</description>
|
||||
<version>7.8.1</version>
|
||||
<version>7.9.2</version>
|
||||
<license>MIT</license>
|
||||
<repository>https://github.com/guzzle/guzzle</repository>
|
||||
</library>
|
||||
@@ -709,7 +709,7 @@ All rights reserved.</copyright>
|
||||
<location>guzzlehttp/promises</location>
|
||||
<name>GuzzleHttp/Promises</name>
|
||||
<description>Guzzle promises library</description>
|
||||
<version>2.0.2</version>
|
||||
<version>2.0.4</version>
|
||||
<license>MIT</license>
|
||||
<repository>https://github.com/guzzle/promises</repository>
|
||||
</library>
|
||||
@@ -725,7 +725,7 @@ All rights reserved.</copyright>
|
||||
<location>guzzlehttp/psr7</location>
|
||||
<name>GuzzleHttp/PSR7</name>
|
||||
<description>PSR-7 message implementation that also provides common utility methods</description>
|
||||
<version>2.6.2</version>
|
||||
<version>2.7.0</version>
|
||||
<license>MIT</license>
|
||||
<repository>https://github.com/guzzle/psr7</repository>
|
||||
</library>
|
||||
@@ -741,7 +741,7 @@ All rights reserved.</copyright>
|
||||
<location>guzzlehttp/kevinrob/guzzlecache</location>
|
||||
<name>Guzzle cache middleware</name>
|
||||
<description>A HTTP Cache for Guzzle as a simple Middleware to be added in the HandlerStack.</description>
|
||||
<version>5.1.0</version>
|
||||
<version>6.0.0</version>
|
||||
<license>MIT</license>
|
||||
<repository>https://github.com/Kevinrob/guzzle-cache-middleware</repository>
|
||||
</library>
|
||||
|
||||
Reference in New Issue
Block a user