Precisazione importante
In un sistema in produzione (serebbe a dire in uno che funziona on-line per utenti reali) la scelta migliore è usare una libreria che aiuta a gestire webservices e ne esistono per diversi linguaggi! Qui creiamo come esempio un file unico senza dipendenze (sarebbe a dire librerie di scaricate da qualche parte su internet) per capire come funziona il gioco.
Il servizio che andiamo a scrivere usa HTTP (cosa che succede usualmente) e quindi tutte le strutture che ci mette a disposizione, non serve inventarsi un meccanismo per specificare come rappresentiamo i dati: ci sono gli header. Non serve di pensare a come comunicare se le cose sono andate bene o male: ci sono già i codici di riposta di HTTP, per sapere cosa fare basta leggere l'azione (es: GET o DELETE) che ci è stata richiesta via HTTP. Quello che ci accingiamo a fare è semplicemente "mettere insieme i pezzi".
PHP
Scegliamo di utilizzare questo linguaggio che ci permette di scrivere programmi (o script che dir si voglia) lato server che girano su server HTTP (come quello di Apache), ovviamente è possibile fare un lavoro analogo con molti altri diversi.
Cosa vuoi?
Per sapere quale è l'azione richiesta dal client non c'è una funzione specifica ma un elemento della superglobal
$_SERVER
:
$_SERVER['REQUEST_METHOD']
che potrebbe ad esempio essere "GET".
Di quale risorsa stiamo parlando
Di nuovo la superglobal $_SERVER
e in particolare il suo elemento REQUEST_URI.
Informazioni per svolgere l'azione?
Per sapere invece quali sono i dati di input possiamo usare le due superglobal $_GET o $_POST a seconda del metodo usato per la richiesta.
In quale formato?
A voler essere proprio precisi potremmo anche rispondere al client in base alle sue esigenze cioè ad esempio alla lingua o al formato della risposta... ovviamente se possibile.
Poniamo ad esempio di essere in grado di rispondere sia in XML che in JSON come posso sapere
quale è il formato che il mio client vorrebbe avere? Guardando l'header Accept
di HTTP, PHP ci mette a disposizone una funzione per questo:
getallheaders()
che ritorna un array di headers. In pratica:
$intestazioni = getallheaders(); if( strpos($intestazioni['Accept'],"application/json") === false ){ echo "JSON non ti va bene\n"; }else{ echo "JSON ti va bene\n"; }
Come è andata
L'esigenza successiva è quella di comunicare come è andata l'operazione richiesta
(se ci viene richiesto di cancellare qualcosa non è detto che vogliamo farlo!):
http_response_code()
serve a questo scopo, http_response_code(200)
comunicherà ad esempio
che la richiesta si è conclusa con successo.
Come ti sto rispondendo
HTTP nella sua intestazione ci consente di specificare il tipo di messaggio che stiamo
inviando al client e PHP mette a disposizione una funzione per impostare un header qualsiasi:
header().
Nello specifico visto che rappresenteremo i dati utilizzando
JSON sarà header('Content-type: application/json')
.
Esempio
<?php http_response_code(200); header('Content-type: application/json'); echo "azione richiesta:${_SERVER['REQUEST_METHOD']}\n"; echo "risorsa:".$_SERVER['REQUEST_URI']."\n"; echo "senza parametri:".parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH)."\n"; echo "valore del parametro nome:".$_GET['nome']."\n"; $intestazioni = getallheaders(); echo "vorresti la risposta nel formato:".$intestazioni['Accept']."\n"; if( strpos($intestazioni['Accept'],"json") > 0 ){ echo "JSON ti va bene\n"; }else{ echo "JSON non ti va bene\n"; } if( strpos($intestazioni['Accept'],"xml") > 0 ){ echo "XML ti va bene\n"; }else{ echo "XML non ti va bene\n"; }
L'esempio sopra ha un errore... quale?
"${" non ha sensoha senso, serve a scrivere variabili più complicate nelle stringhe application/jsonsi, è sbagliato o si mette text/plain o si cambia il testo della risposta (quello negli echo) "REQUEST_URI" non è una chiave di $_SERVERlo è, l'indirizzo della risorsa richiestaConfigurazioni fini
In caso si voglia usare (e si, si vuole!) le normali URL (es: servizio/identificativo)per specificare il servizio non bisogna cambiare lo script PHP... basta istruire il web server.
Nel caso di Apache httpd possiamo configurarlo per trasformare una URL
servizio/identificativo
in servizio.php?p1=identificativo
inserendo
la configurazione sotto nel file .htaccess
o nel file di
configurazione al livello di sistema.
RewriteEngine on # RewriteRule cosa_vai_cercando come_devo_riscriverlo flag # flag: https://httpd.apache.org/docs/2.4/rewrite/flags.html # [L] sta per "ultima regola" (ovviamente se combacia) # tutte le robe che sono un elemento di servizio e finiscono per qualche_numero RewriteRule "^servizio/([0-9]+)$" "servizio.php?p1=$1" [L]
nota: il parametro p1 se presente nell'URL originale (prima di fare rewrite) viene comunque passato allo script
[2024-01-03] è possibile che Apache httpd e in particolare la negoziazione dei contenuti dai errore nel mapping. Può essere di aiuto la configurazione sotto come riportato in post su serverfault.
AddType application/x-httpd-php .php