Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
Diego Luces committed Jul 10, 2019
2 parents c53046d + ca2892a commit 03e3a15
Show file tree
Hide file tree
Showing 14 changed files with 87 additions and 35 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Expand Up @@ -9,7 +9,7 @@ RUN set -xe \
&& composer require guzzlehttp/guzzle


FROM php:7.2
FROM php:7.3

RUN mkdir /guzzle

Expand Down
2 changes: 1 addition & 1 deletion docs/request-options.rst
Expand Up @@ -737,7 +737,7 @@ progress

The function accepts the following positional arguments:

- the total number of bytes expected to be downloaded
- the total number of bytes expected to be downloaded, zero if unknown
- the number of bytes downloaded so far
- the total number of bytes expected to be uploaded
- the number of bytes uploaded so far
Expand Down
7 changes: 5 additions & 2 deletions docs/testing.rst
Expand Up @@ -32,7 +32,7 @@ a response or exception by shifting return values off of a queue.
// Create a mock and queue two responses.
$mock = new MockHandler([
new Response(200, ['X-Foo' => 'Bar']),
new Response(200, ['X-Foo' => 'Bar'], 'Hello, World'),
new Response(202, ['Content-Length' => 0]),
new RequestException('Error Communicating with Server', new Request('GET', 'test'))
]);
Expand All @@ -41,8 +41,11 @@ a response or exception by shifting return values off of a queue.
$client = new Client(['handler' => $handlerStack]);
// The first request is intercepted with the first response.
echo $client->request('GET', '/')->getStatusCode();
$response = $client->request('GET', '/');
echo $response->getStatusCode();
//> 200
echo $response->getBody();
//> Hello, World
// The second request is intercepted with the second response.
echo $client->request('GET', '/')->getStatusCode();
//> 202
Expand Down
27 changes: 17 additions & 10 deletions src/Exception/GuzzleException.php
@@ -1,13 +1,20 @@
<?php
namespace GuzzleHttp\Exception;

/**
* @method string getMessage()
* @method \Throwable|null getPrevious()
* @method mixed getCode()
* @method string getFile()
* @method int getLine()
* @method array getTrace()
* @method string getTraceAsString()
*/
interface GuzzleException {}
use Throwable;

if (interface_exists(Throwable::class)) {
interface GuzzleException extends Throwable {}
} else {
/**
* @method string getMessage()
* @method \Throwable|null getPrevious()
* @method mixed getCode()
* @method string getFile()
* @method int getLine()
* @method array getTrace()
* @method string getTraceAsString()
*/
interface GuzzleException {}
}

29 changes: 22 additions & 7 deletions src/Handler/CurlFactory.php
Expand Up @@ -14,6 +14,9 @@
*/
class CurlFactory implements CurlFactoryInterface
{
const CURL_VERSION_STR = 'curl_version';
const LOW_CURL_VERSION_NUMBER = '7.21.2';

/** @var array */
private $handles = [];

Expand Down Expand Up @@ -117,6 +120,7 @@ public static function finish(
private static function invokeStats(EasyHandle $easy)
{
$curlStats = curl_getinfo($easy->handle);
$curlStats['appconnect_time'] = curl_getinfo($easy->handle, CURLINFO_APPCONNECT_TIME);
$stats = new TransferStats(
$easy->request,
$easy->response,
Expand All @@ -136,7 +140,9 @@ private static function finishError(
$ctx = [
'errno' => $easy->errno,
'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'];
$factory->release($easy);

// Retry when nothing is present or when curl failed to rewind.
Expand Down Expand Up @@ -172,13 +178,22 @@ private static function createRejection(EasyHandle $easy, array $ctx)
)
);
}

$message = sprintf(
'cURL error %s: %s (%s)',
$ctx['errno'],
$ctx['error'],
'see https://curl.haxx.se/libcurl/c/libcurl-errors.html'
);
if (version_compare($ctx[self::CURL_VERSION_STR], self::LOW_CURL_VERSION_NUMBER)) {
$message = sprintf(
'cURL error %s: %s (%s)',
$ctx['errno'],
$ctx['error'],
'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.
$error = isset($connectionErrors[$easy->errno])
Expand Down
6 changes: 3 additions & 3 deletions src/Handler/CurlMultiHandler.php
Expand Up @@ -88,7 +88,7 @@ public function tick()
{
// Add any delayed handles if needed.
if ($this->delays) {
$currentTime = microtime(true);
$currentTime = \GuzzleHttp\_current_time();
foreach ($this->delays as $id => $delay) {
if ($currentTime >= $delay) {
unset($this->delays[$id]);
Expand Down Expand Up @@ -140,7 +140,7 @@ private function addRequest(array $entry)
if (empty($easy->options['delay'])) {
curl_multi_add_handle($this->_mh, $easy->handle);
} else {
$this->delays[$id] = microtime(true) + ($easy->options['delay'] / 1000);
$this->delays[$id] = \GuzzleHttp\_current_time() + ($easy->options['delay'] / 1000);
}
}

Expand Down Expand Up @@ -192,7 +192,7 @@ private function processMessages()

private function timeToNext()
{
$currentTime = microtime(true);
$currentTime = \GuzzleHttp\_current_time();
$nextTime = PHP_INT_MAX;
foreach ($this->delays as $time) {
if ($time < $nextTime) {
Expand Down
4 changes: 2 additions & 2 deletions src/Handler/StreamHandler.php
Expand Up @@ -33,7 +33,7 @@ public function __invoke(RequestInterface $request, array $options)
usleep($options['delay'] * 1000);
}

$startTime = isset($options['on_stats']) ? microtime(true) : null;
$startTime = isset($options['on_stats']) ? \GuzzleHttp\_current_time() : null;

try {
// Does not support the expect header.
Expand Down Expand Up @@ -82,7 +82,7 @@ private function invokeStats(
$stats = new TransferStats(
$request,
$response,
microtime(true) - $startTime,
\GuzzleHttp\_current_time() - $startTime,
$error,
[]
);
Expand Down
12 changes: 12 additions & 0 deletions src/functions.php
Expand Up @@ -331,3 +331,15 @@ function json_encode($value, $options = 0, $depth = 512)

return $json;
}

/**
* Wrapper for the hrtime() or microtime() functions
* (depending on the PHP version, one of the two is used)
*
* @return float|mixed UNIX timestamp
* @internal
*/
function _current_time()
{
return function_exists('hrtime') ? hrtime(true) / 1e9 : microtime(true);
}
14 changes: 11 additions & 3 deletions tests/Cookie/CookieJarTest.php
@@ -1,6 +1,9 @@
<?php
namespace GuzzleHttp\Tests\CookieJar;

use DateInterval;
use DateTime;
use DateTimeImmutable;
use GuzzleHttp\Cookie\CookieJar;
use GuzzleHttp\Cookie\SetCookie;
use GuzzleHttp\Psr7\Request;
Expand Down Expand Up @@ -366,7 +369,7 @@ public function testCanConvertToAndLoadFromArray()
public function testAddsCookiesWithEmptyPathFromResponse()
{
$response = new Response(200, array(
'Set-Cookie' => "fpc=foobar; expires=Fri, 02-Mar-2019 02:17:40 GMT; path=;"
'Set-Cookie' => "fpc=foobar; expires={$this->futureExpirationDate()}; path=;"
));
$request = new Request('GET', 'http://www.example.com');
$this->jar->extractCookies($request, $response);
Expand Down Expand Up @@ -396,11 +399,11 @@ public function testCookiePathWithEmptySetCookiePath($uriPath, $cookiePath)
$response = (new Response(200))
->withAddedHeader(
'Set-Cookie',
"foo=bar; expires=Fri, 02-Mar-2019 02:17:40 GMT; domain=www.example.com; path=;"
"foo=bar; expires={$this->futureExpirationDate()}; domain=www.example.com; path=;"
)
->withAddedHeader(
'Set-Cookie',
"bar=foo; expires=Fri, 02-Mar-2019 02:17:40 GMT; domain=www.example.com; path=foobar;"
"bar=foo; expires={$this->futureExpirationDate()}; domain=www.example.com; path=foobar;"
)
;
$request = (new Request('GET', $uriPath))->withHeader('Host', 'www.example.com');
Expand All @@ -409,4 +412,9 @@ public function testCookiePathWithEmptySetCookiePath($uriPath, $cookiePath)
$this->assertSame($cookiePath, $this->jar->toArray()[0]['Path']);
$this->assertSame($cookiePath, $this->jar->toArray()[1]['Path']);
}

private function futureExpirationDate()
{
return (new DateTimeImmutable)->add(new DateInterval('P1D'))->format(DateTime::COOKIE);
}
}
2 changes: 2 additions & 0 deletions tests/Handler/CurlFactoryTest.php
Expand Up @@ -685,6 +685,7 @@ public function testInvokesOnStatsOnSuccess()
(string) $gotStats->getRequest()->getUri()
);
$this->assertGreaterThan(0, $gotStats->getTransferTime());
$this->assertArrayHasKey('appconnect_time', $gotStats->getHandlerStats());
}

public function testInvokesOnStatsOnError()
Expand All @@ -711,6 +712,7 @@ public function testInvokesOnStatsOnError()
);
$this->assertInternalType('float', $gotStats->getTransferTime());
$this->assertInternalType('int', $gotStats->getHandlerErrorData());
$this->assertArrayHasKey('appconnect_time', $gotStats->getHandlerStats());
}

public function testRewindsBodyIfPossible()
Expand Down
4 changes: 2 additions & 2 deletions tests/Handler/CurlHandlerTest.php
Expand Up @@ -47,9 +47,9 @@ public function testDoesSleep()
Server::enqueue([$response]);
$a = new CurlHandler();
$request = new Request('GET', Server::$url);
$s = microtime(true);
$s = \GuzzleHttp\_current_time();
$a($request, ['delay' => 0.1])->wait();
$this->assertGreaterThan(0.0001, microtime(true) - $s);
$this->assertGreaterThan(0.0001, \GuzzleHttp\_current_time() - $s);
}

public function testCreatesCurlErrorsWithContext()
Expand Down
4 changes: 2 additions & 2 deletions tests/Handler/CurlMultiHandlerTest.php
Expand Up @@ -68,10 +68,10 @@ public function testDelaysConcurrently()
Server::flush();
Server::enqueue([new Response()]);
$a = new CurlMultiHandler();
$expected = microtime(true) + (100 / 1000);
$expected = \GuzzleHttp\_current_time() + (100 / 1000);
$response = $a(new Request('GET', Server::$url), ['delay' => 100]);
$response->wait();
$this->assertGreaterThanOrEqual($expected, microtime(true));
$this->assertGreaterThanOrEqual($expected, \GuzzleHttp\_current_time());
}

public function testUsesTimeoutEnvironmentVariables()
Expand Down
4 changes: 2 additions & 2 deletions tests/Handler/StreamHandlerTest.php
Expand Up @@ -506,9 +506,9 @@ public function testDoesSleep()
Server::enqueue([$response]);
$a = new StreamHandler();
$request = new Request('GET', Server::$url);
$s = microtime(true);
$s = \GuzzleHttp\_current_time();
$a($request, ['delay' => 0.1])->wait();
$this->assertGreaterThan(0.0001, microtime(true) - $s);
$this->assertGreaterThan(0.0001, \GuzzleHttp\_current_time() - $s);
}

/**
Expand Down
5 changes: 5 additions & 0 deletions tests/functionsTest.php
Expand Up @@ -128,6 +128,11 @@ public function testDecodesJsonAndThrowsOnError()
{
\GuzzleHttp\json_decode('{{]]');
}

public function testCurrentTime()
{
$this->assertGreaterThan(0, GuzzleHttp\_current_time());
}
}

final class StrClass
Expand Down

0 comments on commit 03e3a15

Please sign in to comment.