initial commit
This commit is contained in:
46
hamrokhaanpaan/wp-content/__plugins/google-site-kit/third-party/guzzlehttp/ringphp/README.rst
vendored
Normal file
46
hamrokhaanpaan/wp-content/__plugins/google-site-kit/third-party/guzzlehttp/ringphp/README.rst
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
=======
|
||||
RingPHP
|
||||
=======
|
||||
|
||||
Provides a simple API and specification that abstracts away the details of HTTP
|
||||
into a single PHP function. RingPHP be used to power HTTP clients and servers
|
||||
through a PHP function that accepts a request hash and returns a response hash
|
||||
that is fulfilled using a `promise <https://github.com/reactphp/promise>`_,
|
||||
allowing RingPHP to support both synchronous and asynchronous workflows.
|
||||
|
||||
By abstracting the implementation details of different HTTP clients and
|
||||
servers, RingPHP allows you to utilize pluggable HTTP clients and servers
|
||||
without tying your application to a specific implementation.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
use GuzzleHttp\Ring\Client\CurlHandler;
|
||||
|
||||
$handler = new CurlHandler();
|
||||
$response = $handler([
|
||||
'http_method' => 'GET',
|
||||
'uri' => '/',
|
||||
'headers' => [
|
||||
'host' => ['www.google.com'],
|
||||
'x-foo' => ['baz']
|
||||
]
|
||||
]);
|
||||
|
||||
$response->then(function (array $response) {
|
||||
echo $response['status'];
|
||||
});
|
||||
|
||||
$response->wait();
|
||||
|
||||
RingPHP is inspired by Clojure's `Ring <https://github.com/ring-clojure/ring>`_,
|
||||
which, in turn, was inspired by Python's WSGI and Ruby's Rack. RingPHP is
|
||||
utilized as the handler layer in `Guzzle <http://guzzlephp.org>`_ 5.0+ to send
|
||||
HTTP requests.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
See http://ringphp.readthedocs.org/ for the full online documentation.
|
@@ -0,0 +1,173 @@
|
||||
===============
|
||||
Client Handlers
|
||||
===============
|
||||
|
||||
Client handlers accept a request array and return a future response array that
|
||||
can be used synchronously as an array or asynchronously using a promise.
|
||||
|
||||
Built-In Handlers
|
||||
-----------------
|
||||
|
||||
RingPHP comes with three built-in client handlers.
|
||||
|
||||
Stream Handler
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
The ``GuzzleHttp\Ring\Client\StreamHandler`` uses PHP's
|
||||
`http stream wrapper <http://php.net/manual/en/wrappers.http.php>`_ to send
|
||||
requests.
|
||||
|
||||
.. note::
|
||||
|
||||
This handler cannot send requests concurrently.
|
||||
|
||||
You can provide an associative array of custom stream context options to the
|
||||
StreamHandler using the ``stream_context`` key of the ``client`` request
|
||||
option.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Ring\Client\StreamHandler;
|
||||
|
||||
$response = $handler([
|
||||
'http_method' => 'GET',
|
||||
'uri' => '/',
|
||||
'headers' => ['host' => ['httpbin.org']],
|
||||
'client' => [
|
||||
'stream_context' => [
|
||||
'http' => [
|
||||
'request_fulluri' => true,
|
||||
'method' => 'HEAD'
|
||||
],
|
||||
'socket' => [
|
||||
'bindto' => '127.0.0.1:0'
|
||||
],
|
||||
'ssl' => [
|
||||
'verify_peer' => false
|
||||
]
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
// Even though it's already completed, you can still use a promise
|
||||
$response->then(function ($response) {
|
||||
echo $response['status']; // 200
|
||||
});
|
||||
|
||||
// Or access the response using the future interface
|
||||
echo $response['status']; // 200
|
||||
|
||||
cURL Handler
|
||||
~~~~~~~~~~~~
|
||||
|
||||
The ``GuzzleHttp\Ring\Client\CurlHandler`` can be used with PHP 5.5+ to send
|
||||
requests using cURL easy handles. This handler is great for sending requests
|
||||
one at a time because the execute and select loop is implemented in C code
|
||||
which executes faster and consumes less memory than using PHP's
|
||||
``curl_multi_*`` interface.
|
||||
|
||||
.. note::
|
||||
|
||||
This handler cannot send requests concurrently.
|
||||
|
||||
When using the CurlHandler, custom curl options can be specified as an
|
||||
associative array of `cURL option constants <http://php.net/manual/en/curl.constants.php>`_
|
||||
mapping to values in the ``client`` option of a requst using the **curl** key.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Ring\Client\CurlHandler;
|
||||
|
||||
$handler = new CurlHandler();
|
||||
|
||||
$request = [
|
||||
'http_method' => 'GET',
|
||||
'headers' => ['host' => [Server::$host]],
|
||||
'client' => ['curl' => [CURLOPT_LOW_SPEED_LIMIT => 10]]
|
||||
];
|
||||
|
||||
$response = $handler($request);
|
||||
|
||||
// The response can be used directly as an array.
|
||||
echo $response['status']; // 200
|
||||
|
||||
// Or, it can be used as a promise (that has already fulfilled).
|
||||
$response->then(function ($response) {
|
||||
echo $response['status']; // 200
|
||||
});
|
||||
|
||||
cURL Multi Handler
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``GuzzleHttp\Ring\Client\CurlMultiHandler`` transfers requests using
|
||||
cURL's `multi API <http://curl.haxx.se/libcurl/c/libcurl-multi.html>`_. The
|
||||
``CurlMultiHandler`` is great for sending requests concurrently.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Ring\Client\CurlMultiHandler;
|
||||
|
||||
$handler = new CurlMultiHandler();
|
||||
|
||||
$request = [
|
||||
'http_method' => 'GET',
|
||||
'headers' => ['host' => [Server::$host]]
|
||||
];
|
||||
|
||||
// this call returns a future array immediately.
|
||||
$response = $handler($request);
|
||||
|
||||
// Ideally, you should use the promise API to not block.
|
||||
$response
|
||||
->then(function ($response) {
|
||||
// Got the response at some point in the future
|
||||
echo $response['status']; // 200
|
||||
// Don't break the chain
|
||||
return $response;
|
||||
})->then(function ($response) {
|
||||
// ...
|
||||
});
|
||||
|
||||
// If you really need to block, then you can use the response as an
|
||||
// associative array. This will block until it has completed.
|
||||
echo $response['status']; // 200
|
||||
|
||||
Just like the ``CurlHandler``, the ``CurlMultiHandler`` accepts custom curl
|
||||
option in the ``curl`` key of the ``client`` request option.
|
||||
|
||||
Mock Handler
|
||||
~~~~~~~~~~~~
|
||||
|
||||
The ``GuzzleHttp\Ring\Client\MockHandler`` is used to return mock responses.
|
||||
When constructed, the handler can be configured to return the same response
|
||||
array over and over, a future response, or a the evaluation of a callback
|
||||
function.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Ring\Client\MockHandler;
|
||||
|
||||
// Return a canned response.
|
||||
$mock = new MockHandler(['status' => 200]);
|
||||
$response = $mock([]);
|
||||
assert(200 == $response['status']);
|
||||
assert([] == $response['headers']);
|
||||
|
||||
Implementing Handlers
|
||||
---------------------
|
||||
|
||||
Client handlers are just PHP callables (functions or classes that have the
|
||||
``__invoke`` magic method). The callable accepts a request array and MUST
|
||||
return an instance of ``GuzzleHttp\Ring\Future\FutureArrayInterface`` so that
|
||||
the response can be used by both blocking and non-blocking consumers.
|
||||
|
||||
Handlers need to follow a few simple rules:
|
||||
|
||||
1. Do not throw exceptions. If an error is encountered, return an array that
|
||||
contains the ``error`` key that maps to an ``\Exception`` value.
|
||||
2. If the request has a ``delay`` client option, then the handler should only
|
||||
send the request after the specified delay time in seconds. Blocking
|
||||
handlers may find it convenient to just let the
|
||||
``GuzzleHttp\Ring\Core::doSleep($request)`` function handle this for them.
|
||||
3. Always return an instance of ``GuzzleHttp\Ring\Future\FutureArrayInterface``.
|
||||
4. Complete any outstanding requests when the handler is destructed.
|
@@ -0,0 +1,165 @@
|
||||
=================
|
||||
Client Middleware
|
||||
=================
|
||||
|
||||
Middleware intercepts requests before they are sent over the wire and can be
|
||||
used to add functionality to handlers.
|
||||
|
||||
Modifying Requests
|
||||
------------------
|
||||
|
||||
Let's say you wanted to modify requests before they are sent over the wire
|
||||
so that they always add specific headers. This can be accomplished by creating
|
||||
a function that accepts a handler and returns a new function that adds the
|
||||
composed behavior.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Ring\Client\CurlHandler;
|
||||
|
||||
$handler = new CurlHandler();
|
||||
|
||||
$addHeaderHandler = function (callable $handler, array $headers = []) {
|
||||
return function (array $request) use ($handler, $headers) {
|
||||
// Add our custom headers
|
||||
foreach ($headers as $key => $value) {
|
||||
$request['headers'][$key] = $value;
|
||||
}
|
||||
|
||||
// Send the request using the handler and return the response.
|
||||
return $handler($request);
|
||||
}
|
||||
};
|
||||
|
||||
// Create a new handler that adds headers to each request.
|
||||
$handler = $addHeaderHandler($handler, [
|
||||
'X-AddMe' => 'hello',
|
||||
'Authorization' => 'Basic xyz'
|
||||
]);
|
||||
|
||||
$response = $handler([
|
||||
'http_method' => 'GET',
|
||||
'headers' => ['Host' => ['httpbin.org']]
|
||||
]);
|
||||
|
||||
Modifying Responses
|
||||
-------------------
|
||||
|
||||
You can change a response as it's returned from a middleware. Remember that
|
||||
responses returned from an handler (including middleware) must implement
|
||||
``GuzzleHttp\Ring\Future\FutureArrayInterface``. In order to be a good citizen,
|
||||
you should not expect that the responses returned through your middleware will
|
||||
be completed synchronously. Instead, you should use the
|
||||
``GuzzleHttp\Ring\Core::proxy()`` function to modify the response when the
|
||||
underlying promise is resolved. This function is a helper function that makes it
|
||||
easy to create a new instance of ``FutureArrayInterface`` that wraps an existing
|
||||
``FutureArrayInterface`` object.
|
||||
|
||||
Let's say you wanted to add headers to a response as they are returned from
|
||||
your middleware, but you want to make sure you aren't causing future
|
||||
responses to be dereferenced right away. You can achieve this by modifying the
|
||||
incoming request and using the ``Core::proxy`` function.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Ring\Core;
|
||||
use GuzzleHttp\Ring\Client\CurlHandler;
|
||||
|
||||
$handler = new CurlHandler();
|
||||
|
||||
$responseHeaderHandler = function (callable $handler, array $headers) {
|
||||
return function (array $request) use ($handler, $headers) {
|
||||
// Send the request using the wrapped handler.
|
||||
return Core::proxy($handler($request), function ($response) use ($headers) {
|
||||
// Add the headers to the response when it is available.
|
||||
foreach ($headers as $key => $value) {
|
||||
$response['headers'][$key] = (array) $value;
|
||||
}
|
||||
// Note that you can return a regular response array when using
|
||||
// the proxy method.
|
||||
return $response;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Create a new handler that adds headers to each response.
|
||||
$handler = $responseHeaderHandler($handler, ['X-Header' => 'hello!']);
|
||||
|
||||
$response = $handler([
|
||||
'http_method' => 'GET',
|
||||
'headers' => ['Host' => ['httpbin.org']]
|
||||
]);
|
||||
|
||||
assert($response['headers']['X-Header'] == 'hello!');
|
||||
|
||||
Built-In Middleware
|
||||
-------------------
|
||||
|
||||
RingPHP comes with a few basic client middlewares that modify requests
|
||||
and responses.
|
||||
|
||||
Streaming Middleware
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you want to send all requests with the ``streaming`` option to a specific
|
||||
handler but other requests to a different handler, then use the streaming
|
||||
middleware.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Ring\Client\CurlHandler;
|
||||
use GuzzleHttp\Ring\Client\StreamHandler;
|
||||
use GuzzleHttp\Ring\Client\Middleware;
|
||||
|
||||
$defaultHandler = new CurlHandler();
|
||||
$streamingHandler = new StreamHandler();
|
||||
$streamingHandler = Middleware::wrapStreaming(
|
||||
$defaultHandler,
|
||||
$streamingHandler
|
||||
);
|
||||
|
||||
// Send the request using the streaming handler.
|
||||
$response = $streamingHandler([
|
||||
'http_method' => 'GET',
|
||||
'headers' => ['Host' => ['www.google.com']],
|
||||
'stream' => true
|
||||
]);
|
||||
|
||||
// Send the request using the default handler.
|
||||
$response = $streamingHandler([
|
||||
'http_method' => 'GET',
|
||||
'headers' => ['Host' => ['www.google.com']]
|
||||
]);
|
||||
|
||||
Future Middleware
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you want to send all requests with the ``future`` option to a specific
|
||||
handler but other requests to a different handler, then use the future
|
||||
middleware.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Ring\Client\CurlHandler;
|
||||
use GuzzleHttp\Ring\Client\CurlMultiHandler;
|
||||
use GuzzleHttp\Ring\Client\Middleware;
|
||||
|
||||
$defaultHandler = new CurlHandler();
|
||||
$futureHandler = new CurlMultiHandler();
|
||||
$futureHandler = Middleware::wrapFuture(
|
||||
$defaultHandler,
|
||||
$futureHandler
|
||||
);
|
||||
|
||||
// Send the request using the blocking CurlHandler.
|
||||
$response = $futureHandler([
|
||||
'http_method' => 'GET',
|
||||
'headers' => ['Host' => ['www.google.com']]
|
||||
]);
|
||||
|
||||
// Send the request using the non-blocking CurlMultiHandler.
|
||||
$response = $futureHandler([
|
||||
'http_method' => 'GET',
|
||||
'headers' => ['Host' => ['www.google.com']],
|
||||
'future' => true
|
||||
]);
|
23
hamrokhaanpaan/wp-content/__plugins/google-site-kit/third-party/guzzlehttp/ringphp/docs/conf.py
vendored
Normal file
23
hamrokhaanpaan/wp-content/__plugins/google-site-kit/third-party/guzzlehttp/ringphp/docs/conf.py
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import sys, os
|
||||
import sphinx_rtd_theme
|
||||
from sphinx.highlighting import lexers
|
||||
from pygments.lexers.web import PhpLexer
|
||||
|
||||
|
||||
lexers['php'] = PhpLexer(startinline=True, linenos=1)
|
||||
lexers['php-annotations'] = PhpLexer(startinline=True, linenos=1)
|
||||
primary_domain = 'php'
|
||||
|
||||
extensions = []
|
||||
templates_path = ['_templates']
|
||||
source_suffix = '.rst'
|
||||
master_doc = 'index'
|
||||
project = u'RingPHP'
|
||||
copyright = u'2014, Michael Dowling'
|
||||
version = '1.0.0-alpha'
|
||||
exclude_patterns = ['_build']
|
||||
|
||||
html_title = "RingPHP"
|
||||
html_short_title = "RingPHP"
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
164
hamrokhaanpaan/wp-content/__plugins/google-site-kit/third-party/guzzlehttp/ringphp/docs/futures.rst
vendored
Normal file
164
hamrokhaanpaan/wp-content/__plugins/google-site-kit/third-party/guzzlehttp/ringphp/docs/futures.rst
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
=======
|
||||
Futures
|
||||
=======
|
||||
|
||||
Futures represent a computation that may have not yet completed. RingPHP
|
||||
uses hybrid of futures and promises to provide a consistent API that can be
|
||||
used for both blocking and non-blocking consumers.
|
||||
|
||||
Promises
|
||||
--------
|
||||
|
||||
You can get the result of a future when it is ready using the promise interface
|
||||
of a future. Futures expose a promise API via a ``then()`` method that utilizes
|
||||
`React's promise library <https://github.com/reactphp/promise>`_. You should
|
||||
use this API when you do not wish to block.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Ring\Client\CurlMultiHandler;
|
||||
|
||||
$request = [
|
||||
'http_method' => 'GET',
|
||||
'uri' => '/',
|
||||
'headers' => ['host' => ['httpbin.org']]
|
||||
];
|
||||
|
||||
$response = $handler($request);
|
||||
|
||||
// Use the then() method to use the promise API of the future.
|
||||
$response->then(function ($response) {
|
||||
echo $response['status'];
|
||||
});
|
||||
|
||||
You can get the promise used by a future, an instance of
|
||||
``React\Promise\PromiseInterface``, by calling the ``promise()`` method.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$response = $handler($request);
|
||||
$promise = $response->promise();
|
||||
$promise->then(function ($response) {
|
||||
echo $response['status'];
|
||||
});
|
||||
|
||||
This promise value can be used with React's
|
||||
`aggregate promise functions <https://github.com/reactphp/promise#functions>`_.
|
||||
|
||||
Waiting
|
||||
-------
|
||||
|
||||
You can wait on a future to complete and retrieve the value, or *dereference*
|
||||
the future, using the ``wait()`` method. Calling the ``wait()`` method of a
|
||||
future will block until the result is available. The result is then returned or
|
||||
an exception is thrown if and exception was encountered while waiting on the
|
||||
the result. Subsequent calls to dereference a future will return the previously
|
||||
completed result or throw the previously encountered exception. Futures can be
|
||||
cancelled, which stops the computation if possible.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Ring\Client\CurlMultiHandler;
|
||||
|
||||
$response = $handler([
|
||||
'http_method' => 'GET',
|
||||
'uri' => '/',
|
||||
'headers' => ['host' => ['httpbin.org']]
|
||||
]);
|
||||
|
||||
// You can explicitly call block to wait on a result.
|
||||
$realizedResponse = $response->wait();
|
||||
|
||||
// Future responses can be used like a regular PHP array.
|
||||
echo $response['status'];
|
||||
|
||||
In addition to explicitly calling the ``wait()`` function, using a future like
|
||||
a normal value will implicitly trigger the ``wait()`` function.
|
||||
|
||||
Future Responses
|
||||
----------------
|
||||
|
||||
RingPHP uses futures to return asynchronous responses immediately. Client
|
||||
handlers always return future responses that implement
|
||||
``GuzzleHttp\Ring\Future\ArrayFutureInterface``. These future responses act
|
||||
just like normal PHP associative arrays for blocking access and provide a
|
||||
promise interface for non-blocking access.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Ring\Client\CurlMultiHandler;
|
||||
|
||||
$handler = new CurlMultiHandler();
|
||||
|
||||
$request = [
|
||||
'http_method' => 'GET',
|
||||
'uri' => '/',
|
||||
'headers' => ['Host' => ['www.google.com']]
|
||||
];
|
||||
|
||||
$response = $handler($request);
|
||||
|
||||
// Use the promise API for non-blocking access to the response. The actual
|
||||
// response value will be delivered to the promise.
|
||||
$response->then(function ($response) {
|
||||
echo $response['status'];
|
||||
});
|
||||
|
||||
// You can wait (block) until the future is completed.
|
||||
$response->wait();
|
||||
|
||||
// This will implicitly call wait(), and will block too!
|
||||
$response['status'];
|
||||
|
||||
.. important::
|
||||
|
||||
Futures that are not completed by the time the underlying handler is
|
||||
destructed will be completed when the handler is shutting down.
|
||||
|
||||
Cancelling
|
||||
----------
|
||||
|
||||
Futures can be cancelled if they have not already been dereferenced.
|
||||
|
||||
RingPHP futures are typically implemented with the
|
||||
``GuzzleHttp\Ring\Future\BaseFutureTrait``. This trait provides the cancellation
|
||||
functionality that should be common to most implementations. Cancelling a
|
||||
future response will try to prevent the request from sending over the wire.
|
||||
|
||||
When a future is cancelled, the cancellation function is invoked and performs
|
||||
the actual work needed to cancel the request from sending if possible
|
||||
(e.g., telling an event loop to stop sending a request or to close a socket).
|
||||
If no cancellation function is provided, then a request cannot be cancelled. If
|
||||
a cancel function is provided, then it should accept the future as an argument
|
||||
and return true if the future was successfully cancelled or false if it could
|
||||
not be cancelled.
|
||||
|
||||
Wrapping an existing Promise
|
||||
----------------------------
|
||||
|
||||
You can easily create a future from any existing promise using the
|
||||
``GuzzleHttp\Ring\Future\FutureValue`` class. This class's constructor
|
||||
accepts a promise as the first argument, a wait function as the second
|
||||
argument, and a cancellation function as the third argument. The dereference
|
||||
function is used to force the promise to resolve (for example, manually ticking
|
||||
an event loop). The cancel function is optional and is used to tell the thing
|
||||
that created the promise that it can stop computing the result (for example,
|
||||
telling an event loop to stop transferring a request).
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Ring\Future\FutureValue;
|
||||
use React\Promise\Deferred;
|
||||
|
||||
$deferred = new Deferred();
|
||||
$promise = $deferred->promise();
|
||||
|
||||
$f = new FutureValue(
|
||||
$promise,
|
||||
function () use ($deferred) {
|
||||
// This function is responsible for blocking and resolving the
|
||||
// promise. Here we pass in a reference to the deferred so that
|
||||
// it can be resolved or rejected.
|
||||
$deferred->resolve('foo');
|
||||
}
|
||||
);
|
@@ -0,0 +1,50 @@
|
||||
=======
|
||||
RingPHP
|
||||
=======
|
||||
|
||||
Provides a simple API and specification that abstracts away the details of HTTP
|
||||
into a single PHP function. RingPHP be used to power HTTP clients and servers
|
||||
through a PHP function that accepts a request hash and returns a response hash
|
||||
that is fulfilled using a `promise <https://github.com/reactphp/promise>`_,
|
||||
allowing RingPHP to support both synchronous and asynchronous workflows.
|
||||
|
||||
By abstracting the implementation details of different HTTP clients and
|
||||
servers, RingPHP allows you to utilize pluggable HTTP clients and servers
|
||||
without tying your application to a specific implementation.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
spec
|
||||
futures
|
||||
client_middleware
|
||||
client_handlers
|
||||
testing
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
use GuzzleHttp\Ring\Client\CurlHandler;
|
||||
|
||||
$handler = new CurlHandler();
|
||||
$response = $handler([
|
||||
'http_method' => 'GET',
|
||||
'uri' => '/',
|
||||
'headers' => [
|
||||
'host' => ['www.google.com'],
|
||||
'x-foo' => ['baz']
|
||||
]
|
||||
]);
|
||||
|
||||
$response->then(function (array $response) {
|
||||
echo $response['status'];
|
||||
});
|
||||
|
||||
$response->wait();
|
||||
|
||||
RingPHP is inspired by Clojure's `Ring <https://github.com/ring-clojure/ring>`_,
|
||||
which, in turn, was inspired by Python's WSGI and Ruby's Rack. RingPHP is
|
||||
utilized as the handler layer in `Guzzle <http://guzzlephp.org>`_ 5.0+ to send
|
||||
HTTP requests.
|
@@ -0,0 +1 @@
|
||||
sphinx_rtd_theme
|
311
hamrokhaanpaan/wp-content/__plugins/google-site-kit/third-party/guzzlehttp/ringphp/docs/spec.rst
vendored
Normal file
311
hamrokhaanpaan/wp-content/__plugins/google-site-kit/third-party/guzzlehttp/ringphp/docs/spec.rst
vendored
Normal file
@@ -0,0 +1,311 @@
|
||||
=============
|
||||
Specification
|
||||
=============
|
||||
|
||||
RingPHP applications consist of handlers, requests, responses, and
|
||||
middleware.
|
||||
|
||||
Handlers
|
||||
--------
|
||||
|
||||
Handlers are implemented as a PHP ``callable`` that accept a request array
|
||||
and return a response array (``GuzzleHttp\Ring\Future\FutureArrayInterface``).
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Ring\Future\CompletedFutureArray;
|
||||
|
||||
$mockHandler = function (array $request) {
|
||||
return new CompletedFutureArray([
|
||||
'status' => 200,
|
||||
'headers' => ['X-Foo' => ['Bar']],
|
||||
'body' => 'Hello!'
|
||||
]);
|
||||
};
|
||||
|
||||
This handler returns the same response each time it is invoked. All RingPHP
|
||||
handlers must return a ``GuzzleHttp\Ring\Future\FutureArrayInterface``. Use
|
||||
``GuzzleHttp\Ring\Future\CompletedFutureArray`` when returning a response that
|
||||
has already completed.
|
||||
|
||||
Requests
|
||||
--------
|
||||
|
||||
A request array is a PHP associative array that contains the configuration
|
||||
settings need to send a request.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$request = [
|
||||
'http_method' => 'GET',
|
||||
'scheme' => 'http',
|
||||
'uri' => '/',
|
||||
'body' => 'hello!',
|
||||
'client' => ['timeout' => 1.0],
|
||||
'headers' => [
|
||||
'host' => ['httpbin.org'],
|
||||
'X-Foo' => ['baz', 'bar']
|
||||
]
|
||||
];
|
||||
|
||||
The request array contains the following key value pairs:
|
||||
|
||||
request_method
|
||||
(string, required) The HTTP request method, must be all caps corresponding
|
||||
to a HTTP request method, such as ``GET`` or ``POST``.
|
||||
|
||||
scheme
|
||||
(string) The transport protocol, must be one of ``http`` or ``https``.
|
||||
Defaults to ``http``.
|
||||
|
||||
uri
|
||||
(string, required) The request URI excluding the query string. Must
|
||||
start with "/".
|
||||
|
||||
query_string
|
||||
(string) The query string, if present (e.g., ``foo=bar``).
|
||||
|
||||
version
|
||||
(string) HTTP protocol version. Defaults to ``1.1``.
|
||||
|
||||
headers
|
||||
(required, array) Associative array of headers. Each key represents the
|
||||
header name. Each value contains an array of strings where each entry of
|
||||
the array SHOULD be sent over the wire on a separate header line.
|
||||
|
||||
body
|
||||
(string, fopen resource, ``Iterator``, ``GuzzleHttp\Stream\StreamInterface``)
|
||||
The body of the request, if present. Can be a string, resource returned
|
||||
from fopen, an ``Iterator`` that yields chunks of data, an object that
|
||||
implemented ``__toString``, or a ``GuzzleHttp\Stream\StreamInterface``.
|
||||
|
||||
future
|
||||
(bool, string) Controls the asynchronous behavior of a response.
|
||||
|
||||
Set to ``true`` or omit the ``future`` option to *request* that a request
|
||||
will be completed asynchronously. Keep in mind that your request might not
|
||||
necessarily be completed asynchronously based on the handler you are using.
|
||||
Set the ``future`` option to ``false`` to request that a synchronous
|
||||
response be provided.
|
||||
|
||||
You can provide a string value to specify fine-tuned future behaviors that
|
||||
may be specific to the underlying handlers you are using. There are,
|
||||
however, some common future options that handlers should implement if
|
||||
possible.
|
||||
|
||||
lazy
|
||||
Requests that the handler does not open and send the request
|
||||
immediately, but rather only opens and sends the request once the
|
||||
future is dereferenced. This option is often useful for sending a large
|
||||
number of requests concurrently to allow handlers to take better
|
||||
advantage of non-blocking transfers by first building up a pool of
|
||||
requests.
|
||||
|
||||
If an handler does not implement or understand a provided string value,
|
||||
then the request MUST be treated as if the user provided ``true`` rather
|
||||
than the string value.
|
||||
|
||||
Future responses created by asynchronous handlers MUST attempt to complete
|
||||
any outstanding future responses when they are destructed. Asynchronous
|
||||
handlers MAY choose to automatically complete responses when the number
|
||||
of outstanding requests reaches an handler-specific threshold.
|
||||
|
||||
Client Specific Options
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following options are only used in ring client handlers.
|
||||
|
||||
.. _client-options:
|
||||
|
||||
client
|
||||
(array) Associative array of client specific transfer options. The
|
||||
``client`` request key value pair can contain the following keys:
|
||||
|
||||
cert
|
||||
(string, array) Set to a string to specify the path to a file
|
||||
containing a PEM formatted SSL client side certificate. If a password
|
||||
is required, then set ``cert`` to an array containing the path to the
|
||||
PEM file in the first array element followed by the certificate
|
||||
password in the second array element.
|
||||
|
||||
connect_timeout
|
||||
(float) Float describing the number of seconds to wait while trying to
|
||||
connect to a server. Use ``0`` to wait indefinitely (the default
|
||||
behavior).
|
||||
|
||||
debug
|
||||
(bool, fopen() resource) Set to true or set to a PHP stream returned by
|
||||
fopen() to enable debug output with the handler used to send a request.
|
||||
If set to ``true``, the output is written to PHP's STDOUT. If a PHP
|
||||
``fopen`` resource handle is provided, the output is written to the
|
||||
stream.
|
||||
|
||||
"Debug output" is handler specific: different handlers will yield
|
||||
different output and various various level of detail. For example, when
|
||||
using cURL to transfer requests, cURL's `CURLOPT_VERBOSE <http://curl.haxx.se/libcurl/c/CURLOPT_VERBOSE.html>`_
|
||||
will be used. When using the PHP stream wrapper, `stream notifications <http://php.net/manual/en/function.stream-notification-callback.php>`_
|
||||
will be emitted.
|
||||
|
||||
decode_content
|
||||
(bool) Specify whether or not ``Content-Encoding`` responses
|
||||
(gzip, deflate, etc.) are automatically decoded. Set to ``true`` to
|
||||
automatically decode encoded responses. Set to ``false`` to not decode
|
||||
responses. By default, content is *not* decoded automatically.
|
||||
|
||||
delay
|
||||
(int) The number of milliseconds to delay before sending the request.
|
||||
This is often used for delaying before retrying a request. Handlers
|
||||
SHOULD implement this if possible, but it is not a strict requirement.
|
||||
|
||||
progress
|
||||
(function) Defines a function to invoke when transfer progress is made.
|
||||
The function accepts the following arguments:
|
||||
|
||||
1. The total number of bytes expected to be downloaded
|
||||
2. The number of bytes downloaded so far
|
||||
3. The number of bytes expected to be uploaded
|
||||
4. The number of bytes uploaded so far
|
||||
|
||||
proxy
|
||||
(string, array) Pass a string to specify an HTTP proxy, or an
|
||||
associative array to specify different proxies for different protocols
|
||||
where the scheme is the key and the value is the proxy address.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$request = [
|
||||
'http_method' => 'GET',
|
||||
'headers' => ['host' => ['httpbin.org']],
|
||||
'client' => [
|
||||
// Use different proxies for different URI schemes.
|
||||
'proxy' => [
|
||||
'http' => 'http://proxy.example.com:5100',
|
||||
'https' => 'https://proxy.example.com:6100'
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
ssl_key
|
||||
(string, array) Specify the path to a file containing a private SSL key
|
||||
in PEM format. If a password is required, then set to an array
|
||||
containing the path to the SSL key in the first array element followed
|
||||
by the password required for the certificate in the second element.
|
||||
|
||||
save_to
|
||||
(string, fopen resource, ``GuzzleHttp\Stream\StreamInterface``)
|
||||
Specifies where the body of the response is downloaded. Pass a string to
|
||||
open a local file on disk and save the output to the file. Pass an fopen
|
||||
resource to save the output to a PHP stream resource. Pass a
|
||||
``GuzzleHttp\Stream\StreamInterface`` to save the output to a Guzzle
|
||||
StreamInterface. Omitting this option will typically save the body of a
|
||||
response to a PHP temp stream.
|
||||
|
||||
stream
|
||||
(bool) Set to true to stream a response rather than download it all
|
||||
up-front. This option will only be utilized when the corresponding
|
||||
handler supports it.
|
||||
|
||||
timeout
|
||||
(float) Float describing the timeout of the request in seconds. Use 0 to
|
||||
wait indefinitely (the default behavior).
|
||||
|
||||
verify
|
||||
(bool, string) Describes the SSL certificate verification behavior of a
|
||||
request. Set to true to enable SSL certificate verification using the
|
||||
system CA bundle when available (the default). Set to false to disable
|
||||
certificate verification (this is insecure!). Set to a string to provide
|
||||
the path to a CA bundle on disk to enable verification using a custom
|
||||
certificate.
|
||||
|
||||
version
|
||||
(string) HTTP protocol version to use with the request.
|
||||
|
||||
Server Specific Options
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following options are only used in ring server handlers.
|
||||
|
||||
server_port
|
||||
(integer) The port on which the request is being handled. This is only
|
||||
used with ring servers, and is required.
|
||||
|
||||
server_name
|
||||
(string) The resolved server name, or the server IP address. Required when
|
||||
using a Ring server.
|
||||
|
||||
remote_addr
|
||||
(string) The IP address of the client or the last proxy that sent the
|
||||
request. Required when using a Ring server.
|
||||
|
||||
Responses
|
||||
---------
|
||||
|
||||
A response is an array-like object that implements
|
||||
``GuzzleHttp\Ring\Future\FutureArrayInterface``. Responses contain the
|
||||
following key value pairs:
|
||||
|
||||
body
|
||||
(string, fopen resource, ``Iterator``, ``GuzzleHttp\Stream\StreamInterface``)
|
||||
The body of the response, if present. Can be a string, resource returned
|
||||
from fopen, an ``Iterator`` that yields chunks of data, an object that
|
||||
implemented ``__toString``, or a ``GuzzleHttp\Stream\StreamInterface``.
|
||||
|
||||
effective_url
|
||||
(string) The URL that returned the resulting response.
|
||||
|
||||
error
|
||||
(``\Exception``) Contains an exception describing any errors that were
|
||||
encountered during the transfer.
|
||||
|
||||
headers
|
||||
(Required, array) Associative array of headers. Each key represents the
|
||||
header name. Each value contains an array of strings where each entry of
|
||||
the array is a header line. The headers array MAY be an empty array in the
|
||||
event an error occurred before a response was received.
|
||||
|
||||
reason
|
||||
(string) Optional reason phrase. This option should be provided when the
|
||||
reason phrase does not match the typical reason phrase associated with the
|
||||
``status`` code. See `RFC 7231 <http://tools.ietf.org/html/rfc7231#section-6.1>`_
|
||||
for a list of HTTP reason phrases mapped to status codes.
|
||||
|
||||
status
|
||||
(Required, integer) The HTTP status code. The status code MAY be set to
|
||||
``null`` in the event an error occurred before a response was received
|
||||
(e.g., a networking error).
|
||||
|
||||
transfer_stats
|
||||
(array) Provides an associative array of arbitrary transfer statistics if
|
||||
provided by the underlying handler.
|
||||
|
||||
version
|
||||
(string) HTTP protocol version. Defaults to ``1.1``.
|
||||
|
||||
Middleware
|
||||
----------
|
||||
|
||||
Ring middleware augments the functionality of handlers by invoking them in the
|
||||
process of generating responses. Middleware is typically implemented as a
|
||||
higher-order function that takes one or more handlers as arguments followed by
|
||||
an optional associative array of options as the last argument, returning a new
|
||||
handler with the desired compound behavior.
|
||||
|
||||
Here's an example of a middleware that adds a Content-Type header to each
|
||||
request.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Ring\Client\CurlHandler;
|
||||
use GuzzleHttp\Ring\Core;
|
||||
|
||||
$contentTypeHandler = function(callable $handler, $contentType) {
|
||||
return function (array $request) use ($handler, $contentType) {
|
||||
return $handler(Core::setHeader('Content-Type', $contentType));
|
||||
};
|
||||
};
|
||||
|
||||
$baseHandler = new CurlHandler();
|
||||
$wrappedHandler = $contentTypeHandler($baseHandler, 'text/html');
|
||||
$response = $wrappedHandler([/** request hash **/]);
|
@@ -0,0 +1,74 @@
|
||||
=======
|
||||
Testing
|
||||
=======
|
||||
|
||||
RingPHP tests client handlers using `PHPUnit <https://phpunit.de/>`_ and a
|
||||
built-in node.js web server.
|
||||
|
||||
Running Tests
|
||||
-------------
|
||||
|
||||
First, install the dependencies using `Composer <https://getcomposer.org>`_.
|
||||
|
||||
composer.phar install
|
||||
|
||||
Next, run the unit tests using ``Make``.
|
||||
|
||||
make test
|
||||
|
||||
The tests are also run on Travis-CI on each commit: https://travis-ci.org/guzzle/guzzle-ring
|
||||
|
||||
Test Server
|
||||
-----------
|
||||
|
||||
Testing client handlers usually involves actually sending HTTP requests.
|
||||
RingPHP provides a node.js web server that returns canned responses and
|
||||
keep a list of the requests that have been received. The server can then
|
||||
be queried to get a list of the requests that were sent by the client so that
|
||||
you can ensure that the client serialized and transferred requests as intended.
|
||||
|
||||
The server keeps a list of queued responses and returns responses that are
|
||||
popped off of the queue as HTTP requests are received. When there are not
|
||||
more responses to serve, the server returns a 500 error response.
|
||||
|
||||
The test server uses the ``GuzzleHttp\Tests\Ring\Client\Server`` class to
|
||||
control the server.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Ring\Client\StreamHandler;
|
||||
use GuzzleHttp\Tests\Ring\Client\Server;
|
||||
|
||||
// First return a 200 followed by a 404 response.
|
||||
Server::enqueue([
|
||||
['status' => 200],
|
||||
['status' => 404]
|
||||
]);
|
||||
|
||||
$handler = new StreamHandler();
|
||||
|
||||
$response = $handler([
|
||||
'http_method' => 'GET',
|
||||
'headers' => ['host' => [Server::$host]],
|
||||
'uri' => '/'
|
||||
]);
|
||||
|
||||
assert(200 == $response['status']);
|
||||
|
||||
$response = $handler([
|
||||
'http_method' => 'HEAD',
|
||||
'headers' => ['host' => [Server::$host]],
|
||||
'uri' => '/'
|
||||
]);
|
||||
|
||||
assert(404 == $response['status']);
|
||||
|
||||
After requests have been sent, you can get a list of the requests as they
|
||||
were sent over the wire to ensure they were sent correctly.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$received = Server::received();
|
||||
|
||||
assert('GET' == $received[0]['http_method']);
|
||||
assert('HEAD' == $received[1]['http_method']);
|
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Client;
|
||||
|
||||
/**
|
||||
* Client specific utility functions.
|
||||
*/
|
||||
class ClientUtils
|
||||
{
|
||||
/**
|
||||
* Returns the default cacert bundle for the current system.
|
||||
*
|
||||
* First, the openssl.cafile and curl.cainfo php.ini settings are checked.
|
||||
* If those settings are not configured, then the common locations for
|
||||
* bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X
|
||||
* and Windows are checked. If any of these file locations are found on
|
||||
* disk, they will be utilized.
|
||||
*
|
||||
* Note: the result of this function is cached for subsequent calls.
|
||||
*
|
||||
* @return string
|
||||
* @throws \RuntimeException if no bundle can be found.
|
||||
*/
|
||||
public static function getDefaultCaBundle()
|
||||
{
|
||||
static $cached = null;
|
||||
static $cafiles = [
|
||||
// Red Hat, CentOS, Fedora (provided by the ca-certificates package)
|
||||
'/etc/pki/tls/certs/ca-bundle.crt',
|
||||
// Ubuntu, Debian (provided by the ca-certificates package)
|
||||
'/etc/ssl/certs/ca-certificates.crt',
|
||||
// FreeBSD (provided by the ca_root_nss package)
|
||||
'/usr/local/share/certs/ca-root-nss.crt',
|
||||
// OS X provided by homebrew (using the default path)
|
||||
'/usr/local/etc/openssl/cert.pem',
|
||||
// Windows?
|
||||
'C:\\windows\\system32\\curl-ca-bundle.crt',
|
||||
'C:\\windows\\curl-ca-bundle.crt',
|
||||
];
|
||||
if ($cached) {
|
||||
return $cached;
|
||||
}
|
||||
if ($ca = \ini_get('openssl.cafile')) {
|
||||
return $cached = $ca;
|
||||
}
|
||||
if ($ca = \ini_get('curl.cainfo')) {
|
||||
return $cached = $ca;
|
||||
}
|
||||
foreach ($cafiles as $filename) {
|
||||
if (\file_exists($filename)) {
|
||||
return $cached = $filename;
|
||||
}
|
||||
}
|
||||
throw new \RuntimeException(self::CA_ERR);
|
||||
}
|
||||
const CA_ERR = "\nNo system CA bundle could be found in any of the the common system locations.\nPHP versions earlier than 5.6 are not properly configured to use the system's\nCA bundle by default. In order to verify peer certificates, you will need to\nsupply the path on disk to a certificate bundle to the 'verify' request\noption: http://docs.guzzlephp.org/en/5.3/clients.html#verify. If you do not\nneed a specific certificate bundle, then Mozilla provides a commonly used CA\nbundle which can be downloaded here (provided by the maintainer of cURL):\nhttps://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt. Once\nyou have a CA bundle available on disk, you can set the 'openssl.cafile' PHP\nini setting to point to the path to the file, allowing you to omit the 'verify'\nrequest option. See http://curl.haxx.se/docs/sslcerts.html for more\ninformation.";
|
||||
}
|
@@ -0,0 +1,414 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Client;
|
||||
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core;
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\ConnectException;
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\RingException;
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Stream\LazyOpenStream;
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Stream\StreamInterface;
|
||||
/**
|
||||
* Creates curl resources from a request
|
||||
*/
|
||||
class CurlFactory
|
||||
{
|
||||
/**
|
||||
* Creates a cURL handle, header resource, and body resource based on a
|
||||
* transaction.
|
||||
*
|
||||
* @param array $request Request hash
|
||||
* @param null|resource $handle Optionally provide a curl handle to modify
|
||||
*
|
||||
* @return array Returns an array of the curl handle, headers array, and
|
||||
* response body handle.
|
||||
* @throws \RuntimeException when an option cannot be applied
|
||||
*/
|
||||
public function __invoke(array $request, $handle = null)
|
||||
{
|
||||
$headers = [];
|
||||
$options = $this->getDefaultOptions($request, $headers);
|
||||
$this->applyMethod($request, $options);
|
||||
if (isset($request['client'])) {
|
||||
$this->applyHandlerOptions($request, $options);
|
||||
}
|
||||
$this->applyHeaders($request, $options);
|
||||
unset($options['_headers']);
|
||||
// Add handler options from the request's configuration options
|
||||
if (isset($request['client']['curl'])) {
|
||||
$options = $this->applyCustomCurlOptions($request['client']['curl'], $options);
|
||||
}
|
||||
if (!$handle) {
|
||||
$handle = \curl_init();
|
||||
}
|
||||
$body = $this->getOutputBody($request, $options);
|
||||
\curl_setopt_array($handle, $options);
|
||||
return [$handle, &$headers, $body];
|
||||
}
|
||||
/**
|
||||
* Creates a response hash from a cURL result.
|
||||
*
|
||||
* @param callable $handler Handler that was used.
|
||||
* @param array $request Request that sent.
|
||||
* @param array $response Response hash to update.
|
||||
* @param array $headers Headers received during transfer.
|
||||
* @param resource $body Body fopen response.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function createResponse(callable $handler, array $request, array $response, array $headers, $body)
|
||||
{
|
||||
if (isset($response['transfer_stats']['url'])) {
|
||||
$response['effective_url'] = $response['transfer_stats']['url'];
|
||||
}
|
||||
if (!empty($headers)) {
|
||||
$startLine = \explode(' ', \array_shift($headers), 3);
|
||||
$headerList = \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::headersFromLines($headers);
|
||||
$response['headers'] = $headerList;
|
||||
$response['version'] = isset($startLine[0]) ? \substr($startLine[0], 5) : null;
|
||||
$response['status'] = isset($startLine[1]) ? (int) $startLine[1] : null;
|
||||
$response['reason'] = isset($startLine[2]) ? $startLine[2] : null;
|
||||
$response['body'] = $body;
|
||||
\Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::rewindBody($response);
|
||||
}
|
||||
return !empty($response['curl']['errno']) || !isset($response['status']) ? self::createErrorResponse($handler, $request, $response) : $response;
|
||||
}
|
||||
private static function createErrorResponse(callable $handler, array $request, array $response)
|
||||
{
|
||||
static $connectionErrors = [\CURLE_OPERATION_TIMEOUTED => \true, \CURLE_COULDNT_RESOLVE_HOST => \true, \CURLE_COULDNT_CONNECT => \true, \CURLE_SSL_CONNECT_ERROR => \true, \CURLE_GOT_NOTHING => \true];
|
||||
// Retry when nothing is present or when curl failed to rewind.
|
||||
if (!isset($response['err_message']) && (empty($response['curl']['errno']) || $response['curl']['errno'] == 65)) {
|
||||
return self::retryFailedRewind($handler, $request, $response);
|
||||
}
|
||||
$message = isset($response['err_message']) ? $response['err_message'] : \sprintf('cURL error %s: %s', $response['curl']['errno'], isset($response['curl']['error']) ? $response['curl']['error'] : 'See http://curl.haxx.se/libcurl/c/libcurl-errors.html');
|
||||
$error = isset($response['curl']['errno']) && isset($connectionErrors[$response['curl']['errno']]) ? new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\ConnectException($message) : new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\RingException($message);
|
||||
return $response + ['status' => null, 'reason' => null, 'body' => null, 'headers' => [], 'error' => $error];
|
||||
}
|
||||
private function getOutputBody(array $request, array &$options)
|
||||
{
|
||||
// Determine where the body of the response (if any) will be streamed.
|
||||
if (isset($options[\CURLOPT_WRITEFUNCTION])) {
|
||||
return $request['client']['save_to'];
|
||||
}
|
||||
if (isset($options[\CURLOPT_FILE])) {
|
||||
return $options[\CURLOPT_FILE];
|
||||
}
|
||||
if ($request['http_method'] != 'HEAD') {
|
||||
// Create a default body if one was not provided
|
||||
return $options[\CURLOPT_FILE] = \fopen('php://temp', 'w+');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private function getDefaultOptions(array $request, array &$headers)
|
||||
{
|
||||
$url = \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::url($request);
|
||||
$startingResponse = \false;
|
||||
$options = ['_headers' => $request['headers'], \CURLOPT_CUSTOMREQUEST => $request['http_method'], \CURLOPT_URL => $url, \CURLOPT_RETURNTRANSFER => \false, \CURLOPT_HEADER => \false, \CURLOPT_CONNECTTIMEOUT => 150, \CURLOPT_HEADERFUNCTION => function ($ch, $h) use(&$headers, &$startingResponse) {
|
||||
$value = \trim($h);
|
||||
if ($value === '') {
|
||||
$startingResponse = \true;
|
||||
} elseif ($startingResponse) {
|
||||
$startingResponse = \false;
|
||||
$headers = [$value];
|
||||
} else {
|
||||
$headers[] = $value;
|
||||
}
|
||||
return \strlen($h);
|
||||
}];
|
||||
if (isset($request['version'])) {
|
||||
if ($request['version'] == 2.0) {
|
||||
$options[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0;
|
||||
} else {
|
||||
if ($request['version'] == 1.1) {
|
||||
$options[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1;
|
||||
} else {
|
||||
$options[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (\defined('CURLOPT_PROTOCOLS')) {
|
||||
$options[\CURLOPT_PROTOCOLS] = \CURLPROTO_HTTP | \CURLPROTO_HTTPS;
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
private function applyMethod(array $request, array &$options)
|
||||
{
|
||||
if (isset($request['body'])) {
|
||||
$this->applyBody($request, $options);
|
||||
return;
|
||||
}
|
||||
switch ($request['http_method']) {
|
||||
case 'PUT':
|
||||
case 'POST':
|
||||
// See http://tools.ietf.org/html/rfc7230#section-3.3.2
|
||||
if (!\Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::hasHeader($request, 'Content-Length')) {
|
||||
$options[\CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
|
||||
}
|
||||
break;
|
||||
case 'HEAD':
|
||||
$options[\CURLOPT_NOBODY] = \true;
|
||||
unset($options[\CURLOPT_WRITEFUNCTION], $options[\CURLOPT_READFUNCTION], $options[\CURLOPT_FILE], $options[\CURLOPT_INFILE]);
|
||||
}
|
||||
}
|
||||
private function applyBody(array $request, array &$options)
|
||||
{
|
||||
$contentLength = \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::firstHeader($request, 'Content-Length');
|
||||
$size = $contentLength !== null ? (int) $contentLength : null;
|
||||
// Send the body as a string if the size is less than 1MB OR if the
|
||||
// [client][curl][body_as_string] request value is set.
|
||||
if ($size !== null && $size < 1000000 || isset($request['client']['curl']['body_as_string']) || \is_string($request['body'])) {
|
||||
$options[\CURLOPT_POSTFIELDS] = \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::body($request);
|
||||
// Don't duplicate the Content-Length header
|
||||
$this->removeHeader('Content-Length', $options);
|
||||
$this->removeHeader('Transfer-Encoding', $options);
|
||||
} else {
|
||||
$options[\CURLOPT_UPLOAD] = \true;
|
||||
if ($size !== null) {
|
||||
// Let cURL handle setting the Content-Length header
|
||||
$options[\CURLOPT_INFILESIZE] = $size;
|
||||
$this->removeHeader('Content-Length', $options);
|
||||
}
|
||||
$this->addStreamingBody($request, $options);
|
||||
}
|
||||
// If the Expect header is not present, prevent curl from adding it
|
||||
if (!\Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::hasHeader($request, 'Expect')) {
|
||||
$options[\CURLOPT_HTTPHEADER][] = 'Expect:';
|
||||
}
|
||||
// cURL sometimes adds a content-type by default. Prevent this.
|
||||
if (!\Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::hasHeader($request, 'Content-Type')) {
|
||||
$options[\CURLOPT_HTTPHEADER][] = 'Content-Type:';
|
||||
}
|
||||
}
|
||||
private function addStreamingBody(array $request, array &$options)
|
||||
{
|
||||
$body = $request['body'];
|
||||
if ($body instanceof \Google\Site_Kit_Dependencies\GuzzleHttp\Stream\StreamInterface) {
|
||||
$options[\CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use($body) {
|
||||
return (string) $body->read($length);
|
||||
};
|
||||
if (!isset($options[\CURLOPT_INFILESIZE])) {
|
||||
if ($size = $body->getSize()) {
|
||||
$options[\CURLOPT_INFILESIZE] = $size;
|
||||
}
|
||||
}
|
||||
} elseif (\is_resource($body)) {
|
||||
$options[\CURLOPT_INFILE] = $body;
|
||||
} elseif ($body instanceof \Iterator) {
|
||||
$buf = '';
|
||||
$options[\CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use($body, &$buf) {
|
||||
if ($body->valid()) {
|
||||
$buf .= $body->current();
|
||||
$body->next();
|
||||
}
|
||||
$result = (string) \substr($buf, 0, $length);
|
||||
$buf = \substr($buf, $length);
|
||||
return $result;
|
||||
};
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Invalid request body provided');
|
||||
}
|
||||
}
|
||||
private function applyHeaders(array $request, array &$options)
|
||||
{
|
||||
foreach ($options['_headers'] as $name => $values) {
|
||||
foreach ($values as $value) {
|
||||
$options[\CURLOPT_HTTPHEADER][] = "{$name}: {$value}";
|
||||
}
|
||||
}
|
||||
// Remove the Accept header if one was not set
|
||||
if (!\Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::hasHeader($request, 'Accept')) {
|
||||
$options[\CURLOPT_HTTPHEADER][] = 'Accept:';
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Takes an array of curl options specified in the 'curl' option of a
|
||||
* request's configuration array and maps them to CURLOPT_* options.
|
||||
*
|
||||
* This method is only called when a request has a 'curl' config setting.
|
||||
*
|
||||
* @param array $config Configuration array of custom curl option
|
||||
* @param array $options Array of existing curl options
|
||||
*
|
||||
* @return array Returns a new array of curl options
|
||||
*/
|
||||
private function applyCustomCurlOptions(array $config, array $options)
|
||||
{
|
||||
$curlOptions = [];
|
||||
foreach ($config as $key => $value) {
|
||||
if (\is_int($key)) {
|
||||
$curlOptions[$key] = $value;
|
||||
}
|
||||
}
|
||||
return $curlOptions + $options;
|
||||
}
|
||||
/**
|
||||
* Remove a header from the options array.
|
||||
*
|
||||
* @param string $name Case-insensitive header to remove
|
||||
* @param array $options Array of options to modify
|
||||
*/
|
||||
private function removeHeader($name, array &$options)
|
||||
{
|
||||
foreach (\array_keys($options['_headers']) as $key) {
|
||||
if (!\strcasecmp($key, $name)) {
|
||||
unset($options['_headers'][$key]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Applies an array of request client options to a the options array.
|
||||
*
|
||||
* This method uses a large switch rather than double-dispatch to save on
|
||||
* high overhead of calling functions in PHP.
|
||||
*/
|
||||
private function applyHandlerOptions(array $request, array &$options)
|
||||
{
|
||||
foreach ($request['client'] as $key => $value) {
|
||||
switch ($key) {
|
||||
// Violating PSR-4 to provide more room.
|
||||
case 'verify':
|
||||
if ($value === \false) {
|
||||
unset($options[\CURLOPT_CAINFO]);
|
||||
$options[\CURLOPT_SSL_VERIFYHOST] = 0;
|
||||
$options[\CURLOPT_SSL_VERIFYPEER] = \false;
|
||||
continue 2;
|
||||
}
|
||||
$options[\CURLOPT_SSL_VERIFYHOST] = 2;
|
||||
$options[\CURLOPT_SSL_VERIFYPEER] = \true;
|
||||
if (\is_string($value)) {
|
||||
$options[\CURLOPT_CAINFO] = $value;
|
||||
if (!\file_exists($value)) {
|
||||
throw new \InvalidArgumentException("SSL CA bundle not found: {$value}");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'decode_content':
|
||||
if ($value === \false) {
|
||||
continue 2;
|
||||
}
|
||||
$accept = \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::firstHeader($request, 'Accept-Encoding');
|
||||
if ($accept) {
|
||||
$options[\CURLOPT_ENCODING] = $accept;
|
||||
} else {
|
||||
$options[\CURLOPT_ENCODING] = '';
|
||||
// Don't let curl send the header over the wire
|
||||
$options[\CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
|
||||
}
|
||||
break;
|
||||
case 'save_to':
|
||||
if (\is_string($value)) {
|
||||
if (!\is_dir(\dirname($value))) {
|
||||
throw new \RuntimeException(\sprintf('Directory %s does not exist for save_to value of %s', \dirname($value), $value));
|
||||
}
|
||||
$value = new \Google\Site_Kit_Dependencies\GuzzleHttp\Stream\LazyOpenStream($value, 'w+');
|
||||
}
|
||||
if ($value instanceof \Google\Site_Kit_Dependencies\GuzzleHttp\Stream\StreamInterface) {
|
||||
$options[\CURLOPT_WRITEFUNCTION] = function ($ch, $write) use($value) {
|
||||
return $value->write($write);
|
||||
};
|
||||
} elseif (\is_resource($value)) {
|
||||
$options[\CURLOPT_FILE] = $value;
|
||||
} else {
|
||||
throw new \InvalidArgumentException('save_to must be a ' . 'GuzzleHttp\\Stream\\StreamInterface or resource');
|
||||
}
|
||||
break;
|
||||
case 'timeout':
|
||||
if (\defined('CURLOPT_TIMEOUT_MS')) {
|
||||
$options[\CURLOPT_TIMEOUT_MS] = $value * 1000;
|
||||
} else {
|
||||
$options[\CURLOPT_TIMEOUT] = $value;
|
||||
}
|
||||
break;
|
||||
case 'connect_timeout':
|
||||
if (\defined('CURLOPT_CONNECTTIMEOUT_MS')) {
|
||||
$options[\CURLOPT_CONNECTTIMEOUT_MS] = $value * 1000;
|
||||
} else {
|
||||
$options[\CURLOPT_CONNECTTIMEOUT] = $value;
|
||||
}
|
||||
break;
|
||||
case 'proxy':
|
||||
if (!\is_array($value)) {
|
||||
$options[\CURLOPT_PROXY] = $value;
|
||||
} elseif (isset($request['scheme'])) {
|
||||
$scheme = $request['scheme'];
|
||||
if (isset($value[$scheme])) {
|
||||
$options[\CURLOPT_PROXY] = $value[$scheme];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'cert':
|
||||
if (\is_array($value)) {
|
||||
$options[\CURLOPT_SSLCERTPASSWD] = $value[1];
|
||||
$value = $value[0];
|
||||
}
|
||||
if (!\file_exists($value)) {
|
||||
throw new \InvalidArgumentException("SSL certificate not found: {$value}");
|
||||
}
|
||||
$options[\CURLOPT_SSLCERT] = $value;
|
||||
break;
|
||||
case 'ssl_key':
|
||||
if (\is_array($value)) {
|
||||
$options[\CURLOPT_SSLKEYPASSWD] = $value[1];
|
||||
$value = $value[0];
|
||||
}
|
||||
if (!\file_exists($value)) {
|
||||
throw new \InvalidArgumentException("SSL private key not found: {$value}");
|
||||
}
|
||||
$options[\CURLOPT_SSLKEY] = $value;
|
||||
break;
|
||||
case 'progress':
|
||||
if (!\is_callable($value)) {
|
||||
throw new \InvalidArgumentException('progress client option must be callable');
|
||||
}
|
||||
$options[\CURLOPT_NOPROGRESS] = \false;
|
||||
$options[\CURLOPT_PROGRESSFUNCTION] = function () use($value) {
|
||||
$args = \func_get_args();
|
||||
// PHP 5.5 pushed the handle onto the start of the args
|
||||
if (\is_resource($args[0])) {
|
||||
\array_shift($args);
|
||||
}
|
||||
\call_user_func_array($value, $args);
|
||||
};
|
||||
break;
|
||||
case 'debug':
|
||||
if ($value) {
|
||||
$options[\CURLOPT_STDERR] = \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::getDebugResource($value);
|
||||
$options[\CURLOPT_VERBOSE] = \true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This function ensures that a response was set on a transaction. If one
|
||||
* was not set, then the request is retried if possible. This error
|
||||
* typically means you are sending a payload, curl encountered a
|
||||
* "Connection died, retrying a fresh connect" error, tried to rewind the
|
||||
* stream, and then encountered a "necessary data rewind wasn't possible"
|
||||
* error, causing the request to be sent through curl_multi_info_read()
|
||||
* without an error status.
|
||||
*/
|
||||
private static function retryFailedRewind(callable $handler, array $request, array $response)
|
||||
{
|
||||
// If there is no body, then there is some other kind of issue. This
|
||||
// is weird and should probably never happen.
|
||||
if (!isset($request['body'])) {
|
||||
$response['err_message'] = 'No response was received for a request ' . 'with no body. This could mean that you are saturating your ' . 'network.';
|
||||
return self::createErrorResponse($handler, $request, $response);
|
||||
}
|
||||
if (!\Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::rewindBody($request)) {
|
||||
$response['err_message'] = 'The connection unexpectedly failed ' . 'without providing an error. The request would have been ' . 'retried, but attempting to rewind the request body failed.';
|
||||
return self::createErrorResponse($handler, $request, $response);
|
||||
}
|
||||
// Retry no more than 3 times before giving up.
|
||||
if (!isset($request['curl']['retries'])) {
|
||||
$request['curl']['retries'] = 1;
|
||||
} elseif ($request['curl']['retries'] == 2) {
|
||||
$response['err_message'] = 'The cURL request was retried 3 times ' . 'and did no succeed. cURL was unable to rewind the body of ' . 'the request and subsequent retries resulted in the same ' . 'error. Turn on the debug option to see what went wrong. ' . 'See https://bugs.php.net/bug.php?id=47204 for more information.';
|
||||
return self::createErrorResponse($handler, $request, $response);
|
||||
} else {
|
||||
$request['curl']['retries']++;
|
||||
}
|
||||
return $handler($request);
|
||||
}
|
||||
}
|
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Client;
|
||||
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\CompletedFutureArray;
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core;
|
||||
/**
|
||||
* HTTP handler that uses cURL easy handles as a transport layer.
|
||||
*
|
||||
* Requires PHP 5.5+
|
||||
*
|
||||
* When using the CurlHandler, custom curl options can be specified as an
|
||||
* associative array of curl option constants mapping to values in the
|
||||
* **curl** key of the "client" key of the request.
|
||||
*/
|
||||
class CurlHandler
|
||||
{
|
||||
/** @var callable */
|
||||
private $factory;
|
||||
/** @var array Array of curl easy handles */
|
||||
private $handles = [];
|
||||
/** @var array Array of owned curl easy handles */
|
||||
private $ownedHandles = [];
|
||||
/** @var int Total number of idle handles to keep in cache */
|
||||
private $maxHandles;
|
||||
/**
|
||||
* Accepts an associative array of options:
|
||||
*
|
||||
* - factory: Optional callable factory used to create cURL handles.
|
||||
* The callable is passed a request hash when invoked, and returns an
|
||||
* array of the curl handle, headers resource, and body resource.
|
||||
* - max_handles: Maximum number of idle handles (defaults to 5).
|
||||
*
|
||||
* @param array $options Array of options to use with the handler
|
||||
*/
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
$this->handles = $this->ownedHandles = [];
|
||||
$this->factory = isset($options['handle_factory']) ? $options['handle_factory'] : new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Client\CurlFactory();
|
||||
$this->maxHandles = isset($options['max_handles']) ? $options['max_handles'] : 5;
|
||||
}
|
||||
public function __destruct()
|
||||
{
|
||||
foreach ($this->handles as $handle) {
|
||||
if (\is_resource($handle)) {
|
||||
\curl_close($handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param array $request
|
||||
*
|
||||
* @return CompletedFutureArray
|
||||
*/
|
||||
public function __invoke(array $request)
|
||||
{
|
||||
return new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\CompletedFutureArray($this->_invokeAsArray($request));
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @param array $request
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function _invokeAsArray(array $request)
|
||||
{
|
||||
$factory = $this->factory;
|
||||
// Ensure headers are by reference. They're updated elsewhere.
|
||||
$result = $factory($request, $this->checkoutEasyHandle());
|
||||
$h = $result[0];
|
||||
$hd =& $result[1];
|
||||
$bd = $result[2];
|
||||
\Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::doSleep($request);
|
||||
\curl_exec($h);
|
||||
$response = ['transfer_stats' => \curl_getinfo($h)];
|
||||
$response['curl']['error'] = \curl_error($h);
|
||||
$response['curl']['errno'] = \curl_errno($h);
|
||||
$response['transfer_stats'] = \array_merge($response['transfer_stats'], $response['curl']);
|
||||
$this->releaseEasyHandle($h);
|
||||
return \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Client\CurlFactory::createResponse([$this, '_invokeAsArray'], $request, $response, $hd, $bd);
|
||||
}
|
||||
private function checkoutEasyHandle()
|
||||
{
|
||||
// Find an unused handle in the cache
|
||||
if (\false !== ($key = \array_search(\false, $this->ownedHandles, \true))) {
|
||||
$this->ownedHandles[$key] = \true;
|
||||
return $this->handles[$key];
|
||||
}
|
||||
// Add a new handle
|
||||
$handle = \curl_init();
|
||||
$id = (int) $handle;
|
||||
$this->handles[$id] = $handle;
|
||||
$this->ownedHandles[$id] = \true;
|
||||
return $handle;
|
||||
}
|
||||
private function releaseEasyHandle($handle)
|
||||
{
|
||||
$id = (int) $handle;
|
||||
if (\count($this->ownedHandles) > $this->maxHandles) {
|
||||
\curl_close($this->handles[$id]);
|
||||
unset($this->handles[$id], $this->ownedHandles[$id]);
|
||||
} else {
|
||||
// curl_reset doesn't clear these out for some reason
|
||||
static $unsetValues = [\CURLOPT_HEADERFUNCTION => null, \CURLOPT_WRITEFUNCTION => null, \CURLOPT_READFUNCTION => null, \CURLOPT_PROGRESSFUNCTION => null];
|
||||
\curl_setopt_array($handle, $unsetValues);
|
||||
\curl_reset($handle);
|
||||
$this->ownedHandles[$id] = \false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Client;
|
||||
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\FutureArray;
|
||||
use Google\Site_Kit_Dependencies\React\Promise\Deferred;
|
||||
/**
|
||||
* Returns an asynchronous response using curl_multi_* functions.
|
||||
*
|
||||
* This handler supports future responses and the "delay" request client
|
||||
* option that can be used to delay before sending a request.
|
||||
*
|
||||
* When using the CurlMultiHandler, custom curl options can be specified as an
|
||||
* associative array of curl option constants mapping to values in the
|
||||
* **curl** key of the "client" key of the request.
|
||||
*
|
||||
* @property resource $_mh Internal use only. Lazy loaded multi-handle.
|
||||
*/
|
||||
class CurlMultiHandler
|
||||
{
|
||||
/** @var callable */
|
||||
private $factory;
|
||||
private $selectTimeout;
|
||||
private $active;
|
||||
private $handles = [];
|
||||
private $delays = [];
|
||||
private $maxHandles;
|
||||
/**
|
||||
* This handler accepts the following options:
|
||||
*
|
||||
* - mh: An optional curl_multi resource
|
||||
* - handle_factory: An optional callable used to generate curl handle
|
||||
* resources. the callable accepts a request hash and returns an array
|
||||
* of the handle, headers file resource, and the body resource.
|
||||
* - select_timeout: Optional timeout (in seconds) to block before timing
|
||||
* out while selecting curl handles. Defaults to 1 second.
|
||||
* - max_handles: Optional integer representing the maximum number of
|
||||
* open requests. When this number is reached, the queued futures are
|
||||
* flushed.
|
||||
*
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
if (isset($options['mh'])) {
|
||||
$this->_mh = $options['mh'];
|
||||
}
|
||||
$this->factory = isset($options['handle_factory']) ? $options['handle_factory'] : new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Client\CurlFactory();
|
||||
$this->selectTimeout = isset($options['select_timeout']) ? $options['select_timeout'] : 1;
|
||||
$this->maxHandles = isset($options['max_handles']) ? $options['max_handles'] : 100;
|
||||
}
|
||||
public function __get($name)
|
||||
{
|
||||
if ($name === '_mh') {
|
||||
return $this->_mh = \curl_multi_init();
|
||||
}
|
||||
throw new \BadMethodCallException();
|
||||
}
|
||||
public function __destruct()
|
||||
{
|
||||
// Finish any open connections before terminating the script.
|
||||
if ($this->handles) {
|
||||
$this->execute();
|
||||
}
|
||||
if (isset($this->_mh)) {
|
||||
\curl_multi_close($this->_mh);
|
||||
unset($this->_mh);
|
||||
}
|
||||
}
|
||||
public function __invoke(array $request)
|
||||
{
|
||||
$factory = $this->factory;
|
||||
$result = $factory($request);
|
||||
$entry = ['request' => $request, 'response' => [], 'handle' => $result[0], 'headers' => &$result[1], 'body' => $result[2], 'deferred' => new \Google\Site_Kit_Dependencies\React\Promise\Deferred()];
|
||||
$id = (int) $result[0];
|
||||
$future = new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\FutureArray($entry['deferred']->promise(), [$this, 'execute'], function () use($id) {
|
||||
return $this->cancel($id);
|
||||
});
|
||||
$this->addRequest($entry);
|
||||
// Transfer outstanding requests if there are too many open handles.
|
||||
if (\count($this->handles) >= $this->maxHandles) {
|
||||
$this->execute();
|
||||
}
|
||||
return $future;
|
||||
}
|
||||
/**
|
||||
* Runs until all outstanding connections have completed.
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
do {
|
||||
if ($this->active && \curl_multi_select($this->_mh, $this->selectTimeout) === -1) {
|
||||
// Perform a usleep if a select returns -1.
|
||||
// See: https://bugs.php.net/bug.php?id=61141
|
||||
\usleep(250);
|
||||
}
|
||||
// Add any delayed futures if needed.
|
||||
if ($this->delays) {
|
||||
$this->addDelays();
|
||||
}
|
||||
do {
|
||||
$mrc = \curl_multi_exec($this->_mh, $this->active);
|
||||
} while ($mrc === \CURLM_CALL_MULTI_PERFORM);
|
||||
$this->processMessages();
|
||||
// If there are delays but no transfers, then sleep for a bit.
|
||||
if (!$this->active && $this->delays) {
|
||||
\usleep(500);
|
||||
}
|
||||
} while ($this->active || $this->handles);
|
||||
}
|
||||
private function addRequest(array &$entry)
|
||||
{
|
||||
$id = (int) $entry['handle'];
|
||||
$this->handles[$id] = $entry;
|
||||
// If the request is a delay, then add the reques to the curl multi
|
||||
// pool only after the specified delay.
|
||||
if (isset($entry['request']['client']['delay'])) {
|
||||
$this->delays[$id] = \microtime(\true) + $entry['request']['client']['delay'] / 1000;
|
||||
} elseif (empty($entry['request']['future'])) {
|
||||
\curl_multi_add_handle($this->_mh, $entry['handle']);
|
||||
} else {
|
||||
\curl_multi_add_handle($this->_mh, $entry['handle']);
|
||||
// "lazy" futures are only sent once the pool has many requests.
|
||||
if ($entry['request']['future'] !== 'lazy') {
|
||||
do {
|
||||
$mrc = \curl_multi_exec($this->_mh, $this->active);
|
||||
} while ($mrc === \CURLM_CALL_MULTI_PERFORM);
|
||||
$this->processMessages();
|
||||
}
|
||||
}
|
||||
}
|
||||
private function removeProcessed($id)
|
||||
{
|
||||
if (isset($this->handles[$id])) {
|
||||
\curl_multi_remove_handle($this->_mh, $this->handles[$id]['handle']);
|
||||
\curl_close($this->handles[$id]['handle']);
|
||||
unset($this->handles[$id], $this->delays[$id]);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Cancels a handle from sending and removes references to it.
|
||||
*
|
||||
* @param int $id Handle ID to cancel and remove.
|
||||
*
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
private function cancel($id)
|
||||
{
|
||||
// Cannot cancel if it has been processed.
|
||||
if (!isset($this->handles[$id])) {
|
||||
return \false;
|
||||
}
|
||||
$handle = $this->handles[$id]['handle'];
|
||||
unset($this->delays[$id], $this->handles[$id]);
|
||||
\curl_multi_remove_handle($this->_mh, $handle);
|
||||
\curl_close($handle);
|
||||
return \true;
|
||||
}
|
||||
private function addDelays()
|
||||
{
|
||||
$currentTime = \microtime(\true);
|
||||
foreach ($this->delays as $id => $delay) {
|
||||
if ($currentTime >= $delay) {
|
||||
unset($this->delays[$id]);
|
||||
\curl_multi_add_handle($this->_mh, $this->handles[$id]['handle']);
|
||||
}
|
||||
}
|
||||
}
|
||||
private function processMessages()
|
||||
{
|
||||
while ($done = \curl_multi_info_read($this->_mh)) {
|
||||
$id = (int) $done['handle'];
|
||||
if (!isset($this->handles[$id])) {
|
||||
// Probably was cancelled.
|
||||
continue;
|
||||
}
|
||||
$entry = $this->handles[$id];
|
||||
$entry['response']['transfer_stats'] = \curl_getinfo($done['handle']);
|
||||
if ($done['result'] !== \CURLM_OK) {
|
||||
$entry['response']['curl']['errno'] = $done['result'];
|
||||
$entry['response']['curl']['error'] = \curl_error($done['handle']);
|
||||
}
|
||||
$result = \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Client\CurlFactory::createResponse($this, $entry['request'], $entry['response'], $entry['headers'], $entry['body']);
|
||||
$this->removeProcessed($id);
|
||||
$entry['deferred']->resolve($result);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Client;
|
||||
|
||||
/**
|
||||
* Provides basic middleware wrappers.
|
||||
*
|
||||
* If a middleware is more complex than a few lines of code, then it should
|
||||
* be implemented in a class rather than a static method.
|
||||
*/
|
||||
class Middleware
|
||||
{
|
||||
/**
|
||||
* Sends future requests to a future compatible handler while sending all
|
||||
* other requests to a default handler.
|
||||
*
|
||||
* When the "future" option is not provided on a request, any future responses
|
||||
* are automatically converted to synchronous responses and block.
|
||||
*
|
||||
* @param callable $default Handler used for non-streaming responses
|
||||
* @param callable $future Handler used for future responses
|
||||
*
|
||||
* @return callable Returns the composed handler.
|
||||
*/
|
||||
public static function wrapFuture(callable $default, callable $future)
|
||||
{
|
||||
return function (array $request) use($default, $future) {
|
||||
return empty($request['client']['future']) ? $default($request) : $future($request);
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Sends streaming requests to a streaming compatible handler while sendin
|
||||
* all other requests to a default handler.
|
||||
*
|
||||
* This, for example, could be useful for taking advantage of the
|
||||
* performance benefits of curl while still supporting true streaming
|
||||
* through the StreamHandler.
|
||||
*
|
||||
* @param callable $default Handler used for non-streaming responses
|
||||
* @param callable $streaming Handler used for streaming responses
|
||||
*
|
||||
* @return callable Returns the composed handler.
|
||||
*/
|
||||
public static function wrapStreaming(callable $default, callable $streaming)
|
||||
{
|
||||
return function (array $request) use($default, $streaming) {
|
||||
return empty($request['client']['stream']) ? $default($request) : $streaming($request);
|
||||
};
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Client;
|
||||
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core;
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\CompletedFutureArray;
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\FutureArrayInterface;
|
||||
/**
|
||||
* Ring handler that returns a canned response or evaluated function result.
|
||||
*/
|
||||
class MockHandler
|
||||
{
|
||||
/** @var callable|array|FutureArrayInterface */
|
||||
private $result;
|
||||
/**
|
||||
* Provide an array or future to always return the same value. Provide a
|
||||
* callable that accepts a request object and returns an array or future
|
||||
* to dynamically create a response.
|
||||
*
|
||||
* @param array|FutureArrayInterface|callable $result Mock return value.
|
||||
*/
|
||||
public function __construct($result)
|
||||
{
|
||||
$this->result = $result;
|
||||
}
|
||||
public function __invoke(array $request)
|
||||
{
|
||||
\Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::doSleep($request);
|
||||
$response = \is_callable($this->result) ? \call_user_func($this->result, $request) : $this->result;
|
||||
if (\is_array($response)) {
|
||||
$response = new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\CompletedFutureArray($response + ['status' => null, 'body' => null, 'headers' => [], 'reason' => null, 'effective_url' => null]);
|
||||
} elseif (!$response instanceof \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\FutureArrayInterface) {
|
||||
throw new \InvalidArgumentException('Response must be an array or FutureArrayInterface. Found ' . \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::describeType($request));
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
}
|
@@ -0,0 +1,295 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Client;
|
||||
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core;
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\ConnectException;
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\RingException;
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\CompletedFutureArray;
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Stream\InflateStream;
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Stream\StreamInterface;
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Stream\Stream;
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Stream\Utils;
|
||||
/**
|
||||
* RingPHP client handler that uses PHP's HTTP stream wrapper.
|
||||
*/
|
||||
class StreamHandler
|
||||
{
|
||||
private $options;
|
||||
private $lastHeaders;
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
$this->options = $options;
|
||||
}
|
||||
public function __invoke(array $request)
|
||||
{
|
||||
$url = \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::url($request);
|
||||
\Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::doSleep($request);
|
||||
try {
|
||||
// Does not support the expect header.
|
||||
$request = \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::removeHeader($request, 'Expect');
|
||||
$stream = $this->createStream($url, $request);
|
||||
return $this->createResponse($request, $url, $stream);
|
||||
} catch (\Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\RingException $e) {
|
||||
return $this->createErrorResponse($url, $e);
|
||||
}
|
||||
}
|
||||
private function createResponse(array $request, $url, $stream)
|
||||
{
|
||||
$hdrs = $this->lastHeaders;
|
||||
$this->lastHeaders = null;
|
||||
$parts = \explode(' ', \array_shift($hdrs), 3);
|
||||
$response = ['version' => \substr($parts[0], 5), 'status' => $parts[1], 'reason' => isset($parts[2]) ? $parts[2] : null, 'headers' => \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::headersFromLines($hdrs), 'effective_url' => $url];
|
||||
$stream = $this->checkDecode($request, $response, $stream);
|
||||
// If not streaming, then drain the response into a stream.
|
||||
if (empty($request['client']['stream'])) {
|
||||
$dest = isset($request['client']['save_to']) ? $request['client']['save_to'] : \fopen('php://temp', 'r+');
|
||||
$stream = $this->drain($stream, $dest);
|
||||
}
|
||||
$response['body'] = $stream;
|
||||
return new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\CompletedFutureArray($response);
|
||||
}
|
||||
private function checkDecode(array $request, array $response, $stream)
|
||||
{
|
||||
// Automatically decode responses when instructed.
|
||||
if (!empty($request['client']['decode_content'])) {
|
||||
switch (\Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::firstHeader($response, 'Content-Encoding', \true)) {
|
||||
case 'gzip':
|
||||
case 'deflate':
|
||||
$stream = new \Google\Site_Kit_Dependencies\GuzzleHttp\Stream\InflateStream(\Google\Site_Kit_Dependencies\GuzzleHttp\Stream\Stream::factory($stream));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $stream;
|
||||
}
|
||||
/**
|
||||
* Drains the stream into the "save_to" client option.
|
||||
*
|
||||
* @param resource $stream
|
||||
* @param string|resource|StreamInterface $dest
|
||||
*
|
||||
* @return Stream
|
||||
* @throws \RuntimeException when the save_to option is invalid.
|
||||
*/
|
||||
private function drain($stream, $dest)
|
||||
{
|
||||
if (\is_resource($stream)) {
|
||||
if (!\is_resource($dest)) {
|
||||
$stream = \Google\Site_Kit_Dependencies\GuzzleHttp\Stream\Stream::factory($stream);
|
||||
} else {
|
||||
\stream_copy_to_stream($stream, $dest);
|
||||
\fclose($stream);
|
||||
\rewind($dest);
|
||||
return $dest;
|
||||
}
|
||||
}
|
||||
// Stream the response into the destination stream
|
||||
$dest = \is_string($dest) ? new \Google\Site_Kit_Dependencies\GuzzleHttp\Stream\Stream(\Google\Site_Kit_Dependencies\GuzzleHttp\Stream\Utils::open($dest, 'r+')) : \Google\Site_Kit_Dependencies\GuzzleHttp\Stream\Stream::factory($dest);
|
||||
\Google\Site_Kit_Dependencies\GuzzleHttp\Stream\Utils::copyToStream($stream, $dest);
|
||||
$dest->seek(0);
|
||||
$stream->close();
|
||||
return $dest;
|
||||
}
|
||||
/**
|
||||
* Creates an error response for the given stream.
|
||||
*
|
||||
* @param string $url
|
||||
* @param RingException $e
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function createErrorResponse($url, \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\RingException $e)
|
||||
{
|
||||
// Determine if the error was a networking error.
|
||||
$message = $e->getMessage();
|
||||
// This list can probably get more comprehensive.
|
||||
if (\strpos($message, 'getaddrinfo') || \strpos($message, 'Connection refused')) {
|
||||
$e = new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\ConnectException($e->getMessage(), 0, $e);
|
||||
}
|
||||
return new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\CompletedFutureArray(['status' => null, 'body' => null, 'headers' => [], 'effective_url' => $url, 'error' => $e]);
|
||||
}
|
||||
/**
|
||||
* Create a resource and check to ensure it was created successfully
|
||||
*
|
||||
* @param callable $callback Callable that returns stream resource
|
||||
*
|
||||
* @return resource
|
||||
* @throws \RuntimeException on error
|
||||
*/
|
||||
private function createResource(callable $callback)
|
||||
{
|
||||
$errors = null;
|
||||
\set_error_handler(function ($_, $msg, $file, $line) use(&$errors) {
|
||||
$errors[] = ['message' => $msg, 'file' => $file, 'line' => $line];
|
||||
return \true;
|
||||
});
|
||||
$resource = $callback();
|
||||
\restore_error_handler();
|
||||
if (!$resource) {
|
||||
$message = 'Error creating resource: ';
|
||||
foreach ($errors as $err) {
|
||||
foreach ($err as $key => $value) {
|
||||
$message .= "[{$key}] {$value}" . \PHP_EOL;
|
||||
}
|
||||
}
|
||||
throw new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\RingException(\trim($message));
|
||||
}
|
||||
return $resource;
|
||||
}
|
||||
private function createStream($url, array $request)
|
||||
{
|
||||
static $methods;
|
||||
if (!$methods) {
|
||||
$methods = \array_flip(\get_class_methods(__CLASS__));
|
||||
}
|
||||
// HTTP/1.1 streams using the PHP stream wrapper require a
|
||||
// Connection: close header
|
||||
if ((!isset($request['version']) || $request['version'] == '1.1') && !\Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::hasHeader($request, 'Connection')) {
|
||||
$request['headers']['Connection'] = ['close'];
|
||||
}
|
||||
// Ensure SSL is verified by default
|
||||
if (!isset($request['client']['verify'])) {
|
||||
$request['client']['verify'] = \true;
|
||||
}
|
||||
$params = [];
|
||||
$options = $this->getDefaultOptions($request);
|
||||
if (isset($request['client'])) {
|
||||
foreach ($request['client'] as $key => $value) {
|
||||
$method = "add_{$key}";
|
||||
if (isset($methods[$method])) {
|
||||
$this->{$method}($request, $options, $value, $params);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->createStreamResource($url, $request, $options, $this->createContext($request, $options, $params));
|
||||
}
|
||||
private function getDefaultOptions(array $request)
|
||||
{
|
||||
$headers = "";
|
||||
foreach ($request['headers'] as $name => $value) {
|
||||
foreach ((array) $value as $val) {
|
||||
$headers .= "{$name}: {$val}\r\n";
|
||||
}
|
||||
}
|
||||
$context = ['http' => ['method' => $request['http_method'], 'header' => $headers, 'protocol_version' => isset($request['version']) ? $request['version'] : 1.1, 'ignore_errors' => \true, 'follow_location' => 0]];
|
||||
$body = \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::body($request);
|
||||
if (isset($body)) {
|
||||
$context['http']['content'] = $body;
|
||||
// Prevent the HTTP handler from adding a Content-Type header.
|
||||
if (!\Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::hasHeader($request, 'Content-Type')) {
|
||||
$context['http']['header'] .= "Content-Type:\r\n";
|
||||
}
|
||||
}
|
||||
$context['http']['header'] = \rtrim($context['http']['header']);
|
||||
return $context;
|
||||
}
|
||||
private function add_proxy(array $request, &$options, $value, &$params)
|
||||
{
|
||||
if (!\is_array($value)) {
|
||||
$options['http']['proxy'] = $value;
|
||||
} else {
|
||||
$scheme = isset($request['scheme']) ? $request['scheme'] : 'http';
|
||||
if (isset($value[$scheme])) {
|
||||
$options['http']['proxy'] = $value[$scheme];
|
||||
}
|
||||
}
|
||||
}
|
||||
private function add_timeout(array $request, &$options, $value, &$params)
|
||||
{
|
||||
$options['http']['timeout'] = $value;
|
||||
}
|
||||
private function add_verify(array $request, &$options, $value, &$params)
|
||||
{
|
||||
if ($value === \true) {
|
||||
// PHP 5.6 or greater will find the system cert by default. When
|
||||
// < 5.6, use the Guzzle bundled cacert.
|
||||
if (\PHP_VERSION_ID < 50600) {
|
||||
$options['ssl']['cafile'] = \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Client\ClientUtils::getDefaultCaBundle();
|
||||
}
|
||||
} elseif (\is_string($value)) {
|
||||
$options['ssl']['cafile'] = $value;
|
||||
if (!\file_exists($value)) {
|
||||
throw new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\RingException("SSL CA bundle not found: {$value}");
|
||||
}
|
||||
} elseif ($value === \false) {
|
||||
$options['ssl']['verify_peer'] = \false;
|
||||
$options['ssl']['allow_self_signed'] = \true;
|
||||
return;
|
||||
} else {
|
||||
throw new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\RingException('Invalid verify request option');
|
||||
}
|
||||
$options['ssl']['verify_peer'] = \true;
|
||||
$options['ssl']['allow_self_signed'] = \false;
|
||||
}
|
||||
private function add_cert(array $request, &$options, $value, &$params)
|
||||
{
|
||||
if (\is_array($value)) {
|
||||
$options['ssl']['passphrase'] = $value[1];
|
||||
$value = $value[0];
|
||||
}
|
||||
if (!\file_exists($value)) {
|
||||
throw new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\RingException("SSL certificate not found: {$value}");
|
||||
}
|
||||
$options['ssl']['local_cert'] = $value;
|
||||
}
|
||||
private function add_progress(array $request, &$options, $value, &$params)
|
||||
{
|
||||
$fn = function ($code, $_1, $_2, $_3, $transferred, $total) use($value) {
|
||||
if ($code == \STREAM_NOTIFY_PROGRESS) {
|
||||
$value($total, $transferred, null, null);
|
||||
}
|
||||
};
|
||||
// Wrap the existing function if needed.
|
||||
$params['notification'] = isset($params['notification']) ? \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::callArray([$params['notification'], $fn]) : $fn;
|
||||
}
|
||||
private function add_debug(array $request, &$options, $value, &$params)
|
||||
{
|
||||
if ($value === \false) {
|
||||
return;
|
||||
}
|
||||
static $map = [\STREAM_NOTIFY_CONNECT => 'CONNECT', \STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED', \STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT', \STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS', \STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS', \STREAM_NOTIFY_REDIRECTED => 'REDIRECTED', \STREAM_NOTIFY_PROGRESS => 'PROGRESS', \STREAM_NOTIFY_FAILURE => 'FAILURE', \STREAM_NOTIFY_COMPLETED => 'COMPLETED', \STREAM_NOTIFY_RESOLVE => 'RESOLVE'];
|
||||
static $args = ['severity', 'message', 'message_code', 'bytes_transferred', 'bytes_max'];
|
||||
$value = \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::getDebugResource($value);
|
||||
$ident = $request['http_method'] . ' ' . \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::url($request);
|
||||
$fn = function () use($ident, $value, $map, $args) {
|
||||
$passed = \func_get_args();
|
||||
$code = \array_shift($passed);
|
||||
\fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
|
||||
foreach (\array_filter($passed) as $i => $v) {
|
||||
\fwrite($value, $args[$i] . ': "' . $v . '" ');
|
||||
}
|
||||
\fwrite($value, "\n");
|
||||
};
|
||||
// Wrap the existing function if needed.
|
||||
$params['notification'] = isset($params['notification']) ? \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Core::callArray([$params['notification'], $fn]) : $fn;
|
||||
}
|
||||
private function applyCustomOptions(array $request, array &$options)
|
||||
{
|
||||
if (!isset($request['client']['stream_context'])) {
|
||||
return;
|
||||
}
|
||||
if (!\is_array($request['client']['stream_context'])) {
|
||||
throw new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\RingException('stream_context must be an array');
|
||||
}
|
||||
$options = \array_replace_recursive($options, $request['client']['stream_context']);
|
||||
}
|
||||
private function createContext(array $request, array $options, array $params)
|
||||
{
|
||||
$this->applyCustomOptions($request, $options);
|
||||
return $this->createResource(function () use($request, $options, $params) {
|
||||
return \stream_context_create($options, $params);
|
||||
}, $request, $options);
|
||||
}
|
||||
private function createStreamResource($url, array $request, array $options, $context)
|
||||
{
|
||||
return $this->createResource(function () use($url, $context) {
|
||||
if (\false === \strpos($url, 'http')) {
|
||||
\trigger_error("URL is invalid: {$url}", \E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
$resource = \fopen($url, 'r', null, $context);
|
||||
$this->lastHeaders = $http_response_header;
|
||||
return $resource;
|
||||
}, $request, $options);
|
||||
}
|
||||
}
|
317
hamrokhaanpaan/wp-content/__plugins/google-site-kit/third-party/guzzlehttp/ringphp/src/Core.php
vendored
Normal file
317
hamrokhaanpaan/wp-content/__plugins/google-site-kit/third-party/guzzlehttp/ringphp/src/Core.php
vendored
Normal file
@@ -0,0 +1,317 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring;
|
||||
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Stream\StreamInterface;
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\FutureArrayInterface;
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\FutureArray;
|
||||
/**
|
||||
* Provides core functionality of Ring handlers and middleware.
|
||||
*/
|
||||
class Core
|
||||
{
|
||||
/**
|
||||
* Returns a function that calls all of the provided functions, in order,
|
||||
* passing the arguments provided to the composed function to each function.
|
||||
*
|
||||
* @param callable[] $functions Array of functions to proxy to.
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
public static function callArray(array $functions)
|
||||
{
|
||||
return function () use($functions) {
|
||||
$args = \func_get_args();
|
||||
foreach ($functions as $fn) {
|
||||
\call_user_func_array($fn, $args);
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Gets an array of header line values from a message for a specific header
|
||||
*
|
||||
* This method searches through the "headers" key of a message for a header
|
||||
* using a case-insensitive search.
|
||||
*
|
||||
* @param array $message Request or response hash.
|
||||
* @param string $header Header to retrieve
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function headerLines($message, $header)
|
||||
{
|
||||
$result = [];
|
||||
if (!empty($message['headers'])) {
|
||||
foreach ($message['headers'] as $name => $value) {
|
||||
if (!\strcasecmp($name, $header)) {
|
||||
$result = \array_merge($result, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
/**
|
||||
* Gets a header value from a message as a string or null
|
||||
*
|
||||
* This method searches through the "headers" key of a message for a header
|
||||
* using a case-insensitive search. The lines of the header are imploded
|
||||
* using commas into a single string return value.
|
||||
*
|
||||
* @param array $message Request or response hash.
|
||||
* @param string $header Header to retrieve
|
||||
*
|
||||
* @return string|null Returns the header string if found, or null if not.
|
||||
*/
|
||||
public static function header($message, $header)
|
||||
{
|
||||
$match = self::headerLines($message, $header);
|
||||
return $match ? \implode(', ', $match) : null;
|
||||
}
|
||||
/**
|
||||
* Returns the first header value from a message as a string or null. If
|
||||
* a header line contains multiple values separated by a comma, then this
|
||||
* function will return the first value in the list.
|
||||
*
|
||||
* @param array $message Request or response hash.
|
||||
* @param string $header Header to retrieve
|
||||
*
|
||||
* @return string|null Returns the value as a string if found.
|
||||
*/
|
||||
public static function firstHeader($message, $header)
|
||||
{
|
||||
if (!empty($message['headers'])) {
|
||||
foreach ($message['headers'] as $name => $value) {
|
||||
if (!\strcasecmp($name, $header)) {
|
||||
// Return the match itself if it is a single value.
|
||||
$pos = \strpos($value[0], ',');
|
||||
return $pos ? \substr($value[0], 0, $pos) : $value[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Returns true if a message has the provided case-insensitive header.
|
||||
*
|
||||
* @param array $message Request or response hash.
|
||||
* @param string $header Header to check
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasHeader($message, $header)
|
||||
{
|
||||
if (!empty($message['headers'])) {
|
||||
foreach ($message['headers'] as $name => $value) {
|
||||
if (!\strcasecmp($name, $header)) {
|
||||
return \true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return \false;
|
||||
}
|
||||
/**
|
||||
* Parses an array of header lines into an associative array of headers.
|
||||
*
|
||||
* @param array $lines Header lines array of strings in the following
|
||||
* format: "Name: Value"
|
||||
* @return array
|
||||
*/
|
||||
public static function headersFromLines($lines)
|
||||
{
|
||||
$headers = [];
|
||||
foreach ($lines as $line) {
|
||||
$parts = \explode(':', $line, 2);
|
||||
$headers[\trim($parts[0])][] = isset($parts[1]) ? \trim($parts[1]) : null;
|
||||
}
|
||||
return $headers;
|
||||
}
|
||||
/**
|
||||
* Removes a header from a message using a case-insensitive comparison.
|
||||
*
|
||||
* @param array $message Message that contains 'headers'
|
||||
* @param string $header Header to remove
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function removeHeader(array $message, $header)
|
||||
{
|
||||
if (isset($message['headers'])) {
|
||||
foreach (\array_keys($message['headers']) as $key) {
|
||||
if (!\strcasecmp($header, $key)) {
|
||||
unset($message['headers'][$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $message;
|
||||
}
|
||||
/**
|
||||
* Replaces any existing case insensitive headers with the given value.
|
||||
*
|
||||
* @param array $message Message that contains 'headers'
|
||||
* @param string $header Header to set.
|
||||
* @param array $value Value to set.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function setHeader(array $message, $header, array $value)
|
||||
{
|
||||
$message = self::removeHeader($message, $header);
|
||||
$message['headers'][$header] = $value;
|
||||
return $message;
|
||||
}
|
||||
/**
|
||||
* Creates a URL string from a request.
|
||||
*
|
||||
* If the "url" key is present on the request, it is returned, otherwise
|
||||
* the url is built up based on the scheme, host, uri, and query_string
|
||||
* request values.
|
||||
*
|
||||
* @param array $request Request to get the URL from
|
||||
*
|
||||
* @return string Returns the request URL as a string.
|
||||
* @throws \InvalidArgumentException if no Host header is present.
|
||||
*/
|
||||
public static function url(array $request)
|
||||
{
|
||||
if (isset($request['url'])) {
|
||||
return $request['url'];
|
||||
}
|
||||
$uri = (isset($request['scheme']) ? $request['scheme'] : 'http') . '://';
|
||||
if ($host = self::header($request, 'host')) {
|
||||
$uri .= $host;
|
||||
} else {
|
||||
throw new \InvalidArgumentException('No Host header was provided');
|
||||
}
|
||||
if (isset($request['uri'])) {
|
||||
$uri .= $request['uri'];
|
||||
}
|
||||
if (isset($request['query_string'])) {
|
||||
$uri .= '?' . $request['query_string'];
|
||||
}
|
||||
return $uri;
|
||||
}
|
||||
/**
|
||||
* Reads the body of a message into a string.
|
||||
*
|
||||
* @param array|FutureArrayInterface $message Array containing a "body" key
|
||||
*
|
||||
* @return null|string Returns the body as a string or null if not set.
|
||||
* @throws \InvalidArgumentException if a request body is invalid.
|
||||
*/
|
||||
public static function body($message)
|
||||
{
|
||||
if (!isset($message['body'])) {
|
||||
return null;
|
||||
}
|
||||
if ($message['body'] instanceof \Google\Site_Kit_Dependencies\GuzzleHttp\Stream\StreamInterface) {
|
||||
return (string) $message['body'];
|
||||
}
|
||||
switch (\gettype($message['body'])) {
|
||||
case 'string':
|
||||
return $message['body'];
|
||||
case 'resource':
|
||||
return \stream_get_contents($message['body']);
|
||||
case 'object':
|
||||
if ($message['body'] instanceof \Iterator) {
|
||||
return \implode('', \iterator_to_array($message['body']));
|
||||
} elseif (\method_exists($message['body'], '__toString')) {
|
||||
return (string) $message['body'];
|
||||
}
|
||||
default:
|
||||
throw new \InvalidArgumentException('Invalid request body: ' . self::describeType($message['body']));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Rewind the body of the provided message if possible.
|
||||
*
|
||||
* @param array $message Message that contains a 'body' field.
|
||||
*
|
||||
* @return bool Returns true on success, false on failure
|
||||
*/
|
||||
public static function rewindBody($message)
|
||||
{
|
||||
if ($message['body'] instanceof \Google\Site_Kit_Dependencies\GuzzleHttp\Stream\StreamInterface) {
|
||||
return $message['body']->seek(0);
|
||||
}
|
||||
if ($message['body'] instanceof \Generator) {
|
||||
return \false;
|
||||
}
|
||||
if ($message['body'] instanceof \Iterator) {
|
||||
$message['body']->rewind();
|
||||
return \true;
|
||||
}
|
||||
if (\is_resource($message['body'])) {
|
||||
return \rewind($message['body']);
|
||||
}
|
||||
return \is_string($message['body']) || \is_object($message['body']) && \method_exists($message['body'], '__toString');
|
||||
}
|
||||
/**
|
||||
* Debug function used to describe the provided value type and class.
|
||||
*
|
||||
* @param mixed $input
|
||||
*
|
||||
* @return string Returns a string containing the type of the variable and
|
||||
* if a class is provided, the class name.
|
||||
*/
|
||||
public static function describeType($input)
|
||||
{
|
||||
switch (\gettype($input)) {
|
||||
case 'object':
|
||||
return 'object(' . \get_class($input) . ')';
|
||||
case 'array':
|
||||
return 'array(' . \count($input) . ')';
|
||||
default:
|
||||
\ob_start();
|
||||
\var_dump($input);
|
||||
// normalize float vs double
|
||||
return \str_replace('double(', 'float(', \rtrim(\ob_get_clean()));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Sleep for the specified amount of time specified in the request's
|
||||
* ['client']['delay'] option if present.
|
||||
*
|
||||
* This function should only be used when a non-blocking sleep is not
|
||||
* possible.
|
||||
*
|
||||
* @param array $request Request to sleep
|
||||
*/
|
||||
public static function doSleep(array $request)
|
||||
{
|
||||
if (isset($request['client']['delay'])) {
|
||||
\usleep($request['client']['delay'] * 1000);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns a proxied future that modifies the dereferenced value of another
|
||||
* future using a promise.
|
||||
*
|
||||
* @param FutureArrayInterface $future Future to wrap with a new future
|
||||
* @param callable $onFulfilled Invoked when the future fulfilled
|
||||
* @param callable $onRejected Invoked when the future rejected
|
||||
* @param callable $onProgress Invoked when the future progresses
|
||||
*
|
||||
* @return FutureArray
|
||||
*/
|
||||
public static function proxy(\Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\FutureArrayInterface $future, callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
|
||||
{
|
||||
return new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\FutureArray($future->then($onFulfilled, $onRejected, $onProgress), [$future, 'wait'], [$future, 'cancel']);
|
||||
}
|
||||
/**
|
||||
* Returns a debug stream based on the provided variable.
|
||||
*
|
||||
* @param mixed $value Optional value
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
public static function getDebugResource($value = null)
|
||||
{
|
||||
if (\is_resource($value)) {
|
||||
return $value;
|
||||
} elseif (\defined('STDOUT')) {
|
||||
return \STDOUT;
|
||||
} else {
|
||||
return \fopen('php://output', 'w');
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception;
|
||||
|
||||
/**
|
||||
* Marker interface for cancelled exceptions.
|
||||
*/
|
||||
interface CancelledException
|
||||
{
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception;
|
||||
|
||||
class CancelledFutureAccessException extends \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\RingException implements \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\CancelledException
|
||||
{
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception;
|
||||
|
||||
/**
|
||||
* Occurs when the connection failed.
|
||||
*/
|
||||
class ConnectException extends \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\RingException
|
||||
{
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception;
|
||||
|
||||
class RingException extends \RuntimeException
|
||||
{
|
||||
}
|
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future;
|
||||
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\CancelledFutureAccessException;
|
||||
use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\RingException;
|
||||
use Google\Site_Kit_Dependencies\React\Promise\PromiseInterface;
|
||||
/**
|
||||
* Implements common future functionality built on top of promises.
|
||||
*/
|
||||
trait BaseFutureTrait
|
||||
{
|
||||
/** @var callable */
|
||||
private $waitfn;
|
||||
/** @var callable */
|
||||
private $cancelfn;
|
||||
/** @var PromiseInterface */
|
||||
private $wrappedPromise;
|
||||
/** @var \Exception Error encountered. */
|
||||
private $error;
|
||||
/** @var mixed Result of the future */
|
||||
private $result;
|
||||
private $isRealized = \false;
|
||||
/**
|
||||
* @param PromiseInterface $promise Promise to shadow with the future.
|
||||
* @param callable $wait Function that blocks until the deferred
|
||||
* computation has been resolved. This
|
||||
* function MUST resolve the deferred value
|
||||
* associated with the supplied promise.
|
||||
* @param callable $cancel If possible and reasonable, provide a
|
||||
* function that can be used to cancel the
|
||||
* future from completing.
|
||||
*/
|
||||
public function __construct(\Google\Site_Kit_Dependencies\React\Promise\PromiseInterface $promise, callable $wait = null, callable $cancel = null)
|
||||
{
|
||||
$this->wrappedPromise = $promise;
|
||||
$this->waitfn = $wait;
|
||||
$this->cancelfn = $cancel;
|
||||
}
|
||||
public function wait()
|
||||
{
|
||||
if (!$this->isRealized) {
|
||||
$this->addShadow();
|
||||
if (!$this->isRealized && $this->waitfn) {
|
||||
$this->invokeWait();
|
||||
}
|
||||
if (!$this->isRealized) {
|
||||
$this->error = new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\RingException('Waiting did not resolve future');
|
||||
}
|
||||
}
|
||||
if ($this->error) {
|
||||
throw $this->error;
|
||||
}
|
||||
return $this->result;
|
||||
}
|
||||
public function promise()
|
||||
{
|
||||
return $this->wrappedPromise;
|
||||
}
|
||||
public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
|
||||
{
|
||||
return $this->wrappedPromise->then($onFulfilled, $onRejected, $onProgress);
|
||||
}
|
||||
public function cancel()
|
||||
{
|
||||
if (!$this->isRealized) {
|
||||
$cancelfn = $this->cancelfn;
|
||||
$this->waitfn = $this->cancelfn = null;
|
||||
$this->isRealized = \true;
|
||||
$this->error = new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\CancelledFutureAccessException();
|
||||
if ($cancelfn) {
|
||||
$cancelfn($this);
|
||||
}
|
||||
}
|
||||
}
|
||||
private function addShadow()
|
||||
{
|
||||
// Get the result and error when the promise is resolved. Note that
|
||||
// calling this function might trigger the resolution immediately.
|
||||
$this->wrappedPromise->then(function ($value) {
|
||||
$this->isRealized = \true;
|
||||
$this->result = $value;
|
||||
$this->waitfn = $this->cancelfn = null;
|
||||
}, function ($error) {
|
||||
$this->isRealized = \true;
|
||||
$this->error = $error;
|
||||
$this->waitfn = $this->cancelfn = null;
|
||||
});
|
||||
}
|
||||
private function invokeWait()
|
||||
{
|
||||
try {
|
||||
$wait = $this->waitfn;
|
||||
$this->waitfn = null;
|
||||
$wait();
|
||||
} catch (\Exception $e) {
|
||||
// Defer can throw to reject.
|
||||
$this->error = $e;
|
||||
$this->isRealized = \true;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future;
|
||||
|
||||
/**
|
||||
* Represents a future array that has been completed successfully.
|
||||
*/
|
||||
class CompletedFutureArray extends \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\CompletedFutureValue implements \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\FutureArrayInterface
|
||||
{
|
||||
public function __construct(array $result)
|
||||
{
|
||||
parent::__construct($result);
|
||||
}
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->result[$offset]);
|
||||
}
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->result[$offset];
|
||||
}
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->result[$offset] = $value;
|
||||
}
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->result[$offset]);
|
||||
}
|
||||
public function count()
|
||||
{
|
||||
return \count($this->result);
|
||||
}
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->result);
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future;
|
||||
|
||||
use Google\Site_Kit_Dependencies\React\Promise\FulfilledPromise;
|
||||
use Google\Site_Kit_Dependencies\React\Promise\RejectedPromise;
|
||||
/**
|
||||
* Represents a future value that has been resolved or rejected.
|
||||
*/
|
||||
class CompletedFutureValue implements \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\FutureInterface
|
||||
{
|
||||
protected $result;
|
||||
protected $error;
|
||||
private $cachedPromise;
|
||||
/**
|
||||
* @param mixed $result Resolved result
|
||||
* @param \Exception $e Error. Pass a GuzzleHttp\Ring\Exception\CancelledFutureAccessException
|
||||
* to mark the future as cancelled.
|
||||
*/
|
||||
public function __construct($result, \Exception $e = null)
|
||||
{
|
||||
$this->result = $result;
|
||||
$this->error = $e;
|
||||
}
|
||||
public function wait()
|
||||
{
|
||||
if ($this->error) {
|
||||
throw $this->error;
|
||||
}
|
||||
return $this->result;
|
||||
}
|
||||
public function cancel()
|
||||
{
|
||||
}
|
||||
public function promise()
|
||||
{
|
||||
if (!$this->cachedPromise) {
|
||||
$this->cachedPromise = $this->error ? new \Google\Site_Kit_Dependencies\React\Promise\RejectedPromise($this->error) : new \Google\Site_Kit_Dependencies\React\Promise\FulfilledPromise($this->result);
|
||||
}
|
||||
return $this->cachedPromise;
|
||||
}
|
||||
public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
|
||||
{
|
||||
return $this->promise()->then($onFulfilled, $onRejected, $onProgress);
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future;
|
||||
|
||||
/**
|
||||
* Represents a future array value that when dereferenced returns an array.
|
||||
*/
|
||||
class FutureArray implements \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\FutureArrayInterface
|
||||
{
|
||||
use MagicFutureTrait;
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->_value[$offset]);
|
||||
}
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->_value[$offset];
|
||||
}
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->_value[$offset] = $value;
|
||||
}
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->_value[$offset]);
|
||||
}
|
||||
public function count()
|
||||
{
|
||||
return \count($this->_value);
|
||||
}
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->_value);
|
||||
}
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future;
|
||||
|
||||
/**
|
||||
* Future that provides array-like access.
|
||||
*/
|
||||
interface FutureArrayInterface extends \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\FutureInterface, \ArrayAccess, \Countable, \IteratorAggregate
|
||||
{
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future;
|
||||
|
||||
use Google\Site_Kit_Dependencies\React\Promise\PromiseInterface;
|
||||
use Google\Site_Kit_Dependencies\React\Promise\PromisorInterface;
|
||||
/**
|
||||
* Represents the result of a computation that may not have completed yet.
|
||||
*
|
||||
* You can use the future in a blocking manner using the wait() function, or
|
||||
* you can use a promise from the future to receive the result when the future
|
||||
* has been resolved.
|
||||
*
|
||||
* When the future is dereferenced using wait(), the result of the computation
|
||||
* is cached and returned for subsequent calls to wait(). If the result of the
|
||||
* computation has not yet completed when wait() is called, the call to wait()
|
||||
* will block until the future has completed.
|
||||
*/
|
||||
interface FutureInterface extends \Google\Site_Kit_Dependencies\React\Promise\PromiseInterface, \Google\Site_Kit_Dependencies\React\Promise\PromisorInterface
|
||||
{
|
||||
/**
|
||||
* Returns the result of the future either from cache or by blocking until
|
||||
* it is complete.
|
||||
*
|
||||
* This method must block until the future has a result or is cancelled.
|
||||
* Throwing an exception in the wait() method will mark the future as
|
||||
* realized and will throw the exception each time wait() is called.
|
||||
* Throwing an instance of GuzzleHttp\Ring\CancelledException will mark
|
||||
* the future as realized, will not throw immediately, but will throw the
|
||||
* exception if the future's wait() method is called again.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function wait();
|
||||
/**
|
||||
* Cancels the future, if possible.
|
||||
*/
|
||||
public function cancel();
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future;
|
||||
|
||||
/**
|
||||
* Represents a future value that responds to wait() to retrieve the promised
|
||||
* value, but can also return promises that are delivered the value when it is
|
||||
* available.
|
||||
*/
|
||||
class FutureValue implements \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future\FutureInterface
|
||||
{
|
||||
use BaseFutureTrait;
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future;
|
||||
|
||||
/**
|
||||
* Implements common future functionality that is triggered when the result
|
||||
* property is accessed via a magic __get method.
|
||||
*
|
||||
* @property mixed $_value Actual data used by the future. Accessing this
|
||||
* property will cause the future to block if needed.
|
||||
*/
|
||||
trait MagicFutureTrait
|
||||
{
|
||||
use BaseFutureTrait;
|
||||
/**
|
||||
* This function handles retrieving the dereferenced result when requested.
|
||||
*
|
||||
* @param string $name Should always be "data" or an exception is thrown.
|
||||
*
|
||||
* @return mixed Returns the dereferenced data.
|
||||
* @throws \RuntimeException
|
||||
* @throws \GuzzleHttp\Ring\Exception\CancelledException
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
if ($name !== '_value') {
|
||||
throw new \RuntimeException("Class has no {$name} property");
|
||||
}
|
||||
return $this->_value = $this->wait();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user