venerdì, agosto 30, 2013

PHP - Basi di HTTP


Questo post fa parte di una serie preparata qualche anno fa per delle lezioni su PHP.

Basi di HTTP


È molto importante conoscere alcune cose fondamentali di ciò che avviene quando un browser e un server web comunicano tra loro.
Un esercizio interessante è di usare programmi come curl, che consentono di registrare la comunicazione in un file di testo da analizzare con calma.

Il metodo GET

Ad esempio, quando il browser invia una richiesa a google.com con una richiesta simile alla seguente

GET / HTTP/1.1
User-Agent: curl/7.19.5 (i486-pc-linux-gnu) libcurl/7.19.5 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.15
Host: google.com
Accept: */*

viene rediretto a www.google.com:

HTTP/1.1 301 Moved Permanently
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Date: Tue, 02 Mar 2010 20:15:36 GMT
Expires: Thu, 01 Apr 2010 20:15:36 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219
X-XSS-Protection: 0

<HTML><HEAD><meta http-equiv="content-type" content="text/html;c
harset=utf-8"> <TITLE>301 Moved</TITLE></HEAD><BODY> <H1>301 Mov
ed</H1> The document has moved <A HREF="http://www.google.com/">
here</A>.
</BODY></HTML>

A questo punto fa la richiesta a www.google.com:

GET / HTTP/1.1
User-Agent: curl/7.19.5 (i486-pc-linux-gnu) libcurl/7.19.5 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.15
Host: www.google.com
Accept: */*

e riceve un ulteriore reindirezzamento a www.google.it, con l'invito, questa volta, a memorizzare dei cookies:

HTTP/1.1 302 Found
Location: http://www.google.it/
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Set-Cookie: PREF=ID=bd21c8242c754edb:TM=1267563471:LM=1267563471S=NwB1nU_SnFL-QObq; expires=Thu, 01-Mar-2012 20:57:51 GMT; path=/; domain=.google.it
Set-Cookie: NID=32=R74iZCyObDJF0HSpezx6-94w2O9BpeXSR6mD1uOFT4DuGoMY0J6hhQ-1qEXbs04rWbCSkrrch18q5ATv5jnakX-dDPKbCI2U6rpsG5MR05j0a-NmMDasXR9JdK_pRYK3; expires=Wed, 01-Sep-2010 20:16:35 GMT; path=/; domain=.google.com; HttpOnly

Date: Tue, 02 Mar 2010 20:16:35 GMT
Server: gws
Content-Length: 218
X-XSS-Protection: 0

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> <TITLE>302 Moved</TITLE></HEAD><BODY> <H1>302 Moved</H1> The document has moved <A HREF="http://www.google.it/">here</A>.
</BODY></HTML>

La richiesta delle pagine successive avverrà quindi inserendo nella richiesta i cookies:

GET / HTTP/1.1
User-Agent: curl/7.19.5 (i486-pc-linux-gnu) libcurl/7.19.5 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.15
Host: www.google.it
Accept: */*
Cookie: PREF=ID=bd21c8242c754edb:TM=1267563471:LM=1267563471S=NwB1nU_SnFL-QObq
La risposta spesso arriva al browser "spezzettata" (chunked), in modo che non sia necessario informarlo in anticipo della dimensione del file in arrivo (Content-Length)

HTTP/1.1 200 OK
Date: Tue, 02 Mar 2010 20:16:46 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=ISO-8859-1
...Transfer-Encoding: chunked

1000
<!doctype html><html><head><meta http-equiv="content-type" conte
nt="text/html; charset=ISO-8859-1"><title>Google</title><script>
...
ada
ubmit value="Mi sento fortunato" class=lsb></td><td nowrap width
...
rt=(f=(new Date).getTime());.})();.</script>
0

Ogni singolo chunk viene preceduto dalla dimensione in byte (espressa in esadecimale) dello stesso. La fine della trasmissione è contrassegnata dal valore 0.
(Di questo spezzettamente si occupa direttamente il server web, come sviluppatori PHP non dobbiamo preoccuparcene...)

Il metodo POST

Cosa succede invece in caso di POST? Quando compiliamo il modulo di ricerca di www.php.net inviamo dei dati in questo modo:

POST /search.php HTTP/1.1
User-Agent: curl/7.19.5 (i486-pc-linux-gnu) libcurl/7.19.5 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.15
Host: www.php.net
Accept: */*
Content-Length: 29
Content-Type: application/x-www-form-urlencoded

pattern=functions&show=manual

La risposta che riceviamo potrebbe essere una pagina web, ma è buona pratica ridirigere il browser ad un'altra pagina da richiedere con il metodo GET (ed è quello che succede nel caso concreto).

Sulla differenza tra metodo GET e POST è utile la lettura del documento Methods GET and POST in HTML forms - what's the difference? di Jukka "Yucca" Korpela.

Refresh della pagina

Capita spesso di trovare delle pagine web che fanno scattare il refresh della pagina (spesso, ma non solo, per far scaricare un file). Questo di solito viene ottenuto indicando, all'interno dell'elemento META un contenuto simile al seguente:

<html>
<head>
<meta http-equiv="Refresh" content="0;URL=http://www.example.com/" />
</head>
<body>
<script type="text/javascript" language="javascript">
<!--
location.replace("http://www.example.com/")
-->
</script>
</body>
</html>

Nella risposta del server web compare comunque l'intestazione HTTP appropriata, che viene riportata nella pagina web per sicurezza.

Expires: Sun, 28 Mar 2010 09:19:06 GMT
Date: Sun, 21 Mar 2010 09:19:06 GMT
Refresh: 0;URL=http://www.example.com/
...

Nota: il numero prima dell'URL indica dopo quanti secondi il browser è invitato a fare il refresh della pagina.

Approfondimenti

Oltre ai metodi GET e POST, il protocollo HTTP prevede i metodi HEAD, PUT e DELETE (vedi RFC 2616). I browser non supportano direttamente i metodi PUT e DELETE (se si specificano questi come metodi vengono effettivamente fatte richieste con GET), ma è possibile la loro implementazione tramite Javascript.

Le applicazioni che usano in maniera coerente i metodi GET, POST, PUT e DELETE vengono denominate RESTful. Un'ottima introduzione all'argomento è data in RESTful Web services: The basics di Alex Rodriguez.

HEAD

Con il metodo HEAD vengono chieste solo le metainformazioni su una risorsa, non la risorsa stessa.

PUT

Con il metodo PUT viene richiesta l'esecuzione di un'operazione di inserimento o aggiornamento, invocando un URI in cui la risorsa è chiaramente identificata.
Ad esempio,

PUT /picture/123

è diverso rispetto a 

POST /picture/new

in quanto nel primo caso l'URI riflette la conoscenza, da parte dello user-agent, di come verrà identificata la risorsa, mentre nel secondo si affida al server la decisione su cosa fare dei dati ricevuti.

DELETE

Con il metodo DELETE si chiede l'eliminazione di una risorsa.

Esercizio

Predisporre una pagina web con una form HTML per effettuare la ricerca di una funzione nel sito www.php.net.
Esercitarsi nella predisposizione di form di base e verificare con phpinfo() quali sono i dati ricevuti con il metodo GET e con il metodo POST.

Nessun commento:

Posta un commento