Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • dmj/selbstzeugnisse-hab
  • goermar/selbstzeugnisse-hab
2 results
Show changes
Showing
with 320 additions and 111 deletions
# Change Log # Change Log
## 6.5.5 - 2020-06-16
* Unpin version constraint for `symfony/polyfill-intl-idn` [#2678](https://github.com/guzzle/guzzle/pull/2678)
## 6.5.4 - 2020-05-25
* Fix various intl icu issues [#2626](https://github.com/guzzle/guzzle/pull/2626)
## 6.5.3 - 2020-04-18
* Use Symfony intl-idn polyfill [#2550](https://github.com/guzzle/guzzle/pull/2550)
* Remove use of internal functions [#2548](https://github.com/guzzle/guzzle/pull/2548)
## 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)
* Improvement: Added support to pass arbitrary options to `curl_multi_init`. [#2287](https://github.com/guzzle/guzzle/pull/2287)
* Fix: Gracefully handle passing `null` to the `header` option. [#2132](https://github.com/guzzle/guzzle/pull/2132)
* Fix: `RetryMiddleware` did not do exponential delay between retries due unit mismatch. [#2132](https://github.com/guzzle/guzzle/pull/2132)
Previously, `RetryMiddleware` would sleep for 1 millisecond, then 2 milliseconds, then 4 milliseconds.
**After this change, `RetryMiddleware` will sleep for 1 second, then 2 seconds, then 4 seconds.**
`Middleware::retry()` accepts a second callback parameter to override the default timeouts if needed.
* 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)
* Fix: Test if response is readable before returning a summary in `RequestException::getResponseBodySummary()` [#2081](https://github.com/guzzle/guzzle/pull/2081)
* Fix: Add support for GUZZLE_CURL_SELECT_TIMEOUT environment variable [#2161](https://github.com/guzzle/guzzle/pull/2161)
* Improvement: Added `GuzzleHttp\Exception\InvalidArgumentException` [#2163](https://github.com/guzzle/guzzle/pull/2163)
* Improvement: Added `GuzzleHttp\_current_time()` to use `hrtime()` if that function exists. [#2242](https://github.com/guzzle/guzzle/pull/2242)
* Improvement: Added curl's `appconnect_time` in `TransferStats` [#2284](https://github.com/guzzle/guzzle/pull/2284)
* Improvement: Make GuzzleException extend Throwable wherever it's available [#2273](https://github.com/guzzle/guzzle/pull/2273)
* 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 ## 6.3.3 - 2018-04-22
* Fix: Default headers when decode_content is specified * Fix: Default headers when decode_content is specified
......
FROM composer:latest as setup
RUN mkdir /guzzle
WORKDIR /guzzle
RUN set -xe \
&& composer init --name=guzzlehttp/test --description="Simple project for testing Guzzle scripts" --author="Márk Sági-Kazár <mark.sagikazar@gmail.com>" --no-interaction \
&& composer require guzzlehttp/guzzle
FROM php:7.3
RUN mkdir /guzzle
WORKDIR /guzzle
COPY --from=setup /guzzle /guzzle
...@@ -21,19 +21,18 @@ trivial to integrate with web services. ...@@ -21,19 +21,18 @@ trivial to integrate with web services.
```php ```php
$client = new \GuzzleHttp\Client(); $client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle'); $response = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle');
echo $res->getStatusCode();
// 200 echo $response->getStatusCode(); # 200
echo $res->getHeaderLine('content-type'); echo $response->getHeaderLine('content-type'); # 'application/json; charset=utf8'
// 'application/json; charset=utf8' echo $response->getBody(); # '{"id": 1420053, "name": "guzzle", ...}'
echo $res->getBody();
// '{"id": 1420053, "name": "guzzle", ...}' # Send an asynchronous request.
// Send an asynchronous request.
$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org'); $request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org');
$promise = $client->sendAsync($request)->then(function ($response) { $promise = $client->sendAsync($request)->then(function ($response) {
echo 'I completed! ' . $response->getBody(); echo 'I completed! ' . $response->getBody();
}); });
$promise->wait(); $promise->wait();
``` ```
...@@ -57,7 +56,7 @@ curl -sS https://getcomposer.org/installer | php ...@@ -57,7 +56,7 @@ curl -sS https://getcomposer.org/installer | php
Next, run the Composer command to install the latest stable version of Guzzle: Next, run the Composer command to install the latest stable version of Guzzle:
```bash ```bash
php composer.phar require guzzlehttp/guzzle composer require guzzlehttp/guzzle
``` ```
After installing, you need to require Composer's autoloader: After installing, you need to require Composer's autoloader:
...@@ -69,7 +68,7 @@ require 'vendor/autoload.php'; ...@@ -69,7 +68,7 @@ require 'vendor/autoload.php';
You can then later update Guzzle using composer: You can then later update Guzzle using composer:
```bash ```bash
composer.phar update composer update
``` ```
...@@ -79,13 +78,13 @@ composer.phar update ...@@ -79,13 +78,13 @@ composer.phar update
|---------|------------|---------------------|--------------|---------------------|---------------------|-------|-------------| |---------|------------|---------------------|--------------|---------------------|---------------------|-------|-------------|
| 3.x | EOL | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No | >= 5.3.3 | | 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 | | 4.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A | No | >= 5.4 |
| 5.x | Maintained | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No | >= 5.4 | | 5.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No | >= 5.4 |
| 6.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes | >= 5.5 | | 6.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes | >= 5.5 |
[guzzle-3-repo]: https://github.com/guzzle/guzzle3 [guzzle-3-repo]: https://github.com/guzzle/guzzle3
[guzzle-4-repo]: https://github.com/guzzle/guzzle/tree/4.x [guzzle-4-repo]: https://github.com/guzzle/guzzle/tree/4.x
[guzzle-5-repo]: https://github.com/guzzle/guzzle/tree/5.3 [guzzle-5-repo]: https://github.com/guzzle/guzzle/tree/5.3
[guzzle-6-repo]: https://github.com/guzzle/guzzle [guzzle-6-repo]: https://github.com/guzzle/guzzle
[guzzle-3-docs]: http://guzzle3.readthedocs.org/en/latest/ [guzzle-3-docs]: http://guzzle3.readthedocs.org
[guzzle-5-docs]: http://guzzle.readthedocs.org/en/5.3/ [guzzle-5-docs]: http://guzzle.readthedocs.org/en/5.3/
[guzzle-6-docs]: http://guzzle.readthedocs.org/en/latest/ [guzzle-6-docs]: http://guzzle.readthedocs.org/en/latest/
...@@ -2,7 +2,15 @@ ...@@ -2,7 +2,15 @@
"name": "guzzlehttp/guzzle", "name": "guzzlehttp/guzzle",
"type": "library", "type": "library",
"description": "Guzzle is a PHP HTTP client library", "description": "Guzzle is a PHP HTTP client library",
"keywords": ["framework", "http", "rest", "web service", "curl", "client", "HTTP client"], "keywords": [
"framework",
"http",
"rest",
"web service",
"curl",
"client",
"HTTP client"
],
"homepage": "http://guzzlephp.org/", "homepage": "http://guzzlephp.org/",
"license": "MIT", "license": "MIT",
"authors": [ "authors": [
...@@ -14,31 +22,38 @@ ...@@ -14,31 +22,38 @@
], ],
"require": { "require": {
"php": ">=5.5", "php": ">=5.5",
"guzzlehttp/psr7": "^1.4", "ext-json": "*",
"guzzlehttp/promises": "^1.0" "symfony/polyfill-intl-idn": "^1.17.0",
"guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.6.1"
}, },
"require-dev": { "require-dev": {
"ext-curl": "*", "ext-curl": "*",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
"psr/log": "^1.0" "psr/log": "^1.1"
},
"suggest": {
"psr/log": "Required for using the Log middleware"
},
"config": {
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-master": "6.5-dev"
}
}, },
"autoload": { "autoload": {
"files": ["src/functions_include.php"],
"psr-4": { "psr-4": {
"GuzzleHttp\\": "src/" "GuzzleHttp\\": "src/"
} },
"files": [
"src/functions_include.php"
]
}, },
"autoload-dev": { "autoload-dev": {
"psr-4": { "psr-4": {
"GuzzleHttp\\Tests\\": "tests/" "GuzzleHttp\\Tests\\": "tests/"
} }
},
"suggest": {
"psr/log": "Required for using the Log middleware"
},
"extra": {
"branch-alias": {
"dev-master": "6.3-dev"
}
} }
} }
...@@ -2,11 +2,12 @@ ...@@ -2,11 +2,12 @@
namespace GuzzleHttp; namespace GuzzleHttp;
use GuzzleHttp\Cookie\CookieJar; use GuzzleHttp\Cookie\CookieJar;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Promise; use GuzzleHttp\Promise;
use GuzzleHttp\Psr7; use GuzzleHttp\Psr7;
use Psr\Http\Message\UriInterface;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\UriInterface;
/** /**
* @method ResponseInterface get(string|UriInterface $uri, array $options = []) * @method ResponseInterface get(string|UriInterface $uri, array $options = [])
...@@ -46,9 +47,8 @@ class Client implements ClientInterface ...@@ -46,9 +47,8 @@ class Client implements ClientInterface
* wire. The function is called with a Psr7\Http\Message\RequestInterface * wire. The function is called with a Psr7\Http\Message\RequestInterface
* and array of transfer options, and must return a * and array of transfer options, and must return a
* GuzzleHttp\Promise\PromiseInterface that is fulfilled with a * GuzzleHttp\Promise\PromiseInterface that is fulfilled with a
* Psr7\Http\Message\ResponseInterface on success. "handler" is a * Psr7\Http\Message\ResponseInterface on success.
* constructor only option that cannot be overridden in per/request * If no handler is provided, a default handler will be created
* options. If no handler is provided, a default handler will be created
* that enables all of the request options below by attaching all of the * that enables all of the request options below by attaching all of the
* default middleware to the handler. * default middleware to the handler.
* - base_uri: (string|UriInterface) Base URI of the client that is merged * - base_uri: (string|UriInterface) Base URI of the client that is merged
...@@ -75,6 +75,12 @@ class Client implements ClientInterface ...@@ -75,6 +75,12 @@ class Client implements ClientInterface
$this->configureDefaults($config); $this->configureDefaults($config);
} }
/**
* @param string $method
* @param array $args
*
* @return Promise\PromiseInterface
*/
public function __call($method, $args) public function __call($method, $args)
{ {
if (count($args) < 1) { if (count($args) < 1) {
...@@ -89,6 +95,14 @@ class Client implements ClientInterface ...@@ -89,6 +95,14 @@ class Client implements ClientInterface
: $this->request($method, $uri, $opts); : $this->request($method, $uri, $opts);
} }
/**
* Asynchronously send an HTTP request.
*
* @param array $options Request options to apply to the given
* request and to the transfer. See \GuzzleHttp\RequestOptions.
*
* @return Promise\PromiseInterface
*/
public function sendAsync(RequestInterface $request, array $options = []) public function sendAsync(RequestInterface $request, array $options = [])
{ {
// Merge the base URI into the request URI if needed. // Merge the base URI into the request URI if needed.
...@@ -100,12 +114,35 @@ class Client implements ClientInterface ...@@ -100,12 +114,35 @@ class Client implements ClientInterface
); );
} }
/**
* Send an HTTP request.
*
* @param array $options Request options to apply to the given
* request and to the transfer. See \GuzzleHttp\RequestOptions.
*
* @return ResponseInterface
* @throws GuzzleException
*/
public function send(RequestInterface $request, array $options = []) public function send(RequestInterface $request, array $options = [])
{ {
$options[RequestOptions::SYNCHRONOUS] = true; $options[RequestOptions::SYNCHRONOUS] = true;
return $this->sendAsync($request, $options)->wait(); return $this->sendAsync($request, $options)->wait();
} }
/**
* Create and send an asynchronous HTTP request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string $method HTTP method
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
*
* @return Promise\PromiseInterface
*/
public function requestAsync($method, $uri = '', array $options = []) public function requestAsync($method, $uri = '', array $options = [])
{ {
$options = $this->prepareDefaults($options); $options = $this->prepareDefaults($options);
...@@ -125,12 +162,37 @@ class Client implements ClientInterface ...@@ -125,12 +162,37 @@ class Client implements ClientInterface
return $this->transfer($request, $options); return $this->transfer($request, $options);
} }
/**
* Create and send an HTTP request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well.
*
* @param string $method HTTP method.
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
*
* @return ResponseInterface
* @throws GuzzleException
*/
public function request($method, $uri = '', array $options = []) public function request($method, $uri = '', array $options = [])
{ {
$options[RequestOptions::SYNCHRONOUS] = true; $options[RequestOptions::SYNCHRONOUS] = true;
return $this->requestAsync($method, $uri, $options)->wait(); return $this->requestAsync($method, $uri, $options)->wait();
} }
/**
* Get a client configuration option.
*
* These options include default request options of the client, a "handler"
* (if utilized by the concrete client), and a "base_uri" if utilized by
* the concrete client.
*
* @param string|null $option The config option to retrieve.
*
* @return mixed
*/
public function getConfig($option = null) public function getConfig($option = null)
{ {
return $option === null return $option === null
...@@ -138,6 +200,11 @@ class Client implements ClientInterface ...@@ -138,6 +200,11 @@ class Client implements ClientInterface
: (isset($this->config[$option]) ? $this->config[$option] : null); : (isset($this->config[$option]) ? $this->config[$option] : null);
} }
/**
* @param string|null $uri
*
* @return UriInterface
*/
private function buildUri($uri, array $config) private function buildUri($uri, array $config)
{ {
// for BC we accept null which would otherwise fail in uri_for // for BC we accept null which would otherwise fail in uri_for
...@@ -147,6 +214,11 @@ class Client implements ClientInterface ...@@ -147,6 +214,11 @@ class Client implements ClientInterface
$uri = Psr7\UriResolver::resolve(Psr7\uri_for($config['base_uri']), $uri); $uri = Psr7\UriResolver::resolve(Psr7\uri_for($config['base_uri']), $uri);
} }
if (isset($config['idn_conversion']) && ($config['idn_conversion'] !== false)) {
$idnOptions = ($config['idn_conversion'] === true) ? IDNA_DEFAULT : $config['idn_conversion'];
$uri = Utils::idnUriConvert($uri, $idnOptions);
}
return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri; return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri;
} }
...@@ -154,6 +226,7 @@ class Client implements ClientInterface ...@@ -154,6 +226,7 @@ class Client implements ClientInterface
* Configures the default options for a client. * Configures the default options for a client.
* *
* @param array $config * @param array $config
* @return void
*/ */
private function configureDefaults(array $config) private function configureDefaults(array $config)
{ {
...@@ -162,7 +235,8 @@ class Client implements ClientInterface ...@@ -162,7 +235,8 @@ class Client implements ClientInterface
'http_errors' => true, 'http_errors' => true,
'decode_content' => true, 'decode_content' => true,
'verify' => true, 'verify' => true,
'cookies' => false 'cookies' => false,
'idn_conversion' => true,
]; ];
// Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set. // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
...@@ -170,7 +244,7 @@ class Client implements ClientInterface ...@@ -170,7 +244,7 @@ class Client implements ClientInterface
// We can only trust the HTTP_PROXY environment variable in a CLI // We can only trust the HTTP_PROXY environment variable in a CLI
// process due to the fact that PHP has no reliable mechanism to // process due to the fact that PHP has no reliable mechanism to
// get environment variables that start with "HTTP_". // get environment variables that start with "HTTP_".
if (php_sapi_name() == 'cli' && getenv('HTTP_PROXY')) { if (php_sapi_name() === 'cli' && getenv('HTTP_PROXY')) {
$defaults['proxy']['http'] = getenv('HTTP_PROXY'); $defaults['proxy']['http'] = getenv('HTTP_PROXY');
} }
...@@ -210,7 +284,7 @@ class Client implements ClientInterface ...@@ -210,7 +284,7 @@ class Client implements ClientInterface
* *
* @return array * @return array
*/ */
private function prepareDefaults($options) private function prepareDefaults(array $options)
{ {
$defaults = $this->config; $defaults = $this->config;
...@@ -225,7 +299,7 @@ class Client implements ClientInterface ...@@ -225,7 +299,7 @@ class Client implements ClientInterface
if (array_key_exists('headers', $options)) { if (array_key_exists('headers', $options)) {
// Allows default headers to be unset. // Allows default headers to be unset.
if ($options['headers'] === null) { if ($options['headers'] === null) {
$defaults['_conditional'] = null; $defaults['_conditional'] = [];
unset($options['headers']); unset($options['headers']);
} elseif (!is_array($options['headers'])) { } elseif (!is_array($options['headers'])) {
throw new \InvalidArgumentException('headers must be an array'); throw new \InvalidArgumentException('headers must be an array');
...@@ -251,8 +325,7 @@ class Client implements ClientInterface ...@@ -251,8 +325,7 @@ class Client implements ClientInterface
* The URI of the request is not modified and the request options are used * The URI of the request is not modified and the request options are used
* as-is without merging in default options. * as-is without merging in default options.
* *
* @param RequestInterface $request * @param array $options See \GuzzleHttp\RequestOptions.
* @param array $options
* *
* @return Promise\PromiseInterface * @return Promise\PromiseInterface
*/ */
...@@ -271,6 +344,7 @@ class Client implements ClientInterface ...@@ -271,6 +344,7 @@ class Client implements ClientInterface
} }
$request = $this->applyOptions($request, $options); $request = $this->applyOptions($request, $options);
/** @var HandlerStack $handler */
$handler = $options['handler']; $handler = $options['handler'];
try { try {
...@@ -411,6 +485,11 @@ class Client implements ClientInterface ...@@ -411,6 +485,11 @@ class Client implements ClientInterface
return $request; return $request;
} }
/**
* Throw Exception with pre-set message.
* @return void
* @throws \InvalidArgumentException Invalid body.
*/
private function invalidBody() private function invalidBody()
{ {
throw new \InvalidArgumentException('Passing in the "body" request ' throw new \InvalidArgumentException('Passing in the "body" request '
......
<?php <?php
namespace GuzzleHttp; namespace GuzzleHttp;
use GuzzleHttp\Promise\PromiseInterface;
use GuzzleHttp\Exception\GuzzleException; use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Promise\PromiseInterface;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\UriInterface; use Psr\Http\Message\UriInterface;
...@@ -12,7 +12,10 @@ use Psr\Http\Message\UriInterface; ...@@ -12,7 +12,10 @@ use Psr\Http\Message\UriInterface;
*/ */
interface ClientInterface interface ClientInterface
{ {
const VERSION = '6.3.3'; /**
* @deprecated Will be removed in Guzzle 7.0.0
*/
const VERSION = '6.5.5';
/** /**
* Send an HTTP request. * Send an HTTP request.
......
...@@ -94,8 +94,8 @@ class CookieJar implements CookieJarInterface ...@@ -94,8 +94,8 @@ class CookieJar implements CookieJarInterface
*/ */
public function getCookieByName($name) public function getCookieByName($name)
{ {
// don't allow a null name // don't allow a non string name
if ($name === null) { if ($name === null || !is_scalar($name)) {
return null; return null;
} }
foreach ($this->cookies as $cookie) { foreach ($this->cookies as $cookie) {
...@@ -103,6 +103,8 @@ class CookieJar implements CookieJarInterface ...@@ -103,6 +103,8 @@ class CookieJar implements CookieJarInterface
return $cookie; return $cookie;
} }
} }
return null;
} }
public function toArray() public function toArray()
...@@ -120,7 +122,7 @@ class CookieJar implements CookieJarInterface ...@@ -120,7 +122,7 @@ class CookieJar implements CookieJarInterface
} elseif (!$path) { } elseif (!$path) {
$this->cookies = array_filter( $this->cookies = array_filter(
$this->cookies, $this->cookies,
function (SetCookie $cookie) use ($path, $domain) { function (SetCookie $cookie) use ($domain) {
return !$cookie->matchesDomain($domain); return !$cookie->matchesDomain($domain);
} }
); );
......
...@@ -58,9 +58,9 @@ interface CookieJarInterface extends \Countable, \IteratorAggregate ...@@ -58,9 +58,9 @@ interface CookieJarInterface extends \Countable, \IteratorAggregate
* arguments, then the cookie with the specified name, path and domain is * arguments, then the cookie with the specified name, path and domain is
* removed. * removed.
* *
* @param string $domain Clears cookies matching a domain * @param string|null $domain Clears cookies matching a domain
* @param string $path Clears cookies matching a domain and path * @param string|null $path Clears cookies matching a domain and path
* @param string $name Clears cookies matching a domain, path, and name * @param string|null $name Clears cookies matching a domain, path, and name
* *
* @return CookieJarInterface * @return CookieJarInterface
*/ */
......
...@@ -23,6 +23,7 @@ class FileCookieJar extends CookieJar ...@@ -23,6 +23,7 @@ class FileCookieJar extends CookieJar
*/ */
public function __construct($cookieFile, $storeSessionCookies = false) public function __construct($cookieFile, $storeSessionCookies = false)
{ {
parent::__construct();
$this->filename = $cookieFile; $this->filename = $cookieFile;
$this->storeSessionCookies = $storeSessionCookies; $this->storeSessionCookies = $storeSessionCookies;
...@@ -56,7 +57,7 @@ class FileCookieJar extends CookieJar ...@@ -56,7 +57,7 @@ class FileCookieJar extends CookieJar
} }
$jsonStr = \GuzzleHttp\json_encode($json); $jsonStr = \GuzzleHttp\json_encode($json);
if (false === file_put_contents($filename, $jsonStr)) { if (false === file_put_contents($filename, $jsonStr, LOCK_EX)) {
throw new \RuntimeException("Unable to save file {$filename}"); throw new \RuntimeException("Unable to save file {$filename}");
} }
} }
......
...@@ -22,6 +22,7 @@ class SessionCookieJar extends CookieJar ...@@ -22,6 +22,7 @@ class SessionCookieJar extends CookieJar
*/ */
public function __construct($sessionKey, $storeSessionCookies = false) public function __construct($sessionKey, $storeSessionCookies = false)
{ {
parent::__construct();
$this->sessionKey = $sessionKey; $this->sessionKey = $sessionKey;
$this->storeSessionCookies = $storeSessionCookies; $this->storeSessionCookies = $storeSessionCookies;
$this->load(); $this->load();
......
...@@ -227,7 +227,7 @@ class SetCookie ...@@ -227,7 +227,7 @@ class SetCookie
/** /**
* Get whether or not this is a secure cookie * Get whether or not this is a secure cookie
* *
* @return null|bool * @return bool|null
*/ */
public function getSecure() public function getSecure()
{ {
...@@ -247,7 +247,7 @@ class SetCookie ...@@ -247,7 +247,7 @@ class SetCookie
/** /**
* Get whether or not this is a session cookie * Get whether or not this is a session cookie
* *
* @return null|bool * @return bool|null
*/ */
public function getDiscard() public function getDiscard()
{ {
......
...@@ -4,4 +4,6 @@ namespace GuzzleHttp\Exception; ...@@ -4,4 +4,6 @@ namespace GuzzleHttp\Exception;
/** /**
* Exception when a client error is encountered (4xx codes) * Exception when a client error is encountered (4xx codes)
*/ */
class ClientException extends BadResponseException {} class ClientException extends BadResponseException
{
}
<?php <?php
namespace GuzzleHttp\Exception; namespace GuzzleHttp\Exception;
/** use Throwable;
* @method string getMessage()
* @method \Throwable|null getPrevious() if (interface_exists(Throwable::class)) {
* @method mixed getCode() interface GuzzleException extends Throwable
* @method string getFile() {
* @method int getLine() }
* @method array getTrace() } else {
* @method string getTraceAsString() /**
*/ * @method string getMessage()
interface GuzzleException {} * @method \Throwable|null getPrevious()
* @method mixed getCode()
* @method string getFile()
* @method int getLine()
* @method array getTrace()
* @method string getTraceAsString()
*/
interface GuzzleException
{
}
}
<?php
namespace GuzzleHttp\Exception;
final class InvalidArgumentException extends \InvalidArgumentException implements GuzzleException
{
}
<?php <?php
namespace GuzzleHttp\Exception; namespace GuzzleHttp\Exception;
use GuzzleHttp\Promise\PromiseInterface;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Promise\PromiseInterface;
use Psr\Http\Message\UriInterface; use Psr\Http\Message\UriInterface;
/** /**
...@@ -14,7 +14,7 @@ class RequestException extends TransferException ...@@ -14,7 +14,7 @@ class RequestException extends TransferException
/** @var RequestInterface */ /** @var RequestInterface */
private $request; private $request;
/** @var ResponseInterface */ /** @var ResponseInterface|null */
private $response; private $response;
/** @var array */ /** @var array */
...@@ -124,42 +124,17 @@ class RequestException extends TransferException ...@@ -124,42 +124,17 @@ class RequestException extends TransferException
*/ */
public static function getResponseBodySummary(ResponseInterface $response) public static function getResponseBodySummary(ResponseInterface $response)
{ {
$body = $response->getBody(); return \GuzzleHttp\Psr7\get_message_body_summary($response);
if (!$body->isSeekable()) {
return null;
}
$size = $body->getSize();
if ($size === 0) {
return null;
}
$summary = $body->read(120);
$body->rewind();
if ($size > 120) {
$summary .= ' (truncated...)';
}
// Matches any printable character, including unicode characters:
// letters, marks, numbers, punctuation, spacing, and separators.
if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/', $summary)) {
return null;
}
return $summary;
} }
/** /**
* Obfuscates URI if there is an username and a password present * Obfuscates URI if there is a username and a password present
* *
* @param UriInterface $uri * @param UriInterface $uri
* *
* @return UriInterface * @return UriInterface
*/ */
private static function obfuscateUri($uri) private static function obfuscateUri(UriInterface $uri)
{ {
$userInfo = $uri->getUserInfo(); $userInfo = $uri->getUserInfo();
......
...@@ -4,4 +4,6 @@ namespace GuzzleHttp\Exception; ...@@ -4,4 +4,6 @@ namespace GuzzleHttp\Exception;
/** /**
* Exception when a server error is encountered (5xx codes) * Exception when a server error is encountered (5xx codes)
*/ */
class ServerException extends BadResponseException {} class ServerException extends BadResponseException
{
}
<?php <?php
namespace GuzzleHttp\Exception; namespace GuzzleHttp\Exception;
class TooManyRedirectsException extends RequestException {} class TooManyRedirectsException extends RequestException
{
}
<?php <?php
namespace GuzzleHttp\Exception; namespace GuzzleHttp\Exception;
class TransferException extends \RuntimeException implements GuzzleException {} class TransferException extends \RuntimeException implements GuzzleException
{
}
<?php <?php
namespace GuzzleHttp\Handler; namespace GuzzleHttp\Handler;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Promise\FulfilledPromise; use GuzzleHttp\Promise\FulfilledPromise;
use GuzzleHttp\Psr7; use GuzzleHttp\Psr7;
use GuzzleHttp\Psr7\LazyOpenStream; use GuzzleHttp\Psr7\LazyOpenStream;
...@@ -14,6 +14,9 @@ use Psr\Http\Message\RequestInterface; ...@@ -14,6 +14,9 @@ use Psr\Http\Message\RequestInterface;
*/ */
class CurlFactory implements CurlFactoryInterface class CurlFactory implements CurlFactoryInterface
{ {
const CURL_VERSION_STR = 'curl_version';
const LOW_CURL_VERSION_NUMBER = '7.21.2';
/** @var array */ /** @var array */
private $handles = []; private $handles = [];
...@@ -117,6 +120,7 @@ class CurlFactory implements CurlFactoryInterface ...@@ -117,6 +120,7 @@ class CurlFactory implements CurlFactoryInterface
private static function invokeStats(EasyHandle $easy) private static function invokeStats(EasyHandle $easy)
{ {
$curlStats = curl_getinfo($easy->handle); $curlStats = curl_getinfo($easy->handle);
$curlStats['appconnect_time'] = curl_getinfo($easy->handle, CURLINFO_APPCONNECT_TIME);
$stats = new TransferStats( $stats = new TransferStats(
$easy->request, $easy->request,
$easy->response, $easy->response,
...@@ -136,7 +140,9 @@ class CurlFactory implements CurlFactoryInterface ...@@ -136,7 +140,9 @@ class CurlFactory implements CurlFactoryInterface
$ctx = [ $ctx = [
'errno' => $easy->errno, 'errno' => $easy->errno,
'error' => curl_error($easy->handle), 'error' => curl_error($easy->handle),
'appconnect_time' => curl_getinfo($easy->handle, CURLINFO_APPCONNECT_TIME),
] + curl_getinfo($easy->handle); ] + curl_getinfo($easy->handle);
$ctx[self::CURL_VERSION_STR] = curl_version()['version'];
$factory->release($easy); $factory->release($easy);
// Retry when nothing is present or when curl failed to rewind. // Retry when nothing is present or when curl failed to rewind.
...@@ -172,13 +178,22 @@ class CurlFactory implements CurlFactoryInterface ...@@ -172,13 +178,22 @@ class CurlFactory implements CurlFactoryInterface
) )
); );
} }
if (version_compare($ctx[self::CURL_VERSION_STR], self::LOW_CURL_VERSION_NUMBER)) {
$message = sprintf( $message = sprintf(
'cURL error %s: %s (%s)', 'cURL error %s: %s (%s)',
$ctx['errno'], $ctx['errno'],
$ctx['error'], $ctx['error'],
'see http://curl.haxx.se/libcurl/c/libcurl-errors.html' 'see https://curl.haxx.se/libcurl/c/libcurl-errors.html'
); );
} else {
$message = sprintf(
'cURL error %s: %s (%s) for %s',
$ctx['errno'],
$ctx['error'],
'see https://curl.haxx.se/libcurl/c/libcurl-errors.html',
$easy->request->getUri()
);
}
// Create a connection exception if it was a specific error code. // Create a connection exception if it was a specific error code.
$error = isset($connectionErrors[$easy->errno]) $error = isset($connectionErrors[$easy->errno])
...@@ -439,11 +454,16 @@ class CurlFactory implements CurlFactoryInterface ...@@ -439,11 +454,16 @@ class CurlFactory implements CurlFactoryInterface
} }
if (isset($options['ssl_key'])) { if (isset($options['ssl_key'])) {
$sslKey = $options['ssl_key']; if (is_array($options['ssl_key'])) {
if (is_array($sslKey)) { if (count($options['ssl_key']) === 2) {
$conf[CURLOPT_SSLKEYPASSWD] = $sslKey[1]; list($sslKey, $conf[CURLOPT_SSLKEYPASSWD]) = $options['ssl_key'];
$sslKey = $sslKey[0]; } else {
list($sslKey) = $options['ssl_key'];
}
} }
$sslKey = isset($sslKey) ? $sslKey: $options['ssl_key'];
if (!file_exists($sslKey)) { if (!file_exists($sslKey)) {
throw new \InvalidArgumentException( throw new \InvalidArgumentException(
"SSL private key not found: {$sslKey}" "SSL private key not found: {$sslKey}"
......
...@@ -3,7 +3,7 @@ namespace GuzzleHttp\Handler; ...@@ -3,7 +3,7 @@ namespace GuzzleHttp\Handler;
use GuzzleHttp\Promise as P; use GuzzleHttp\Promise as P;
use GuzzleHttp\Promise\Promise; use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Psr7; use GuzzleHttp\Utils;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
/** /**
...@@ -23,6 +23,7 @@ class CurlMultiHandler ...@@ -23,6 +23,7 @@ class CurlMultiHandler
private $active; private $active;
private $handles = []; private $handles = [];
private $delays = []; private $delays = [];
private $options = [];
/** /**
* This handler accepts the following options: * This handler accepts the following options:
...@@ -30,6 +31,8 @@ class CurlMultiHandler ...@@ -30,6 +31,8 @@ class CurlMultiHandler
* - handle_factory: An optional factory used to create curl handles * - handle_factory: An optional factory used to create curl handles
* - select_timeout: Optional timeout (in seconds) to block before timing * - select_timeout: Optional timeout (in seconds) to block before timing
* out while selecting curl handles. Defaults to 1 second. * out while selecting curl handles. Defaults to 1 second.
* - options: An associative array of CURLMOPT_* options and
* corresponding values for curl_multi_setopt()
* *
* @param array $options * @param array $options
*/ */
...@@ -37,14 +40,31 @@ class CurlMultiHandler ...@@ -37,14 +40,31 @@ class CurlMultiHandler
{ {
$this->factory = isset($options['handle_factory']) $this->factory = isset($options['handle_factory'])
? $options['handle_factory'] : new CurlFactory(50); ? $options['handle_factory'] : new CurlFactory(50);
$this->selectTimeout = isset($options['select_timeout'])
? $options['select_timeout'] : 1; if (isset($options['select_timeout'])) {
$this->selectTimeout = $options['select_timeout'];
} elseif ($selectTimeout = getenv('GUZZLE_CURL_SELECT_TIMEOUT')) {
$this->selectTimeout = $selectTimeout;
} else {
$this->selectTimeout = 1;
}
$this->options = isset($options['options']) ? $options['options'] : [];
} }
public function __get($name) public function __get($name)
{ {
if ($name === '_mh') { if ($name === '_mh') {
return $this->_mh = curl_multi_init(); $this->_mh = curl_multi_init();
foreach ($this->options as $option => $value) {
// A warning is raised in case of a wrong option.
curl_multi_setopt($this->_mh, $option, $value);
}
// Further calls to _mh will return the value directly, without entering the
// __get() method at all.
return $this->_mh;
} }
throw new \BadMethodCallException(); throw new \BadMethodCallException();
...@@ -82,7 +102,7 @@ class CurlMultiHandler ...@@ -82,7 +102,7 @@ class CurlMultiHandler
{ {
// Add any delayed handles if needed. // Add any delayed handles if needed.
if ($this->delays) { if ($this->delays) {
$currentTime = microtime(true); $currentTime = Utils::currentTime();
foreach ($this->delays as $id => $delay) { foreach ($this->delays as $id => $delay) {
if ($currentTime >= $delay) { if ($currentTime >= $delay) {
unset($this->delays[$id]); unset($this->delays[$id]);
...@@ -134,7 +154,7 @@ class CurlMultiHandler ...@@ -134,7 +154,7 @@ class CurlMultiHandler
if (empty($easy->options['delay'])) { if (empty($easy->options['delay'])) {
curl_multi_add_handle($this->_mh, $easy->handle); curl_multi_add_handle($this->_mh, $easy->handle);
} else { } else {
$this->delays[$id] = microtime(true) + ($easy->options['delay'] / 1000); $this->delays[$id] = Utils::currentTime() + ($easy->options['delay'] / 1000);
} }
} }
...@@ -186,7 +206,7 @@ class CurlMultiHandler ...@@ -186,7 +206,7 @@ class CurlMultiHandler
private function timeToNext() private function timeToNext()
{ {
$currentTime = microtime(true); $currentTime = Utils::currentTime();
$nextTime = PHP_INT_MAX; $nextTime = PHP_INT_MAX;
foreach ($this->delays as $time) { foreach ($this->delays as $time) {
if ($time < $nextTime) { if ($time < $nextTime) {
......