При интеграции сайта на Битрикс часто возникает необходимость парсинга других сайтов или интеграции с внешними сервисами, а следовательно возникает вопрос о том, как обратиться к стороннему URL. В старом ядре был класс CHTTP для этих целей, но из-за отсутствия документации по нему, обычно искали решение в fopen, file_get_contents, curl и т.п. Эта статья посвящена новым классам для работы с URL и HTTP-запросами в Битрикс D7. Классы собраны в пространстве имён Bitrix\Main\Web. В статье используются следующие сокращения:

use \Bitrix\Main\Application,
    \Bitrix\Main\Web\Uri,
    \Bitrix\Main\Web\HttpClient;

Судя по документации, класс HttpClient появился в версии 14.0.15, Uri появился в 12.0.7, но большинство методов были реализованы только в 15.5.10.

Bitrix\Main\Web\Uri

Класс Uri содержит методы для работы с адресом страницы. Фактически это надстройка над функциями PHP parse_url и http_build_query.

Конструктор принимает адрес, возьмем для примера адрес текущей страницы с некоторыми дополнениями:

$uri = new Uri("http://username:[email protected]/blog/post/work-with-http-bitrix-d7/?param1=value#comments");

Ниже перечислены примеры работы с этим адресом:

Timeweb

$uri->getLocator(); // "http://mrcappuccino.ru/blog/post/work-with-http-bitrix-d7/?param1=value"
$uri->getUri(); // "http://mrcappuccino.ru/blog/post/work-with-http-bitrix-d7/?param1=value#comments"
$uri->getHost(); // "mrcappuccino.ru"
$uri->getUser(); // "username"
$uri->getPass(); // "password"
$uri->getPath(); // "/blog/post/work-with-http-bitrix-d7/"
$uri->getPathQuery(); // "/blog/post/work-with-http-bitrix-d7/?param1=value"
$uri->getPort(); // 80
$uri->getQuery(); // "param1=value"
$uri->getScheme(); // "http"
$uri->deleteParams(array("param1"));
$uri->getUri(); // "http://mrcappuccino.ru/blog/post/work-with-http-bitrix-d7/#comments"
$uri->addParams(array("param2" => "value"));
$uri->getUri(); // "http://mrcappuccino.ru/blog/post/work-with-http-bitrix-d7/?param2=value#comments"

Сменив протокол на https, получим:

$uri = new Uri("https://mrcappuccino.ru/blog/post/work-with-http-bitrix-d7/");
$uri->getScheme(); // "https"
$uri->getPort(); // 443

Таким образом, получаем аналог CMain::GetCurPageParam из старого ядра и генератор URI для запросов:

$uri = new Uri("http://api.ru/");
$uri->addParams(array("token" => "89ud98gdfj78w", "data" => "ЙЦУКЕН ГШЩЗХЪ"));
var_dump($uri->getUri()); // string(113) "http://api.ru/?token=89ud98gdfj78w&data=%D0%99%D0%A6%D0%A3%D0%9A%D0%95%D0%9D+%D0%93%D0%A8%D0%A9%D0%97%D0%A5%D0%AA"

Bitrix\Main\Web\HttpClient

Класс HttpClient является реализацией HTTP-клиента в Битрикс D7, конструктор класса принимает необязательный массив опций:

// опции по умолчанию:
$options = array(
    "redirect" => true, // true, если нужно выполнять редиректы
    "redirectMax" => 5, // Максимальное количество редиректов
    "waitResponse" => true, // true - ждать ответа, false - отключаться после запроса
    "socketTimeout" => 30, // Таймаут соединения, сек
    "streamTimeout" => 60, // Таймаут чтения ответа, сек, 0 - без таймаута
    "version" => HttpClient::HTTP_1_0, // версия HTTP (HttpClient::HTTP_1_0 или HttpClient::HTTP_1_1)
    "proxyHost" => "", // адрес
    "proxyPort" => "", // порт
    "proxyUser" => "", // имя
    "proxyPassword" => "", // пароль
    "compress" => false, // true - принимать gzip (Accept-Encoding: gzip)
    "charset" => "", // Кодировка тела для POST и PUT
    "disableSslVerification" => false, // true - отключить проверку ssl (с 15.5.9)
);
$httpClient = new HttpClient($options);

Также опции можно установить сеттерами:

/** @param bool $followRedirects,  @param int $redirectMax(default null) */
$httpClient->setRedirect($followRedirects, $redirectMax = null);
/** @param bool $waitResponse */
$httpClient->waitResponse($waitResponse);
/** @param int $socketTimeout */
$httpClient->setTimeout($socketTimeout);
/** @param int $streamTimeout */
$httpClient->setStreamTimeout($streamTimeout);
/** @param string $version */
$httpClient->setVersion($version);
/** @param string $proxyHost, @param int $proxyPort(default null), @param string $proxyUser(default null), @param string $proxyPassword(default null) */
$httpClient->setProxy($proxyHost, $proxyPort = null, $proxyUser = null, $proxyPassword = null);
/** @param bool $compress */
$httpClient->setCompress($compress);
/** @param string $charset */
$httpClient->setCharset($charset);
$httpClient->disableSslVerification();

С версии 16.0.14 опции по умолчанию также можно менять в файле настроек в http_client_options.

// ...
'http_client_options' =>
    array (
        'value' =>
            array (
                'redirect' => true,
                'redirectMax' => 3,
                //...
            ),
        'readonly' => false,
    ),
// ...

Установить заголовки можно методом setHeader, третий аргумент $replace определяет нужно ли заменить заголовок (true, по умолчанию) или добавить еще с этим именем (false):

$name = "User-Agent";
$value = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A";
$httpClient->setHeader($name, $value, true);

Установить cookies для запроса можно методом setCookies, метод принимает массив имя => значение:

$cookies = array(
    "name" => "value",
);
$httpClient->setCookies($cookies);

Для установки имени и пароля для basic authorization нужно вызвать метод setAuthorization:

$httpClient->setAuthorization($user, $pass);

Для выполнения запроса используется метод query:

$httpClient->query($method, $url, $entityBody = null);

Аргумент $method - метод запроса: GET, POST и т.д., можно использовать константы класса: HttpClient::HTTP_GET, HttpClient::HTTP_POST, HttpClient::HTTP_PUT, HttpClient::HTTP_HEAD и HttpClient::HTTP_PATCH. В $entityBody передаём тело запроса.

Метод возвращает результат запроса - true или false. Чтобы получить информацию об ответе, можно использовать методы:

$httpClient->getResult(); // текст ответа
$httpClient->getStatus(); // код статуса ответа
$httpClient->getContentType(); // Content-Type ответа
$httpClient->getEffectiveUrl(); // реальный url ответа, т.е. после редиректов
$httpClient->getCookies(); // объект Bitrix\Main\Web\HttpCookies
$httpClient->getHeaders(); // объект Bitrix\Main\Web\HttpHeaders
$httpClient->getError(); // массив ошибок

У объектов Bitrix\Main\Web\HttpCookies и Bitrix\Main\Web\HttpHeaders есть метод toArray() для получения массива cookies и заголовков соответственно.

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

$httpClient->get($url); // Возвращает тело ответа
$httpClient->post($url, $postData); // Возвращает тело ответа
$httpClient->head($url); // Возвращает объект Bitrix\Main\Web\HttpHeaders

Также класс HttpClient позволяет скачивать файлы методом GET:

$httpClient->download('http://example.ru/file.pdf', Application::getDocumentRoot() . '/upload/example/document.pdf');

Про объект Application можно узнать из статьи Объекты Application и Context.