Perché il mio endpoint API personalizzato non funziona?
Ho provato a includere questo codice nei file php del mio plugin così come in functions.php
.
(Alla fine vorrei che fosse nel file php del plugin ma non sono ancora sicuro se sia possibile, probabilmente sarà l'argomento di un'altra domanda.)
Per ora è un metodo molto basilare, sto solo cercando di ottenere una risposta con qualche contenuto.
In entrambi i casi, ottengo una risposta 404.
add_action( 'rest_api_init', function () {
// Registra la rotta API personalizzata
register_rest_route( plugin_dir_url(__DIR__).'my-project/api/v1/form', '/action', array(
'methods' => 'GET, POST',
'callback' => 'api_method',
) );
});
// Funzione di callback per l'endpoint API
function api_method($data) {
var_dump($data);
return 'Fine del metodo API.';
}
E ho provato ad accedere agli URL (nel browser o con 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/
Credo che mi stia sfuggendo qualcosa.
Ecco il tuo problema:
register_rest_route( plugin_dir_url(__DIR__).'my-project/api/v1/form', '/action', array(
Nello specifico, l'idea che questo sia possibile:
http://my-domain.local/wp-content/plugins/my-project/api/v1/form
Questo è estremamente insolito e va contro quanto riportato nella documentazione, manuali e tutorial.
Gli endpoint dell'API REST risiedono nell'API REST, che si trova all'URL restituito da rest_url()
. Risiedono in tuosito.com/wp-json
. Un endpoint non è un percorso URL completo, né un'API indipendente disconnessa dall'API principale.
Invece, devi definire i nomi dei tuoi endpoint in termini di namespace ed endpoint, e visitare l'URL corretto come descritto nei meccanismi di scoperta dell'API REST.
Se usiamo questo:
register_rest_route( plugin_dir_url(__DIR__).'my-project/api/v1/form', '/action', array(
Allora ci aspetteremmo questo:
example.com/wp-json/wp-content/plugins/my-project/api/v1/form/action
Questo URL è piuttosto lungo e presenta diversi problemi:
- Il primo parametro è un namespace, non un URL
- non è possibile separare correttamente la versione v1 dell'API dalla v2 a causa del modo in cui il componente
/form
è stato inserito nel primo parametro, non nel secondo. Il primo parametro è un namespace, il secondo una route /action
è/action
, non viene sostituito conGET
oPOST
Ci sono anche problemi con la funzione di callback:
function api_method($data) {
var_dump($data);
Un endpoint deve restituire i suoi dati, non può emetterli direttamente come farebbe var_dump
, altrimenti i dati restituiti non saranno JSON validi.
Infine, il parametro dei metodi è incorretto:
'methods' => 'GET, POST',
methods
non accetta un elenco separato da virgole, nessuna documentazione suggerisce di fare ciò. Invece, usa i valori predefiniti forniti dall'API REST come WP_REST_Server::READABLE
o WP_REST_Server::ALLMETHODS
, tutti menzionati nel manuale e nella documentazione ufficiale di register_rest_route
.
Una route migliore da registrare sarebbe:
register_rest_route( 'my-project/form/v1', '/action', array(
Che ci dà:
example.com/wp-json/my-project/form/v1/action
Nota come ho rimosso l'URL del plugin e il frammento ridondante /api
(è già ovvio che si tratta di un'API)

Grazie per la spiegazione dettagliata. Ho già selezionato come soluzione una risposta arrivata più rapidamente però.

Puoi cambiare idea su quale risposta sia la migliore, ma in ogni caso considera il sito come un wiki, può esserci più di una buona risposta

Un motivo per cui non voglio cambiare risposta è che ho testato e applicato concretamente la soluzione che ho selezionato. La tua risposta ha portato maggiori dettagli e ha corretto alcune mie idee sbagliate, ma non l'ho testata e verificata completamente.
Penso inoltre che nella maggior parte dei siti StackExchange, le prime buone risposte vengono selezionate, mentre quelle successive ricevono voti. Anche se questo mi lascia un po' perplesso, non vedo motivo di togliere il riconoscimento di soluzione alla persona che ha risposto per prima.

Forse inizia solo con GET
. Anche la tua route sembra strana. Prova semplicemente:
register_rest_route('my-project/v1', '/action/', [
'methods' => WP_REST_Server::READABLE,
'callback' => 'api_method',
]);
E la tua callback non restituisce una risposta valida. Fai in modo che la tua callback sia più simile a questa:
$data = [ 'foo' => 'bar' ];
$response = new WP_REST_Response($data, 200);
// Imposta gli header.
$response->set_headers([ 'Cache-Control' => 'must-revalidate, no-cache, no-store, private' ]);
return $response;
Infine devi combinare wp-json
, il namespace my-project/v1
e la tua route action
nell'URL che ora puoi controllare per vedere cosa ottieni:
https://my-domain.local/wp-json/my-project/v1/action

Ho semplicemente seguito il tuo suggerimento, ho provato http://my-domain.local/my-project/v1/ , http://my-domain.local/my-project/v1/get/ (con e senza slash finali), ma continuo a ricevere una risposta 404. Al momento, il codice è in functions.php.

@TTT – Deve essere https://my-domain.local/wp-json/my-project/v1/action come hai specificato /action/
per essere la tua route.

Grazie, questo ha funzionato. Beh, visto che la risposta è nei commenti, non sono sicuro se dovrei segnare subito la risposta come soluzione.
Inoltre, posso fare in modo che restituisca qualcosa di diverso dal JSON, giusto? (Non intendo come XML, ma codice HTML processato da php.) ... Allora l'URL conterrebbe ancora "wp-json". Strano... o c'è un altro tipo di API?

@TTT puoi memorizzare HTML in JSON come stringa e poi decodificare JSON nel browser

Ho appena trovato e testato questo metodo che sembra più pulito rispetto a includere HTML in JSON: https://gist.github.com/petenelson/6dc1a405a6e7627b4834

Nel mio caso, basta aggiungere wp-json all'URL del mittente del webhook, che risulterà in
https://my-domain.local/wp-json/my-plugin/v1/action
e nel mio functions.php queste righe di codice funzionano
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) {
// Elabora la richiesta del webhook
$data = $request->get_body(); // Ottieni il corpo della richiesta
// Esegui azioni in base ai dati del webhook ricevuti
// Restituisci una risposta se necessario
return new WP_REST_Response('Webhook ricevuto.', 200);
}
