Документация для разработчиков
Темная тема

PSR-18: HTTP Client

Интерфейс \Psr\Http\Client\ClientInterface содержит всего один метод для отправки HTTP-запроса:

interface ClientInterface
{
	public function sendRequest(RequestInterface $request): ResponseInterface;
}

PSR требует создать и передать объект запроса типа RequestInterface и возвращает объект ответа типа ResponseInterface (описаны в PSR-7). Обработка ошибок реализуется на исключениях. В ядре интерфейсы PSR-7 реализованы в классах:

  • \Bitrix\Main\Web\Uri – URI;
  • \Bitrix\Main\Web\Http\Request – запрос;
  • \Bitrix\Main\Web\Http\Response – ответ;
  • \Bitrix\Main\Web\Http\Stream – тело запроса/ответа;
  • \Bitrix\Main\Web\Http\ClientException – исключение верхнего уровня;
  • \Bitrix\Main\Web\Http\RequestException – ошибка запроса;
  • \Bitrix\Main\Web\Http\NetworkException – сетевая ошибка.

Особенностью PSR-7 является использование потоков для тела запроса и ответа. Ниже пример отправки формы методом POST:

use Bitrix\Main\Web\HttpClient;
use Bitrix\Main\Web\Uri;
use Bitrix\Main\Web\Http\Request;
use Bitrix\Main\Web\Http\Method;
use Bitrix\Main\Web\Http\Stream;
//use Bitrix\Main\Web\Http\FormStream;
use Bitrix\Main\Web\Http\ClientException;
	
$http = new HttpClient([
	'compress' => true,
]);
	
$data = [
	"k1" => "v1",
	"k2" => "v2",
];
	
$uri = new Uri('http://vm.vad/test.php');
	
// подготовка тела запроса
$body = new Stream('php://temp', 'r+');
$body->write(http_build_query($data, '', '&'));
	
// ИЛИ более простой способ (main 23.300.0)
// $body = new FormStream($data);
	
$request = new Request(Method::POST, $uri, [], $body);
	
try
{
	$response = $http->sendRequest($request);
	
	var_dump($response->getStatusCode());
	var_dump($response->getHeaders());
	var_dump((string)$response->getBody());
}
catch (ClientException $e)
{
	var_dump($e->getMessage());
}

Рассмотрим более сложный пример, когда нужно передать файл методом POST:

use Bitrix\Main\Web\HttpClient;
use Bitrix\Main\Web\Uri;
use Bitrix\Main\Web\Http\Request;
use Bitrix\Main\Web\Http\Method;
use Bitrix\Main\Web\Http\MultipartStream;
use Bitrix\Main\Web\Http\ClientException;
	
$http = new HttpClient([
	'compress' => true,
]);
	
	
$res = fopen("/home/bitrix/www/20190807_120929.jpg", 'r');
	
$data = [
	"k1" => "v1",
	"k2" => "v2",
	"k3" => [
		'resource' => $res,
		'filename' => "pic.jpg",
	],
];
	
$uri = new Uri('http://vm.vad/test.php');
	
$body = new MultipartStream($data);
	
$headers = [
	'User-Agent' => 'bitrix',
	'Content-type' => 'multipart/form-data; boundary=' . $body->getBoundary(),
];
	
$request = new Request(Method::POST, $uri, $headers, $body);
	
fclose($res);
	
try
{
	$response = $http->sendRequest($request);
	
	var_dump($response->getStatusCode());
	var_dump($response->getHeaders());
	var_dump((string)$response->getBody());
}
catch (ClientException $e)
{
	var_dump($e->getMessage());
}

Обратите внимание, что ответ с редиректом будет возвращён как есть, без перехода по заголовку Location. PSR-18 считает, что ответы с кодом 30x ничем не отличаются от всех остальных. Пример обработки редиректа может выглядеть так:

use Bitrix\Main\Web\HttpClient;
use Bitrix\Main\Web\Uri;
use Bitrix\Main\Web\Http\Request;
use Bitrix\Main\Web\Http\Method;
use Bitrix\Main\Web\Http\ClientException;
	
$http = new HttpClient([
	'compress' => true,
	'disableSslVerification' => true,
]);
	
$uri = new Uri('http://1с-битрикс.рф/');
	
$request = new Request(Method::GET, $uri);
	
try
{
	do
	{	
		$response = $http->sendRequest($request);
		
		if ($response->hasHeader('Location'))
		{
			$location = $response->getHeader('Location')[0];
			var_dump($location);
			
			$request = $request->withUri(new Uri($location));
		}
	}
	while ($response->hasHeader('Location'));
	
//	var_dump((string)$response->getBody());
}
catch (ClientException $e)
{
	var_dump($e->getMessage());
}
	
/*
Распечатает:
string(37) "https://xn--1--clc2aam4begg.xn--p1ai/"
string(25) "https://www.1c-bitrix.ru/"
*/

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

use Bitrix\Main\Web\HttpClient;
	
$http = (new HttpClient())->disableSslVerification();
	
var_dump($http->get('http://1с-битрикс.рф/'));


© «Битрикс», 2001-2024, «1С-Битрикс», 2024