¿Por qué no funciona mi endpoint API personalizado?

10 abr 2019, 17:30:12
Vistas: 18.3K
Votos: 6

Intenté incluir este código en los archivos PHP de mi plugin así como en functions.php. (Al final me gustaría que estuviera en el archivo PHP del plugin pero no estoy seguro si es posible, eso probablemente sería tema para otra pregunta).

Es un método muy básico por ahora, solo estoy tratando de obtener una respuesta con algún contenido.

En ambos casos, obtengo una respuesta 404.

add_action( 'rest_api_init', function () {
  register_rest_route( plugin_dir_url(__DIR__).'my-project/api/v1/form', '/action', array(
    'methods' => 'GET, POST',
    'callback' => 'api_method',
  ) );
});

function api_method($data) {
    var_dump($data);
    return 'API method end.';
}

Y probé acceder a las URLs (en el navegador o con AJAX)

Supongo que me estoy perdiendo algo.

3
Comentarios

Los endpoints de la API REST se encuentran en /wp-json, incluir plugin_dir_url en el registro de tu endpoint es extremadamente inusual, recomendaría encarecidamente no usar URLs de endpoints REST en la carpeta de plugins (principalmente porque así no es como funciona la API, no puedes tener ese tipo de URLs)

Tom J Nowell Tom J Nowell
10 abr 2019 18:07:53

@TomJNowell – ¿Puedes ver por qué esta pregunta tuvo tantas visitas en tan poco tiempo? ¿Debería preguntar esto en Meta?

norman.lol norman.lol
11 abr 2019 00:40:59

Preguntar en meta es una buena idea, no estoy seguro de cómo podemos ver las visitas. ¿Quizás tu pregunta estaba bien escrita y fue popular? :)

Tom J Nowell Tom J Nowell
11 abr 2019 12:20:13
Todas las respuestas a la pregunta 3
3

Aquí está tu problema:

register_rest_route( plugin_dir_url(__DIR__).'my-project/api/v1/form', '/action', array(

Específicamente, la idea de que esto sea posible:

http://my-domain.local/wp-content/plugins/my-project/api/v1/form

Esto es extremadamente inusual y va en contra de lo que dicen los documentos, el manual y los tutoriales.

Los endpoints de la API REST viven en la API REST, que reside en la URL devuelta por rest_url(). Viven en tusitio.com/wp-json. Un endpoint no es una ruta URL completa, ni una API independiente desconectada de la API principal.

En su lugar, debes definir tus nombres de endpoints en términos de espacios de nombres y endpoints, y visitar la URL correcta como se describe en los mecanismos de descubrimiento de la API REST.

Si usamos esto:

register_rest_route( plugin_dir_url(__DIR__).'my-project/api/v1/form', '/action', array(

Entonces esperaríamos esto:

example.com/wp-json/wp-content/plugins/my-project/api/v1/form/action

Esa URL es bastante larga y tiene varios problemas:

  • El primer parámetro es un espacio de nombres, no una URL
  • No es posible separar correctamente la versión v1 de la API de la v2 debido a que el componente /form se ha colocado en el primer parámetro, no en el segundo. El primer parámetro es un espacio de nombres, el segundo una ruta.
  • /action es /action, no se intercambia por GET o POST

También hay problemas con la función de callback:

function api_method($data) {
    var_dump($data);

Un endpoint necesita devolver sus datos, no puede mostrarlos directamente como lo haría var_dump, de lo contrario los datos devueltos no son JSON válido.

Finalmente, el parámetro de métodos es incorrecto:

'methods' => 'GET, POST',

methods no toma una lista separada por comas, ningún documento sugiere hacer esto tampoco. En su lugar, usa los valores predefinidos proporcionados por la API REST como WP_REST_Server::READABLE o WP_REST_Server::ALLMETHODS, todos mencionados en el manual y la documentación oficial de register_rest_route.

Una mejor ruta para registrar sería:

    register_rest_route( 'my-project/form/v1', '/action', array(

Dándonos:

example.com/wp-json/my-project/form/v1/action

Observa cómo eliminé la URL del plugin y el fragmento redundante /api (ya es obvio que es una API).

10 abr 2019 18:19:18
Comentarios

Gracias por la explicación detallada. Sin embargo, ya he marcado como solución una respuesta que llegó más rápido.

TTT TTT
10 abr 2019 18:25:42

Puedes cambiar de opinión sobre qué respuesta es la mejor, pero de cualquier manera piensa en el sitio como un wiki, puede haber más de una buena respuesta

Tom J Nowell Tom J Nowell
10 abr 2019 20:21:00

Una razón por la que no quiero cambiar la respuesta es que he probado y aplicado concretamente la respuesta que seleccioné como solución. Tu respuesta aportó más detalles y aclaró cosas en las que de alguna manera estaba equivocado, pero no lo he probado y verificado todo literalmente.

También creo que en la mayoría de los sitios StackExchange, las primeras buenas respuestas son seleccionadas, las siguientes obtienen votos. Y aunque esto me hace rascarme un poco la cabeza, no veo razón para quitarle la recompensa de solución a la persona que lo resolvió primero.

TTT TTT
10 abr 2019 20:42:32
6

Quizás deberías comenzar solo con GET. Tu ruta también se ve extraña. Prueba con:

register_rest_route('my-project/v1', '/action/', [
  'methods'  => WP_REST_Server::READABLE,
  'callback' => 'api_method',
]);

Y tu callback no está devolviendo una respuesta válida. Haz que tu callback se vea más así:

$data = [ 'foo' => 'bar' ];

$response = new WP_REST_Response($data, 200);

// Configurar cabeceras
$response->set_headers([ 'Cache-Control' => 'must-revalidate, no-cache, no-store, private' ]);

return $response;

Finalmente debes combinar wp-json, el namespace my-project/v1 y tu ruta action para obtener la URL que ahora puedes verificar:

 https://my-domain.local/wp-json/my-project/v1/action
10 abr 2019 17:36:51
Comentarios

Acabo de seguir lo que sugeriste, probé http://my-domain.local/my-project/v1/ , http://my-domain.local/my-project/v1/get/ (con y sin barras al final), pero sigo recibiendo una respuesta 404. Por el momento, el código está en functions.php.

TTT TTT
10 abr 2019 18:02:18

@TTT – Debe ser https://my-domain.local/wp-json/my-project/v1/action como has especificado /action/ para ser tu ruta.

norman.lol norman.lol
10 abr 2019 18:12:34

Gracias, esto funcionó. Bueno, dado que la respuesta está en el comentario, no estoy seguro si debería marcar la respuesta como solución inmediatamente.

Además, ¿puedo hacer que esto devuelva algo diferente a JSON, cierto? (No me refiero a XML, sino a código HTML procesado por php.) ... Entonces la URL aún contendría "wp-json". Raro... ¿o hay otro tipo de API?

TTT TTT
10 abr 2019 18:17:23

@TTT puedes almacenar HTML en JSON como una cadena y luego decodificar el JSON en el navegador

Tom J Nowell Tom J Nowell
10 abr 2019 18:20:00

Acabo de encontrar y probar esta forma que parece más limpia que incluir HTML en JSON: https://gist.github.com/petenelson/6dc1a405a6e7627b4834

TTT TTT
10 abr 2019 19:01:03

@TTT – ¡Oh, genial! Gracias por compartir. Guardado en favoritos.

norman.lol norman.lol
10 abr 2019 19:27:59
Mostrar los 1 comentarios restantes
0

En mi caso, simplemente añado wp-json en la URL del webhook emisor, lo que resultará en

https://mi-dominio.local/wp-json/mi-plugin/v1/accion

y en mi archivo functions.php estas líneas de código funcionan

add_action('rest_api_init', 'registrar_endpoint_webhook');

function registrar_endpoint_webhook() {
  register_rest_route('mi-plugin/v1', '/accion', array(
    'methods' => 'POST',
    'callback' => 'manejar_solicitud_webhook',
  ));
}

function manejar_solicitud_webhook(WP_REST_Request $request) {
  // Procesar la solicitud del webhook
  $data = $request->get_body(); // Obtener el cuerpo de la solicitud
  // Realizar acciones basadas en los datos del webhook recibido

  // Devolver una respuesta si es necesario
  return new WP_REST_Response('Webhook recibido.', 200);
}
5 jun 2023 20:58:52