Почему не работает мой кастомный API эндпоинт?

10 апр. 2019 г., 17:30:12
Просмотры: 18.3K
Голосов: 6

Я попытался добавить этот код в файлы моего плагина, а также в 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):

Думаю, я что-то упускаю.

3
Комментарии

Конечные точки REST API находятся по адресу /wp-json, использование plugin_dir_url при регистрации конечных точек является крайне необычным, я настоятельно не рекомендую размещать URL конечных точек REST в папке плагинов (в основном потому, что API так не работает, такие URL просто невозможны)

Tom J Nowell Tom J Nowell
10 апр. 2019 г. 18:07:53

@TomJNowell – Видишь, почему этот вопрос получил так много просмотров за такое короткое время? Мне стоит задать этот вопрос на Meta?

norman.lol norman.lol
11 апр. 2019 г. 00:40:59

Задать на meta — хорошая идея, хотя я не уверен, как мы можем видеть количество просмотров. Возможно, твой вопрос просто был хорошо написан и стал популярным? :)

Tom J Nowell Tom J Nowell
11 апр. 2019 г. 12:20:13
Все ответы на вопрос 3
3

Вот ваша проблема:

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).

10 апр. 2019 г. 18:19:18
Комментарии

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

TTT TTT
10 апр. 2019 г. 18:25:42

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

Tom J Nowell Tom J Nowell
10 апр. 2019 г. 20:21:00

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

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

TTT TTT
10 апр. 2019 г. 20:42:32
6

Возможно, стоит начать просто с 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
10 апр. 2019 г. 17:36:51
Комментарии

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

TTT TTT
10 апр. 2019 г. 18:02:18

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

norman.lol norman.lol
10 апр. 2019 г. 18:12:34

Спасибо, это сработало. Поскольку ответ содержится в комментарии, я не уверен, стоит ли сразу отмечать его как решение.

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

TTT TTT
10 апр. 2019 г. 18:17:23

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

Tom J Nowell Tom J Nowell
10 апр. 2019 г. 18:20:00

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

TTT TTT
10 апр. 2019 г. 19:01:03

@TTT – О, отлично! Спасибо, что поделился. Добавил в закладки.

norman.lol norman.lol
10 апр. 2019 г. 19:27:59
Показать остальные 1 комментариев
0

В моем случае просто добавьте 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);
}
5 июн. 2023 г. 20:58:52