UNA PRIMA RICHIESTA HTTP
Creazione di una connessione TCP tra client e server tramite
telnet e invio di una richiesta HTTP
Tra le conoscenze di uno sviluppatore web dovrebbe sempre campeggiare
quella del protocollo HTTP (come tutti sappiamo acronimo di
Hyper-Text Transfer Protocol), sul quale, più o meno consapevolmente, si
basa la totalità del suo lavoro. In questo articolo tenteremo di
riassumerne i caratteri principali e quelli più utili al web-developer.
Per prima cosa bisogna dire che HTTP è un protocollo di comunicazione
standard (per ulteriori dettagli consultare le specifiche ufficiali
RFC) di cui esistono diverse versioni, ad oggi esistono la 1.0 e la
1.1. HTTP/1.1 aggiunge varie novità tra le quali
principalmente vi è la persistenza della connessioni (vedremo tra poco
di cosa si tratta). HTTP/1.0 è invece ormai obsoleto e quasi tutti i
moderni browser e server web supportano la versione 1.1, per questo
motivo in questo articolo si farà riferimento alla versione più recente.
HTTP si basa su TCP, protocollo di livello inferiore che permette di creare una
connessione tra due macchine, una in attesa (in listening,
il server web in questo caso) e una che effettua la connessione (il
client, il browser web). TCP identifica le macchine coinvolte in una
connessione tramite i loro indirizzi IP (es. 209.85.135.103) e la
porta
su cui avviene la connessione. La porta è un numero compreso tra 1 e
65535 e in genere ad ogni servizio corrisponde una porta, ad esempio per
HTTP è in genere 80, per FTP la porta 21 e così via.
È un po' come una casa (il server) in cui vi sono varie porte numerate
che fanno accedere a stanze dove ci viene offerto un servizio differente
(la porta 80 per il web, la porta 21 per il trasferimento di file via
FTP ecc.): noi (ovvero il nostro browser-client) bussa presso una porta,
dietro la quale vi è una persona che ci attende (in ascolto, listening),
quando ci apre iniziamo la nostra discussione (abbiamo così stabilito la
connessione).
Ulteriori dettagli su TCP non sono oggetto di questo articolo,
ritorniamo dunque ad HTTP. Per vedere come funziona una connessione HTTP
ci connetteremo al nostro server web (locale, ma anche se fosse in
remoto basterebbe sostituire a arcadi67.startlogicmysql.com il dominio del sito) sulla porta 80 e gli
invieremo dei dati. Per fare questo avviare il server web, e poi dal
prompt dei comandi (Start, Esegui, digitare cmd e dare conferma)
scriviamo quanto segue:
telnet arcadi67.startlogicmysql.com 80
Questa semplice sintassi richiamerà il tool telnet che ci permette di
effettuare una connessione TCP a arcadi67.startlogicmysql.com (ovvero il nostro server
locale) sulla porta 80. Formuliamo ora dal Blocco Note la richiesta HTTP più semplice
possibile e incolliamola nel prompt dei comandi (click destro, Incolla):
GET /pagina.htm HTTP/1.1
Host: arcadi67.startlogicmysql.com
Analizziamo brevemente la richiesta che abbiamo effettuato: GET indica
il tipo di richiesta (ne vedremo in seguito altre), lo slash è il path, il percorso della pagina richiesta (in questo caso
dunque, la pagina principale del sito, corrisponde all'URL
http://arcadi67.startlogicmysql.com/pagina.htm) e HTTP/1.1 indica che è una
richiesta HTTP versione 1.1. Di per sé questo GET sarebbe già
sufficiente, ma poiché su una stessa macchina (o meglio su uno stesso
IP) possono essere configurati
più siti è necessario specificare quello a cui ci si riferisce tramite
il parametro Host. In questo caso si suppone che esista un sito
configurato sotto il nome arcadi67.startlogicmysql.com.
Nota: dopo ogni richiesta HTTP si devono trasmettere due ritorni a capo
(ovvero due sequenze di caratteri CR e LF),
per permettere all'interlocutore (il server) di capire
che la richiesta è stata completata e che può quindi elaborarla per poi inviare una risposta.
IL RESPONSO DEL SERVER
Status code, codici di errore, Content-Type, Content-Length,
encoding e compressione
Una volta incollato quanto sopra riportato il server ci invierà una
risposta di questo tipo:
HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
Content-Type: text/html; charset=iso-8859-1
Content-Length: %LunghezzaPagina%
Content-Encoding: identity
%ContenutoPagina%
Nota: ogni server web invia in genere molti più parametri (ad esempio se
si utilizza ASP .Net è probabile che ci sia X-Powered-By: ASP.NET), qui
vengono riportati solamente quelli essenziali.
Prima di tutto troviamo riportata l'indicazione della versione di HTTP
utilizzata (in questo caso HTTP/1.1), seguita da un codice numerico di
tre cifre e un breve messaggio testuale. Il codice numerico di tre
cifre, lo status code serve al server per comunicare al client se
l'operazione richiesta ha avuto successo o meno. Gli status code si dividono in 5
categorie: la prima di informazione (100-199), la seconda messaggi di
successo o conferma (200-299), la terza di redirezione di vario genere
(300-399), la quarta di segnalazione di un errore del client (400-499) e
la quinta per gli errori del server (500-599).
Tra gli status code che è importante ricordare vi sono:
- 200 OK: la pagina esiste e sta per essere restituita con
successo;
- 301 Moved Permanently: spostato permanentemente, un redirect
verso un'altra pagina;
- 302 Found: pagina trovata, altra forma di redirect;
- 307 Temporary Redirect: pagina spostata temporaneamente, forma
di redirect temporanea;
- 400 Bad Request: la richiesta non è stata formulata
correttamente da parte del client;
- 401 Unauthorized: autenticazione fallita, accesso negato;
- 403 Forbidden: accesso negato alla risorsa;
- 404 Not Found: risorsa non trovata, l'indirizzo non esiste;
- 408 Request Timeout: timeout, la richiesta ha impiegato troppo
tempo per essere elaborata e per questo è stata interrotta;
- 500 Internal Server Error: in genere indica un errore da parte
del linguaggio lato server (come potrebbe essere ASP .Net o PHP) ma
potrebbe anche essere dovuto ad un errore del server web (IIS,
Apache o altri);
- 503 Service Unavaiable: il sito web è momentaneamente fuori
servizio, in genere per questioni di manutenzione;
Ne esistono poi diversi altri per ogni categoria, per ulteriori
dettagli riferirsi all'RFC di HTTP.
Dopo versione HTTP e status code abbiamo una serie di parametri.
Server, che indica quale e che versione del web server si sta
usando (in questo caso Microsoft Internet Information Services 5.1).
Il parametro Content-Type ha una certa importanza perché
specifica il MIME-type della risorsa richiesta (come text/html,
image/jpeg,
image/gif e tanti altri ancora) e nel caso sia testuale la codifica con
cui interpretarla (ad esempio ISO-8859-1, ovvero Latin-1, UTF-8, UTF-16
o altri).
Content-Length indica la quantità di dati che sta per essere inviata in
byte, ad esempio 1024 indicherà che la pagina (o più in generale la
risorsa) che si sta per scaricare peserà 1 Kb.
Infine, se presente, il parametro Content-Encoding indica come e se è
stato compresso il responso della richiesta. I possibili valori sono
identity (il responso non è compresso), gzip (formato GNU Zip),
compress
(LZW) e deflate (zlib). Comprimere l'output può offrire un notevole
risparmio di banda, ammesso che il client supporti questa funzionalità (su come
questo venga determinato si discuterà più avanti).
Dopo questa serie arbitrariamente lunga e varia di parametri il server
invierà due ritorni a capo e la quantità di byte specificata dal
parametro Content-Length: si tratta dell'HTML della pagina, oppure dei
dati che compongono l'immagine, il video o altro.
UNA TIPICA RICHIESTA GET
I più frequenti parametri HTTP
Vediamo ora una richiesta da parte del client un po' più articolata, ad
esempio una tipica richiesta GET di Firefox:
GET /pagina.aspx?valore1=contenuto&valore2=contenuto2 HTTP/1.1
Host: arcadi67.startlogicmysql.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.12) Gecko/20080201 Firefox/2.0.0.12
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: it-it,it;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Sulla prima riga di questa richiesta non ci sono grandi novità tranne il
fatto che questa volta sono stati passati due valori (valore1 e
valore2) tramite
l'URL, il cui contenuto può essere determinato con $_GET['valore1'] in
PHP o Request.QueryString("valore1") in ASP .Net. La
parte dell'URL che segue il punto interrogativo (?) è chiamata
query: se presente, contiene una lista di coppie nome-valore separate da
una E commerciale (&). Nomi e valori sono separati dal simbolo di
uguale.
Analizziamo e vediamo il significato dei parametri che sono mandati dal
client.
User-Agent è un parametro che comunica al server che browser (o più in
generale, client) e quale versione si sta utilizzando; questo dato è
importante, oltre che per fini statistici anche per restituire responsi
differenti e specifici per un client rispetto ad un altro. Come si può
vedere la stringa dell'user-agent, oltre a informazioni su nome e
versione del browser, contiene vari dati tra i quali anche
alcuni riguardanti il sistema operativo in uso e la lingua del browser.
Accept comunica al server quali MIME type il browser è in grado di
accettare; la lista è separata da virgola e può contenere anche
informazioni riguardanti una sorta di indice di preferenza del MIME in
questione. Ad esempio text/html;q=0.9 indica che il formato text/html è
preferenziale rispetto a text/plain (text/plain;q=0.8) dato che il
valore di q è inferiore. Si noti che */* indica qualsiasi MIME type e
così pure in seguito l'asterisco sarà da considerarsi con il valore di
"tutti i valori possibili".
Accept-Language funziona similarmente a Accept ma al posto di MIME type
sono specificati i codici di un cultura accettati (it-it, solo it,
en-us,
en-uk, en-au o altri ancora), sempre con rispettivi indici di
preferenza.
Accept-Encoding comunica al server quali formati di compressione è in
grado di accettare, in questo caso gzip e deflate.
Accept-Charset indica quali codifiche di carattere il browser è in grado
di interpretare e quali preferisce. In questo caso Firefox preferisce
ISO-8859-1 (ovvero Latin-1), ma se non disponibile accetta parimenti
UTF-8 con una preferenza di 0,7 o qualunque altro con la stessa
preferenza.
Il parametro Connection indica al server se, una volta inviato il
responso, debba tenere aperta (valore keep-alive) oppure chiudere
(valore close) la connessione TCP; in questo caso la connessione
deve rimanere aperta.
Infine il parametro Keep-Alive specifica il timeout dopo il quale la
connessione verrà chiusa: è un valore in secondi che devono trascorrere
dall'ultima richiesta effettuata.
|