# HTTP API WordPress
В PHP есть несколько способов отправки HTTP-запросов, но в WordPress доступен только один. Этот единственный способ включает в себя все поддерживаемые PHP опции — это API, который является стандартом и удобен!
## Содержание
- Введение в HTTP API
- Функции HTTP API и отправка запросов
- Примеры использования WP HTTP API
- #1 Передача параметров запроса в GET и POST
- #2 Изменение параметров запроса
- #3 Получение тела ответа (наш любимый)
- #4 Получение заголовков ответа
- #5 Отладка: данные запроса
- #6 Получение кода ответа
- #7 Пользовательс��ий тип запроса
- #8 Получение данных о фильмах с КиноПоиск
- #9 Управление кэшированием
- #10 Хук: разрешить внутренние запросы с htpasswd
- #11 Пример использования прокси
- Сохранение результата запроса (кэширование)
- Кэширование в временных опциях (транзиенты)
- Удаление временной опции
- Кэширование в метаполях
- Коды ответа HTTP
## Введение в HTTP API
Для абсолютных новичков, давайте объясним, что такое HTTP-запрос. Это запрос от браузера к серверу, или от одного сервера к другому. Пример диалога такой:
1. Привет, сервер, можешь показать файл: file.html?
2. Привет! Могу, вот он...
При создании HTTP-запросов в PHP обычно используют одну из следующих опций: библиотеку cURL или встроенные потоки PHP. Чтобы упростить и стандартизировать различные способы отправки запросов, в WordPress с версии 2.7 появилась класс WP_Http, который стал основой HTTP API.
### Зачем нам HTTP API
Удобство и необходимость такого API связаны с тем, что разные хосты поддерживают разные способы отправки запросов, и некоторые не поддерживают никаких. Задача HTTP API — создать единый стандарт для использования запросов в WordPress и гарантировать их работу. Если один способ передачи запроса не поддерживается, будет найден альтернативный.
Также HTTP API упрощает разработку. Авторам плагинов нужно писать много кода и изобретать велосипеды, чтобы их плагины работали с любым хостом. С HTTP API эта задача сводится к нескольким встроенным функциям WordPress.
Кроме того, HTTP API предоставляет единый стандарт для указания данных при работе с разными типами передачи запросов. Например, мы всегда указываем одни и те же параметры и передаем их в функцию HTTP API. Класс уже выбирает подходящий тип транспорта, модифицирует наши параметры и отправляет запрос.
С версии 2.7 HTTP API работал только с основными элементами запроса: заголовком, телом и ответом. С версии 2.8 были добавлены:
- сжатие
- поддержка кук
- поддержка прокси
Некоторые функции работают автоматически, без настройки дополнительных параметров запроса.
### Библиотека запросов
С версии WP 4.6 HTTP API работает на основе библиотеки Requests, которая разрабатывается и поддерживается WordPress.
Таким образом, основной класс WP_Http был полностью заменён библиотекой PHP Requests, и теперь все запросы выполняются через него.
HTTP API WordPress сегодня — это полноценный API, �� котором учтено множество деталей и исправлено сотни ошибок. Стоит отметить, что до версии WP 4.4 HTTP API значительно отличался от того, что есть сейчас, поэтому некоторые моменты из этого руководства могут не работать в версиях до 4.4.
Практически все возможности транспорта можно изменять через опции или фильтры. Например, с помощью фильтра http_api_transports
можно добавить свой класс транспорта.
## Функции HTTP API и отправка запросов
Использовать HTTP API очень просто, есть специальные функции:
### Функции отправки запросов:
- wp_remote_get( $url, $args )
— отправляет HTTP GET запрос.
- wp_remote_post( $url, $args )
— отправляет HTTP POST запрос.
- wp_remote_head( $url, $args )
— отправляет HTTP HEAD запрос.
- wp_get_http_headers( $url )
— получает только HTTP заголовки указанного URL.
- wp_remote_request( $url, $args )
— отправляет запрос любого типа: GET, POST, HEAD, PUT, DELETE.
- wp_safe_remote_request( $url, $args )
— аналогично wp_remote_request()
, но избегает небезопасных редиректов и перенаправлений.
Все функции возвращают: массив или WP_Error. Если запрос успешен, возвращается массив с данными ответа. Если возникает ошибка, возвращается WP_Error.
### Функции обработки ответа:
- wp_remote_retrieve_body( $response )
— получает только тело ответа.
- wp_remote_retrieve_headers( $response )
— получает весь массив заголовков ответа.
- wp_remote_retrieve_header( $response, $header )
— получает один заголовок; $header
— это имя заголовка.
- wp_remote_retrieve_response_code( $response )
— получает код HTTP ответа (статус ответа).
- wp_remote_retrieve_response_message( $response )
— получает сообщение ответа, соответствующее коду ответа.
- wp_remote_retrieve_cookies( $response )
— получает все куки ответа.
- wp_remote_retrieve_cookie( $response, $name )
— получает все данные указанного куки, где $name
— это имя куки.
- wp_remote_retrieve_cookie_value( $response, $name )
— получает значение указанного куки.
### Параметры функции
$url
(строка) (обязательный) — URL, на который будет отправлен запрос.
$args
(массив) — параметры запроса. Смотрите описание wp_remote_request()
для списка параметров.
$response
(массив) — результат запроса, возвращаемый любой функцией запроса.
### Простой пример использования
Теперь, когда мы знаем все функции запроса, давайте попробуем создать простой запрос.
```php
$response = wp_remote_get('http://httpbin.org/get?a=b&c=d');
Здесь мы отправили запрос на URL: http://httpbin.org/get
и добавили два параметра запроса. В результате $response
будет содержать следующий массив:
Array (
[headers] => Array (
[server] => nginx
[date] => Sun, 19 Jun 2016 08:18:20 GMT
[content-type] => application/json
[content-length] => 316
[connection] => close
[access-control-allow-origin] => *
[access-control-allow-credentials] => true
)
[body] => {
"args": {
"a": "b",
"c": "d"
},
// Остальные данные
}
[response] => Array (
=> 200
[message] => OK
)
[cookies] => Array()
[filename] =>
[http_response] => WP_HTTP_Requests_Response Object (
// ...
)
)
Каждый элемент ответа можно получить, выбрав его из массива. Например, чтобы получить заголовки ответа:
$response = wp_remote_get('http://httpbin.org/get?a=b&c=d');
$headers = $response['headers'];
echo $headers['server']; // nginx
echo $headers['content-type']; // application/json
echo $headers['content-length']; // 316
Однако рекомендуется использовать специальные функции для получения частей ответа, чтобы избежать ошибок.
Примеры использования WP HTTP API
1 Передача параметров запроса в GET и POST
Для GET-запроса параметры передаются непосредственно в URL:
$url = 'http://httpbin.org/get';
$params = array(
'foo' => 'значение 1',
'bar' => 10
);
$params = urlencode_deep($params);
$url = add_query_arg($params, $url);
$response = wp_remote_get($url);
$body = wp_remote_retrieve_body($response);
print_r($body);
Для POST-запроса параметры передаются в теле:
$url = 'http://httpbin.org/post';
$args = [
'body' => [
'foo' => 'значение 1',
'bar' => 10,
],
'timeout' => '5',
];
$response = wp_remote_post($url, $args);
2 Изменение параметров запроса
Перед отправкой запроса можно изменить настройки по умолчанию:
$url = 'http://httpbin.org/get';
$args = array(
'timeout' => 5, // Время в секундах ожидания ответа
'user-agent' => 'Mozilla/5.0',
);
$response = wp_remote_get($url, $args);
3 Получение тела ответа
Как передать заголовок в запросе и получить тело ответа:
$url = 'http://httpbin.org/get?a=b&c=d';
$args = array(
'headers' => array( "Content-type" => "application/json" )
);
$response = wp_remote_get($url, $args);
$body = wp_remote_retrieve_body($response);
4 Получение заголовков ответа
1. Полный запрос и получение только заголовков
$response = wp_remote_get('http://httpbin.org/get?a=b&c=d');
$response_headers = wp_remote_retrieve_headers($response);
$content_type = wp_remote_retrieve_header($response, 'content-type');
2. Запрос только заголовков
$response = wp_remote_head('http://httpbin.org/get?a=b&c=d');
$response_headers = wp_remote_retrieve_headers($response);
5 Отладка: данные запроса
Добавьте следующий код, чтобы отладить запросы:
add_action('http_api_debug', function($response, $type, $class, $args, $url) {
echo sprintf("Запрос URL: %sn", print_r($url, 1));
echo sprintf("Параметры запроса: %sn", print_r($args, 1));
echo sprintf("Ответ запроса: %sn", print_r($response, 1));
}, 10, 5);
6 Получение кода ответа
$response = wp_remote_get('http://httpbin.org/get?a=b&c=d');
echo wp_remote_retrieve_response_code($response); // 200
echo wp_remote_retrieve_response_message($response); // OK
7 Пользовательский тип запроса
Вы можете отправлять запросы других типов, например PUT или DELETE:
$url = 'http://httpbin.org';
$args = array(
'method' => 'PUT',
);
$response = wp_remote_request($url, $args);
8 Получение данных о фильмах с КиноПоиск
Пример функции для получения информации о фильме:
function kinopoisk_get_movie($id) {
$params = array('filmID' => absint($id));
$url = 'http://api.kinopoisk.cf/getFilm';
$url = add_query_arg($params, esc_url_raw($url));
$response = wp_remote_get($url);
$response_code = wp_remote_retrieve_response_code($response);
$response_message = wp_remote_retrieve_response_message($response);
$response_body = json_decode(wp_remote_retrieve_body($response));
if (200 != $response_code) {
return new WP_Error($response_code, $response_message);
}
return $response_body;
}
9 Управление кэшированием
Чтобы управлять кэшированием, нужно указать заголовок Cache-Control
:
$readme_url = 'http://example.com/foo';
$http_params = [
'headers' => [
'Authorization' => "token $auth_token",
'Cache-Control' => 'no-cache',
],
];
$res = wp_remote_get($readme_url, $http_params);
10 Хук: разрешить внутренние запросы с Htpasswd
Если на сервере установлена защита с использованием .htpasswd:
if ('production' !== wp_get_environment_type()) {
add_filter('http_request_args', function($parsed_args, $url) {
if (str_contains($url, parse_url(home_url(), PHP_URL_HOST))) {
$log_pass = 'логин:пароль';
$auth = &$parsed_args['headers']['Authorization'];
if (!$auth) {
$auth = 'Basic ' . base64_encode($log_pass);
}
}
return $parsed_args;
}, 10, 2);
}
11 Пример использования прокси
Для работы с прокси:
$proxy = '180.168.232.64:8001';
$proxyauth = 'k7yQJa:R9Cdeu';
$url = 'https://example.com';
[$host, $port] = explode(':', $proxy);
[$log, $pass] = explode(':', $proxyauth);
define('WP_PROXY_HOST', $host);
define('WP_PROXY_PORT', $port);
define('WP_PROXY_USERNAME', $log);
define('WP_PROXY_PASSWORD', $pass);
$resp = wp_remote_get($url);
$headers = wp_remote_retrieve_headers($resp);
$code = wp_remote_retrieve_response_code($resp);
$body = wp_remote_retrieve_body($resp);
var_dump($code);
print_r($headers);
echo $body;
После этого мы можем использовать кэширование результатов запросов.
Кэширование в временных опциях (транзиенты)
Чтобы кэшировать результаты HTTP-запросов, используйте функции WordPress:
set_transient( $transient, $value, $expiration )
— устанавливает/обновляет временную опцию.get_transient( $transient )
— получает значение временной опции.delete_transient( $transient )
— удаляет временную опцию.
Пример кэширования HTTP-запроса в временной опции
$transient = 'курс_usd'; // название временной опции
$usd_in_rub = get_transient($transient);
if (!$usd_in_rub) {
$url = 'http://www.cbr.ru/scripts/XML_daily.asp';
$expiration = DAY_IN_SECONDS / 2; // срок кэширования - полдня
$resp = wp_remote_get($url); // получить данные
if (wp_remote_retrieve_response_code($resp) === 200) {
// Обработать ответ
$body = wp_remote_retrieve_body($resp);
$usd_in_rub = // обработка данных...
}
set_transient($transient, $usd_in_rub, $expiration);
}
echo 'Курс доллара к рублю сегодня: $1 = ' . $usd_in_rub . ' руб.';
Удаление временной опции
Если временная опция больше не требуется, её можно удалить:
delete_transient('имя_временной_опции');
Кэширование в метаполях
Для более целесообразного кэширования используйте метаполя для хранения данных, например, при получении рейтинга фильмов с КиноПоиск.
function get_film_rating($post_id = 0) {
if (!$post_id) $post_id = $GLOBALS['post']->ID;
$rating = get_post_meta($post_id, 'kinopoisk_rating', true);
$up_time = get_post_meta($post_id, 'kinopoisk_rating_uptime', true);
if (time() > $up_time + WEEK_IN_SECONDS) {
$film_id = get_post_meta($post_id, 'kinopoisk_id', true);
$res = kinopoisk_get_movie($film_id);
if (!is_wp_error($res) && $res->ratingData->rating)
$rating = $res->ratingData->rating;
else
$rating = '-1';
update_post_meta($post_id, 'kinopoisk_rating_uptime', time());
update_post_meta($post_id, 'kinopoisk_rating', $rating);
}
return $rating;
}
echo get_film_rating();
Коды ответа HTTP
Стандартные коды состояния HTTP и ответы на них:
$phrases = [
200 => 'OK',
404 => 'Not Found',
500 => 'Internal Server Error',
// И другие...
];
Такой список поможет быстро разобраться с ответами сервера.