Perché il mio endpoint API personalizzato non funziona?

10 apr 2019, 17:30:12
Visualizzazioni: 18.3K
Voti: 6

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)

Credo che mi stia sfuggendo qualcosa.

3
Commenti

Gli endpoint della REST API si trovano in /wp-json, includere plugin_dir_url nella registrazione del tuo endpoint è estremamente insolito, consiglio vivamente di evitare URL di endpoint REST nella cartella dei plugin (principalmente perché non è così che funziona l'API, non puoi avere quel tipo di URL)

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

@TomJNowell – Riesci a capire perché questa domanda ha ottenuto così tante visualizzazioni in così poco tempo? Dovrei chiederlo su Meta?

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

chiedere su meta è una buona idea, non sono sicuro di come possiamo vedere le visualizzazioni però. Forse la tua domanda era ben scritta e popolare? :)

Tom J Nowell Tom J Nowell
11 apr 2019 12:20:13
Tutte le risposte alla domanda 3
3

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 con GET o POST

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)

10 apr 2019 18:19:18
Commenti

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

TTT TTT
10 apr 2019 18:25:42

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

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

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.

TTT TTT
10 apr 2019 20:42:32
6

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
10 apr 2019 17:36:51
Commenti

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 TTT
10 apr 2019 18:02:18

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

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

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 TTT
10 apr 2019 18:17:23

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

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

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

TTT TTT
10 apr 2019 19:01:03

@TTT – Uh ottimo! Grazie per la condivisione. Aggiunto ai preferiti.

norman.lol norman.lol
10 apr 2019 19:27:59
Mostra i restanti 1 commenti
0

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);
}
5 giu 2023 20:58:52