PSR-18: HTTP Client
Interface \Psr\Http\Client\ClientInterface
contains only a single method for sending a HTTP query:
interface ClientInterface { public function sendRequest(RequestInterface $request): ResponseInterface; }
PSR requires creating and passing a query object RequestInterface and returning ResponseInterface query object (described in PSR-7). Error processing is implemented in exceptions. Kernel has PSR-7 interfaces implemented in classes:
\Bitrix\Main\Web\Uri
– URI;\Bitrix\Main\Web\Http\Request
– query;\Bitrix\Main\Web\Http\Response
– response;\Bitrix\Main\Web\Http\Stream
– query/response body;\Bitrix\Main\Web\Http\ClientException
– top level exception;\Bitrix\Main\Web\Http\RequestException
– query error;\Bitrix\Main\Web\Http\NetworkException
– network error.
PSR-7 peculiarity is the use of streams for query body and response. Below is the example for sending forms via POST method:
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'); // query body preparation $body = new Stream('php://temp', 'r+'); $body->write(http_build_query($data, '', '&')); // OR a simpler method (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()); }
Let's overview a more complex example, when you need to pass a file using POST method:
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()); }
Please note, the response with redirect will be returned as is, without forwarding via title Location. PSR-18 deems responses with code 30x as identical to the rest of responses. Example for redirect processing can look as follows:
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://bitrxi24.eu/'); $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()); } /* Prints: string(37) "https://xn--1--clc2aam4begg.xn--p1ai/" string(25) "https://www.bitrxi24.eu/" */
Instead of the above you can use the old method:
use Bitrix\Main\Web\HttpClient; $http = (new HttpClient())->disableSslVerification(); var_dump($http->get('http://bitrxi24.eu/'));