Skip to content

Commit

Permalink
Merge branch 'master' into force-ip-resolve-stream
Browse files Browse the repository at this point in the history
  • Loading branch information
Christian Schmidt committed Mar 29, 2017
2 parents fbab002 + a1c4a74 commit 8b0fa76
Show file tree
Hide file tree
Showing 20 changed files with 284 additions and 43 deletions.
19 changes: 10 additions & 9 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
build/* export-ignore
docs/* export-ignore
tests/* export-ignore
.editorconfig export-ignore
.gitattributes export-ignore
.gitignore export-ignore
.travis export-ignore
Makefile export-ignore
phpunit.xml.dist export-ignore
.editorconfig export-ignore
.gitattributes export-ignore
/.github/ export-ignore
.gitignore export-ignore
/.travis.yml export-ignore
/build/ export-ignore
/docs/ export-ignore
/Makefile export-ignore
/phpunit.xml.dist export-ignore
/tests/ export-ignore
3 changes: 3 additions & 0 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Contributing

Please see our [contributing guide](http://docs.guzzlephp.org/en/latest/overview.html#contributing).
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ before_script:
- composer install --no-interaction --prefer-source --dev
- ~/.nvm/nvm.sh install v0.6.14
- ~/.nvm/nvm.sh run v0.6.14
- '[ "$TRAVIS_PHP_VERSION" != "7.0" ] || echo "xdebug.overload_var_dump = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini'
- if [[ "$TRAVIS_PHP_VERSION" != "7.0" || "$TRAVIS_PHP_VERSION" != "7.1" ]]; then echo "xdebug.overload_var_dump = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini || true; fi

script: make test

Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# CHANGELOG

## 6.2.3 - 2017-02-28

* Fix deprecations with guzzle/psr7 version 1.4

## 6.2.2 - 2016-10-08

* Allow to pass nullable Response to delay callable
Expand Down
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ $promise->wait();
## Help and docs

- [Documentation](http://guzzlephp.org/)
- [stackoverflow](http://stackoverflow.com/questions/tagged/guzzle)
- [Stack Overflow](http://stackoverflow.com/questions/tagged/guzzle)
- [Gitter](https://gitter.im/guzzle/guzzle)


Expand Down Expand Up @@ -73,14 +73,15 @@ composer.phar update

## Version Guidance

| Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 |
|---------|-------------|---------------------|--------------|---------------------|---------------------|-------|
| 3.x | EOL | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No |
| 4.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | N/A | N/A | No |
| 5.x | Maintained | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No |
| 6.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes |
| Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 | PHP Version |
|---------|------------|---------------------|--------------|---------------------|---------------------|-------|-------------|
| 3.x | EOL | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No | >= 5.3.3 |
| 4.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A | No | >= 5.4 |
| 5.x | Maintained | `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 |

[guzzle-3-repo]: https://github.com/guzzle/guzzle3
[guzzle-4-repo]: https://github.com/guzzle/guzzle/tree/4.x
[guzzle-5-repo]: https://github.com/guzzle/guzzle/tree/5.3
[guzzle-6-repo]: https://github.com/guzzle/guzzle
[guzzle-3-docs]: http://guzzle3.readthedocs.org/en/latest/
Expand Down
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
],
"require": {
"php": ">=5.5",
"guzzlehttp/psr7": "^1.3.1",
"guzzlehttp/psr7": "^1.4",
"guzzlehttp/promises": "^1.0"
},
"require-dev": {
Expand All @@ -33,6 +33,9 @@
"GuzzleHttp\\Tests\\": "tests/"
}
},
"suggest": {
"psr/log": "Required for using the Log middleware"
},
"extra": {
"branch-alias": {
"dev-master": "6.2-dev"
Expand Down
45 changes: 45 additions & 0 deletions docs/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,48 @@ setting the ``expect`` request option to ``false``:
// Disable the expect header on all client requests
$client = new GuzzleHttp\Client(['expect' => false]);
How can I track a redirected requests?
======================================

You can enable tracking of redirected URIs and status codes via the
`track_redirects` option. Each redirected URI and status code will be stored in the
``X-Guzzle-Redirect-History`` and the ``X-Guzzle-Redirect-Status-History``
header respectively.

The initial request's URI and the final status code will be excluded from the results.
With this in mind you should be able to easily track a request's full redirect path.

For example, let's say you need to track redirects and provide both results
together in a single report:

.. code-block:: php
// First you configure Guzzle with redirect tracking and make a request
$client = new Client([
RequestOptions::ALLOW_REDIRECTS => [
'max' => 10, // allow at most 10 redirects.
'strict' => true, // use "strict" RFC compliant redirects.
'referer' => true, // add a Referer header
'track_redirects' => true,
],
]);
$initialRequest = '/redirect/3'; // Store the request URI for later use
$response = $client->request('GET', $initialRequest); // Make your request
// Retrieve both Redirect History headers
$redirectUriHistory = $response->getHeader('X-Guzzle-Redirect-History'); // retrieve Redirect URI history
$redirectCodeHistory = $response->getHeader('X-Guzzle-Redirect-Status-History'); // retrieve Redirect HTTP Status history
// Add the initial URI requested to the (beginning of) URI history
array_unshift($redirectUriHistory, $initialRequest);
// Add the final HTTP status code to the end of HTTP response history
array_push($redirectCodeHistory, $response->getStatusCode());
// (Optional) Combine the items of each array into a single result set
$fullRedirectReport = [];
foreach ($redirectUriHistory as $key => $value) {
$fullRedirectReport[$key] = ['location' => $value, 'code' => $redirectCodeHistory[$key]];
}
echo json_encode($fullRedirectReport);
4 changes: 2 additions & 2 deletions docs/psr7.rst
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ scheme can be set to "http" or "https".
$request = new Request('GET', 'http://httpbin.org');
echo $request->getUri()->getScheme(); // http
echo $request->getUri(); // http://httpbin.org/get
echo $request->getUri(); // http://httpbin.org
Host
Expand All @@ -257,7 +257,7 @@ No port is necessary when using the "http" or "https" schemes.

.. code-block:: php
$request = $client->createRequest('GET', 'http://httpbin.org:8080');
$request = new Request('GET', 'http://httpbin.org:8080');
echo $request->getUri()->getPort(); // 8080
echo $request->getUri(); // http://httpbin.org:8080
Expand Down
6 changes: 3 additions & 3 deletions docs/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ requests.
// You can access each result using the key provided to the unwrap
// function.
echo $results['image']->getHeader('Content-Length');
echo $results['png']->getHeader('Content-Length');
echo $results['image']['value']->getHeader('Content-Length')[0]
echo $results['png']['value']->getHeader('Content-Length')[0]
You can use the ``GuzzleHttp\Pool`` object when you have an indeterminate
amount of requests you wish to send.
Expand Down Expand Up @@ -427,7 +427,7 @@ Cookies

Guzzle can maintain a cookie session for you if instructed using the
``cookies`` request option. When sending a request, the ``cookies`` option
must be set an an instance of ``GuzzleHttp\Cookie\CookieJarInterface``.
must be set to an instance of ``GuzzleHttp\Cookie\CookieJarInterface``.

.. code-block:: php
Expand Down
56 changes: 51 additions & 5 deletions docs/request-options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,14 @@ pairs:
is encountered. The callable is invoked with the original request and the
redirect response that was received. Any return value from the on_redirect
function is ignored.
- track_redirects: (bool) When set to ``true``, each redirected URI encountered
will be tracked in the ``X-Guzzle-Redirect-History`` header in the order in
which the redirects were encountered.
- track_redirects: (bool) When set to ``true``, each redirected URI and status
code encountered will be tracked in the ``X-Guzzle-Redirect-History`` and
``X-Guzzle-Redirect-Status-History`` headers respectively. All URIs and
status codes will be stored in the order which the redirects were encountered.

Note: When tracking redirects the ``X-Guzzle-Redirect-History`` header will
exclude the initial request's URI and the ``X-Guzzle-Redirect-Status-History``
header will exclude the final status code.

.. code-block:: php
Expand Down Expand Up @@ -105,6 +110,9 @@ pairs:
echo $res->getHeaderLine('X-Guzzle-Redirect-History');
// http://first-redirect, http://second-redirect, etc...
echo $res->getHeaderLine('X-Guzzle-Redirect-Status-History');
// 301, 302, etc...
.. warning::

This option only has an effect if your handler has the
Expand Down Expand Up @@ -154,6 +162,20 @@ digest
creating a replacement that can be used with any HTTP handler is
planned.

ntlm
Use `Microsoft NTLM authentication <https://msdn.microsoft.com/en-us/library/windows/desktop/aa378749(v=vs.85).aspx>`_
(must be supported by the HTTP handler).

.. code-block:: php
$client->request('GET', '/get', [
'auth' => ['username', 'password', 'ntlm']
]);
.. note::

This is currently only supported when using the cURL handler.


body
----
Expand Down Expand Up @@ -557,7 +579,7 @@ over the wire.
$clientHandler = $client->getConfig('handler');
// Create a middleware that echoes parts of the request.
$tapMiddleware = Middleware::tap(function ($request) {
echo $request->getHeader('Content-Type');
echo $request->getHeaderLine('Content-Type');
// application/json
echo $request->getBody();
// {"foo":"bar"}
Expand Down Expand Up @@ -802,14 +824,38 @@ query
// Send a GET request to /get?foo=bar
$client->request('GET', '/get', ['query' => ['foo' => 'bar']]);
Query strings specified in the ``query`` option will overwrite a query string
Query strings specified in the ``query`` option will overwrite all query string
values supplied in the URI of a request.

.. code-block:: php
// Send a GET request to /get?foo=bar
$client->request('GET', '/get?abc=123', ['query' => ['foo' => 'bar']]);
read_timeout
------------

:Summary: Float describing the timeout to use when reading a streamed body
:Types: float
:Default: Defaults to the value of the ``default_socket_timeout`` PHP ini setting
:Constant: ``GuzzleHttp\RequestOptions::READ_TIMEOUT``

The timeout applies to individual read operations on a streamed body (when the ``stream`` option is enabled).

.. code-block:: php
$response = $client->request('GET', '/stream', [
'stream' => true,
'read_timeout' => 10,
]);
$body = $response->getBody();
// Returns false on timeout
$data = $body->read(1024);
// Returns false on timeout
$line = fgets($body->detach());
.. _sink-option:

Expand Down
10 changes: 8 additions & 2 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ public function __construct(array $config = [])
{
if (!isset($config['handler'])) {
$config['handler'] = HandlerStack::create();
} elseif (!is_callable($config['handler'])) {
throw new \InvalidArgumentException('handler must be a callable');
}

// Convert the base_uri to a UriInterface
Expand Down Expand Up @@ -142,7 +144,7 @@ private function buildUri($uri, array $config)
$uri = Psr7\uri_for($uri === null ? '' : $uri);

if (isset($config['base_uri'])) {
$uri = Psr7\Uri::resolve(Psr7\uri_for($config['base_uri']), $uri);
$uri = Psr7\UriResolver::resolve(Psr7\uri_for($config['base_uri']), $uri);
}

return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri;
Expand Down Expand Up @@ -350,6 +352,10 @@ private function applyOptions(RequestInterface $request, array &$options)
$options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_DIGEST;
$options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
break;
case 'ntlm':
$options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_NTLM;
$options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
break;
}
}

Expand Down Expand Up @@ -402,7 +408,7 @@ private function invalidBody()
throw new \InvalidArgumentException('Passing in the "body" request '
. 'option as an array to send a POST request has been deprecated. '
. 'Please use the "form_params" request option to send a '
. 'application/x-www-form-urlencoded request, or a the "multipart" '
. 'application/x-www-form-urlencoded request, or the "multipart" '
. 'request option to send a multipart/form-data request.');
}
}
22 changes: 21 additions & 1 deletion src/Exception/BadResponseException.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
<?php
namespace GuzzleHttp\Exception;

use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

/**
* Exception when an HTTP error occurs (4xx or 5xx error)
*/
class BadResponseException extends RequestException {}
class BadResponseException extends RequestException
{
public function __construct(
$message,
RequestInterface $request,
ResponseInterface $response = null,
\Exception $previous = null,
array $handlerContext = []
) {
if (null === $response) {
@trigger_error(
'Instantiating the ' . __CLASS__ . ' class without a Response is deprecated since version 6.3 and will be removed in 7.0.',
E_USER_DEPRECATED
);
}
parent::__construct($message, $request, $response, $previous, $handlerContext);
}
}
2 changes: 1 addition & 1 deletion src/Handler/CurlFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
class CurlFactory implements CurlFactoryInterface
{
/** @var array */
private $handles;
private $handles = [];

/** @var int Total number of idle handles to keep in cache */
private $maxHandles;
Expand Down
20 changes: 19 additions & 1 deletion src/Handler/StreamHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,16 @@ private function createStream(RequestInterface $request, array $options)
);
}

// Microsoft NTLM authentication only supported with curl handler
if (isset($options['auth'])
&& is_array($options['auth'])
&& isset($options['auth'][2])
&& 'ntlm' == $options['auth'][2]
) {

throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler');
}

$uri = $this->resolveHost($request, $options);

$context = $this->createResource(
Expand All @@ -310,9 +320,17 @@ function () use ($context, $params) {
);

return $this->createResource(
function () use ($uri, &$http_response_header, $context) {
function () use ($uri, &$http_response_header, $context, $options) {
$resource = fopen((string) $uri, 'r', null, $context);
$this->lastHeaders = $http_response_header;

if (isset($options['read_timeout'])) {
$readTimeout = $options['read_timeout'];
$sec = (int) $readTimeout;
$usec = ($readTimeout - $sec) * 100000;
stream_set_timeout($resource, $sec, $usec);
}

return $resource;
}
);
Expand Down
Loading

0 comments on commit 8b0fa76

Please sign in to comment.