Guzzle client error

Эта страница содержит краткое введение в Guzzle и ознакомительные примеры. Если вы еще не установили Guzzle, перейдите на Установка страницу.

Быстрый старт¶

Эта страница содержит краткое введение в Guzzle и ознакомительные примеры.
Если вы еще не установили Guzzle, перейдите на Установка
страницу.

Создание запроса¶

Вы можете отправлять запросы с помощью Guzzle, используя объект GuzzleHttpClientInterface.

Создание клиента¶

use GuzzleHttpClient;

$client = new Client([
    // Base URI is used with relative requests
    'base_uri' => 'http://httpbin.org',
    // You can set any number of default request options.
    'timeout'  => 2.0,
]);

Клиенты неизменяемы в Guzzle, что означает, что вы не можете изменить значения по умолчанию, используемые клиентом после его создания.

Конструктор клиента принимает ассоциативный массив опций:

base_uri

(string|UriInterface) Базовый URI клиента, который объединяется в относительные
URI. Может быть строкой или экземпляром UriInterface. Когда относительный URI
предоставляется клиенту, клиент объединяет базовый URI с
относительным URI, используя правила, описанные в
RFC 3986, раздел 5.2.

// Создаем клиента с базовым URI
$client = new GuzzleHttpClient(['base_uri' => 'https://foo.com/api/']);
// Отправляем запрос на https://foo.com/api/test
$response = $client->request('GET', 'test');
// Отправляем запрос на https://foo.com/root
$response = $client->request('GET', '/root');

Не хочется читать RFC 3986? Вот несколько коротких примеров того, как base_uri разрешается с помощью другого URI.

base_uri URI Result
http://foo.com /bar http://foo.com/bar
http://foo.com/foo /bar http://foo.com/bar
http://foo.com/foo бар http://foo.com/bar
http://foo.com/foo/ бар http://foo.com/foo/bar
http://foo.com http://baz.com http://baz.com
http://foo.com/?bar бар http://foo.com/bar
обработчик.
(вызываемая) Функция, передающая HTTP-запросы по проводам.
вызывается с Psr7HttpMessageRequestInterface и массивом
опций передачи, и должен возвращать
GuzzleHttpPromisePromiseInterface, который выполняется с помощью
Psr7HttpMessageResponseInterface при успехе.
....
(смешанный) Все остальные параметры, переданные в конструктор, используются как параметры по умолчанию
опции запроса с каждым запросом, создаваемым клиентом.

Отправка запросов¶

Магические методы на клиенте упрощают отправку синхронных запросов:

$response = $client->get('http://httpbin.org/get');
$response = $client->delete('http://httpbin.org/delete');
$response = $client->head('http://httpbin.org/get');
$response = $client->options('http://httpbin.org/get');
$response = $client->patch('http://httpbin.org/patch');
$response = $client->post('http://httpbin.org/post');
$response = $client->put('http://httpbin.org/put');

Вы можете создать запрос, а затем отправить его вместе с клиентом, когда будете готовы:

use GuzzleHttpPsr7Request;

$request = new Request('PUT', 'http://httpbin.org/put');
$response = $client->send($request, ['timeout' => 2]);

Объекты клиента обеспечивают большую гибкость в том, как передаются запросы
включая опции запроса по умолчанию, промежуточное программное обеспечение стека обработчиков по умолчанию
которые используются каждым запросом, и базовый URI, который позволяет отправлять запросы
с относительными URI.

Вы можете узнать больше о клиентском промежуточном ПО на странице Handlers and Middleware документации.

Async Requests¶

Вы можете отправлять асинхронные запросы, используя магические методы, предоставляемые клиентом:

$promise = $client->getAsync('http://httpbin.org/get');
$promise = $client->deleteAsync('http://httpbin.org/delete');
$promise = $client->headAsync('http://httpbin.org/get');
$promise = $client->optionsAsync('http://httpbin.org/get');
$promise = $client->patchAsync('http://httpbin.org/patch');
$promise = $client->postAsync('http://httpbin.org/post');
$promise = $client->putAsync('http://httpbin.org/put');

Вы также можете использовать методы sendAsync() и requestAsync() клиента:

use GuzzleHttpPsr7Request;

// Create a PSR-7 request object to send
$headers = ['X-Foo' => 'Bar'];
$body = 'Hello!';
$request = new Request('HEAD', 'http://httpbin.org/head', $headers, $body);
$promise = $client->sendAsync($request);

// Or, if you don't need to pass in a request instance:
$promise = $client->requestAsync('GET', 'http://httpbin.org/get');

Обещание, возвращаемое этими методами, реализует стандарт
Promises/A+ spec, предоставляемый
Guzzle promises library. Это означает.
что вы можете создавать цепочки then() вызовов от обещания. Эти вызовы then
либо выполняются с успешным PsrHttpMessageResponseInterface, либо
отклоняется с исключением.

use PsrHttpMessageResponseInterface;
use GuzzleHttpExceptionRequestException;

$promise = $client->requestAsync('GET', 'http://httpbin.org/get');
$promise->then(
    function (ResponseInterface $res) {
        echo $res->getStatusCode() . "n";
    },
    function (RequestException $e) {
        echo $e->getMessage() . "n";
        echo $e->getRequest()->getMethod();
    }
);

Одновременные запросы¶

Вы можете отправлять несколько запросов одновременно, используя обещания и асинхронные запросы.

use GuzzleHttpClient;
use GuzzleHttpPromise;

$client = new Client(['base_uri' => 'http://httpbin.org/']);

// Initiate each request but do not block
$promises = [
    'image' => $client->getAsync('/image'),
    'png'   => $client->getAsync('/image/png'),
    'jpeg'  => $client->getAsync('/image/jpeg'),
    'webp'  => $client->getAsync('/image/webp')
];

// Wait for the requests to complete; throws a ConnectException
// if any of the requests fail
$responses = PromiseUtils::unwrap($promises);

// You can access each response using the key of the promise
echo $responses['image']->getHeader('Content-Length')[0];
echo $responses['png']->getHeader('Content-Length')[0];

// Wait for the requests to complete, even if some of them fail
$responses = PromiseUtils::settle($promises)->wait();

// Values returned above are wrapped in an array with 2 keys: "state" (either fulfilled or rejected) and "value" (contains the response)
echo $responses['image']['state']; // returns "fulfilled"
echo $responses['image']['value']->getHeader('Content-Length')[0];
echo $responses['png']['value']->getHeader('Content-Length')[0];

Вы можете использовать объект GuzzleHttpPool, когда у вас есть неопределенное количество запросов, которые вы хотите отправить.

use GuzzleHttpClient;
use GuzzleHttpExceptionRequestException;
use GuzzleHttpPool;
use GuzzleHttpPsr7Request;
use GuzzleHttpPsr7Response;

$client = new Client();

$requests = function ($total) {
    $uri = 'http://127.0.0.1:8126/guzzle-server/perf';
    for ($i = 0; $i < $total; $i++) {
        yield new Request('GET', $uri);
    }
};

$pool = new Pool($client, $requests(100), [
    'concurrency' => 5,
    'fulfilled' => function (Response $response, $index) {
        // this is delivered each successful response
    },
    'rejected' => function (RequestException $reason, $index) {
        // this is delivered each failed request
    },
]);

// Initiate the transfers and create a promise
$promise = $pool->promise();

// Force the pool of requests to complete.
$promise->wait();

Или использовать закрытие, которое вернет обещание, когда пул вызовет закрытие.

$client = new Client();

$requests = function ($total) use ($client) {
    $uri = 'http://127.0.0.1:8126/guzzle-server/perf';
    for ($i = 0; $i < $total; $i++) {
        yield function() use ($client, $uri) {
            return $client->getAsync($uri);
        };
    }
};

$pool = new Pool($client, $requests(100));

Использование ответов¶

В предыдущих примерах мы извлекали переменную $response или нам был
получили ответ из обещания. Объект response реализует PSR-7
ответ, PsrHttpMessageResponseInterface, и содержит много
полезной информации.

Вы можете получить код состояния и фразу причины ответа:

$code = $response->getStatusCode(); // 200
$reason = $response->getReasonPhrase(); // OK

Вы можете получить заголовки из ответа:

// Check if a header exists.
if ($response->hasHeader('Content-Length')) {
    echo "It exists";
}

// Get a header from the response.
echo $response->getHeader('Content-Length')[0];

// Get all of the response headers.
foreach ($response->getHeaders() as $name => $values) {
    echo $name . ': ' . implode(', ', $values) . "rn";
}

Тело ответа можно получить с помощью метода getBody. Тело может быть использовано как строка, приведено к строке или использовано как потокоподобный объект.

$body = $response->getBody();
// Implicitly cast the body to a string and echo it
echo $body;
// Explicitly cast the body to a string
$stringBody = (string) $body;
// Read 10 bytes from the body
$tenBytes = $body->read(10);
// Read the remaining contents of the body as a string
$remainingBytes = $body->getContents();

Параметры строки запроса¶

Вы можете предоставить параметры строки запроса вместе с запросом несколькими способами.

Вы можете задать параметры строки запроса в URI запроса:

$response = $client->request('GET', 'http://httpbin.org?foo=bar');

Параметры строки запроса можно задать с помощью опции запроса query в виде массива.

$client->request('GET', 'http://httpbin.org', [
    'query' => ['foo' => 'bar']
]);

Если предоставить опцию в виде массива, то для форматирования строки запроса будет использоваться функция PHP http_build_query.

И, наконец, вы можете предоставить параметр запроса query в виде строки.

$client->request('GET', 'http://httpbin.org', ['query' => 'foo=bar']);

Загрузка данных¶

Guzzle предоставляет несколько методов для загрузки данных.

Вы можете отправлять запросы, содержащие поток данных, передавая строку,
ресурс, возвращаемый из fopen, или экземпляр файла
PsrHttpMessageStreamInterface в опцию body запроса.

use GuzzleHttpPsr7;

// Provide the body as a string.
$r = $client->request('POST', 'http://httpbin.org/post', [
    'body' => 'raw data'
]);

// Provide an fopen resource.
$body = Psr7Utils::tryFopen('/path/to/file', 'r');
$r = $client->request('POST', 'http://httpbin.org/post', ['body' => $body]);

// Use the Utils::streamFor method to create a PSR-7 stream.
$body = Psr7Utils::streamFor('hello!');
$r = $client->request('POST', 'http://httpbin.org/post', ['body' => $body]);

Простой способ загрузить данные JSON и установить соответствующий заголовок — использовать опцию запроса json:

$r = $client->request('PUT', 'http://httpbin.org/put', [
    'json' => ['foo' => 'bar']
]);

POST/Form Requests¶

Помимо указания исходных данных запроса с помощью опции запроса body, Guzzle предоставляет полезные абстракции для отправки POST-данных.

Поля формы отправки¶

Отправка application/x-www-form-urlencoded POST-запросов требует указания POST-полей в виде массива в опциях запроса form_params.

$response = $client->request('POST', 'http://httpbin.org/post', [
    'form_params' => [
        'field_name' => 'abc',
        'other_field' => '123',
        'nested_field' => [
            'nested' => 'hello'
        ]
    ]
]);

Отправка файлов формы¶

Вы можете отправлять файлы вместе с формой (multipart/form-data POST-запросы),
используя опцию multipart запроса. multipart принимает массив из
ассоциативных массивов, где каждый ассоциативный массив содержит следующие ключи:

  • name: (required, string) ключ, отображающий имя поля формы.
  • содержимое: (требуется, смешанный) Предоставьте строку для отправки содержимого
    файла в виде строки, предоставить ресурс fopen для передачи содержимого из потока
    PHP потока, или PsrHttpMessageStreamInterface для передачи содержимого из потока PSR-7.
    содержимого из потока PSR-7.
use GuzzleHttpPsr7;

$response = $client->request('POST', 'http://httpbin.org/post', [
    'multipart' => [
        [
            'name'     => 'field_name',
            'contents' => 'abc'
        ],
        [
            'name'     => 'file_name',
            'contents' => Psr7Utils::tryFopen('/path/to/file', 'r')
        ],
        [
            'name'     => 'other_file',
            'contents' => 'hello',
            'filename' => 'filename.txt',
            'headers'  => [
                'X-Foo' => 'this is an extra header to include'
            ]
        ]
    ]
]);

Cookies¶

Guzzle может поддерживать сессию cookie для вас, если вы проинструктированы с помощью опции
cookies опцию запроса. При отправке запроса опция cookies
должна быть установлена на экземпляр GuzzleHttpCookieCookieJarInterface.

// Use a specific cookie jar
$jar = new GuzzleHttpCookieCookieJar;
$r = $client->request('GET', 'http://httpbin.org/cookies', [
    'cookies' => $jar
]);

Вы можете установить cookies в true в конструкторе клиента, если вы хотите использовать общий банк cookie для всех запросов.

// Use a shared client cookie jar
$client = new GuzzleHttpClient(['cookies' => true]);
$r = $client->request('GET', 'http://httpbin.org/cookies');

Для GuzzleHttpCookieCookieJarInterface существуют различные реализации:

  • Класс GuzzleHttpCookieCookieJar хранит cookies в виде массива.
  • Класс GuzzleHttpCookieFileCookieJar сохраняет несеансовые cookies
    используя файл в формате JSON.
  • Класс GuzzleHttpCookieSessionCookieJar сохраняет cookies в
    клиентской сессии.

Вы можете вручную установить куки в банку куки с помощью именованного конструктора fromArray(array $cookies, $domain).

$jar = GuzzleHttpCookieCookieJar::fromArray(
    [
        'some_cookie' => 'foo',
        'other_cookie' => 'barbaz1234'
    ],
    'example.org'
);

Вы можете получить cookie по его имени с помощью метода getCookieByName($name), который возвращает экземпляр GuzzleHttpCookieSetCookie.

$cookie = $jar->getCookieByName('some_cookie');

$cookie->getValue(); // 'foo'
$cookie->getDomain(); // 'example.org'
$cookie->getExpires(); // expiration date as a Unix timestamp

Куки также могут быть собраны в массив благодаря методу toArray().
Интерфейс GuzzleHttpCookieCookieJarInterface расширяет.
Traversable, поэтому его можно итерировать в цикле foreach.

Перенаправления¶

Guzzle будет автоматически следовать перенаправлениям, если вы не запретите ему это делать. Вы можете настроить поведение перенаправления с помощью опции запроса allow_redirects.

  • Установите значение true, чтобы включить нормальные перенаправления с максимальным числом 5
    перенаправлений. Это значение установлено по умолчанию.
  • Установите значение false, чтобы отключить перенаправления.
  • Передайте ассоциативный массив, содержащий ключ ‘max’ для указания максимального
    количество перенаправлений и, по желанию, значение ключа ‘strict’ для указания того.
    использовать ли строгие RFC-совместимые перенаправления (то есть перенаправлять POST-запросы с POST-запросами, а не делать то, что делает большинство браузеров).
    запросы с POST-запросами, а не делать то, что делает большинство браузеров, а именно
    перенаправлять POST-запросы с GET-запросами).
$response = $client->request('GET', 'http://github.com');
echo $response->getStatusCode();
// 200

В следующем примере показано, что перенаправления могут быть отключены.

$response = $client->request('GET', 'http://github.com', [
    'allow_redirects' => false
]);
echo $response->getStatusCode();
// 301

Исключения¶

Вид дерева

Следующее древовидное представление описывает, как исключения Guzzle зависят друг от друга.

. RuntimeException
└── TransferException (implements GuzzleException)
    ├── ConnectException (implements NetworkExceptionInterface)
    └── RequestException
        ├── BadResponseException
        │   ├── ServerException
        │   └── ClientException
        └── TooManyRedirectsException

Guzzle выбрасывает исключения для ошибок, возникающих во время передачи.

  • Исключение GuzzleHttpExceptionConnectException выбрасывается в случае ошибки подключения к сети.
    в случае ошибки подключения к сети. Это исключение расширяется от
    GuzzleHttpExceptionTransferException.

  • Исключение GuzzleHttpExceptionClientException бросается для 400
    уровня, если опция http_errors запроса установлена в true. Этот
    исключение расширяется от GuzzleHttpExceptionBadResponseException и
    GuzzleHttpExceptionBadResponseException расширяется от
    GuzzleHttpExceptionRequestException.

    use GuzzleHttpPsr7;
    use GuzzleHttpExceptionClientException;
    
    try {
        $client->request('GET', 'https://github.com/_abc_123_404');
    } catch (ClientException $e) {
        echo Psr7Message::toString($e->getRequest());
        echo Psr7Message::toString($e->getResponse());
    }
    
  • Исключение GuzzleHttpExceptionServerException выбрасывается для 500 уровня
    ошибки, если опция http_errors запроса установлена в true. Этот
    исключение расширяется от GuzzleHttpExceptionBadResponseException.

  • Исключение GuzzleHttpExceptionTooManyRedirectsException выбрасывается, когда слишком
    много перенаправлений. Это исключение расширяет GuzzleHttpExceptionRequestException.

Все вышеперечисленные исключения вытекают из GuzzleHttpExceptionTransferException.

Переменные среды¶

Guzzle предоставляет несколько переменных окружения, которые можно использовать для настройки поведения библиотеки.

GUZZLE_CURL_SELECT_TIMEOUT
Контролирует продолжительность в секундах, которую обработчик curl_multi_* будет использовать при
выбора в обработчиках curl с помощью curl_multi_select(). Некоторые системы
имеют проблемы с реализацией PHP curl_multi_select(), где
вызов этой функции всегда приводит к ожиданию максимальной продолжительности
таймаута.
HTTP_PROXY

Определяет прокси-сервер для использования при отправке запросов по протоколу «http»

Примечание: поскольку переменная HTTP_PROXY может содержать произвольный пользовательский ввод в некоторых (CGI) средах, эта переменная используется только в CLI SAPI. См. https://httpoxy.org для получения дополнительной информации.

HTTPS_PROXY
Определяет прокси-сервер, который будет использоваться при отправке запросов по протоколу «https».
NO_PROXY
Определяет URL, для которых не следует использовать прокси. Об использовании см. в proxy.

Guzzle gives PHP developers complete control over HTTP requests while utilizing HTTP/1.1 best practices. Guzzle’s HTTP
functionality is a robust framework built on top of the PHP libcurl bindings.

The three main parts of the Guzzle HTTP client are:

Clients GuzzleHttpClient (creates and sends requests, associates a response with a request)
Requests GuzzleHttpMessageRequest (requests with no body),
GuzzleHttpMessageEntityEnclosingRequest (requests with a body)
Responses GuzzleHttpMessageResponse

Creating a Client¶

Clients create requests, send requests, and set responses on a request object. When instantiating a client object,
you can pass an optional «base URL» and optional array of configuration options. A base URL is a
URI template that contains the URL of a remote server. When creating requests with a relative
URL, the base URL of a client will be merged into the request’s URL.

use GuzzleHttpClient;

// Create a client and provide a base URL
$client = new Client('https://api.github.com');

$request = $client->get('/user');
$request->setAuth('user', 'pass');
echo $request->getUrl();
// >>> https://api.github.com/user

// You must send a request in order for the transfer to occur
$response = $request->send();

echo $response->getBody();
// >>> {"type":"User", ...

echo $response->getHeader('Content-Length');
// >>> 792

$data = $response->json();
echo $data['type'];
// >>> User

Base URLs¶

Notice that the URL provided to the client’s get() method is relative. Relative URLs will always merge into the
base URL of the client. There are a few rules that control how the URLs are merged.

Tip

Guzzle follows RFC 3986 when merging base URLs and
relative URLs.

In the above example, we passed /user to the get() method of the client. This is a relative URL, so it will
merge into the base URL of the client— resulting in the derived URL of https://api.github.com/users.

/user is a relative URL but uses an absolute path because it contains the leading slash. Absolute paths will
overwrite any existing path of the base URL. If an absolute path is provided (e.g. /path/to/something), then the
path specified in the base URL of the client will be replaced with the absolute path, and the query string provided
by the relative URL will replace the query string of the base URL.

Omitting the leading slash and using relative paths will add to the path of the base URL of the client. So using a
client base URL of https://api.twitter.com/v1.1 and creating a GET request with statuses/user_timeline.json
will result in a URL of https://api.twitter.com/v1.1/statuses/user_timeline.json. If a relative path and a query
string are provided, then the relative path will be appended to the base URL path, and the query string provided will
be merged into the query string of the base URL.

If an absolute URL is provided (e.g. http://httpbin.org/ip), then the request will completely use the absolute URL
as-is without merging in any of the URL parts specified in the base URL.

Configuration options¶

The second argument of the client’s constructor is an array of configuration data. This can include URI template data
or special options that alter the client’s behavior:

request.options Associative array of Request options to apply to every
request created by the client.
redirect.disable Disable HTTP redirects for every request created by the client.
curl.options Associative array of cURL options to apply to every request created by the client.
if either the key or value of an entry in the array is a string, Guzzle will
attempt to find a matching defined cURL constant automatically (e.g.
«CURLOPT_PROXY» will be converted to the constant CURLOPT_PROXY).
ssl.certificate_authority

Set to true to use the Guzzle bundled SSL certificate bundle (this is used by
default, ‘system’ to use the bundle on your system, a string pointing to a file to
use a specific certificate file, a string pointing to a directory to use multiple
certificates, or false to disable SSL validation (not recommended).

When using Guzzle inside of a phar file, the bundled SSL certificate will be
extracted to your system’s temp folder, and each time a client is created an MD5
check will be performed to ensure the integrity of the certificate.

command.params When using a GuzzleServiceClient object, this is an associative array of
default options to set on each command created by the client.

Here’s an example showing how to set various configuration options, including default headers to send with each request,
default query string parameters to add to each request, a default auth scheme for each request, and a proxy to use for
each request. Values can be injected into the client’s base URL using variables from the configuration array.

use GuzzleHttpClient;

$client = new Client('https://api.twitter.com/{version}', array(
    'version'        => 'v1.1',
    'request.options' => array(
        'headers' => array('Foo' => 'Bar'),
        'query'   => array('testing' => '123'),
        'auth'    => array('username', 'password', 'Basic|Digest|NTLM|Any'),
        'proxy'   => 'tcp://localhost:80'
    )
));

Setting a custom User-Agent¶

The default Guzzle User-Agent header is Guzzle/<Guzzle_Version> curl/<curl_version> PHP/<PHP_VERSION>. You can
customize the User-Agent header of a client by calling the setUserAgent() method of a Client object.

// Completely override the default User-Agent
$client->setUserAgent('Test/123');

// Prepend a string to the default User-Agent
$client->setUserAgent('Test/123', true);

Creating requests with a client¶

A Client object exposes several methods used to create Request objects:

  • Create a custom HTTP request: $client->createRequest($method, $uri, array $headers, $body, $options)
  • Create a GET request: $client->get($uri, array $headers, $options)
  • Create a HEAD request: $client->head($uri, array $headers, $options)
  • Create a DELETE request: $client->delete($uri, array $headers, $body, $options)
  • Create a POST request: $client->post($uri, array $headers, $postBody, $options)
  • Create a PUT request: $client->put($uri, array $headers, $body, $options)
  • Create a PATCH request: $client->patch($uri, array $headers, $body, $options)
use GuzzleHttpClient;

$client = new Client('http://baseurl.com/api/v1');

// Create a GET request using Relative to base URL
// URL of the request: http://baseurl.com/api/v1/path?query=123&value=abc)
$request = $client->get('path?query=123&value=abc');
$response = $request->send();

// Create HEAD request using a relative URL with an absolute path
// URL of the request: http://baseurl.com/path?query=123&value=abc
$request = $client->head('/path?query=123&value=abc');
$response = $request->send();

// Create a DELETE request using an absolute URL
$request = $client->delete('http://www.example.com/path?query=123&value=abc');
$response = $request->send();

// Create a PUT request using the contents of a PHP stream as the body
// Specify custom HTTP headers
$request = $client->put('http://www.example.com/upload', array(
    'X-Header' => 'My Header'
), fopen('http://www.test.com/', 'r'));
$response = $request->send();

// Create a POST request and add the POST files manually
$request = $client->post('http://localhost:8983/solr/update')
    ->addPostFiles(array('file' => '/path/to/documents.xml'));
$response = $request->send();

// Check if a resource supports the DELETE method
$supportsDelete = $client->options('/path')->send()->isMethodAllowed('DELETE');
$response = $request->send();

Client objects create Request objects using a request factory (GuzzleHttpMessageRequestFactoryInterface).
You can inject a custom request factory into the Client using $client->setRequestFactory(), but you can typically
rely on a Client’s default request factory.

Static clients¶

You can use Guzzle’s static client facade to more easily send simple HTTP requests.

// Mount the client so that you can access it at Guzzle
GuzzleHttpStaticClient::mount();
$response = Guzzle::get('http://guzzlephp.org');

Each request method of the static client (e.g. get(), post()`, «put(), etc) accepts an associative array of request
options to apply to the request.

$response = Guzzle::post('http://test.com', array(
    'headers' => array('X-Foo' => 'Bar'),
    'body'    => array('Test' => '123'),
    'timeout' => 10
));

Request options¶

Request options can be specified when creating a request or in the request.options parameter of a client. These
options can control various aspects of a request including: headers to send, query string data, where the response
should be downloaded, proxies, auth, etc.

query¶

Associative array of query string parameters to the request. When specified in the $options argument of a client
creational method, the query string parameters in the $options array will overwrite query string parameters
specified in the $url.

$request = $client->get($url, array(), array(
    'query' => array('abc' => '123')
));

Query string parameters can be specified on a client to add default query string parameters to every request sent by a
client.

$client = new GuzzleHttpClient();

// Set a single query string parameter using path syntax
$client->setDefaultOption('query/abc', '123');

// Set an array of default query string parameters
$client->setDefaultOption('query', array('abc' => '123'));

body¶

Sets the body of a request. The value supplied to the body option can be a GuzzleHttpEntityBodyInterface, string,
fopen resource, or array when sending POST requests. When a body request option is supplied, the option value will
overwrite the $body argument of a client creational method.

auth¶

Specifies and array of HTTP authorization parameters parameters to use with the request. The array must contain the
username in index [0], the password in index [1], and can optionally contain the authentication type in index [2].
The available authentication types are: «Basic» (default), «Digest», «NTLM», or «Any».

$request = $client->get($url, array(), array(
    'auth' => array('username', 'password', 'Digest')
));

// You can add auth headers to every request of a client
$client->setDefaultOption('auth', array('username', 'password', 'Digest'));

cookies¶

Specifies an associative array of cookies to add to the request.

allow_redirects¶

Specifies whether or not the request should follow redirects. Requests will follow redirects by default. Set
allow_redirects to false to disable redirects.

save_to¶

The save_to option specifies where the body of a response is downloaded. You can pass the path to a file, an fopen
resource, or a GuzzleHttpEntityBodyInterface object.

See Changing where a response is downloaded for more information on setting the
save_to option.

events¶

The events option makes it easy to attach listeners to the various events emitted by a request object. The events
options must be an associative array mapping an event name to a Closure or array the contains a Closure and the
priority of the event.

$request = $client->get($url, array(), array(
    'events' => array(
        'request.before_send' => function (GuzzleCommonEvent $e) {
            echo 'About to send ' . $e['request'];
        }
    )
));

// Using the static client:
Guzzle::get($url, array(
    'events' => array(
        'request.before_send' => function (GuzzleCommonEvent $e) {
            echo 'About to send ' . $e['request'];
        }
    )
));

plugins¶

The plugins options makes it easy to attach an array of plugins to a request.

// Using the static client:
Guzzle::get($url, array(
    'plugins' => array(
        new GuzzlePluginCacheCachePlugin(),
        new GuzzlePluginCookieCookiePlugin()
    )
));

exceptions¶

The exceptions option can be used to disable throwing exceptions for unsuccessful HTTP response codes
(e.g. 404, 500, etc). Set exceptions to false to not throw exceptions.

params¶

The params options can be used to specify an associative array of data parameters to add to a request. Note that
these are not query string parameters.

timeout / connect_timeout¶

You can specify the maximum number of seconds to allow for an entire transfer to take place before timing out using
the timeout request option. You can specify the maximum number of seconds to wait while trying to connect using the
connect_timeout request option. Set either of these options to 0 to wait indefinitely.

$request = $client->get('http://www.example.com', array(), array(
    'timeout'         => 20,
    'connect_timeout' => 1.5
));

verify¶

Set to true to enable SSL certificate validation (the default), false to disable SSL certificate validation, or supply
the path to a CA bundle to enable verification using a custom certificate.

cert¶

The cert option lets you specify a PEM formatted SSL client certificate to use with servers that require one. If the
certificate requires a password, provide an array with the password as the second item.

This would typically be used in conjunction with the ssl_key option.

$request = $client->get('https://www.example.com', array(), array(
    'cert' => '/etc/pki/client_certificate.pem'
)

$request = $client->get('https://www.example.com', array(), array(
    'cert' => array('/etc/pki/client_certificate.pem', 's3cr3tp455w0rd')
)

ssl_key¶

The ssl_key option lets you specify a file containing your PEM formatted private key, optionally protected by a password.
Note: your password is sensitive, keep the PHP script containing it safe.

This would typically be used in conjunction with the cert option.

$request = $client->get('https://www.example.com', array(), array(
    'ssl_key' => '/etc/pki/private_key.pem'
)

$request = $client->get('https://www.example.com', array(), array(
    'ssl_key' => array('/etc/pki/private_key.pem', 's3cr3tp455w0rd')
)

proxy¶

The proxy option is used to specify an HTTP proxy (e.g. http://username:password@192.168.16.1:10).

debug¶

The debug option is used to show verbose cURL output for a transfer.

stream¶

When using a static client, you can set the stream option to true to return a GuzzleStreamStream object that can
be used to pull data from a stream as needed (rather than have cURL download the entire contents of a response to a
stream all at once).

$stream = Guzzle::get('http://guzzlephp.org', array('stream' => true));
while (!$stream->feof()) {
    echo $stream->readLine();
}

Sending requests¶

Requests can be sent by calling the send() method of a Request object, but you can also send requests using the
send() method of a Client.

$request = $client->get('http://www.amazon.com');
$response = $client->send($request);

Sending requests in parallel¶

The Client’s send() method accept a single GuzzleHttpMessageRequestInterface object or an array of
RequestInterface objects. When an array is specified, the requests will be sent in parallel.

Sending many HTTP requests serially (one at a time) can cause an unnecessary delay in a script’s execution. Each
request must complete before a subsequent request can be sent. By sending requests in parallel, a pool of HTTP
requests can complete at the speed of the slowest request in the pool, significantly reducing the amount of time
needed to execute multiple HTTP requests. Guzzle provides a wrapper for the curl_multi functions in PHP.

Here’s an example of sending three requests in parallel using a client object:

use GuzzleCommonExceptionMultiTransferException;

try {
    $responses = $client->send(array(
        $client->get('http://www.google.com/'),
        $client->head('http://www.google.com/'),
        $client->get('https://www.github.com/')
    ));
} catch (MultiTransferException $e) {

    echo "The following exceptions were encountered:n";
    foreach ($e as $exception) {
        echo $exception->getMessage() . "n";
    }

    echo "The following requests failed:n";
    foreach ($e->getFailedRequests() as $request) {
        echo $request . "nn";
    }

    echo "The following requests succeeded:n";
    foreach ($e->getSuccessfulRequests() as $request) {
        echo $request . "nn";
    }
}

If the requests succeed, an array of GuzzleHttpMessageResponse objects are returned. A single request failure
will not cause the entire pool of requests to fail. Any exceptions thrown while transferring a pool of requests will
be aggregated into a GuzzleCommonExceptionMultiTransferException exception.

Plugins and events¶

Guzzle provides easy to use request plugins that add behavior to requests based on signal slot event notifications
powered by the
Symfony2 Event Dispatcher component. Any
event listener or subscriber attached to a Client object will automatically be attached to each request created by the
client.

Using the same cookie session for each request¶

Attach a GuzzlePluginCookieCookiePlugin to a client which will in turn add support for cookies to every request
created by a client, and each request will use the same cookie session:

use GuzzlePluginCookieCookiePlugin;
use GuzzlePluginCookieCookieJarArrayCookieJar;

// Create a new cookie plugin
$cookiePlugin = new CookiePlugin(new ArrayCookieJar());

// Add the cookie plugin to the client
$client->addSubscriber($cookiePlugin);

Events emitted from a client¶

A GuzzleHttpClient object emits the following events:

Event name Description Event data
client.create_request Called when a client creates a request
  • client: The client
  • request: The created request
use GuzzleCommonEvent;
use GuzzleHttpClient;

$client = new Client();

// Add a listener that will echo out requests as they are created
$client->getEventDispatcher()->addListener('client.create_request', function (Event $e) {
    echo 'Client object: ' . spl_object_hash($e['client']) . "n";
    echo "Request object: {$e['request']}n";
});

Исходники на GitHub .

Документация здесь .

Guzzle

Guzzle — это PHP-HTTP-клиент, который упрощает отправку HTTP-запросов и интеграцию с веб-сервисами. Guzzle может отправлять как синхронные, так и асинхронные запросы, используя один и тот же интерфейс. Среди его плюсов: простой интерфейс работы со строкой запросов, использование HTTP-кук (cookies), загрузка данных. Если вы не хотите сами настраивать POST или GET запросы через cURL, то библиотека Guzzle как раз для вас.

Будем использовать Guzzle 6. Именно в этой версии есть поддержка стандарта PSR-7 — HTTP Message Interface

Установка Guzzle HTTP-клиент

Рекомендуемый способ установки Guzzle — с помощью Composer. В файле composer.json

{
  "require": {
    "guzzlehttp/guzzle": "~6.0"
  }
}

Или из консоли (терминала):

php composer.phar require guzzlehttp/guzzle

Если нужна последняя нестабильная версия пакета:

{
  "require": {
    "guzzlehttp/guzzle": "~6.0@dev"
  }
}

После установки вам понадобится автозагрузчик Composer:

require 'vendor/autoload.php';

Создание клиента

Можно делать запросы в Guzzle, используя объект GuzzleHttpClientInterface:

$client = new Client([
  // Базовый URI используется с относительными запросами
  'base_uri' => 'http://httpbin.org',
  // Вы можете установить любое количество параметров запроса по умолчанию.
  'timeout'  => 2.0,
]);

Клиент является неизменными в Guzzle 6, что означает, что вы не можете изменить значения по умолчанию, используемые клиентом после его создания.

Конструктор клиента принимает ассоциативный массив опций:

base_uri

(string|UriInterface) Базовый URI клиента, который объединен в относительные URI. Может быть строкой или экземпляром UriInterface. Когда клиенту предоставляется относительный URI,
клиент объединяет базовый URI с относительным URI, используя правила, описанные в RFC 3986, section 2.

// Создать клиента с базовым URI
$client = new GuzzleHttpClient(['base_uri' => 'https://foo.com/api/']);

// Отправить запрос на https://foo.com/api/test
$response = $client->request('GET', 'test');

// Отправить запрос на https://foo.com/root
$response = $client->request('GET', '/root');

Не хочется читать RFC 3986? Вот несколько быстрых примеров того, как base_uri разрешается с другим URI:

base_uri URI Результат
http://foo.com /bar http://foo.com/bar
http://foo.com/foo /bar http://foo.com/bar
http://foo.com/foo bar http://foo.com/bar
http://foo.com/foo/ bar http://foo.com/foo/bar
http://foo.com http://baz.com http://baz.com
http://foo.com/?bar bar http://foo.com/bar

handler

(callable) Функция, которая передает HTTP-запросы по сети. Функция вызывается с Psr7HttpMessageRequestInterface и массив опций передачи, и должен возвращать GuzzleHttpPromisePromiseInterface который выполняется с Psr7HttpMessageResponseInterface в случае успеха. handler это опция только для конструктора, которая не может быть переопределена в параметрах per/request.

(mixed) Все остальные параметры, передаваемые конструктору, используются в качестве параметров запроса по умолчанию для каждого запроса, создаваемого клиентом.

Отправка запросов

Магические методы на клиенте позволяют легко отправлять синхронные запросы:

$client = new GuzzleHttpClient();

$response = $client->get('http://httpbin.org/get');
$response = $client->delete('http://httpbin.org/delete');
$response = $client->head('http://httpbin.org/get');
$response = $client->options('http://httpbin.org/get');
$response = $client->patch('http://httpbin.org/patch');
$response = $client->post('http://httpbin.org/post');
$response = $client->put('http://httpbin.org/put');

Вы можете создать запрос и затем отправить запрос клиенту, когда будете готовы:

use GuzzleHttpPsr7Request;

$request = new Request('PUT', 'http://httpbin.org/put');
$response = $client->send($request, ['timeout' => 2]);

Клиентские объекты обеспечивают большую гибкость в том, как передаются запросы, включая параметры запроса по умолчанию, промежуточное программное обеспечение стека обработчиков по умолчанию, которое используется каждым запросом, и базовый URI, который позволяет отправлять запросы с относительными URI.

Асинхронные запросы

Вы можете отправлять асинхронные запросы, используя магические методы, предоставляемые клиентом:

$client = new GuzzleHttpClient();

$promise = $client->getAsync('http://httpbin.org/get');
$promise = $client->deleteAsync('http://httpbin.org/delete');
$promise = $client->headAsync('http://httpbin.org/get');
$promise = $client->optionsAsync('http://httpbin.org/get');
$promise = $client->patchAsync('http://httpbin.org/patch');
$promise = $client->postAsync('http://httpbin.org/post');
$promise = $client->putAsync('http://httpbin.org/put');

Вы также можете использовать методы sendAsync() и requestAsync() клиента:

// Создать объект запроса PSR-7 для отправки
$headers = ['X-Foo' => 'Bar'];
$body = 'Hello!';
$request = new Request('HEAD', 'http://httpbin.org/head', $headers, $body);
$promise = $client->sendAsync($request);

// Или, если вам не нужно передавать экземпляр запроса:
$promise = $client->requestAsync('GET', 'http://httpbin.org/get');

$promise, возвращаемые этими методами, реализуют Promises/A+ spec, предоставленные библиотекой Guzzle promises. Это означает, что вы сможете связать цепочкой then() вызовы promise. Эти then затем реализуют либо успешный результат с помощью PsrHttpMessageResponseInterface, либо запрос отклоняется с выбросом исключения exception:

use PsrHttpMessageResponseInterface;
use GuzzleHttpExceptionRequestException;

$promise = $client->requestAsync('GET', 'http://httpbin.org/get');
$promise->then(
  function (ResponseInterface $res) {
    echo $res->getStatusCode() . "n";
  },
  function (RequestException $e) {
  echo $e->getMessage() . "n";
    echo $e->getRequest()->getMethod();
  }
);

Параллельные запросы

Вы можете отправлять несколько запросов одновременно, используя Promise и асинхронные запросы:

use GuzzleHttpClient;
use GuzzleHttpPromise;

$client = new Client(['base_uri' => 'http://httpbin.org/']);

// Инициируем каждый запрос, но не блокируем
$promises = [
  'image' => $client->getAsync('/image'),
  'png'   => $client->getAsync('/image/png'),
  'jpeg'  => $client->getAsync('/image/jpeg'),
  'webp'  => $client->getAsync('/image/webp')
];

// Дождаться завершения всех запросов. Выдает исключение ConnectException
// если какой-либо из запросов не выполнен
$results = Promiseunwrap($promises);

// Дождемся завершения запросов, даже если некоторые из них завершатся неудачно
$results = Promisesettle($promises)->wait();

// Можно получить доступ к каждому результату, используя key, предоставленный для функции развертки
echo $results['image']['value']->getHeader('Content-Length')[0]
echo $results['png']['value']->getHeader('Content-Length')[0]

Можно использовать GuzzleHttpPool объект, когда у вас есть неопределенное количество запросов, которые вы хотите отправить:

use GuzzleHttpPool;
use GuzzleHttpClient;
use GuzzleHttpPsr7Request;

$client = new Client();

$requests = function ($total) {
  $uri = 'http://127.0.0.1:8126/guzzle-server/perf';
  for ($i = 0; $i < $total; $i++) {
    yield new Request('GET', $uri);
  }
};

$pool = new Pool($client, $requests(100), [
  'concurrency' => 5,
  'fulfilled' => function ($response, $index) {
  // Здесь обработка успешного запроса
  },
  'rejected' => function ($reason, $index) {
  // Здесь обработка запроса, который завершился неудачей
  },
]);

// Инициализируем трансферы и создаём promise
$promise = $pool->promise();

// Ожидаем ответ promise // Принудительно завершаем пул запросов
$promise->wait();

Или используя замыкание, которое вернет promise, как только пул вызовет замыкание:

$client = new Client();

$requests = function ($total) use ($client) {
  $uri = 'http://127.0.0.1:8126/guzzle-server/perf';
  for ($i = 0; $i < $total; $i++) {
    yield function() use ($client, $uri) {
      return $client->getAsync($uri);
    };
  }
};

$pool = new Pool($client, $requests(100));

Использование ответов

В предыдущих примерах мы получили $response или мы получили ответ от promise. Объект ответа реализует ответ PSR-7, PsrHttpMessageResponseInterface, и содержит много полезной информации.

Вы можете получить код состояния и фразу ответа:

$code = $response->getStatusCode(); // 200
$reason = $response->getReasonPhrase(); // OK

Вы можете извлечь заголовки из ответа:

// Проверка, есть ли заголовок
if ($response->hasHeader('Content-Length')) {
echo "It exists";
}

// Получаем заголовок из ответа
echo $response->getHeader('Content-Length')[0];

// Получаем все заголовки ответа
foreach ($response->getHeaders() as $name => $values) {
echo $name . ': ' . implode(', ', $values) . "rn";
}

Тело ответа может быть получено с помощью метода getBody(). Тело ответа может быть использовано как строка, приведено к строке или как объект, подобный потоку:

$body = $response->getBody();

// Неявно приводим тело ответа к строке и отображаем его
echo $body;

// Явное приведение тела к строке
$stringBody = (string) $body;

// Читаем первые 10 байт тела ответа
$tenBytes = $body->read(10);

// Прочитать оставшееся содержимое тела ответа как строку
$remainingBytes = $body->getContents();

Параметры строки запроса

Вы можете предоставить параметры строки запроса несколькими способами. Можно установить параметры строки запроса в URI запроса:

$response = $client->request('GET', 'http://httpbin.org?foo=bar');

Можно указать параметры строки запроса, используя query как массив:

$client->request('GET', 'http://httpbin.org', [
'query' => ['foo' => 'bar']
]);

Предоставление опции в качестве массива будет использовать нативную функцию PHP http_build_query для форматирования строки с параметрами.

И, наконец, можно предоставить query в роли строки:

$client->request('GET', 'http://httpbin.org', ['query' => 'foo=bar']);

Загрузка данных

Guzzle предоставляет несколько способов загрузки данных.

Можно отправлять запросы, содержащие поток данных, передавая строку, ресурс возвращается из fopen, или как экземпляр PsrHttpMessageStreamInterface в опцию запроса body:

// Предоставляем тело запроса в виде строки
$r = $client->request('POST', 'http://httpbin.org/post', [
  'body' => 'raw data'
]);

// Предоставляем fopen ресурс
$body = fopen('/path/to/file', 'r');
$r = $client->request('POST', 'http://httpbin.org/post', ['body' => $body]);

// Используем функцию stream_for() для создания потока PSR-7
$body = GuzzleHttpPsr7stream_for('hello!');
$r = $client->request('POST', 'http://httpbin.org/post', ['body' => $body]);

Простой способ загрузить данные JSON и установить соответствующий заголовок — использовать опцию запроса json:

$r = $client->request('PUT', 'http://httpbin.org/put', [
  'json' => ['foo' => 'bar']
]);

POST/Form запросы

В дополнение к указанию необработанных данных запроса с использованием опции запроса body, Guzzle предоставляет полезные абстракции при отправке данных POST.

Отправка полей формы

Для отправки POST-запросов application/x-www-form-urlencoded необходимо указать поля POST в виде массива в параметрах запроса form_params:

$response = $client->request('POST', 'http://httpbin.org/post', [
  'form_params' => [
  'field_name' => 'abc',
  'other_field' => '123',
  'nested_field' => [
    'nested' => 'hello'
   ]
  ]
]);

Отправка файлов форм

Можно отправлять файлы вместе с формой (POST-запросы multipart/form-data), используя опцию запроса multipart. Она принимает массив ассоциативных массивов, где каждый ассоциативный массив содержит следующие ключи:

  • name: (required, string) имя ключа поля формы.
  • contents: (required, mixed) Укажите тут строку для отправки содержимого файла в виде строки, предоставьте ресурс fopen для потоковой передачи содержимого из потока PHP или укажите PsrHttpMessageStreamInterface для потоковой передачи содержимого из потока PSR-7.
$response = $client->request('POST', 'http://httpbin.org/post', [
 'multipart' => [
  [
    'name'     => 'field_name',
    'contents' => 'abc'
  ],
  [
    'name'     => 'file_name',
    'contents' => fopen('/path/to/file', 'r')
  ],
  [
    'name'     => 'other_file',
    'contents' => 'hello',
    'filename' => 'filename.txt',
    'headers'  => [
      'X-Foo' => 'this is an extra header to include'
    ]
  ]
 ]
]);

Cookies

Guzzle может поддерживать для вас сеанс файлов cookie, если это указано с помощью параметра запроса файлов cookie. При отправке запроса параметр cookie должен быть установлен на экземпляр GuzzleHttpCookieCookieJarInterface:

// Использование конкретного cookie jar
$jar = new GuzzleHttpCookieCookieJar;
$r = $client->request('GET', 'http://httpbin.org/cookies', [
  'cookies' => $jar
]);

Можно установить для cookie значение true в конструкторе клиента, если хотите использовать общий файл cookie для всех запросов:

// Используем общий клиентский файл cookie
$client = new GuzzleHttpClient(['cookies' => true]);
$r = $client->request('GET', 'http://httpbin.org/cookies');

Редиректы (перенаправления)

Guzzle будет автоматически следовать за редиректами, только если чётко не указать этого не делать. Вы можете настроить поведение перенаправления, используя опцию запроса allow_redirects:

  • Установите значение true, чтобы включить нормальные перенаправления с максимальным количеством 5 перенаправлений. Это значение по умолчанию.
  • Установите в false, чтобы отключить перенаправления.
  • Передайте ассоциативный массив, содержащий ключ max, чтобы указать максимальное количество перенаправлений, и при необходимости укажите значение ключа strict, чтобы указать, следует ли использовать строгие перенаправления, совместимые с RFC (что означает запросы перенаправления POST со следующими запросами тоже типа POST, тогда как в обычном режиме большинство браузеров по умолчанию перенаправляют запросы POST со следующими запросами GET)./li>
$response = $client->request('GET', 'http://github.com');
echo $response->getStatusCode();
// 200

В следующем примере показано, как можно отключить редиректы:

$response = $client->request('GET', 'http://github.com', [
  'allow_redirects' => false
]);
echo $response->getStatusCode();
// 301

Исключения при обработке ошибок

Guzzle генерирует исключения для ошибок, возникающих во время передачи:

В случае сетевой ошибки (тайм-аут соединения, ошибки DNS и т.д.) выдается сообщение GuzzleHttpExceptionRequestException. Это исключение распространяется на GuzzleHttpExceptionTransferException. Поймав это исключение, вы поймете любое исключение, которое может быть сгенерировано при передаче запросов.

use GuzzleHttpPsr7;
use GuzzleHttpExceptionRequestException;

try {
  $client->request('GET', 'https://github.com/_abc_123_404');
} catch (RequestException $e) {
  echo Psr7str($e->getRequest());
  if ($e->hasResponse()) {
    echo Psr7str($e->getResponse());
  }
}

Исключение GuzzleHttpExceptionConnectException выдается в случае сетевой ошибки. Это исключение происходит от GuzzleHttpExceptionRequestException.
GuzzleHttpExceptionClientException выбрасывается для ошибок уровня 400, если для параметра запроса http_errors установлено значение true. Это исключение распространяется на GuzzleHttpExceptionBadResponseException и GuzzleHttpExceptionBadResponseException распространяется на GuzzleHttpExceptionRequestException.

use GuzzleHttpExceptionClientException;

try {
  $client->request('GET', 'https://github.com/_abc_123_404');
} catch (ClientException $e) {
  echo Psr7str($e->getRequest());
  echo Psr7str($e->getResponse());
}

GuzzleHttpExceptionServerException генерируется для ошибок уровня 500, если для параметра запроса http_errors установлено значение true. Это исключение происходит от GuzzleHttpExceptionBadResponseException.

GuzzleHttpExceptionTooManyRedirectsException генерируется, когда выполняется слишком много перенаправлений. Это исключение происходит от GuzzleHttpExceptionRequestException.

Все вышеперечисленные исключения происходят из GuzzleHttpExceptionTransferException.

Переменные окружения

Guzzle предоставляет несколько переменных среды, которые можно использовать для настройки поведения библиотеки:

GUZZLE_CURL_SELECT_TIMEOUT

Управляет продолжительностью в секундах, которую обработчик curl_multi_* будет использовать при выборе обработчика curl, используя curl_multi_select(). Некоторые системы имеют проблемы с реализацией PHP curl_multi_select(), где вызов этой функции всегда приводит к ожиданию максимальной продолжительности времени ожидания.

HTTP_PROXY

Определяет прокси для использования при отправке запросов по протоколу http.

Поскольку переменная HTTP_PROXY может содержать произвольный пользовательский ввод в некоторых (CGI) средах, эта переменная используется только в CLI SAPI. Смотрите https://httpoxy.org для получения дополнительной информации.

HTTPS_PROXY

Определяет прокси для использования при отправке запросов по протоколу https.

Соответствующие настройки php.ini

Guzzle может использовать настройки php.ini при настройке клиентов:

openssl.cafile

Указывает путь на диске к файлу CA (сертификат SSL/TLS безопасности) в формате PEM, который будет использоваться при отправке запросов через «https». Подробнее: https://wiki.php.net/rfc/tls-peer-verification#phpini_defaults

Опции запросов

Version


HTTP Client

  • Introduction
  • Making Requests

    • Request Data
    • Headers
    • Authentication
    • Timeout
    • Retries
    • Error Handling
    • Guzzle Middleware
    • Guzzle Options
  • Concurrent Requests
  • Macros
  • Testing

    • Faking Responses
    • Inspecting Requests
    • Preventing Stray Requests
  • Events

Introduction

Laravel provides an expressive, minimal API around the Guzzle HTTP client, allowing you to quickly make outgoing HTTP requests to communicate with other web applications. Laravel’s wrapper around Guzzle is focused on its most common use cases and a wonderful developer experience.

Before getting started, you should ensure that you have installed the Guzzle package as a dependency of your application. By default, Laravel automatically includes this dependency. However, if you have previously removed the package, you may install it again via Composer:

composer require guzzlehttp/guzzle

Making Requests

To make requests, you may use the head, get, post, put, patch, and delete methods provided by the Http facade. First, let’s examine how to make a basic GET request to another URL:

use IlluminateSupportFacadesHttp;

$response = Http::get('http://example.com');

The get method returns an instance of IlluminateHttpClientResponse, which provides a variety of methods that may be used to inspect the response:

$response->body() : string;

$response->json($key = null, $default = null) : array|mixed;

$response->object() : object;

$response->collect($key = null) : IlluminateSupportCollection;

$response->status() : int;

$response->successful() : bool;

$response->redirect(): bool;

$response->failed() : bool;

$response->clientError() : bool;

$response->header($header) : string;

$response->headers() : array;

The IlluminateHttpClientResponse object also implements the PHP ArrayAccess interface, allowing you to access JSON response data directly on the response:

return Http::get('http://example.com/users/1')['name'];

In addition to the response methods listed above, the following methods may be used to determine if the response has a given status code:

$response->ok() : bool; // 200 OK

$response->created() : bool; // 201 Created

$response->accepted() : bool; // 202 Accepted

$response->noContent() : bool; // 204 No Content

$response->movedPermanently() : bool; // 301 Moved Permanently

$response->found() : bool; // 302 Found

$response->badRequest() : bool; // 400 Bad Request

$response->unauthorized() : bool; // 401 Unauthorized

$response->paymentRequired() : bool; // 402 Payment Required

$response->forbidden() : bool; // 403 Forbidden

$response->notFound() : bool; // 404 Not Found

$response->requestTimeout() : bool; // 408 Request Timeout

$response->conflict() : bool; // 409 Conflict

$response->unprocessableEntity() : bool; // 422 Unprocessable Entity

$response->tooManyRequests() : bool; // 429 Too Many Requests

$response->serverError() : bool; // 500 Internal Server Error

URI Templates

The HTTP client also allows you to construct request URLs using the URI template specification. To define the URL parameters that can be expanded by your URI template, you may use the withUrlParameters method:

Http::withUrlParameters([

'endpoint' => 'https://laravel.com',

'page' => 'docs',

'version' => '9.x',

'topic' => 'validation',

])->get('{+endpoint}/{page}/{version}/{topic}');

Dumping Requests

If you would like to dump the outgoing request instance before it is sent and terminate the script’s execution, you may add the dd method to the beginning of your request definition:

return Http::dd()->get('http://example.com');

Request Data

Of course, it is common when making POST, PUT, and PATCH requests to send additional data with your request, so these methods accept an array of data as their second argument. By default, data will be sent using the application/json content type:

use IlluminateSupportFacadesHttp;

$response = Http::post('http://example.com/users', [

'name' => 'Steve',

'role' => 'Network Administrator',

]);

GET Request Query Parameters

When making GET requests, you may either append a query string to the URL directly or pass an array of key / value pairs as the second argument to the get method:

$response = Http::get('http://example.com/users', [

'name' => 'Taylor',

'page' => 1,

]);

Sending Form URL Encoded Requests

If you would like to send data using the application/x-www-form-urlencoded content type, you should call the asForm method before making your request:

$response = Http::asForm()->post('http://example.com/users', [

'name' => 'Sara',

'role' => 'Privacy Consultant',

]);

Sending A Raw Request Body

You may use the withBody method if you would like to provide a raw request body when making a request. The content type may be provided via the method’s second argument:

$response = Http::withBody(

base64_encode($photo), 'image/jpeg'

)->post('http://example.com/photo');

Multi-Part Requests

If you would like to send files as multi-part requests, you should call the attach method before making your request. This method accepts the name of the file and its contents. If needed, you may provide a third argument which will be considered the file’s filename:

$response = Http::attach(

'attachment', file_get_contents('photo.jpg'), 'photo.jpg'

)->post('http://example.com/attachments');

Instead of passing the raw contents of a file, you may pass a stream resource:

$photo = fopen('photo.jpg', 'r');

$response = Http::attach(

'attachment', $photo, 'photo.jpg'

)->post('http://example.com/attachments');

Headers

Headers may be added to requests using the withHeaders method. This withHeaders method accepts an array of key / value pairs:

$response = Http::withHeaders([

'X-First' => 'foo',

'X-Second' => 'bar'

])->post('http://example.com/users', [

'name' => 'Taylor',

]);

You may use the accept method to specify the content type that your application is expecting in response to your request:

$response = Http::accept('application/json')->get('http://example.com/users');

For convenience, you may use the acceptJson method to quickly specify that your application expects the application/json content type in response to your request:

$response = Http::acceptJson()->get('http://example.com/users');

Authentication

You may specify basic and digest authentication credentials using the withBasicAuth and withDigestAuth methods, respectively:

// Basic authentication...

$response = Http::withBasicAuth('[email protected]', 'secret')->post(/* ... */);

// Digest authentication...

$response = Http::withDigestAuth('[email protected]', 'secret')->post(/* ... */);

Bearer Tokens

If you would like to quickly add a bearer token to the request’s Authorization header, you may use the withToken method:

$response = Http::withToken('token')->post(/* ... */);

Timeout

The timeout method may be used to specify the maximum number of seconds to wait for a response:

$response = Http::timeout(3)->get(/* ... */);

If the given timeout is exceeded, an instance of IlluminateHttpClientConnectionException will be thrown.

You may specify the maximum number of seconds to wait while trying to connect to a server using the connectTimeout method:

$response = Http::connectTimeout(3)->get(/* ... */);

Retries

If you would like the HTTP client to automatically retry the request if a client or server error occurs, you may use the retry method. The retry method accepts the maximum number of times the request should be attempted and the number of milliseconds that Laravel should wait in between attempts:

$response = Http::retry(3, 100)->post(/* ... */);

If needed, you may pass a third argument to the retry method. The third argument should be a callable that determines if the retries should actually be attempted. For example, you may wish to only retry the request if the initial request encounters an ConnectionException:

$response = Http::retry(3, 100, function ($exception, $request) {

return $exception instanceof ConnectionException;

})->post(/* ... */);

If a request attempt fails, you may wish to make a change to the request before a new attempt is made. You can achieve this by modifying the request argument provided to the callable you provided to the retry method. For example, you might want to retry the request with a new authorization token if the first attempt returned an authentication error:

$response = Http::withToken($this->getToken())->retry(2, 0, function ($exception, $request) {

if (! $exception instanceof RequestException || $exception->response->status() !== 401) {

return false;

}

$request->withToken($this->getNewToken());

return true;

})->post(/* ... */);

If all of the requests fail, an instance of IlluminateHttpClientRequestException will be thrown. If you would like to disable this behavior, you may provide a throw argument with a value of false. When disabled, the last response received by the client will be returned after all retries have been attempted:

$response = Http::retry(3, 100, throw: false)->post(/* ... */);

Warning
If all of the requests fail because of a connection issue, a IlluminateHttpClientConnectionException will still be thrown even when the throw argument is set to false.

Error Handling

Unlike Guzzle’s default behavior, Laravel’s HTTP client wrapper does not throw exceptions on client or server errors (400 and 500 level responses from servers). You may determine if one of these errors was returned using the successful, clientError, or serverError methods:

// Determine if the status code is >= 200 and < 300...

$response->successful();

// Determine if the status code is >= 400...

$response->failed();

// Determine if the response has a 400 level status code...

$response->clientError();

// Determine if the response has a 500 level status code...

$response->serverError();

// Immediately execute the given callback if there was a client or server error...

$response->onError(callable $callback);

Throwing Exceptions

If you have a response instance and would like to throw an instance of IlluminateHttpClientRequestException if the response status code indicates a client or server error, you may use the throw or throwIf methods:

$response = Http::post(/* ... */);

// Throw an exception if a client or server error occurred...

$response->throw();

// Throw an exception if an error occurred and the given condition is true...

$response->throwIf($condition);

// Throw an exception if an error occurred and the given closure resolves to true...

$response->throwIf(fn ($response) => true);

// Throw an exception if an error occurred and the given condition is false...

$response->throwUnless($condition);

// Throw an exception if an error occurred and the given closure resolves to false...

$response->throwUnless(fn ($response) => false);

// Throw an exception if the response has a specific status code...

$response->throwIfStatus(403);

// Throw an exception unless the response has a specific status code...

$response->throwUnlessStatus(200);

return $response['user']['id'];

The IlluminateHttpClientRequestException instance has a public $response property which will allow you to inspect the returned response.

The throw method returns the response instance if no error occurred, allowing you to chain other operations onto the throw method:

return Http::post(/* ... */)->throw()->json();

If you would like to perform some additional logic before the exception is thrown, you may pass a closure to the throw method. The exception will be thrown automatically after the closure is invoked, so you do not need to re-throw the exception from within the closure:

return Http::post(/* ... */)->throw(function ($response, $e) {

//

})->json();

Guzzle Middleware

Since Laravel’s HTTP client is powered by Guzzle, you may take advantage of Guzzle Middleware to manipulate the outgoing request or inspect the incoming response. To manipulate the outgoing request, register a Guzzle middleware via the withMiddleware method in combination with Guzzle’s mapRequest middleware factory:

use GuzzleHttpMiddleware;

use IlluminateSupportFacadesHttp;

use PsrHttpMessageRequestInterface;

$response = Http::withMiddleware(

Middleware::mapRequest(function (RequestInterface $request) {

$request = $request->withHeader('X-Example', 'Value');

return $request;

})

)->get('http://example.com');

Likewise, you can inspect the incoming HTTP response by registering a middleware via the withMiddleware method in combination with Guzzle’s mapResponse middleware factory:

use GuzzleHttpMiddleware;

use IlluminateSupportFacadesHttp;

use PsrHttpMessageResponseInterface;

$response = Http::withMiddleware(

Middleware::mapResponse(function (ResponseInterface $response) {

$header = $response->getHeader('X-Example');

// ...

return $response;

})

)->get('http://example.com');

Guzzle Options

You may specify additional Guzzle request options using the withOptions method. The withOptions method accepts an array of key / value pairs:

$response = Http::withOptions([

'debug' => true,

])->get('http://example.com/users');

Concurrent Requests

Sometimes, you may wish to make multiple HTTP requests concurrently. In other words, you want several requests to be dispatched at the same time instead of issuing the requests sequentially. This can lead to substantial performance improvements when interacting with slow HTTP APIs.

Thankfully, you may accomplish this using the pool method. The pool method accepts a closure which receives an IlluminateHttpClientPool instance, allowing you to easily add requests to the request pool for dispatching:

use IlluminateHttpClientPool;

use IlluminateSupportFacadesHttp;

$responses = Http::pool(fn (Pool $pool) => [

$pool->get('http://localhost/first'),

$pool->get('http://localhost/second'),

$pool->get('http://localhost/third'),

]);

return $responses[0]->ok() &&

$responses[1]->ok() &&

$responses[2]->ok();

As you can see, each response instance can be accessed based on the order it was added to the pool. If you wish, you can name the requests using the as method, which allows you to access the corresponding responses by name:

use IlluminateHttpClientPool;

use IlluminateSupportFacadesHttp;

$responses = Http::pool(fn (Pool $pool) => [

$pool->as('first')->get('http://localhost/first'),

$pool->as('second')->get('http://localhost/second'),

$pool->as('third')->get('http://localhost/third'),

]);

return $responses['first']->ok();

Macros

The Laravel HTTP client allows you to define «macros», which can serve as a fluent, expressive mechanism to configure common request paths and headers when interacting with services throughout your application. To get started, you may define the macro within the boot method of your application’s AppProvidersAppServiceProvider class:

use IlluminateSupportFacadesHttp;

/**

* Bootstrap any application services.

*

* @return void

*/

public function boot()

{

Http::macro('github', function () {

return Http::withHeaders([

'X-Example' => 'example',

])->baseUrl('https://github.com');

});

}

Once your macro has been configured, you may invoke it from anywhere in your application to create a pending request with the specified configuration:

$response = Http::github()->get('/');

Testing

Many Laravel services provide functionality to help you easily and expressively write tests, and Laravel’s HTTP client is no exception. The Http facade’s fake method allows you to instruct the HTTP client to return stubbed / dummy responses when requests are made.

Faking Responses

For example, to instruct the HTTP client to return empty, 200 status code responses for every request, you may call the fake method with no arguments:

use IlluminateSupportFacadesHttp;

Http::fake();

$response = Http::post(/* ... */);

Faking Specific URLs

Alternatively, you may pass an array to the fake method. The array’s keys should represent URL patterns that you wish to fake and their associated responses. The * character may be used as a wildcard character. Any requests made to URLs that have not been faked will actually be executed. You may use the Http facade’s response method to construct stub / fake responses for these endpoints:

Http::fake([

// Stub a JSON response for GitHub endpoints...

'github.com/*' => Http::response(['foo' => 'bar'], 200, $headers),

// Stub a string response for Google endpoints...

'google.com/*' => Http::response('Hello World', 200, $headers),

]);

If you would like to specify a fallback URL pattern that will stub all unmatched URLs, you may use a single * character:

Http::fake([

// Stub a JSON response for GitHub endpoints...

'github.com/*' => Http::response(['foo' => 'bar'], 200, ['Headers']),

// Stub a string response for all other endpoints...

'*' => Http::response('Hello World', 200, ['Headers']),

]);

Faking Response Sequences

Sometimes you may need to specify that a single URL should return a series of fake responses in a specific order. You may accomplish this using the Http::sequence method to build the responses:

Http::fake([

// Stub a series of responses for GitHub endpoints...

'github.com/*' => Http::sequence()

->push('Hello World', 200)

->push(['foo' => 'bar'], 200)

->pushStatus(404),

]);

When all the responses in a response sequence have been consumed, any further requests will cause the response sequence to throw an exception. If you would like to specify a default response that should be returned when a sequence is empty, you may use the whenEmpty method:

Http::fake([

// Stub a series of responses for GitHub endpoints...

'github.com/*' => Http::sequence()

->push('Hello World', 200)

->push(['foo' => 'bar'], 200)

->whenEmpty(Http::response()),

]);

If you would like to fake a sequence of responses but do not need to specify a specific URL pattern that should be faked, you may use the Http::fakeSequence method:

Http::fakeSequence()

->push('Hello World', 200)

->whenEmpty(Http::response());

Fake Callback

If you require more complicated logic to determine what responses to return for certain endpoints, you may pass a closure to the fake method. This closure will receive an instance of IlluminateHttpClientRequest and should return a response instance. Within your closure, you may perform whatever logic is necessary to determine what type of response to return:

use IlluminateHttpClientRequest;

Http::fake(function (Request $request) {

return Http::response('Hello World', 200);

});

Preventing Stray Requests

If you would like to ensure that all requests sent via the HTTP client have been faked throughout your individual test or complete test suite, you can call the preventStrayRequests method. After calling this method, any requests that do not have a corresponding fake response will throw an exception rather than making the actual HTTP request:

use IlluminateSupportFacadesHttp;

Http::preventStrayRequests();

Http::fake([

'github.com/*' => Http::response('ok'),

]);

// An "ok" response is returned...

Http::get('https://github.com/laravel/framework');

// An exception is thrown...

Http::get('https://laravel.com');

Inspecting Requests

When faking responses, you may occasionally wish to inspect the requests the client receives in order to make sure your application is sending the correct data or headers. You may accomplish this by calling the Http::assertSent method after calling Http::fake.

The assertSent method accepts a closure which will receive an IlluminateHttpClientRequest instance and should return a boolean value indicating if the request matches your expectations. In order for the test to pass, at least one request must have been issued matching the given expectations:

use IlluminateHttpClientRequest;

use IlluminateSupportFacadesHttp;

Http::fake();

Http::withHeaders([

'X-First' => 'foo',

])->post('http://example.com/users', [

'name' => 'Taylor',

'role' => 'Developer',

]);

Http::assertSent(function (Request $request) {

return $request->hasHeader('X-First', 'foo') &&

$request->url() == 'http://example.com/users' &&

$request['name'] == 'Taylor' &&

$request['role'] == 'Developer';

});

If needed, you may assert that a specific request was not sent using the assertNotSent method:

use IlluminateHttpClientRequest;

use IlluminateSupportFacadesHttp;

Http::fake();

Http::post('http://example.com/users', [

'name' => 'Taylor',

'role' => 'Developer',

]);

Http::assertNotSent(function (Request $request) {

return $request->url() === 'http://example.com/posts';

});

You may use the assertSentCount method to assert how many requests were «sent» during the test:

Http::fake();

Http::assertSentCount(5);

Or, you may use the assertNothingSent method to assert that no requests were sent during the test:

Http::fake();

Http::assertNothingSent();

Recording Requests / Responses

You may use the recorded method to gather all requests and their corresponding responses. The recorded method returns a collection of arrays that contains instances of IlluminateHttpClientRequest and IlluminateHttpClientResponse:

Http::fake([

'https://laravel.com' => Http::response(status: 500),

'https://nova.laravel.com/' => Http::response(),

]);

Http::get('https://laravel.com');

Http::get('https://nova.laravel.com/');

$recorded = Http::recorded();

[$request, $response] = $recorded[0];

Additionally, the recorded method accepts a closure which will receive an instance of IlluminateHttpClientRequest and IlluminateHttpClientResponse and may be used to filter request / response pairs based on your expectations:

use IlluminateHttpClientRequest;

use IlluminateHttpClientResponse;

Http::fake([

'https://laravel.com' => Http::response(status: 500),

'https://nova.laravel.com/' => Http::response(),

]);

Http::get('https://laravel.com');

Http::get('https://nova.laravel.com/');

$recorded = Http::recorded(function (Request $request, Response $response) {

return $request->url() !== 'https://laravel.com' &&

$response->successful();

});

Events

Laravel fires three events during the process of sending HTTP requests. The RequestSending event is fired prior to a request being sent, while the ResponseReceived event is fired after a response is received for a given request. The ConnectionFailed event is fired if no response is received for a given request.

The RequestSending and ConnectionFailed events both contain a public $request property that you may use to inspect the IlluminateHttpClientRequest instance. Likewise, the ResponseReceived event contains a $request property as well as a $response property which may be used to inspect the IlluminateHttpClientResponse instance. You may register event listeners for this event in your AppProvidersEventServiceProvider service provider:

/**

* The event listener mappings for the application.

*

* @var array

*/

protected $listen = [

'IlluminateHttpClientEventsRequestSending' => [

'AppListenersLogRequestSending',

],

'IlluminateHttpClientEventsResponseReceived' => [

'AppListenersLogResponseReceived',

],

'IlluminateHttpClientEventsConnectionFailed' => [

'AppListenersLogConnectionFailed',

],

];

  • Введение
  • Выполнение запросов

    • Данные запроса
    • Заголовки
    • Аутентификация
    • Время ожидания
    • Повторные попытки
    • Обработка ошибок
    • Параметры Guzzle
  • Параллельные запросы
  • Тестирование

    • Фиктивные ответы
    • Инспектирование запросов
  • События

Введение

Laravel предлагает минимальный и выразительный API для HTTP-клиента Guzzle, позволяющий быстро выполнять исходящие запросы для взаимодействия с другими веб-приложениями. Обертка вокруг Guzzle ориентирована на наиболее распространенные варианты использования и дает прекрасные возможности для разработчиков.

Вы должны убедиться, что пакет Guzzle включен в зависимости вашего приложения. По умолчанию Laravel автоматически включает эту зависимость. Однако, если вы ранее удалили пакет, то вы можете установить его снова через Composer:

composer require guzzlehttp/guzzle

Выполнение запросов

Для отправки запросов вы можете использовать методы get, post, put, patch и delete фасада Http. Сначала давайте рассмотрим, как сделать основной запрос GET:

use IlluminateSupportFacadesHttp;

$response = Http::get('http://example.com');

Метод get возвращает экземпляр IlluminateHttpClientResponse, содержащий методы, которые можно использовать для получения информации об ответе:

$response->body() : string;
$response->json() : array|mixed;
$response->object() : object;
$response->collect() : IlluminateSupportCollection;
$response->status() : int;
$response->ok() : bool;
$response->successful() : bool;
$response->failed() : bool;
$response->serverError() : bool;
$response->clientError() : bool;
$response->header($header) : string;
$response->headers() : array;

Объект IlluminateHttpClientResponse также реализует интерфейс ArrayAccess PHP, позволяющий напрямую получать доступ к данным ответа JSON:

return Http::get('http://example.com/users/1')['name'];

Вывод информации о запросах

Если вы хотите получить информацию о сформированном экземпляре исходящего запроса перед его отправкой и прекратить выполнение скрипта, вы можете добавить метод dd в начало определения вашего запроса:

return Http::dd()->get('http://example.com');

Данные запроса

При выполнении запросов POST, PUT и PATCH обычно отправляются дополнительные данные, поэтому эти методы принимают массив данных в качестве второго аргумента. По умолчанию данные будут отправляться с использованием типа содержимого application/json:

use IlluminateSupportFacadesHttp;

$response = Http::post('http://example.com/users', [
    'name' => 'Steve',
    'role' => 'Network Administrator',
]);

Параметры GET-запроса

При выполнении запросов GET вы можете либо напрямую добавить строку запроса к URL, либо передать массив пар ключ / значение в качестве второго аргумента метода get:

$response = Http::get('http://example.com/users', [
    'name' => 'Taylor',
    'page' => 1,
]);

Отправка запросов с передачей данных в URL-кодированной строке

Если вы хотите отправлять данные с использованием типа содержимого application/x-www-form-urlencoded, то вы должны вызвать метод asForm перед выполнением запроса:

$response = Http::asForm()->post('http://example.com/users', [
    'name' => 'Sara',
    'role' => 'Privacy Consultant',
]);

Отправка необработанного тела запроса

Вы можете использовать метод withBody, если хотите передать необработанное тело запроса при его выполнении. Тип контента может быть указан вторым аргументом метода:

$response = Http::withBody(
    base64_encode($photo), 'image/jpeg'
)->post('http://example.com/photo');

Составные запросы

Если вы хотите отправлять файлы в запросах, состоящих из нескольких частей, необходимо вызвать метод attach перед выполнением запроса. Этот метод принимает имя файла и его содержимое. При желании вы можете указать третий аргумент, который будет считаться именем файла:

$response = Http::attach(
    'attachment', file_get_contents('photo.jpg'), 'photo.jpg'
)->post('http://example.com/attachments');

Вы также можете передать потоковый ресурс вместо передачи необработанного содержимого файла:

$photo = fopen('photo.jpg', 'r');

$response = Http::attach(
    'attachment', $photo, 'photo.jpg'
)->post('http://example.com/attachments');

Заголовки

Заголовки могут быть добавлены к запросам с помощью метода withHeaders. Метод withHeaders принимает массив пар ключ / значение:

$response = Http::withHeaders([
    'X-First' => 'foo',
    'X-Second' => 'bar'
])->post('http://example.com/users', [
    'name' => 'Taylor',
]);

Вы можете использовать метод accept, чтобы указать тип контента, который ваше приложение ожидает в ответ на ваш запрос:

$response = Http::accept('application/json')->get('http://example.com/users');

Для удобства вы можете использовать метод acceptJson, чтобы быстро указать, что ваше приложение ожидает тип содержимого application/json в ответ на ваш запрос:

$response = Http::acceptJson()->get('http://example.com/users');

Аутентификация

Вы можете указать данные basic и digest аутентификации, используя методы withBasicAuth и withDigestAuth, соответственно:

// Basic HTTP-аутентификация ...
$response = Http::withBasicAuth('taylor@laravel.com', 'secret')->post(...);

// Digest HTTP-аутентификациия ...
$response = Http::withDigestAuth('taylor@laravel.com', 'secret')->post(...);

Токены Bearer

Если вы хотите добавить токен в заголовок Authorization запроса, то используйте метод withToken:

$response = Http::withToken('token')->post(...);

Время ожидания

Метод timeout используется для указания максимального количества секунд ожидания ответа:

$response = Http::timeout(3)->get(...);

Если указанный тайм-аут превышен, то будет выброшено исключение IlluminateHttpClientConnectionException.

Повторные попытки

Если вы хотите, чтобы HTTP-клиент автоматически повторял запрос при возникновении ошибки клиента или сервера, то используйте метод retry. Метод retry принимает максимальное количество попыток выполнения запроса и количество миллисекунд, которые Laravel должен ждать между попытками:

$response = Http::retry(3, 100)->post(...);

При необходимости вы можете передать третий аргумент методу retry. Третий аргумент должен быть callable-функцией, которая определяет, следует ли на самом деле попытаться повторить попытку. Например, вы можете захотеть повторить запрос только в том случае, если начальный запрос обнаруживает исключение ConnectionException:

$response = Http::retry(3, 100, function ($exception) {
    return $exception instanceof ConnectionException;
})->post(...);

Если все запросы окажутся неуспешными, то будет выброшено исключение IlluminateHttpClientRequestException.

Обработка ошибок

В отличие от поведения Guzzle по умолчанию, обертка HTTP-клиента Laravel не генерирует исключений при возникновении ошибок клиента или сервера (ответы 400 и 500, соответственно). Вы можете определить, была ли возвращена одна из этих ошибок, используя методы successful, clientError, или serverError:

// Определить, имеет ли ответ код состояния >= 200 and < 300...
$response->successful();

// Определить, имеет ли ответ код состояния >= 400...
$response->failed();

// Определить, имеет ли ответ код состояния 400 ...
$response->clientError();

// Определить, имеет ли ответ код состояния 500 ...
$response->serverError();

Выброс исключений

Если у вас есть экземпляр ответа и вы хотите выбросить исключение IlluminateHttpClientRequestException, если код состояния ответа указывает на ошибку клиента или сервера, используйте методы throw или throwIf:

$response = Http::post(...);

// Выбросить исключение, если произошла ошибка клиента или сервера ...
$response->throw();

// Выбросить исключение, если произошла ошибка и данное условие истинно...
$response->throwIf($condition);

return $response['user']['id'];

Экземпляр IlluminateHttpClientRequestException имеет свойство $response, которое позволит вам проверить возвращенный ответ.

Метод throw возвращает экземпляр ответа, если ошибки не произошло, что позволяет вам использовать цепочку вызовов после метода throw:

return Http::post(...)->throw()->json();

Если вы хотите выполнить некоторую дополнительную логику до того, как будет сгенерировано исключение, вы можете передать замыкание методу throw. Исключение будет сгенерировано автоматически после вызова замыкания, поэтому вам не нужно повторно генерировать исключение изнутри замыкания:

return Http::post(...)->throw(function ($response, $e) {
    //
})->json();

Параметры Guzzle

Вы можете указать дополнительные параметры запроса для Guzzle, используя метод withOptions. Метод withOptions принимает массив пар ключ / значение:

$response = Http::withOptions([
    'debug' => true,
])->get('http://example.com/users');

Параллельные запросы

Иногда вы можете захотеть выполнить несколько HTTP-запросов одновременно. Другими словами, вы хотите, чтобы несколько запросов отправлялись одновременно вместо того, чтобы отправлять их последовательно. Это может привести к значительному повышению производительности при взаимодействии с медленными HTTP API.

Вы можете сделать это с помощью метода pool. Метод pool принимает функцию с аргументом IlluminateHttpClientPool, при помощи которого вы можете добавлять запросы в пул запросов для отправки:

use IlluminateHttpClientPool;
use IlluminateSupportFacadesHttp;

$responses = Http::pool(fn (Pool $pool) => [
    $pool->get('http://localhost/first'),
    $pool->get('http://localhost/second'),
    $pool->get('http://localhost/third'),
]);

return $responses[0]->ok() &&
       $responses[1]->ok() &&
       $responses[2]->ok();

Как видите, к каждому экземпляру ответа можно получить доступ в том порядке, в котором он был добавлен в пул. При желании вы можете назвать запросы с помощью метода as, что позволит вам получить доступ к соответствующим ответам по имени:

use IlluminateHttpClientPool;
use IlluminateSupportFacadesHttp;

$responses = Http::pool(fn (Pool $pool) => [
    $pool->as('first')->get('http://localhost/first'),
    $pool->as('second')->get('http://localhost/second'),
    $pool->as('third')->get('http://localhost/third'),
]);

return $responses['first']->ok();

Тестирование

Многие службы Laravel содержат функционал, помогающий вам легко и выразительно писать тесты, и HTTP-клиент Laravel не является исключением. Метод fake фасада Http позволяет указать HTTP-клиенту возвращать заглушенные / фиктивные ответы при выполнении запросов.

Фиктивные ответы

Например, чтобы дать указание HTTP-клиенту возвращать пустые ответы с кодом состояния 200 на каждый запрос, вы можете вызвать метод fake без аргументов:

use IlluminateSupportFacadesHttp;

Http::fake();

$response = Http::post(...);

При фальсификации запросов посредник HTTP-клиента не выполняется. Вы должны определить ожидания для фиктивных ответов, как если бы этот посредник работал правильно.

Фальсификация конкретных URL

В качестве альтернативы вы можете передать массив методу fake. Ключи массива должны представлять шаблоны URL, которые вы хотите подделать, и связанные с ними ответы. Допускается использование метасимвола подстановки *. Любые запросы к URL-адресам, которые не были сфальсифицированы, будут выполнены фактически. Вы можете использовать метод response фасада Http для создания заглушек / фиктивных ответов для этих адресов:

Http::fake([
    // Заглушка JSON ответа для адресов GitHub ...
    'github.com/*' => Http::response(['foo' => 'bar'], 200, $headers),

    // Заглушка строкового ответа для адресов Google ...
    'google.com/*' => Http::response('Hello World', 200, $headers),
]);

Если вы хотите указать шаблон резервного URL-адреса, который будет заглушать все не сопоставленные URL-адреса, то используйте символ *:

Http::fake([
    // Заглушка JSON ответа для адресов GitHub ...
    'github.com/*' => Http::response(['foo' => 'bar'], 200, ['Headers']),

    // Заглушка строкового ответа для всех остальных адресов ...
    '*' => Http::response('Hello World', 200, ['Headers']),
]);

Фальсификация серии ответов

По желанию можно указать, что один URL должен возвращать серию фиктивных ответов в определенном порядке. Вы можете сделать это, используя метод Http::sequence для составления ответов:

Http::fake([
    // Заглушка серии ответов для адресов GitHub ...
    'github.com/*' => Http::sequence()
                            ->push('Hello World', 200)
                            ->push(['foo' => 'bar'], 200)
                            ->pushStatus(404),
]);

Когда все ответы в этой последовательности будут использованы, любые дальнейшие запросы приведут к выбросу исключения. Если вы хотите указать ответ по умолчанию, который должен возвращаться, когда последовательность пуста, то используйте метод whenEmpty:

Http::fake([
    // Заглушка серии ответов для адресов GitHub ...
    'github.com/*' => Http::sequence()
                            ->push('Hello World', 200)
                            ->push(['foo' => 'bar'], 200)
                            ->whenEmpty(Http::response()),
]);

Если вы хотите подделать серию ответов без указания конкретного шаблона URL, который следует подделать, то используйте метод Http::fakeSequence:

Http::fakeSequence()
        ->push('Hello World', 200)
        ->whenEmpty(Http::response());

Анонимные фальсификаторы

Если вам требуется более сложная логика для определения того, какие ответы возвращать для определенных адресов, то вы можете передать замыкание методу fake. Это замыкание получит экземпляр IlluminateHttpClientRequest и должно вернуть экземпляр ответа. В замыкании вы можете выполнить любую логику, необходимую для определения типа ответа, который нужно вернуть:

Http::fake(function ($request) {
    return Http::response('Hello World', 200);
});

Инспектирование запросов

При фальсификации ответов вы можете иногда захотеть проверить запросы, которые получает клиент, чтобы убедиться, что ваше приложение отправляет правильные данные или заголовки. Вы можете сделать это, вызвав метод Http::assertSent после вызова Http::fake.

Метод assertSent принимает замыкание, которому будет передан экземпляр IlluminateHttpClientRequest и, которое должно возвращать значение логического типа, указывающее, соответствует ли запрос вашим ожиданиям. Для успешного прохождения теста должен быть отправлен хотя бы один запрос, соответствующий указанным ожиданиям:

use IlluminateHttpClientRequest;
use IlluminateSupportFacadesHttp;

Http::fake();

Http::withHeaders([
    'X-First' => 'foo',
])->post('http://example.com/users', [
    'name' => 'Taylor',
    'role' => 'Developer',
]);

Http::assertSent(function (Request $request) {
    return $request->hasHeader('X-First', 'foo') &&
           $request->url() == 'http://example.com/users' &&
           $request['name'] == 'Taylor' &&
           $request['role'] == 'Developer';
});

При необходимости вы можете утверждать, что конкретный запрос не был отправлен с помощью метода assertNotSent:

use IlluminateHttpClientRequest;
use IlluminateSupportFacadesHttp;

Http::fake();

Http::post('http://example.com/users', [
    'name' => 'Taylor',
    'role' => 'Developer',
]);

Http::assertNotSent(function (Request $request) {
    return $request->url() === 'http://example.com/posts';
});

Или используйте метод assertNothingSent, чтобы утверждать, что во время теста не было отправлено никаких запросов:

Http::fake();

Http::assertNothingSent();

События

Laravel запускает три события в процессе отправки HTTP-запросов. Событие RequestSending запускается до отправки запроса, а событие ResponseReceived запускается после получения ответа на данный запрос. Событие ConnectionFailed запускается, если на данный запрос ответ не получен.

События RequestSending и ConnectionFailed содержат общедоступное свойство $request, которое вы можете использовать для проверки экземпляра IlluminateHttpClientRequest. Аналогично, событие ResponseReceived содержит свойство $request, а также свойство $response, которое может использоваться для проверки экземпляра IlluminateHttpClientResponse. Вы можете зарегистрировать прослушиватели событий для этого события в вашем сервис-провайдере AppProvidersEventServiceProvider:

/**
 * Сопоставления прослушивателей событий для приложения.
 *
 * @var array
 */
protected $listen = [
    'IlluminateHttpClientEventsRequestSending' => [
        'AppListenersLogRequestSending',
    ],
    'IlluminateHttpClientEventsResponseReceived' => [
        'AppListenersLogResponseReceived',
    ],
    'IlluminateHttpClientEventsConnectionFailed' => [
        'AppListenersLogConnectionFailed',
    ],
];

Эта страница содержит краткое введение в Guzzle и вводные примеры. Если вы еще не установили его, рекомендую обратиться к странице Установка Guzzle.

  • Как делать запросы

  • Создание клиента

  • Отправка запросов

  • Асинхронные запросы

  • Параллельные запросы

  • Использование ответов

  • Параметры строки запроса

  • Загрузка данных

  • POST/Form запросы

  • Отправка полей формы

  • Отправка файлов форм

  • Cookies

  • Редиректы (перенаправления)

  • Исключения при обработке ошибок

  • Переменные окружения

  • Соответствующие настройки php.ini

Как делать запросы

Можно делать запросы в Guzzle, используя объект GuzzleHttpClientInterface:

Создание клиента

use GuzzleHttpClient;

$client = new Client([
    // Базовый URI используется с относительными запросами
    'base_uri' => 'http://httpbin.org',
    // Можно установить любое количество параметров запроса по умолчанию.
    'timeout'  => 2.0,
]);

Клиенты являются неизменными в Guzzle 6, что означает, что вы не можете изменить значения по умолчанию, используемые клиентом после его создания.

Конструктор клиента принимает ассоциативный массив опций:

base_uri
(string|UriInterface) Базовый URI клиента, который объединен в относительные URI. Может быть строкой или экземпляром UriInterface. Когда клиенту предоставляется относительный URI, клиент объединяет базовый URI с относительным URI, используя правила, описанные в RFC 3986, section 2.

// Создать клиента с базовым URI
$client = new GuzzleHttpClient(['base_uri' => 'https://foo.com/api/']);

// Отправить запрос на https://foo.com/api/test
$response = $client->request('GET', 'test');

// Отправить запрос на https://foo.com/root
$response = $client->request('GET', '/root');

Не хочется читать RFC 3986? Вот несколько быстрых примеров того, как base_uri разрешается с другим URI:

base_uri URI Результат
http://foo.com /bar http://foo.com/bar
http://foo.com/foo /bar http://foo.com/bar
http://foo.com/foo bar http://foo.com/bar
http://foo.com/foo/ bar http://foo.com/foo/bar
http://foo.com http://baz.com http://baz.com
http://foo.com/?bar bar http://foo.com/bar
handler
(callable) Функция, которая передает HTTP-запросы по сети. Функция вызывается с Psr7HttpMessageRequestInterface и массив опций передачи, и должен возвращать GuzzleHttpPromisePromiseInterface который выполняется с Psr7HttpMessageResponseInterface в случае успеха. handler это опция только для конструктора, которая не может быть переопределена в параметрах per/request.
(mixed) Все остальные параметры, передаваемые конструктору, используются в качестве параметров запроса по умолчанию для каждого запроса, создаваемого клиентом.

Отправка запросов

Магические методы на клиенте позволяют легко отправлять синхронные запросы:

$response = $client->get('http://httpbin.org/get');
$response = $client->delete('http://httpbin.org/delete');
$response = $client->head('http://httpbin.org/get');
$response = $client->options('http://httpbin.org/get');
$response = $client->patch('http://httpbin.org/patch');
$response = $client->post('http://httpbin.org/post');
$response = $client->put('http://httpbin.org/put');

Вы можете создать запрос и затем отправить запрос клиенту, когда будете готовы:

use GuzzleHttpPsr7Request;

$request = new Request('PUT', 'http://httpbin.org/put');
$response = $client->send($request, ['timeout' => 2]);

Клиентские объекты обеспечивают большую гибкость в том, как передаются запросы, включая параметры запроса по умолчанию, промежуточное программное обеспечение стека обработчиков по умолчанию, которое используется каждым запросом, и базовый URI, который позволяет отправлять запросы с относительными URI.

Вы можете узнать больше о клиентском промежуточном программном обеспечении на странице Обработчики и связующее ПО документации.

Асинхронные запросы

Вы можете отправлять асинхронные запросы, используя магические методы, предоставляемые клиентом:

$promise = $client->getAsync('http://httpbin.org/get');
$promise = $client->deleteAsync('http://httpbin.org/delete');
$promise = $client->headAsync('http://httpbin.org/get');
$promise = $client->optionsAsync('http://httpbin.org/get');
$promise = $client->patchAsync('http://httpbin.org/patch');
$promise = $client->postAsync('http://httpbin.org/post');
$promise = $client->putAsync('http://httpbin.org/put');

Вы также можете использовать методы sendAsync() и requestAsync() клиента:

// Создать объект запроса PSR-7 для отправки
$headers = ['X-Foo' => 'Bar'];
$body = 'Hello!';
$request = new Request('HEAD', 'http://httpbin.org/head', $headers, $body);
$promise = $client->sendAsync($request);

// Или, если вам не нужно передавать экземпляр запроса:
$promise = $client->requestAsync('GET', 'http://httpbin.org/get');

$promise, возвращаемые этими методами, реализуют Promises/A+ spec, предоставленные библиотекой Guzzle promises. Это означает, что вы сможете связать цепочкой then() вызовы promise. Эти then затем реализуют либо успешный результат с помощью PsrHttpMessageResponseInterface, либо запрос отклоняется с выбросом исключения exception:

use PsrHttpMessageResponseInterface;
use GuzzleHttpExceptionRequestException;

$promise = $client->requestAsync('GET', 'http://httpbin.org/get');
$promise->then(
    function (ResponseInterface $res) {
        echo $res->getStatusCode() . "n";
    },
    function (RequestException $e) {
        echo $e->getMessage() . "n";
        echo $e->getRequest()->getMethod();
    }
);

Параллельные запросы

Вы можете отправлять несколько запросов одновременно, используя Promise и асинхронные запросы:

use GuzzleHttpClient;
use GuzzleHttpPromise;

$client = new Client(['base_uri' => 'http://httpbin.org/']);

// Инициируем каждый запрос, но не блокируем
$promises = [
    'image' => $client->getAsync('/image'),
    'png'   => $client->getAsync('/image/png'),
    'jpeg'  => $client->getAsync('/image/jpeg'),
    'webp'  => $client->getAsync('/image/webp')
];

// Дождаться завершения всех запросов. Выдает исключение ConnectException
// если какой-либо из запросов не выполнен
$results = Promiseunwrap($promises);

// Дождемся завершения запросов, даже если некоторые из них завершатся неудачно
$results = Promisesettle($promises)->wait();

// Можно получить доступ к каждому результату, используя key, предоставленный для функции развертки
echo $results['image']['value']->getHeader('Content-Length')[0];
echo $results['png']['value']->getHeader('Content-Length')[0];

Можно использовать GuzzleHttpPool объект, когда у вас есть неопределенное количество запросов, которые вы хотите отправить:

use GuzzleHttpPool;
use GuzzleHttpClient;
use GuzzleHttpPsr7Request;

$client = new Client();

$requests = function ($total) {
    $uri = 'http://127.0.0.1:8126/guzzle-server/perf';
    for ($i = 0; $i < $total; $i++) {
        yield new Request('GET', $uri);
    }
};

$pool = new Pool($client, $requests(100), [
    'concurrency' => 5,
    'fulfilled' => function ($response, $index) {
        // Тут обработка успешного запроса
    },
    'rejected' => function ($reason, $index) {
        // Тут обработка запроса, который завершился неудачей
    },
]);

// Инициализируем трансферы и создаём promise
$promise = $pool->promise();

// Ожидаем ответ promise // Принудительно завершаем пул запросов
$promise->wait();

Или используя замыкание, которое вернет promise, как только пул вызовет замыкание:

$client = new Client();

$requests = function ($total) use ($client) {
    $uri = 'http://127.0.0.1:8126/guzzle-server/perf';
    for ($i = 0; $i < $total; $i++) {
        yield function() use ($client, $uri) {
            return $client->getAsync($uri);
        };
    }
};

$pool = new Pool($client, $requests(100));

Использование ответов

В предыдущих примерах мы получили $response или мы получили ответ от promise. Объект ответа реализует ответ PSR-7, PsrHttpMessageResponseInterface, и содержит много полезной информации.

Вы можете получить код состояния и фразу ответа:

$code = $response->getStatusCode(); // 200
$reason = $response->getReasonPhrase(); // OK

Вы можете извлечь заголовки из ответа:

// Проверка, есть ли заголовок
if ($response->hasHeader('Content-Length')) {
    echo "It exists";
}

// Получаем заголовок из ответа
echo $response->getHeader('Content-Length')[0];

// Получаем все заголовки ответа
foreach ($response->getHeaders() as $name => $values) {
    echo $name . ': ' . implode(', ', $values) . "rn";
}

Тело ответа может быть получено с помощью метода getBody. Тело ответа может быть использовано как строка, приведено к строке или как объект, подобный потоку:

$body = $response->getBody();

// Неявно приводим тело ответа к строке и отображаем его
echo $body;

// Явное приведение тела к строке
$stringBody = (string) $body;

// Читаем первые 10 байт тела ответа
$tenBytes = $body->read(10);

// Прочитать оставшееся содержимое тела ответа как строку
$remainingBytes = $body->getContents();

Параметры строки запроса

Вы можете предоставить параметры строки запроса несколькими способами.

Можно установить параметры строки запроса в URI запроса:

$response = $client->request('GET', 'http://httpbin.org?foo=bar');

Можно указать параметры строки запроса, используя query как массив:

$client->request('GET', 'http://httpbin.org', [
    'query' => ['foo' => 'bar']
]);

Предоставление опции в качестве массива будет использовать нативную функцию PHP http_build_query для форматирования строки с параметрами.

И, наконец, можно предоставить query в роли строки:

$client->request('GET', 'http://httpbin.org', ['query' => 'foo=bar']);

Загрузка данных

Guzzle предоставляет несколько способов загрузки данных.

Можно отправлять запросы, содержащие поток данных, передавая строку, ресурс возвращается из fopen, или как экземпляр PsrHttpMessageStreamInterface в опцию запроса body:

// Предоставляем тело запроса в виде строки
$r = $client->request('POST', 'http://httpbin.org/post', [
    'body' => 'raw data'
]);

// Предоставляем fopen ресурс
$body = fopen('/path/to/file', 'r');
$r = $client->request('POST', 'http://httpbin.org/post', ['body' => $body]);

// Используем функцию stream_for() для создания потока PSR-7
$body = GuzzleHttpPsr7stream_for('hello!');
$r = $client->request('POST', 'http://httpbin.org/post', ['body' => $body]);

Простой способ загрузить данные JSON и установить соответствующий заголовок — использовать опцию запроса json:

$r = $client->request('PUT', 'http://httpbin.org/put', [
    'json' => ['foo' => 'bar']
]);

POST/Form запросы

В дополнение к указанию необработанных данных запроса с использованием опции запросаbody, Guzzle предоставляет полезные абстракции при отправке данных POST.

Отправка полей формы

Для отправки POST-запросов application/x-www-form-urlencoded необходимо указать поля POST в виде массива в параметрах запроса form_params:

$response = $client->request('POST', 'http://httpbin.org/post', [
    'form_params' => [
        'field_name' => 'abc',
        'other_field' => '123',
        'nested_field' => [
            'nested' => 'hello'
        ]
    ]
]);

Отправка файлов форм

Можно отправлять файлы вместе с формой (POST-запросы multipart/form-data), используя опцию запроса multipart. Она принимает массив ассоциативных массивов, где каждый ассоциативный массив содержит следующие ключи:

  • name: (required, string) имя ключа поля формы.
  • contents: (required, mixed) Укажите тут строку для отправки содержимого файла в виде строки, предоставьте ресурс fopen для потоковой передачи содержимого из потока PHP или укажите PsrHttpMessageStreamInterface для потоковой передачи содержимого из потока PSR-7.
$response = $client->request('POST', 'http://httpbin.org/post', [
    'multipart' => [
        [
            'name'     => 'field_name',
            'contents' => 'abc'
        ],
        [
            'name'     => 'file_name',
            'contents' => fopen('/path/to/file', 'r')
        ],
        [
            'name'     => 'other_file',
            'contents' => 'hello',
            'filename' => 'filename.txt',
            'headers'  => [
                'X-Foo' => 'this is an extra header to include'
            ]
        ]
    ]
]);

Cookies

Guzzle может поддерживать для вас сеанс файлов cookie, если это указано с помощью параметра запроса файлов cookie. При отправке запроса параметр cookie должен быть установлен на экземпляр GuzzleHttpCookieCookieJarInterface:

// Использование конкретного cookie jar
$jar = new GuzzleHttpCookieCookieJar;
$r = $client->request('GET', 'http://httpbin.org/cookies', [
    'cookies' => $jar
]);

Можно установить для cookie значение true в конструкторе клиента, если хотите использовать общий файл cookie для всех запросов:

// Используем общий клиентский файл cookie
$client = new GuzzleHttpClient(['cookies' => true]);
$r = $client->request('GET', 'http://httpbin.org/cookies');

Редиректы (перенаправления)

Guzzle будет автоматически следовать за редиректами, только если чётко не указать этого не делать. Вы можете настроить поведение перенаправления, используя опцию запроса allow_redirects:

  • Установите значение true, чтобы включить нормальные перенаправления с максимальным количеством 5 перенаправлений. Это значение по умолчанию.
  • Установите в false, чтобы отключить перенаправления.
  • Передайте ассоциативный массив, содержащий ключ max, чтобы указать максимальное количество перенаправлений, и при необходимости укажите значение ключа strict, чтобы указать, следует ли использовать строгие перенаправления, совместимые с RFC (что означает запросы перенаправления POST со следующими запросами тоже типа POST, тогда как в обычном режиме большинство браузеров по умолчанию перенаправляют запросы POST со следующими запросами GET).
$response = $client->request('GET', 'http://github.com');
echo $response->getStatusCode();
// 200

В следующем примере показано, как можно отключить редиректы:

$response = $client->request('GET', 'http://github.com', [
    'allow_redirects' => false
]);
echo $response->getStatusCode();
// 301

Исключения при обработке ошибок

Guzzle генерирует исключения для ошибок, возникающих во время передачи:

  • В случае сетевой ошибки (тайм-аут соединения, ошибки DNS и т.д.) выдается сообщение GuzzleHttpExceptionRequestException. Это исключение распространяется на GuzzleHttpExceptionTransferException. Поймав это исключение, вы поймете любое исключение, которое может быть сгенерировано при передаче запросов. Пример:
    use GuzzleHttpPsr7;
    use GuzzleHttpExceptionRequestException;
    
    try {
        $client->request('GET', 'https://github.com/_abc_123_404');
    } catch (RequestException $e) {
        echo Psr7str($e->getRequest());
        if ($e->hasResponse()) {
            echo Psr7str($e->getResponse());
        }
    }
    
  • Исключение GuzzleHttpExceptionConnectException выдается в случае сетевой ошибки. Это исключение происходит от GuzzleHttpExceptionRequestException.
  • GuzzleHttpExceptionClientException выбрасывается для ошибок уровня 400, если для параметра запроса http_errors установлено значение true. Это исключение распространяется на GuzzleHttpExceptionBadResponseException и GuzzleHttpExceptionBadResponseException распространяется на GuzzleHttpExceptionRequestException. Пример:
    use GuzzleHttpExceptionClientException;
    
    try {
        $client->request('GET', 'https://github.com/_abc_123_404');
    } catch (ClientException $e) {
        echo Psr7str($e->getRequest());
        echo Psr7str($e->getResponse());
    }
    
  • GuzzleHttpExceptionServerException генерируется для ошибок уровня 500, если для параметра запроса http_errors установлено значение true. Это исключение происходит от GuzzleHttpExceptionBadResponseException.
  • GuzzleHttpExceptionTooManyRedirectsException генерируется, когда выполняется слишком много перенаправлений. Это исключение происходит от GuzzleHttpExceptionRequestException.

Все вышеперечисленные исключения происходят из GuzzleHttpExceptionTransferException.

Переменные окружения

Guzzle предоставляет несколько переменных среды, которые можно использовать для настройки поведения библиотеки:

GUZZLE_CURL_SELECT_TIMEOUT
Управляет продолжительностью в секундах, которую обработчик curl_multi_* будет использовать при выборе обработчика curl, используя curl_multi_select(). Некоторые системы имеют проблемы с реализацией PHP curl_multi_select(), где вызов этой функции всегда приводит к ожиданию максимальной продолжительности времени ожидания.
HTTP_PROXY
Определяет прокси для использования при отправке запросов по протоколу http.

Поскольку переменная HTTP_PROXY может содержать произвольный пользовательский ввод в некоторых (CGI) средах, эта переменная используется только в CLI SAPI. Смотрите https://httpoxy.org для получения дополнительной информации.

HTTPS_PROXY
Определяет прокси для использования при отправке запросов по протоколу https.

Соответствующие настройки php.ini

Guzzle может использовать настройки php.ini при настройке клиентов:

openssl.cafile
Указывает путь на диске к файлу CA (сертификат SSL/TLS безопасности) в формате PEM, который будет использоваться при отправке запросов через «https». Подробнее: https://wiki.php.net/rfc/tls-peer-verification#phpini_defaults

Смотрите далее: Опции запросов Guzzle | Ранее: Обзор и установка Guzzle | Главная по Guzzle

While the answers above are good they will not catch network errors. As Mark mentioned, BadResponseException is just a super class for ClientException and ServerException. But RequestException is also a super class of BadResponseException. RequestException will be thrown for not only 400 and 500 errors but network errors and infinite redirects too. So let’s say you request the page below but your network is playing up and your catch is only expecting a BadResponseException. Well your application will throw an error.

It’s better in this case to expect RequestException and check for a response.

try {
  $client->get('http://123123123.com')
} catch (RequestException $e) {

  // If there are network errors, we need to ensure the application doesn't crash.
  // if $e->hasResponse is not null we can attempt to get the message
  // Otherwise, we'll just pass a network unavailable message.
  if ($e->hasResponse()) {
    $exception = (string) $e->getResponse()->getBody();
    $exception = json_decode($exception);
    return new JsonResponse($exception, $e->getCode());
  } else {
    return new JsonResponse($e->getMessage(), 503);
  }

}

Guzzle 3.x

Per the docs, you can catch the appropriate exception type (ClientErrorResponseException for 4xx errors) and call its getResponse() method to get the response object, then call getBody() on that:

use GuzzleHttpExceptionClientErrorResponseException;

...

try {
    $response = $request->send();
} catch (ClientErrorResponseException $exception) {
    $responseBody = $exception->getResponse()->getBody(true);
}

Passing true to the getBody function indicates that you want to get the response body as a string. Otherwise you will get it as instance of class GuzzleHttpEntityBody.

Guzzle 6.x

Per the docs, the exception types you may need to catch are:

  • GuzzleHttpExceptionClientException for 400-level errors
  • GuzzleHttpExceptionServerException for 500-level errors
  • GuzzleHttpExceptionBadResponseException for both (it’s their superclass)

Code to handle such errors thus now looks something like this:

$client = new GuzzleHttpClient;
try {
    $client->get('http://google.com/nosuchpage');    
}
catch (GuzzleHttpExceptionClientException $e) {
    $response = $e->getResponse();
    $responseBodyAsString = $response->getBody()->getContents();
}

Tags:

Php

Guzzle

Related

Понравилась статья? Поделить с друзьями:

Читайте также:

  • Guvcview error no video device found
  • Gutrend style 220 ошибки
  • Gutrend style 200 aqua ошибки
  • Gutrend fun 110 pet ошибка e10
  • Guru meditation virtualbox как исправить

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии