Почему не работает мой кастомный API эндпоинт?
Я попытался добавить этот код в файлы моего плагина, а также в functions.php
.
(В конечном итоге я хочу, чтобы это было в файле плагина, но пока не уверен, возможно ли это - это будет темой другого вопроса.)
Пока это очень базовый метод, я просто пытаюсь получить ответ с каким-либо содержимым.
В обоих случаях я получаю ответ 404.
add_action( 'rest_api_init', function () {
// Регистрируем кастомный маршрут для REST API
register_rest_route( plugin_dir_url(__DIR__).'my-project/api/v1/form', '/action', array(
'methods' => 'GET, POST', // Разрешенные HTTP методы
'callback' => 'api_method', // Функция-обработчик
) );
});
function api_method($data) {
var_dump($data); // Выводим полученные данные
return 'Конец метода API.'; // Возвращаем строку
}
И я пробовал обращаться по URL (в браузере или через AJAX):
- http://my-domain.local/wp-content/plugins/my-project/api/v1/form
- http://my-domain.local/wp-content/plugins/my-project/api/v1/form/
- http://my-domain.local/wp-content/plugins/my-project/api/v1/form/get
- http://my-domain.local/wp-content/plugins/my-project/api/v1/form/get/
Думаю, я что-то упускаю.

Вот ваша проблема:
register_rest_route( plugin_dir_url(__DIR__).'my-project/api/v1/form', '/action', array(
Конкретно, идея о том, что это возможно:
http://my-domain.local/wp-content/plugins/my-project/api/v1/form
Это крайне необычно и противоречит документации, руководствам и учебным материалам.
Конечные точки REST API находятся в REST API, который располагается по URL, возвращаемому функцией rest_url()
. Они находятся по адресу yoursite.com/wp-json
. Конечная точка — это не полный URL-путь и не независимый API, отключенный от основного API.
Вместо этого вам нужно определить имена конечных точек в терминах пространств имен и конечных точек и переходить по правильному URL, как описано в механизмах обнаружения REST API.
Если мы используем это:
register_rest_route( plugin_dir_url(__DIR__).'my-project/api/v1/form', '/action', array(
То мы ожидаем это:
example.com/wp-json/wp-content/plugins/my-project/api/v1/form/action
Этот URL довольно длинный и имеет ряд проблем:
- Первый параметр — это пространство имен, а не URL
- невозможно правильно отделить версию v1 API от v2 из-за того, что компонент
/form
был помещен в первый параметр, а не во второй. Первый параметр — это пространство имен, второй — маршрут /action
— это/action
, он не заменяется наGET
илиPOST
Также есть проблемы с функцией обратного вызова:
function api_method($data) {
var_dump($data);
Конечная точка должна возвращать данные, а не выводить их напрямую, как это делает var_dump
, иначе возвращаемые данные будут недействительным JSON.
Наконец, параметр методов указан неверно:
'methods' => 'GET, POST',
Параметр methods
не принимает список, разделенный запятыми, и ни в одной документации это не предлагается. Вместо этого используйте предопределенные значения, предоставляемые REST API, такие как WP_REST_Server::READABLE
или WP_REST_Server::ALLMETHODS
, все они упоминаются в руководстве и официальной документации для register_rest_route
.
Лучшим вариантом для регистрации маршрута будет:
register_rest_route( 'my-project/form/v1', '/action', array(
Что дает нам:
example.com/wp-json/my-project/form/v1/action
Обратите внимание, как я удалил URL плагина и избыточный фрагмент /api
(и так очевидно, что это API).

Спасибо за подробное объяснение. Однако я уже отметил как решение ответ, который пришел быстрее.

Вы можете передумать о том, какой ответ лучший, но в любом случае думайте о сайте как о вики - может быть больше одного хорошего ответа

Одна из причин, по которой я не хочу менять ответ, заключается в том, что я конкретно протестировал и применил ответ, который выбрал в качестве решения. Ваш ответ дал больше деталей и исправил некоторые мои ошибочные представления, но я буквально не тестировал и не проверял его полностью.
Я также считаю, что на большинстве сайтов StackExchange первые хорошие ответы выбираются как решения, а следующие получают голоса. И хотя это заставляет меня немного почесать голову, я не вижу причин лишать награды за решение человека, который решил проблему первым.

Возможно, стоит начать просто с GET
. Ваш роут также выглядит странно. Попробуйте так:
register_rest_route('my-project/v1', '/action/', [
'methods' => WP_REST_Server::READABLE,
'callback' => 'api_method',
]);
И ваш callback не возвращает корректный ответ. Пусть ваш callback выглядит примерно так:
$data = [ 'foo' => 'bar' ];
$response = new WP_REST_Response($data, 200);
// Установка заголовков.
$response->set_headers([ 'Cache-Control' => 'must-revalidate, no-cache, no-store, private' ]);
return $response;
Наконец, вы должны объединить wp-json
, пространство имен my-project/v1
и ваш роут action
в URL, который теперь можно проверить на предмет получаемых данных:
https://my-domain.local/wp-json/my-project/v1/action

Я просто последовал вашему совету, попробовал http://my-domain.local/my-project/v1/, http://my-domain.local/my-project/v1/get/ (с конечным слэшем и без), но всё равно получаю ответ 404. На данный момент код находится в functions.php.

@TTT – Должно быть https://my-domain.local/wp-json/my-project/v1/action, так как вы указали /action/
в качестве своего роута.

Спасибо, это сработало. Поскольку ответ содержится в комментарии, я не уверен, стоит ли сразу отмечать его как решение.
Также, могу ли я сделать так, чтобы возвращалось что-то другое вместо JSON? (Я имею в виду не XML, а обработанный PHP HTML-код.) ... Но тогда URL всё равно будет содержать "wp-json". Странно... или существует другой тип API?

@TTT вы можете хранить HTML в JSON в виде строки, а затем декодировать JSON в браузере

Я только что нашел и протестировал этот способ, который выглядит чище, чем включение HTML в JSON: https://gist.github.com/petenelson/6dc1a405a6e7627b4834

В моем случае просто добавьте wp-json в URL отправителя вебхука, что даст в результате
https://my-domain.local/wp-json/my-plugin/v1/action
и в моем functions.php эти строки кода работают
add_action('rest_api_init', 'register_webhook_endpoint');
function register_webhook_endpoint() {
register_rest_route('my-plugin/v1', '/action', array(
'methods' => 'POST',
'callback' => 'handle_webhook_request',
));
}
function handle_webhook_request(WP_REST_Request $request) {
// Обработка запроса вебхука
$data = $request->get_body(); // Получение тела запроса
// Выполнение действий на основе полученных данных вебхука
// Возврат ответа, если необходимо
return new WP_REST_Response('Вебхук получен.', 200);
}
