Pagine Dinamiche, Forms HTML e CGI

Giovedì, 22 Novembre 2007

OBIETTIVI DELLA LEZIONE

In questa lezione:

  1. impareremo la differenze tra pagine statiche e dinamiche
  2. vedremo come costruire un FORM HTML
  3. vedremo come vengono passati i dati ad una CGI
  4. comprenderemo in dettaglio i meccanismi che possono essere utilizzati per dotare di una certa "persistenza" una connessione Web

Pagine statiche vs pagine dinamiche

Nella scorsa lezione abbiamo cominciato a costruire alcune pagine HTML. Le pagine che abbiamo creato ovviamente non cambiano da sole: dobbiamo aprirle con un editor e manualmente editarle. In fondo una pagina HTML è solo un file di testo con qualche TAG che ne organizza il contenuto e la visualizzazione.

Inoltre abbiamo creato, durante l'esercitazione, alcuni programmi Java che costruivano pagine non esistenti fino all'esecuzione del programma. Ma una volta create, le pagine erano sempre dei semplici files di testo caratterizzati da TAGS.

Esiste una importante differenza terminologica per distingure questi due tipi di files

Come fa il programma CGI a generare automaticamente le pagine? Nei casi più semplici esegue una istruzione di sistema e ne ritorna il risultato. Esempio: i primi contatori del numero di accessi ad una data pagina erano semplici script di shell Unix che una volta invocati leggevano da un file il numero di accessi effettuati in precedenza, ne incrementavano il valore e producevano una pagina contenete il valore numerico.

Un alternativa al programma CGI autonomo, è quella dei moduli del server, softwares che lavorano in cooperazione con il server HTTP. Tipici moduli sono PHP, ASP, ... Come funzionano:




FORMS

Dispense introduttiva [da studiare]: 2-FORMSinHTML.pdf

Controlli per FORM HTML

INPUT

SELECT

TEXTAREA

<textarea cols=40 rows=5 name="testo">
Testo che si trova già digitato in una frase molto lunga.
</textarea>

Un esempio: Form che scarica una pagina TELEVIDEO

<html>
<head>
<title>Esempio di form che accede a Televideo</title>
</head>
<body>
VISUALIZZA LA PAGINA TELEVIDEO
<br />
<form method="get" action="http://www.televideo.rai.it/televideo/pub/solotesto.jsp">
<table>
    <tr>
    <th>Pagina Televideo:</th>
    <td><input type="text" name="pagina"></td>
    </tr>
    <tr>
    <th></th>
    <td><input type="submit" value="Visualizza"></td>
    </tr>
</table>
<input type="hidden" name="sottopagina" value="03">
</form>
</body>
</html>

CGI [approfondimento]

Dispense introduttive: 1-PagineDinamiche.pdf

CGI="common gataway interface" è una modalità di interazione standard tra il server HTTP ed un programma lato server. Infatti, un server HTTP, oltre che fornire materiale statico ai client, spesso deve interagire con altro software presente sul client (ad esempio per creare le pagine dinamiche!). CGI è un accordo che si è instaurato tra i produttori di server HTTP circa le modalità di interazione con questi script e programmi.
E' indipendente dal:

E' sostanziamente una serie di convenzioni che fanno si che un web server sappia come rispondere a richieste del tipo: www.dti.unimi.it/~sassi/LIA2007/provaform.php

I file CGI sono riconosciuti dal web server perchè:

  1. sono contenuti in una cartella specifica sul server (esempio: cgi-bin);
  2. (oppure) perché terminano con una estensione standard (.cgi, .php, .asp, ...).

Un programma CGI viene

e restituisce la pagina HTML prodotta dinamicamente al server WEB scrivendo sullo stdout.

Materiale di consultazione:

Interazione tra FORM HTML e CGI

Lo scambio di informazioni tra il server e il programma CGI avviene differentemente a seconda del method che si è impiegato nella richiesta. Vediamo i due casi principali, le modalità HTTP GET e POST.

GET [method="get"]

I dati che il client vuole inviare alla CGI vengono codificati e aggiunti all'URI. (scritti in fondo all'indirizzo come se ne fossero una parte).

Convenzione HTTP (request con method GET):

URI + ? + controllo1=valorecontrollo1 + & + controllo2=valorecontrollo2 + & + ...

Esempio, Richiesta del client:

GET /~sassi/LIA2007/provaform.php?nome=Giovanni&cognome=Rossi&matricola=123456 HTTP/1.1
Host: www.dti.unimi.it
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 Firefox/0.8
Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml, [...]
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive

Risposta del server:

HTTP/1.x 200 OK
Date: Mon, 19 Apr 2004 07:33:48 GMT
Server: Apache/1.3.26 (Unix) Debian GNU/Linux PHP/4.1.2 mod_ssl/2.8.9 OpenSSL/0.9.6g mod_perl/1.26
X-Powered-By: PHP/4.1.2
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=iso-8859-1

<html>
<head>
<title>Prova FORM. La tua matricola è
...

Lo standard CGI prevede che i caratteri dopo il "?" vengano copiati dal server nella variabile di ambiente "QUERY_STRING". Ogni programma CGI deve quindi estrare i valori dalla variabile di ambiente e decodificarli opportunamente.
ATTENZIONE alcuni sistemi operativi limitano il numero di caratteri di una variabile di ambiente a 256. Se prevedete di doverne inoltrare di più non usate GET: verrebbero troncati e mai ricevuti dal programma CGI!

POST [method="post"]

I dati vengono posti nel body della richiesta HTTP. Risultato: l'URI non cambia.

Esempio, richiesta del client:

POST /~sassi/LIA2007/provaform.php HTTP/1.1
Host: www.dti.unimi.it
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040206 Firefox/0.8
Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml, [...]
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 44

nome=Giovanni&cognome=Rossi&matricola=123456

La risposta del server è identica alla precedente!

Il metodo POST non ha nessun limite sulla dimensione dei dati da trasferire. Lo standar CGI prevede che il server debba estrarre la stringa dei valori dei controlli dal body della richiesta HTTP e copiarla sullo stdin. Il numero dei caratteri posti dal server sullo stdin viene posto nella variabile di ambiente "CONTENT_LENGTH".

Approfondimento HTTP. Creare persistenza tra richieste successive

Nella lezione scorsa [dispense HTTP], abbiamo vista che il protocollo HTTP NON ha stato. Questo vuol dire che le varie coppie di richiesta/risposta sono tra loro indipendenti e, in linea di principio, non sarebbe possibile "propagare" il valore di una "informazione" tra di esse.

Sin dall'inizio dell'espansione del Web questo si è rivelato un forte limite. Per ovviarvi, invece di stravolgere il protocollo HTTP si sono inventati tre "trucchetti" per simulare lo stato. Rivediamoli in dettaglio.

Il problema che ci poniamo è il seguente: vogliamo contare il numero di volte che un utente ha visitato il nostro sito WEB.

  1. URL con informazioni aggiuntive

    Le variabili vengono aggiunte all'URI, proprio come se fossero dei controlli

    http://www.dti.unimi.it/~sassi/LIA2007/mioSito.php?visite=1
    ...
    http://www.dti.unimi.it/~sassi/LIA2007/mioSito.php?visite=2
    
  2. Campi nascosti [type="hidden"] con informazioni aggiuntive (tipicamente con il metodo POST)

    <form method="post" action="http://www.dti.unimi.it/~sassi/LIA2007/mioSito.php">
    ...
    <input type="hidden" name="visite" value="1">
    ...
    </form>
    
    <form method="post" action="http://www.dti.unimi.it/~sassi/LIA2007/mioSito.php">
    ...
    <input type="hidden" name="visite" value="2">
    ...
    </form>
    
  3. Cookie

    Il server, oltre alla pagina richiesta, può includere nell'header della risposta la richiesta al client di ricevere un cookie. Il cookie è di fatto una variabile che ha un nome ed un valore. Il client (se è abilitato a ricevere cookies) salva il nome ed il valore della variabile sul proprio disco in un file che ha lo stesso nome del server che ha inviato il cookie (questo per distinguere tra cookie di siti differenti). Il cookie scade: dopo un certo tempo, specificato dal server, il file del cookie viene rimosso dal disco dal client.





    Prima di effettuare ogni richiesta al server, il client verifica se ha sul suo disco un cookie di quel server (cioè che ha lo stesso nome del server). Se lo trova ne copia il contenuto nell'header della richiesta HTTP.





Lab

Alcuni suggerimenti

Esercizio 1

Costruire una pagina HTML che contenga un FORM che richieda all'utente di inserire nome, cognome e matricola. Il FORM deve inviare i dati con il metodo GET all'indirizzo http://www.dti.unimi.it/~sassi/LIA2007/provaform.php; i dati devono essere contenuti in controlli chiamati rispettivamente "nome", "cognome" e "matricola".

Una volta ottenuta la risposta corretta dal server, rifate l'esercizio utilizzando il metodo POST per l'invio dei dati. Cosa cambia?

Esercizio 2

Dal sito www.trenitalia.com è possibile ottenere informazioni circa l'orario ferroviario. La pagina è però appensantita da immagini e applets. Scriviamo noi una nostra interfaccia!

Ispirandosi all'interfaccia di Televideo vista a lezione, preparare una pagina HTML che contenga un FORM che permetta di ottenere dal server http://orario.trenitalia.com/b2c/TimeTable l'orario di un particolare treno.

I controlli da fornire con il metodo POST e GET sono:

  • "stazin" (stazione di partenza),
  • "stazout" (stazione di arrivo),
  • "datag" (giorno di partenza),
  • "datam" (mese di partenza),
  • "dataa" (anno di partenza),
  • "timsh", (ora di partenza),
  • "timsm" (minuti dopo l'ora di partenza),
  • "lang" (linguaggio; suggerimento: predisporre un controllo hidden con il valore predefinito "it"),
  • "nreq" (numero di risultati da visualizzare).

Funzionano entrambi?

Esercizio 3 [Soluzione]

Il signor Rossi è ossessionato dai consumi elettrici di casa e tenta in ogni modo di ridurli. A questo fine introduce spesso migliorie all'impianto (introduzione lampadine a basso consumo, elettrodomestici più avanzati, ...).
A fronte di ogni miglioria si annota su di un foglio la data e la lettura del contatore.
Sapendo che siete dei brillanti studenti, vi commissiona il programma TabellaConsumi.java che gli permetta di tenere nota delle lettura e creare a richiesta una pagina HTML con una tabella riassuntiva.
Il programma una volta eseguito, deve mostrare il testo "PRONTO> " e rimanere in attesa di un comando. Una volta eseguito il comando deve tornare di nuovo nello stato di attesa (dovete scrivere un semplice interprete di comandi). I comandi che il programma accetta sono:

  1. 'E': termina il programma
  2. 'N': crea un file di testo vuoto consumienel.txt. Se il file esiste già chiede conferma prima di cancellarlo. [Suggerimento: utilizzate i metodi createNewFile() e delete() della classe File].
  3. 'C': cancella il file di testo consumienel.txt. Chiede sempre conferma prima di cancellare. [Suggerimento: utilizzate il metodo delete() della classe File].
  4. 'A': aggiunge una lettura al file consumienel.txt. La lettura contiene quattro valori: giorno, mese, anno e KWh consumati. I valori vanno in colonne separate da tabulazioni ('\t') Suggerimento: per prima cosa chiedete il valore della lettura all'utente, quindi aprite il file e aggiungetela in fondo. Il file viene chiuso dopo ogni lettura aggiunta. [Suggerimento: create ogni volta un nuovo stream FileWriter in modalità append (vedere l'help in linea). Alla fine utilizzate il metodo close].
  5. 'H': crea il file HTML consumienel.html che DEVE contenere una tabella HTML in cui ogni riga contenga una lettura differente (tutte quelle che sono nel file consumienel.txt). Le colonne devono contenere: numero della lettura (progressivo), la data e il numero di KWh consumati.
  6. Per effettuare l'input da console, prendete spunto dall'esempio Lune.java (Esercizio 3 della lezione 2).

©2007 Roberto Sassi