2. Nozioni di base
In questo capitolo presentiamo le nozioni di base della programmazione web. Il suo obiettivo principale è quello di introdurre i principi chiave della programmazione web, che sono indipendenti dalla tecnologia specifica utilizzata per implementarli. Include numerosi esempi che vi invitiamo a provare per "assorbire" gradualmente la filosofia dello sviluppo web. Gli strumenti gratuiti necessari per provarli sono elencati alla fine del documento nell'appendice intitolata "Strumenti Web".
2.1. Componenti di un'applicazione web
Server

Macchina client15
Numero | Ruolo | Esempi comuni |
Sistema operativo server | Linux, Windows | |
Server Web | Apache (Linux, Windows) IIS (NT), PWS (Win9x), Cassini (Windows + piattaforma .NET) | |
Script lato server. Possono essere eseguiti da moduli del server o da programmi esterni al server (CGI). | PERL (Apache, IIS, PWS) VBSCRIPT (IIS, PWS) JAVASCRIPT (IIS, PWS) PHP (Apache, IIS, PWS) JAVA (Apache, IIS, PWS) C#, VB.NET (IIS) | |
Database - Può trovarsi sulla stessa macchina del programma che lo utilizza o su un'altra macchina tramite Internet. | Oracle (Linux, Windows) MySQL (Linux, Windows) Postgres (Linux, Windows) Access (Windows) SQL Server (Windows) | |
Sistema operativo client | Linux, Windows | |
Browser Web | Netscape, Internet Explorer, Mozilla, Opera | |
Script lato client eseguiti all'interno del browser. Questi script non hanno accesso ai dischi del computer client. | VBScript (IE) JavaScript (IE, Netscape) PerlScript (IE) Applet Java |
2.2. Gli scambi di dati in un'applicazione web con un modulo

ServerMacchina client
Numero | Ruolo |
Il browser richiede un URL per la prima volta (http://machine/url). Non vengono passati parametri. | |
Il server web invia la pagina web corrispondente a quell'URL. Può essere statica o generata dinamicamente da uno script lato server (SA) che potrebbe aver utilizzato contenuti provenienti da database (SB, SC). In questo caso, lo script rileverà che l'URL è stato richiesto senza alcun parametro e genererà la pagina web iniziale. Il browser riceve la pagina e la visualizza (CA). Gli script lato browser (CB) potrebbero aver modificato la pagina iniziale inviata dal server. Quindi, attraverso le interazioni tra l'utente (CD) e gli script (CB), la pagina web verrà modificata. In particolare, verranno compilati i moduli. | |
L'utente invia i dati del modulo, che vengono poi inviati al server web. Il browser ricarica l'URL originale o uno diverso, a seconda dei casi, e contemporaneamente invia i valori del modulo al server. A tal fine può utilizzare due metodi: GET e POST. Una volta ricevuta la richiesta del client, il server esegue lo script (SA) associato all'URL richiesto, che rileverà i parametri e li elaborerà. | |
Il server fornisce la pagina web generata dal programma (SA, SB, SC). Questo passaggio è identico al precedente Passaggio 2. La comunicazione procede ora secondo i Passaggi 2 e 3. |
2.3. Notazioni
Di seguito, supporremo che siano stati installati una serie di strumenti e adotteremo le seguenti notazioni:
notazione | significato |
radice dell'albero delle directory del server Apache | |
Directory principale delle pagine web servite da Apache. Le pagine web devono trovarsi in questa directory principale. Pertanto, l'URL http://localhost/page1.htm corrisponde al file <apache-DocumentRoot>\page1.htm. | |
Radice dell'albero di directory associato all'alias cgi-bin, dove possono essere collocati gli script CGI per Apache. Pertanto, l'URL http://localhost/cgi-bin/test1.pl corrisponde al file <apache-cgi-bin>\test1.pl. | |
La directory radice per le pagine web servite da IIS, PWS o Cassini. Le pagine web devono trovarsi in questa directory radice. Pertanto, l'URL http://localhost/page1.htm corrisponde al file <IIS-DocumentRoot>\page1.htm. | |
Radice dell'albero delle directory del linguaggio Perl. L'eseguibile perl.exe si trova solitamente in <perl>\bin. | |
Radice dell'albero di directory di PHP. Il file eseguibile php.exe si trova solitamente in <php>. | |
Radice dell'albero di directory Java. I file eseguibili relativi a Java si trovano in <java>\bin. | |
Radice del server Tomcat. Esempi di servlet sono disponibili in <tomcat>\webapps\examples\servlets ed esempi di pagine JSP in <tomcat>\webapps\examples\jsp |
Per ciascuno di questi strumenti, consultare l'appendice, che fornisce le istruzioni di installazione.
2.4. Pagine Web statiche, pagine Web dinamiche
Una pagina statica è rappresentata da un file HTML. Una pagina dinamica, invece, viene generata "al volo" dal server web. In questa sezione presentiamo vari test che utilizzano diversi server web e linguaggi di programmazione per dimostrare l'universalità del concetto di web. Utilizzeremo due server web: Apache e IIS. Sebbene IIS sia un prodotto commerciale, è disponibile in due versioni più limitate ma gratuite:
- PWS per macchine Win9x
- Cassini per macchine con Windows 2000 e XP
La cartella <IIS-DocumentRoot> è solitamente la cartella [unità:\inetpub\wwwroot], dove [unità] è l'unità (C, D, ...) su cui è stato installato IIS. Lo stesso vale per PWS. Per Cassini, la cartella <IIS-DocumentRoot> dipende da come è stato avviato il server. L'appendice mostra che il server Cassini può essere avviato in una finestra DOS (o tramite un collegamento) come segue:
L'applicazione [WebServer], nota anche come server web Cassini, accetta tre parametri:
- /port: numero di porta del servizio web. Può essere qualsiasi numero. Il valore predefinito è 80
- /path: percorso fisico di una cartella sul disco
- /vpath: cartella virtuale associata alla cartella fisica precedente. Si noti che la sintassi non è /path=path ma /vpath:path, contrariamente a quanto indicato nel pannello di aiuto sopra riportato.
Se Cassini viene avviato come segue:
allora la cartella P è la radice dell'albero delle directory web del server Cassini. Questa è quindi la cartella designata da <IIS-DocumentRoot>. Pertanto, nell'esempio seguente:
il server Cassini funzionerà sulla porta 80 e la radice della sua directory <IIS-DocumentRoot> sarà la cartella [d:\data\devel\webmatrix]. Le pagine web da testare devono trovarsi sotto questa radice.
D'ora in poi, ogni applicazione web sarà rappresentata da un singolo file che può essere creato utilizzando qualsiasi editor di testo. Non è richiesto alcun IDE.
2.4.1. Pagina HTML statica (HyperText Markup Language)
Si consideri il seguente codice HTML:
<html>
<head>
<title>essai 1 : une page statique</title>
</head>
<body>
<center>
<h1>Une page statique...</h1>
</body>
</html>
che genera la seguente pagina web:
I test

Test1
- Avvia il server Apache
- Inserire lo script test1.html in <apache-DocumentRoot>
- Visualizza l'URL http://localhost/essai1.html in un browser
- Arresta il server Apache
Test2
- Avvia il server IIS/PWS/Cassini
- Inserisci lo script test1.html in <IIS-DocumentRoot>
- Visualizza l'URL http://localhost/essai1.html in un browser
2.4.2. Una pagina ASP (Active Server Pages)
Lo script test2.asp:
<html>
<head>
<title>essai 1 : une page asp</title>
</head>
<body>
<center>
<h1>Une page asp générée dynamiquement par le serveur PWS</h1>
<h2>Il est <% =time %></h2>
<br>
A chaque fois que vous rafraîchissez la page, l'heure change.
</body>
</html>
genera la seguente pagina web:

Il test
- Avvia il server IIS/PWS
- Inserire lo script essai2.asp in <IIS-DocumentRoot>
- Richiedere l'URL http://localhost/essai2.asp utilizzando un browser
2.4.3. Uno script P ERL (Practical Extracting and Reporting Language)
Lo script essai3.pl:
#!d:\perl\bin\perl.exe
($secondes,$minutes,$heure)=localtime(time);
print <<HTML
Content-type: text/html
<html>
<head>
<title>essai 1 : un script Perl</title>
</head>
<body>
<center>
<h1>Une page générée dynamiquement par un script Perl</h1>
<h2>Il est $heure:$minutes:$secondes</h2>
<br>
A chaque fois que vous rafraîchissez la page, l'heure change.
</body>
</html>
HTML
;
La prima riga è il percorso dell'eseguibile perl.exe. Potrebbe essere necessario modificarlo se necessario. Una volta eseguito da un server web, lo script produce la seguente pagina:

Il
- server Web: Apache
- Per riferimento, visualizza il file di configurazione srm.conf o httpd.conf (a seconda della versione di Apache) in <apache>\confs e cerca la riga che menziona cgi-bin per determinare la directory <apache-cgi-bin> in cui dovresti collocare essai3.pl.
- Posizionare lo script essai3.pl in <apache-cgi-bin>
- Richiedere l'URL http://localhost/cgi-bin/essai3.pl
Si noti che il caricamento della pagina Perl richiede più tempo rispetto a quello della pagina ASP. Ciò è dovuto al fatto che lo script Perl viene eseguito da un interprete Perl che deve essere caricato prima di poter eseguire lo script. Non rimane in memoria in modo permanente.
2.4.4. Uno script PHP
Lo script essai4.php
<html>
<head>
<title>essai 4 : une page php</title>
</head>
<body>
<center>
<h1>Une page PHP générée dynamiquement</h1>
<h2>
<?
$maintenant=time();
echo date("j/m/y, h:i:s",$maintenant);
?>
</h2>
<br>
A chaque fois que vous rafraîchissez la page, l'heure change.
</body>
</html>
Lo script precedente genera la seguente pagina web:

Test
Test1
- Controlla il file di configurazione srm.conf o httpd.conf di Apache in <Apache>\confs
- Come riferimento, controllare le righe di configurazione PHP
- Avvia il server Apache
- Inserire essai4.php in <apache-DocumentRoot>
- Richiedi l'URL http://localhost/essai4.php
Test2
- Avvia il server IIS/PWS
- Per riferimento, controllare la configurazione di PWS relativa a PHP
- Inserire essai4.php in <IIS-DocumentRoot>\php
- Richiedi l'URL http://localhost/essai4.php
2.4.5. Uno script JSP
Lo script heure.jsp
<% //programme Java affichant l'heure %>
<%@ page import="java.util.*" %>
<%
// code JAVA pour calculer l'heure
Calendar calendrier=Calendar.getInstance();
int heures=calendrier.get(Calendar.HOUR_OF_DAY);
int minutes=calendrier.get(Calendar.MINUTE);
int secondes=calendrier.get(Calendar.SECOND);
// heures, minutes, secondes sont des variables globales
// qui pourront être utilisées dans le code HTML
%>
<% // code HTML %>
<html>
<head>
<title>Page JSP affichant l'heure</title>
</head>
<body>
<center>
<h1>Une page JSP générée dynamiquement</h1>
<h2>Il est <%=heures%>:<%=minutes%>:<%=secondes%></h2>
<br>
<h3>A chaque fois que vous rechargez la page, l'heure change</h3>
</body>
</html>
Una volta eseguito dal server web, questo script produce la seguente pagina:

I test
- Inserisci lo script heure.jsp in <tomcat>\jakarta-tomcat\webapps\examples\jsp (Tomcat 3.x) o in <tomcat>\webapps\examples\jsp (Tomcat 4.x)
- Avviare il server Tomcat
- Richiedere l'URL http://localhost:8080/examples/jsp/heure.jsp
2.4.6. Una pagina ASP.NET
Lo script heure1.aspx:
<html>
<head>
<title>Démo asp.net </title>
</head>
<body>
Il est <% =Date.Now.ToString("hh:mm:ss") %>
</body>
</html>
Una volta eseguito dal server web, questo script genera la seguente pagina:

Questo test richiede un computer Windows su cui sia stata installata la piattaforma .NET (vedere l'appendice).
- Inserire lo script heure1.aspx in <IIS-DocumentRoot>
- Avviare il server IIS/CASSINI
- Richiedere l'URL http://localhost/heure1.aspx
2.4.7. Conclusione
Gli esempi precedenti hanno dimostrato che:
- una pagina HTML può essere generata dinamicamente da un programma. Questo è il punto centrale della programmazione web.
- i linguaggi e i server web utilizzati possono variare. Attualmente si osservano le seguenti tendenze principali:
- le combinazioni Apache/PHP (Windows, Linux) e IIS/PHP (Windows)
- la tecnologia ASP.NET su piattaforme Windows, che combina il server IIS con un linguaggio .NET (C#, VB.NET, ecc.)
- tecnologia Java servlet e pagine JSP in esecuzione su vari server (Tomcat, Apache, IIS) e su varie piattaforme (Windows, Linux).
2.5. Script lato browser
Una pagina HTML può contenere script che verranno eseguiti dal browser. Esistono molti linguaggi di scripting lato browser. Eccone alcuni:
Linguaggio | Browser supportati |
VBScript | IE |
JavaScript | IE, Netscape |
PerlScript | IE |
Java | IE, Netscape |
Vediamo alcuni esempi.
2.5.1. Una pagina web con uno script VBScript, sul lato browser
La pagina vbs1.html
<html>
<head>
<title>essai : une page web avec un script vb</title>
<script language="vbscript">
function reagir
alert "Vous avez cliqué sur le bouton OK"
end function
</script>
</head>
<body>
<center>
<h1>Une page Web avec un script VB</h1>
<table>
<tr>
<td>Cliquez sur le bouton</td>
<td><input type="button" value="OK" name="cmdOK" onclick="reagir"></td>
</tr>
</table>
</body>
</html>
La pagina HTML sopra riportata contiene non solo codice HTML, ma anche un programma destinato ad essere eseguito dal browser che carica questa pagina. Il codice è il seguente:
<script language="vbscript">
function reagir
alert "Vous avez cliqué sur le bouton OK"
end function
</script>
I tag <script></script> vengono utilizzati per delimitare gli script all'interno di una pagina HTML. Questi script possono essere scritti in vari linguaggi e l'attributo language del tag <script> specifica il linguaggio utilizzato. In questo caso, si tratta di VBScript. Non entreremo nei dettagli di questo linguaggio. Lo script sopra riportato definisce una funzione chiamata react che visualizza un messaggio. Quando viene chiamata questa funzione? Ce lo dice la seguente riga di codice HTML:
L'attributo onclick specifica il nome della funzione da chiamare quando l'utente clicca sul pulsante OK. Una volta che il browser ha caricato questa pagina e l'utente clicca sul pulsante OK, apparirà la seguente pagina:

Test
Solo Internet Explorer è in grado di eseguire script VBScript. Netscape richiede dei componenti aggiuntivi per farlo. Possiamo eseguire i seguenti test:
- Server Apache
- Script vbs1.html in <apache-DocumentRoot>
- Richiedere l'URL http://localhost/vbs1.html utilizzando Internet Explorer
- Server IIS/PWS
- Script vbs1.html in <pws-DocumentRoot>
- Richiedere l'URL http://localhost/vbs1.html utilizzando Internet Explorer
Una pagina web con uno script JavaScript, sul lato browser
La page : js1.html
<html>
<head>
<title>essai 4 : une page web avec un script Javascript</title>
<script language="javascript">
function reagir(){
alert ("Vous avez cliqué sur le bouton OK");
}
</script>
</head>
<body>
<center>
<h1>Une page Web avec un script Javascript</h1>
<table>
<tr>
<td>Cliquez sur le bouton</td>
<td><input type="button" value="OK" name="cmdOK" onclick="reagir()"></td>
</tr>
</table>
</body>
</html>
Questa pagina è identica alla precedente, tranne per il fatto che abbiamo sostituito VBScript con JavaScript. JavaScript ha il vantaggio di essere supportato sia da Internet Explorer che da Netscape. L'esecuzione di questo codice produce gli stessi risultati:

I test
- Server Apache
- Script js1.html in <apache-DocumentRoot>
- Richiedere l'URL http://localhost/js1.html utilizzando Internet Explorer o Netscape
- Server IIS/PWS
- Script js1.html in <pws-DocumentRoot>
- Richiedere l'URL http://localhost/js1.html utilizzando Internet Explorer o Netscape
2.6. Comunicazione client-server
Torniamo al nostro diagramma iniziale che illustra i componenti di un'applicazione web:

Macchina server
Qui ci concentriamo sugli scambi tra il computer client e il computer server. Questi avvengono su una rete, ed è utile rivedere la struttura generale degli scambi tra due computer remoti.
2.6.1. Il modello OSI
Il modello di rete aperto noto come OSI (Open Systems Interconnection Reference Model), definito dall'ISO (International Organization for Standardization), descrive una rete ideale in cui la comunicazione tra macchine può essere rappresentata da un modello a sette livelli:

Ogni livello riceve servizi dal livello sottostante e fornisce i propri servizi al livello sovrastante. Supponiamo che due applicazioni situate su macchine diverse A e B vogliano comunicare: lo fanno a livello di Applicazione. Non hanno bisogno di conoscere tutti i dettagli di come funziona la rete: ogni applicazione passa le informazioni che desidera trasmettere al livello sottostante: il livello di Presentazione. L'applicazione deve quindi conoscere solo le regole per interfacciarsi con il livello di Presentazione. Una volta che le informazioni si trovano nel livello di Presentazione, vengono passate secondo altre regole al livello di Sessione, e così via, fino a quando le informazioni raggiungono il mezzo fisico e vengono trasmesse fisicamente alla macchina di destinazione. Lì, subiranno il processo inverso di quello che hanno subito sulla macchina mittente.
Ad ogni livello, il processo mittente responsabile dell'invio delle informazioni le invia a un processo ricevente sull'altra macchina appartenente allo stesso livello. Lo fa secondo determinate regole note come protocollo di livello. Abbiamo quindi il seguente diagramma di comunicazione finale:

I ruoli dei diversi livelli sono i seguenti:
Garantisce la trasmissione di bit su un mezzo fisico. Questo livello include apparecchiature terminali di elaborazione dati (DPTE) come terminali o computer, nonché apparecchiature di terminazione del circuito dati (DCTE) come modulatori/demodulatori, multiplexer e concentratori. I punti chiave a questo livello sono: . la scelta della codifica delle informazioni (analogica o digitale) . la scelta della modalità di trasmissione (sincrona o asincrona). | |
Nasconde le caratteristiche fisiche del livello fisico. Rileva e corregge gli errori di trasmissione. | |
Gestisce il percorso che le informazioni inviate sulla rete devono seguire. Questo processo è chiamato routing: determinare il percorso che le informazioni devono seguire per raggiungere la loro destinazione. | |
Consente la comunicazione tra due applicazioni, mentre i livelli precedenti permettevano solo la comunicazione tra macchine. Un servizio fornito da questo livello può essere il multiplexing: il livello di trasporto può utilizzare una singola connessione di rete (da macchina a macchina) per trasmettere dati appartenenti a più applicazioni. | |
Questo livello fornisce servizi che consentono a un'applicazione di aprire e mantenere una sessione di lavoro su una macchina remota. | |
Il suo scopo è quello di standardizzare la rappresentazione dei dati tra macchine diverse. Pertanto, i dati provenienti dalla macchina A saranno "formattati" dal livello di presentazione della macchina A secondo un formato standard prima di essere inviati in rete. Una volta raggiunto il livello di presentazione della macchina di destinazione B, che li riconoscerà grazie al loro formato standard, saranno riformattati in modo che l'applicazione sulla macchina B possa riconoscerli. | |
A questo livello si trovano le applicazioni che sono generalmente vicine all'utente, come la posta elettronica o il trasferimento di file. |
2.6.2. Il modello TCP/IP
Il modello OSI è un modello ideale. La suite di protocolli TCP/IP lo approssima come segue:

- l'interfaccia di rete (la scheda di rete del computer) svolge le funzioni dei livelli 1 e 2 del modello OSI
- il livello IP (Internet Protocol) svolge le funzioni del livello 3 (rete)
- il livello TCP (Transmission Control Protocol) o UDP (User Datagram Protocol) svolge le funzioni del livello 4 (trasporto). Il protocollo TCP garantisce che i pacchetti di dati scambiati tra le macchine raggiungano la loro destinazione. In caso contrario, invia nuovamente i pacchetti persi. Il protocollo UDP non svolge questo compito, quindi spetta allo sviluppatore dell'applicazione farlo. Questo è il motivo per cui, su Internet, che non è una rete affidabile al 100%, il protocollo TCP è il più utilizzato. Si parla in questo caso di rete TCP-IP.
- Il livello Applicazione copre le funzioni dei livelli da 5 a 7 del modello OSI.
Le applicazioni web risiedono nel livello Applicazione e quindi si basano sui protocolli TCP/IP. I livelli Applicazione delle macchine client e server si scambiano messaggi, che vengono poi trasferiti ai livelli da 1 a 4 del modello per essere instradati verso la loro destinazione. Per comunicare tra loro, i livelli Applicazione di entrambe le macchine devono "parlare" la stessa lingua o lo stesso protocollo. Il protocollo utilizzato dalle applicazioni web si chiama HTTP (HyperText Transfer Protocol). Si tratta di un protocollo basato su testo, il che significa che le macchine scambiano righe di testo attraverso la rete per comunicare. Questi scambi sono standardizzati, il che significa che il client dispone di una serie di messaggi per comunicare al server esattamente ciò che desidera, e anche il server dispone di una serie di messaggi per fornire al client la propria risposta. Questo scambio di messaggi assume la seguente forma:

Client --> Server
Quando il client effettua una richiesta al server web, invia
- righe di testo in formato HTTP per indicare ciò che desidera
- una riga vuota
- facoltativamente un documento
Server --> Client
Quando il server risponde al client, invia
- righe di testo in formato HTTP per indicare ciò che sta inviando
- una riga vuota
- facoltativamente un documento
Le comunicazioni seguono quindi lo stesso formato in entrambe le direzioni. In entrambi i casi, può essere inviato un documento, anche se è raro che un client invii un documento al server. Ma il protocollo HTTP lo consente. Questo è ciò che permette, ad esempio, agli abbonati di un ISP di caricare vari documenti sul proprio sito web personale ospitato da quell'ISP. I documenti scambiati possono essere di qualsiasi tipo. Consideriamo un browser che richiede una pagina web contenente immagini:
- il browser si connette al server web e richiede la pagina desiderata. Le risorse richieste sono identificate in modo univoco dagli URL (Uniform Resource Locators). Il browser invia solo intestazioni HTTP e nessun documento.
- Il server risponde. Innanzitutto invia le intestazioni HTTP indicando il tipo di risposta che sta inviando. Potrebbe trattarsi di un errore se la pagina richiesta non esiste. Se la pagina esiste, il server indicherà nelle intestazioni HTTP della sua risposta che invierà un documento HTML (HyperText Markup Language) a seguire. Questo documento è una sequenza di righe di testo in formato HTML. Il testo HTML contiene tag (indicatori) che forniscono al browser le istruzioni su come visualizzare il testo.
- Il client sa dalle intestazioni HTTP del server che riceverà un documento HTML. Analizzerà questo documento e potrebbe notare che contiene riferimenti a immagini. Queste immagini non sono incluse nel documento HTML. Effettua quindi una nuova richiesta allo stesso server web per richiedere la prima immagine di cui ha bisogno. Questa richiesta è identica a quella effettuata nel passaggio 1, tranne per il fatto che la risorsa richiesta è diversa. Il server elaborerà questa richiesta inviando l'immagine richiesta al client. Questa volta, nella sua risposta, le intestazioni HTTP specificheranno che il documento inviato è un'immagine e non un documento HTML.
- Il client recupera l'immagine inviata. I passaggi 3 e 4 verranno ripetuti fino a quando il client (di solito un browser) non avrà tutti i documenti necessari per visualizzare l'intera pagina.
2.6.3. Il protocollo HTTP
Esploriamo il protocollo HTTP attraverso alcuni esempi. Cosa si scambiano un browser e un server web?
2.6.3.1. La risposta da un server HTTP
Qui vedremo come un server web risponde alle richieste dei suoi clienti. Il servizio web o servizio HTTP è un servizio TCP/IP che di solito funziona sulla porta 80. Potrebbe funzionare su una porta diversa. In quel caso, il browser del cliente dovrebbe specificare quella porta nell'URL che richiede. Un URL di solito segue questo formato:
dove
protocollo | http per il servizio Web. Un browser può anche fungere da client per FTP, news, Telnet e altri servizi. |
macchina | nome della macchina che ospita il servizio web |
porta | Porta del servizio web. Se è 80, il numero di porta può essere omesso. Questo è il caso più comune |
percorso | percorso della risorsa richiesta |
info | informazioni aggiuntive fornite al server per specificare la richiesta del client |
Cosa fa un browser quando un utente richiede il caricamento di un URL?
- Stabilisce una connessione TCP/IP con la macchina e la porta specificate nella parte machine[:port] dell'URL. Stabilire una connessione TCP/IP significa creare un "canale" di comunicazione tra due macchine. Una volta stabilito questo canale, tutte le informazioni scambiate tra le due macchine passeranno attraverso di esso. La creazione di questo canale TCP-IP non coinvolge ancora il protocollo HTTP del Web.
- Una volta stabilita la connessione TCP-IP, il client invia la sua richiesta al server web inviando righe di testo (comandi) in formato HTTP. Invia la parte path/info dell'URL al server
- Il server risponderà allo stesso modo e attraverso la stessa connessione
- Una delle due parti deciderà di chiudere la connessione. Ciò dipende dal protocollo HTTP utilizzato. Con HTTP 1.0, il server chiude la connessione dopo ciascuna delle sue risposte. Ciò costringe un client che deve effettuare più richieste per recuperare i vari documenti che compongono una pagina web ad aprire una nuova connessione per ogni richiesta, il che comporta un costo. Con il protocollo HTTP/1.1, il client può indicare al server di mantenere aperta la connessione fino a quando non gli dirà di chiuderla. Può quindi recuperare tutti i documenti di una pagina web utilizzando un'unica connessione e chiudere la connessione una volta ottenuto l'ultimo documento. Il server rileverà questa chiusura e chiuderà a sua volta la connessione.
Per esaminare gli scambi tra un client e un server web, useremo uno strumento chiamato curl. Curl è un'applicazione DOS che permette di agire come client per servizi Internet che supportano vari protocolli (HTTP, FTP, TELNET, GOPHER, ecc.). Curl è disponibile all'URL http://curl.haxx.se/. Qui, scaricheremo preferibilmente la versione Windows win32-nossl, poiché la versione win32-ssl richiede DLL aggiuntive non incluse nel pacchetto curl. Questo pacchetto contiene una serie di file che devono semplicemente essere estratti in una cartella che d'ora in poi chiameremo <curl>. Questa cartella contiene un file eseguibile denominato [curl.exe]. Questo sarà il nostro client per l'interrogazione dei server web. Apri una finestra del Prompt dei comandi e naviga fino alla cartella <curl>:
dos>dir curl.exe
22/03/2004 13:29 299 008 curl.exe
E:\curl2>curl
curl: try 'curl --help' for more information
dos>curl --help | more
Usage: curl [options...] <url>
Options: (H) means HTTP/HTTPS only, (F) means FTP only
-a/--append Append to target file when uploading (F)
-A/--user-agent <string> User-Agent to send to server (H)
--anyauth Tell curl to choose authentication method (H)
-b/--cookie <name=string/file> Cookie string or file to read cookies from (H)
--basic Enable HTTP Basic Authentication (H)
-B/--use-ascii Use ASCII/text transfer
-c/--cookie-jar <file> Write cookies to this file after operation (H)
....
Utilizziamo questa applicazione per interrogare un server web ed esaminare gli scambi tra il client e il server. Ci troveremo nella seguente situazione:

Il server web può essere qualsiasi server. In questo caso, il nostro obiettivo è scoprire gli scambi che avverranno tra il client web curl e il server web. In precedenza, abbiamo creato la seguente pagina HTML statica:
<html>
<head>
<title>essai 1 : une page statique</title>
</head>
<body>
<center>
<h1>Une page statique...</h1>
</body>
</html>
che visualizziamo in un browser:

Possiamo vedere che l'URL richiesto è: http://localhost/aspnet/chap1/statique1.html. Il server web è quindi localhost (=macchina locale) sulla porta 80. Se visualizziamo il codice sorgente HTML di questa pagina web (Visualizza/Sorgente), vediamo il testo HTML che è stato originariamente creato:

Ora utilizziamo il nostro client CURL per richiedere lo stesso URL:
dos>curl http://localhost/aspnet/chap1/statique1.html
<html>
<head>
<title>essai 1 : une page statique</title>
</head>
<body>
<center>
<h1>Une page statique...</h1>
</body>
</html>
Possiamo vedere che il server web ha inviato una serie di righe di testo che rappresentano il codice HTML della pagina richiesta. Abbiamo accennato in precedenza che la risposta di un server web assume la forma:

Tuttavia, qui non abbiamo visto le intestazioni HTTP. Questo perché [curl] non le visualizza per impostazione predefinita. L'opzione --include consente di visualizzarle:
E:\curl2>curl --include http://localhost/aspnet/chap1/statique1.html
HTTP/1.1 200 OK
Server: Microsoft ASP.NET Web Matrix Server/0.6.0.0
Date: Mon, 22 Mar 2004 16:51:00 GMT
X-AspNet-Version: 1.1.4322
Cache-Control: public
ETag: "1C4102CEE8C6400:1C4102CFBBE2250"
Content-Type: text/html
Content-Length: 161
Connection: Close
<html>
<head>
<title>essai 1 : une page statique</title>
</head>
<body>
<center>
<h1>Une page statique...</h1>
</body>
</html>
Il server ha effettivamente inviato una serie di intestazioni HTTP seguite da una riga vuota:
HTTP/1.1 200 OK
Server: Microsoft ASP.NET Web Matrix Server/0.6.0.0
Date: Mon, 22 Mar 2004 16:51:00 GMT
X-AspNet-Version: 1.1.4322
Cache-Control: public
ETag: "1C4102CEE8C6400:1C4102CFBBE2250"
Content-Type: text/html
Content-Length: 161
Connection: Close
il server dice
| |
il server si identifica. In questo caso si tratta di un server Cassini | |
la data e l'ora della risposta | |
intestazione specifica del server Cassini | |
fornisce al client informazioni sulla possibilità di memorizzare nella cache la risposta inviata. L'attributo [public] indica al client che può memorizzare la pagina nella cache. Un attributo [no-cache] avrebbe indicato al client di non memorizzare la pagina nella cache. | |
... | |
Il server indica che invierà testo in formato HTML. | |
Il numero di byte nel documento che verrà inviato dopo le intestazioni HTTP. Questo numero corrisponde in realtà alla dimensione in byte del file essai1.html: | |
il server indica che chiuderà la connessione una volta inviato il documento |
Il client riceve queste intestazioni HTTP e ora sa che riceverà 161 byte che rappresentano un documento HTML. Il server invia questi 161 byte immediatamente dopo la riga vuota che ha segnalato la fine delle intestazioni HTTP:
<html>
<head>
<title>essai 1 : une page statique</title>
</head>
<body>
<center>
<h1>Une page statique...</h1>
</body>
</html>
Qui vediamo il file HTML così come è stato originariamente costruito. Se il nostro client fosse un browser, dopo aver ricevuto queste righe di testo, le interpreterebbe per visualizzare la seguente pagina all'utente:

Utilizziamo nuovamente il nostro client [curl] per richiedere la stessa risorsa, ma questa volta chiedendo solo le intestazioni di risposta:
dos>curl --head http://localhost/aspnet/chap1/statique1.html
HTTP/1.1 200 OK
Server: Microsoft ASP.NET Web Matrix Server/0.6.0.0
Date: Tue, 23 Mar 2004 07:11:54 GMT
Cache-Control: public
ETag: "1C410A504D60680:1C410A58621AD3E"
Content-Type: text/html
Content-Length: 161
Connection: Close
Otteniamo lo stesso risultato di prima senza il documento HTML. Ora richiediamo un'immagine utilizzando sia un browser che il client TCP generico. Innanzitutto, utilizzando un browser:

Il file univ01.gif è di 4052 byte:
Ora utilizziamo il client [curl]:
dos>curl --head http://localhost/aspnet/chap1/univ01.gif
HTTP/1.1 200 OK
Server: Microsoft ASP.NET Web Matrix Server/0.6.0.0
Date: Tue, 23 Mar 2004 07:18:44 GMT
Cache-Control: public
ETag: "1C410A6795D7500:1C410A6868B1476"
Content-Type: image/gif
Content-Length: 4052
Connection: Close
Si prega di tenere presente quanto segue riguardo al ciclo richiesta-risposta sopra riportato:
| |
| |
|
2.6.3.2. La richiesta di un client HTTP
Ora poniamoci la seguente domanda: se vogliamo scrivere un programma che "comunichi" con un server web, quali comandi deve inviare al server web per ottenere una determinata risorsa? Negli esempi precedenti abbiamo visto cosa ha ricevuto il client, ma non cosa ha inviato. Useremo l'opzione [--verbose] di curl per vedere anche cosa il client invia al server. Iniziamo richiedendo la pagina statica:
dos>curl --verbose http://localhost/aspnet/chap1/statique1.html
* About to connect() to localhost:80
* Connected to portable1_tahe (127.0.0.1) port 80
> GET /aspnet/chap1/statique1.html HTTP/1.1
User-Agent: curl/7.10.8 (win32) libcurl/7.10.8 OpenSSL/0.9.7a zlib/1.1.4
Host: localhost
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
< HTTP/1.1 200 OK
< Server: Microsoft ASP.NET Web Matrix Server/0.6.0.0
< Date: Tue, 23 Mar 2004 07:37:06 GMT
< Cache-Control: public
< ETag: "1C410A504D60680:1C410A58621AD3E"
< Content-Type: text/html
< Content-Length: 161
< Connection: Close
<html>
<head>
<title>essai 1 : une page statique</title>
</head>
<body>
<center>
<h1>Une page statique...</h1>
</body>
</html>
* Closing connection #0
In primo luogo, il client [curl] stabilisce una connessione TCP/IP alla porta 80 sul computer localhost (=127.0.0.1)
Una volta stabilita la connessione, invia la sua richiesta HTTP. Si tratta di una sequenza di righe di testo che termina con una riga vuota:
GET /aspnet/chap1/statique1.html HTTP/1.1
User-Agent: curl/7.10.8 (win32) libcurl/7.10.8 OpenSSL/0.9.7a zlib/1.1.4
Host: localhost
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
La richiesta HTTP di un client web ha due funzioni:
- specificare la risorsa desiderata. Questo è il ruolo della prima riga, GET
- fornire informazioni sul client che effettua la richiesta in modo che il server possa potenzialmente adattare la propria risposta a questo specifico tipo di client.
Il significato delle righe inviate sopra dal client [curl] è il seguente:
per richiedere una determinata risorsa utilizzando una versione specifica del protocollo HTTP. Il server invia una risposta in formato HTTP seguita da una riga vuota e dalla risorsa richiesta | |
per indicare chi è il client | |
per specificare (protocollo HTTP 1.1) la macchina e la porta del server web interrogato | |
qui per specificare che il client non supporta la memorizzazione nella cache. | |
Tipi MIME che specificano i tipi di file che il client è in grado di gestire |
Proviamo nuovamente l'operazione con l'opzione --head di [curl]:
dos>curl --verbose --head --output reponse.txt http://localhost/aspnet/chap1/statique1.html
* About to connect() to localhost:80
* Connected to portable1_tahe (127.0.0.1) port 80
> HEAD /aspnet/chap1/statique1.html HTTP/1.1
User-Agent: curl/7.10.8 (win32) libcurl/7.10.8 OpenSSL/0.9.7a zlib/1.1.4
Host: localhost
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
< HTTP/1.1 200 OK
< Server: Microsoft ASP.NET Web Matrix Server/0.6.0.0
< Date: Tue, 23 Mar 2004 07:54:22 GMT
< Cache-Control: public
< ETag: "1C410A504D60680:1C410A58621AD3E"
< Content-Type: text/html
< Content-Length: 161
< Connection: Close
Ci concentreremo solo sulle intestazioni HTTP inviate dal client:
HEAD /aspnet/chap1/statique1.html HTTP/1.1
User-Agent: curl/7.10.8 (win32) libcurl/7.10.8 OpenSSL/0.9.7a zlib/1.1.4
Host: localhost
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
È cambiato solo il comando che richiede la risorsa. Al posto di un comando GET, ora abbiamo un comando HEAD. Questo comando richiede che la risposta del server sia limitata alle intestazioni HTTP e che non invii la risorsa richiesta. Lo screenshot qui sopra non mostra le intestazioni HTTP ricevute. Queste sono state salvate in un file utilizzando l'opzione [--output response.txt] del comando [curl]:
dos>more reponse.txt
HTTP/1.1 200 OK
Server: Microsoft ASP.NET Web Matrix Server/0.6.0.0
Date: Tue, 23 Mar 2004 07:54:22 GMT
Cache-Control: public
ETag: "1C410A504D60680:1C410A58621AD3E"
Content-Type: text/html
Content-Length: 161
Connection: Close
2.6.4. Conclusione
Abbiamo esaminato la struttura della richiesta di un client web e la risposta del server web ad essa utilizzando alcuni esempi. La comunicazione avviene tramite il protocollo HTTP, un insieme di comandi basati su testo scambiati tra le due parti. La richiesta del client e la risposta del server condividono la seguente struttura:

Nel caso di una richiesta del client (spesso chiamata query), la sezione [Document] è solitamente assente. Tuttavia, è possibile che un client invii un documento al server. Lo fa utilizzando un comando chiamato PUT. I due comandi comuni per richiedere una risorsa sono GET e POST. Il secondo verrà discusso più avanti. Il comando HEAD viene utilizzato per richiedere solo le intestazioni HTTP. I comandi GET e POST sono quelli più comunemente utilizzati dai client web basati su browser.
In risposta alla richiesta di un client, il server invia una risposta con la stessa struttura. La risorsa richiesta viene trasmessa nella sezione [Document], a meno che il comando del client non fosse HEAD, nel qual caso vengono inviate solo le intestazioni HTTP.
2.7. HTML
Un browser web può visualizzare vari documenti, il più comune dei quali è il documento HTML (HyperText Markup Language). Si tratta di testo formattato utilizzando tag della forma <tag>testo</tag>. Pertanto, il testo <B>importante</B> visualizzerà il testo "importante" in grassetto. Esistono tag autonomi come il tag , che visualizza una linea orizzontale. Non esamineremo tutti i tag che si possono trovare nel testo HTML. Esistono molti programmi software WYSIWYG che consentono di creare una pagina web senza scrivere una sola riga di codice HTML. Questi strumenti generano automaticamente il codice HTML per un layout creato utilizzando il mouse e controlli predefiniti. È quindi possibile inserire (utilizzando il mouse) una tabella nella pagina e poi visualizzare il codice HTML generato dal software per scoprire i tag da utilizzare per definire una tabella su una pagina web. È semplicissimo. Inoltre, la conoscenza dell'HTML è essenziale poiché le applicazioni web dinamiche devono generare autonomamente il codice HTML da inviare ai client web. Questo codice viene generato a livello di programmazione e, ovviamente, è necessario sapere cosa generare affinché il client riceva la pagina web desiderata.
In breve, non è necessario conoscere l'intero linguaggio HTML per iniziare a programmare per il web. Tuttavia, questa conoscenza è necessaria e può essere acquisita utilizzando editor di pagine web WYSIWYG come Word, FrontPage, DreamWeaver e decine di altri. Un altro modo per scoprire le complessità dell'HTML è navigare sul web e visualizzare il codice sorgente delle pagine che presentano elementi interessanti che non avete mai incontrato prima.
2.7.1. Un esempio
Si consideri il seguente esempio, creato con FrontPage Express, uno strumento gratuito incluso in Internet Explorer. Il codice generato da FrontPage è stato semplificato. Questo esempio presenta alcuni elementi comunemente presenti in un documento web, quali:
- una tabella
- un'immagine
- un link

Un documento HTML ha generalmente la seguente forma:
L'intero documento è racchiuso tra i tag <html>...</html>. È composto da due parti:
- <head>...</head>: questa è la parte non visualizzabile del documento. Fornisce informazioni al browser che visualizzerà il documento. Spesso contiene il tag <title>...</title>, che imposta il testo che apparirà nella barra del titolo del browser. Può contenere anche altri tag, compresi quelli che definiscono le parole chiave del documento, che vengono poi utilizzate dai motori di ricerca. Questa sezione può contenere anche script, solitamente scritti in JavaScript o VBScript, che verranno eseguiti dal browser.
- <body attributes>...</body>: Questa è la sezione che verrà visualizzata dal browser. I tag HTML contenuti in questa sezione indicano al browser il layout visivo "desiderato" per il documento. Ogni browser interpreta questi tag a modo suo. Di conseguenza, due browser potrebbero visualizzare lo stesso documento web in modo diverso. Questa è generalmente una delle sfide che devono affrontare i web designer.
Il codice HTML per il nostro documento di esempio è il seguente:
<html>
<head>
<title>balises</title>
</head>
<body background="/images/standard.jpg">
<center>
<h1>Les balises HTML</h1>
<hr>
</center>
<table border="1">
<tr>
<td>cellule(1,1)</td>
<td valign="middle" align="center" width="150">cellule(1,2)</td>
<td>cellule(1,3)</td>
</tr>
<tr>
<td>cellule(2,1)</td>
<td>cellule(2,2)</td>
<td>cellule(2,3</td>
</tr>
</table>
<table border="0">
<tr>
<td>Une image</td>
<td><img border="0" src="/images/univ01.gif" width="80" height="95"></td>
</tr>
<tr>
<td>le site de l'ISTIA</td>
<td><a href="http://istia.univ-angers.fr">ici</a></td>
</tr>
</table>
</body>
</html>
Nel codice sono stati evidenziati solo i punti di nostro interesse:
HTML | Tag HTML ed esempi |
<title>tag</title> Il testo apparirà nella barra del titolo del browser quando il documento viene visualizzato | |
<horizontal> : visualizza una linea orizzontale | |
<attributi tabella>....</table> : per definire la tabella <tr attributi>... : per definire una riga <td attributi>... : per definire una cella esempi: <table border="1">... : l'attributo border definisce lo spessore del bordo della tabella <td valign="middle" align="center" width="150">cell(1,2) : definisce una cella il cui contenuto sarà cell(1,2). Questo contenuto sarà centrato verticalmente (valign="middle") e orizzontalmente (align="center"). La cella avrà una larghezza di 150 pixel (width="150") | |
<img border="0" src="/images/univ01.gif" width="80" height="95"> : definisce un'immagine senza bordo (border="0"), alta 95 pixel (height="95"), larga 80 pixel (width="80") e il cui file sorgente è /images/univ01.gif sul server web (src="/images/univ01.gif"). Questo collegamento si trova in un documento web accessibile tramite l'URL http://localhost:81/html/balises.htm. Pertanto, il browser richiederà l'URL http://localhost:81/images/univ01.gif per recuperare l'immagine qui referenziata. | |
<a href="http://istia.univ-angers.fr">qui: fa sì che il testo "qui" funga da collegamento all'URL http://istia.univ-angers.fr. | |
<body background="/images/standard.jpg">: indica che l'immagine da utilizzare come sfondo della pagina si trova all'URL /images/standard.jpg sul server web. Nel contesto del nostro esempio, il browser richiederà l'URL http://localhost:81/images/standard.jpg per recuperare questa immagine di sfondo. |
In questo semplice esempio possiamo vedere che, per costruire l’intero documento, il browser deve effettuare tre richieste al server:
- http://localhost:81/html/balises.htm per recuperare il codice sorgente HTML del documento
- http://localhost:81/images/univ01.gif per recuperare l'immagine univ01.gif
- http://localhost:81/images/standard.jpg per recuperare l'immagine di sfondo standard.jpg
L'esempio seguente mostra un modulo web creato anch'esso con FrontPage.

Il codice HTML generato da FrontPage e leggermente ripulito è il seguente:
<html>
<head>
<title>balises</title>
<script language="JavaScript">
function effacer(){
alert("Vous avez cliqué sur le bouton Effacer");
}//effacer
</script>
</head>
<body background="/images/standard.jpg">
<form method="POST" >
<table border="0">
<tr>
<td>Etes-vous marié(e)</td>
<td>
<input type="radio" value="Oui" name="R1">Oui
<input type="radio" name="R1" value="non" checked>Non
</td>
</tr>
<tr>
<td>Cases à cocher</td>
<td>
<input type="checkbox" name="C1" value="un">1
<input type="checkbox" name="C2" value="deux" checked>2
<input type="checkbox" name="C3" value="trois">3
</td>
</tr>
<tr>
<td>Champ de saisie</td>
<td>
<input type="text" name="txtSaisie" size="20" value="qqs mots">
</td>
</tr>
<tr>
<td>Mot de passe</td>
<td>
<input type="password" name="txtMdp" size="20" value="unMotDePasse">
</td>
</tr>
<tr>
<td>Boîte de saisie</td>
<td>
<textarea rows="2" name="areaSaisie" cols="20">
ligne1
ligne2
ligne3
</textarea>
</td>
</tr>
<tr>
<td>combo</td>
<td>
<select size="1" name="cmbValeurs">
<option>choix1</option>
<option selected>choix2</option>
<option>choix3</option>
</select>
</td>
</tr>
<tr>
<td>liste à choix simple</td>
<td>
<select size="3" name="lst1">
<option selected>liste1</option>
<option>liste2</option>
<option>liste3</option>
<option>liste4</option>
<option>liste5</option>
</select>
</td>
</tr>
<tr>
<td>liste à choix multiple</td>
<td>
<select size="3" name="lst2" multiple>
<option>liste1</option>
<option>liste2</option>
<option selected>liste3</option>
<option>liste4</option>
<option>liste5</option>
</select>
</td>
</tr>
<tr>
<td>bouton</td>
<td>
<input type="button" value="Effacer" name="cmdEffacer" onclick="effacer()">
</td>
</tr>
<tr>
<td>envoyer</td>
<td>
<input type="submit" value="Envoyer" name="cmdRenvoyer">
</td>
</tr>
<tr>
<td>rétablir</td>
<td>
<input type="reset" value="Rétablir" name="cmdRétablir">
</td>
</tr>
</table>
<input type="hidden" name="secret" value="uneValeur">
</form>
</body>
</html>
La mappatura tra elementi visivi e tag HTML è la seguente:
Controllo visivo | Tag HTML |
<form method="POST" > | |
<input type="text" name="txtInput" size="20" value="a few words"> | |
<input type="password" name="txtPassword" size="20" value="aPassword"> | |
<textarea rows="2" name="inputArea" cols="20"> riga1 riga2 riga3 </textarea> | |
<input type="radio" value="Sì" name="R1">Sì <input type="radio" name="R1" value="No" checked>No | |
<input type="checkbox" name="C1" value="uno">1 <input type="checkbox" name="C2" value="due" checked>2 <input type="checkbox" name="C3" value="tre">3 | |
<select size="1" name="cmbValues"> <option>scelta1</option> <option selected>opzione2</option> <option>opzione3</option> </select> | |
<select size="3" name="lst1"> <option selected>elenco1</option> <option>elenco2</option> <option>elenco3</option> <option>elenco4</option> <option>elenco5</option> </select> | |
<select size="3" name="lst2" multiple> <option>elenco1</option> <option>list2</option> <option selected>elenco3</option> <option>elenco4</option> <option>list5</option> </select> | |
<input type="submit" value="Invia" name="cmdSubmit"> | |
<input type="reset" value="Reimposta" name="cmdReset"> | |
<input type="button" value="Cancella" name="cmdClear" onclick="clear()"> |
Esaminiamo questi diversi controlli.
2.7.1.1. Il modulo
<form method="POST" > |
<form name="..." method="..." action="...">...</form> | |
name="exampleform": nome del modulo method="..." : metodo utilizzato dal browser per inviare i valori raccolti nel modulo al server web action="..." : URL a cui verranno inviati i valori raccolti nel modulo. Un modulo web è racchiuso tra i tag <form>...</form>. Il modulo può avere un nome (name="xx"). Ciò vale per tutti i controlli presenti all'interno di un modulo. Questo nome è utile se il documento web contiene script che devono fare riferimento agli elementi del modulo. Lo scopo di un modulo è quello di raccogliere le informazioni inserite dall'utente tramite la tastiera o il mouse e inviarle a un URL di un server web. Quale? Quello a cui fa riferimento l'attributo action="URL". Se questo attributo manca, le informazioni saranno inviate all'URL del documento in cui si trova il modulo. Questo sarebbe il caso nell'esempio sopra riportato. Finora abbiamo sempre considerato il client web come un soggetto che "richiede" informazioni da un server web, mai come un soggetto che "fornisce" informazioni ad esso. In che modo un client web fornisce informazioni (i dati contenuti nel modulo) a un server web? Torneremo su questo argomento in dettaglio più avanti. Può utilizzare due metodi diversi chiamati POST e GET. L'attributo method="method" del tag <form>, dove method è impostato su GET o POST, indica al browser quale metodo utilizzare per inviare le informazioni raccolte nel modulo all'URL specificato dall'attributo action="URL". Quando l'attributo method non è specificato, viene utilizzato per impostazione predefinita il metodo GET. |
2.7.1.2. Campo di immissione
![]()
![]()
<input type="text" name="txtInput" size="20" value="alcune parole"> <input type="password" name="txtMdp" size="20" value="aPassword"> |
<input type="..." name="..." size=".." value=".."> Il tag input esiste per vari controlli. È l'attributo type che distingue questi diversi controlli l'uno dall'altro. | |
type="text": specifica che si tratta di un campo di immissione testo type="password": i caratteri nel campo di immissione vengono sostituiti da asterischi (*). Questa è l'unica differenza rispetto a un normale campo di immissione. Questo tipo di controllo è adatto per l'immissione di password. size="20": numero di caratteri visibili nel campo — non impedisce l’inserimento di più caratteri name="txtInput": nome del controllo value="alcune parole": testo che verrà visualizzato nel campo di immissione. |
2.7.1.3. Campo di immissione multilinea
![]()
<textarea rows="2" name="areaSaisie" cols="20"> riga1 riga2 riga3 </textarea> |
<textarea ...>testo</textarea> visualizza un campo di immissione testo multilinea con testo iniziale all'interno | |
rows="2": numero di righe cols="'20": numero di colonne name="areaSaisie": nome del controllo |
2.7.1.4. Pulsanti di opzione
![]()
<input type="radio" value="Yes" name="R1">Sì <input type="radio" name="R1" value="no" checked>No |
<input type="radio" attribute2="value2" ....>testo Visualizza un pulsante di opzione con del testo accanto. | |
name="radio": nome del controllo. I pulsanti di opzione con lo stesso nome formano un gruppo di pulsanti mutuamente esclusivi: è possibile selezionarne solo uno. value="value": valore assegnato al pulsante di opzione. Non confondere questo valore con il testo visualizzato accanto al pulsante di opzione. Il testo serve solo a scopo di visualizzazione. checked: se questa parola chiave è presente, il pulsante di opzione è selezionato; in caso contrario, non lo è. |
2.7.1.5. Caselle di controllo
<input type="checkbox" name="C1" value="one">1 <input type="checkbox" name="C2" value="due" checked>2 <input type="checkbox" name="C3" value="three">3 |
![]()
<input type="checkbox" attribute2="value2" ....>testo visualizza una casella di controllo con del testo accanto. | |
name="C1": nome del controllo. Le caselle di controllo possono avere o meno lo stesso nome. Le caselle di controllo con lo stesso nome formano un gruppo di caselle di controllo associate. value="value": valore assegnato alla casella di controllo. Non confondere questo valore con il testo visualizzato accanto al pulsante di opzione. Il testo serve solo a scopo di visualizzazione. selezionato: se questa parola chiave è presente, il pulsante di opzione è selezionato; in caso contrario, non lo è. |
2.7.1.6. Elenco a discesa (combo)
<select size="1" name="cmbValues"> <option>scelta1</option> <option selected>opzione2</option> <option>opzione3</option> </select> |
![]()
<select size=".." name=".."> <option [selected]>...</option> ... </select> visualizza il testo tra i tag <option>...</option> in un elenco | |
name="cmbValues": nome del controllo. size="1": numero di voci visibili dell'elenco. size="1" rende l'elenco equivalente a una casella combinata. selected: se questo attributo è presente per una voce dell'elenco, tale voce appare selezionata nell'elenco. Nel nostro esempio sopra, la voce dell'elenco "choice2" appare come voce selezionata nella casella combinata quando viene visualizzata per la prima volta. |
2.7.1.7. Elenco a selezione singola
<select size="3" name="lst1"> <option selected>list1</option> <option>list2</option> <option>elenco3</option> <option>elenco4</option> <option>elenco5</option> </select> |

<select size=".." name=".."> <option [selected]>...</option> ... </select> visualizza il testo tra i tag <option>...</option> in un elenco | |
gli stessi dell'elenco a discesa che visualizza un solo elemento. Questo controllo differisce dal precedente elenco a discesa solo per l'attributo size>1. |
2.7.1.8. Elenco a selezione multipla
<select size="3" name="lst2" multiple> <option selected>list1</option> <option>list2</option> <option selected>elenco3</option> <option>elenco4</option> <option>list5</option> </select> |

<select size=".." name=".." multiple> <option [selected]>...</option> ... </select> visualizza il testo tra i tag <option>...</option> in un elenco | |
multiple: consente di selezionare più elementi dall'elenco. Nell'esempio sopra, gli elementi list1 e list3 sono entrambi selezionati. |
2.7.1.9. Pulsante
<input type="button" value="Cancella" name="cmdClear" onclick="clear()"> |
![]()
<input type="button" value="..." name="..." onclick="clear()" ....> | |
type="button": definisce un controllo pulsante. Esistono altri due tipi di pulsanti: submit e reset. value="Clear": il testo visualizzato sul pulsante onclick="function()": consente di definire una funzione da eseguire quando l'utente fa clic sul pulsante. Questa funzione fa parte degli script definiti nel documento web visualizzato. La sintassi sopra riportata è sintassi JavaScript. Se gli script sono scritti in VBScript, si scriverebbe onclick="function" senza le parentesi. La sintassi rimane la stessa se è necessario passare dei parametri alla funzione: onclick="function(val1, val2,...)" Nel nostro esempio, cliccando sul pulsante Cancella si richiama la seguente funzione JavaScript clear: La funzione clear visualizza un messaggio: ![]() |
2.7.1.10. Pulsante Invia
<input type="submit" value="Invia" name="cmdSend"> |
![]()
<input type="submit" value="Invia" name="cmdRenvoyer"> | |
type="submit": definisce il pulsante come pulsante per l'invio dei dati del modulo al server web. Quando l'utente fa clic su questo pulsante, il browser invierà i dati del modulo all'URL definito nell'attributo action del tag <form> utilizzando il metodo definito dall'attributo method dello stesso tag. value="Invia": il testo visualizzato sul pulsante |
2.7.1.11. Pulsante di reset
<input type="reset" value="Reset" name="cmdReset"> |
![]()
<input type="reset" value="Reset" name="cmdReset"> | |
type="reset": definisce il pulsante come pulsante di reset del modulo. Quando l'utente clicca su questo pulsante, il browser ripristinerà il modulo allo stato in cui è stato ricevuto. value="Reset": il testo visualizzato sul pulsante |
2.7.1.12. Campo nascosto
<input type="hidden" name="secret" value="aValue"> |
<input type="hidden" name="..." value="..."> | |
type="hidden": specifica che si tratta di un campo nascosto. Un campo nascosto fa parte del modulo ma non viene visualizzato dall'utente. Tuttavia, se l'utente dovesse visualizzare il codice sorgente nel proprio browser, vedrebbe il tag <input type="hidden" value="..."> e quindi il valore del campo nascosto. value="aValue": valore del campo nascosto. Qual è lo scopo di un campo nascosto? Consente al server web di conservare le informazioni tra le richieste di un client. Si consideri un'applicazione di shopping online. Il cliente acquista un primo articolo art1 in quantità q1 nella prima pagina di un catalogo e poi passa a una nuova pagina del catalogo. Per ricordare che il cliente ha acquistato q1 articoli di art1, il server può inserire queste due informazioni in un campo nascosto nel modulo web della nuova pagina. In questa nuova pagina, il cliente acquista q2 unità dell'articolo art2. Quando i dati di questo secondo modulo vengono inviati al server, il server non solo riceverà le informazioni (q2,art2) ma anche (q1,art1), che fa anch'esse parte del modulo come campo nascosto che non può essere modificato dall'utente. Il server web inserirà quindi le informazioni (q1,art1) e (q2,art2) in un nuovo campo nascosto e invierà una nuova pagina del catalogo. E così via. |
2.7.2. Invio dei valori del modulo a un server web da parte di un client web
Nello studio precedente abbiamo accennato al fatto che il client web dispone di due metodi per inviare i valori di un modulo visualizzato a un server web: i metodi GET e POST. Vediamo un esempio per capire la differenza tra i due metodi. La pagina di cui abbiamo parlato prima è una pagina statica. Per accedere alle intestazioni HTTP inviate dal browser che richiede questo documento, la convertiremo in una pagina dinamica per un server web .NET (IIS o Cassini). L'attenzione qui non è sulla tecnologia .NET, che tratteremo nel prossimo capitolo, ma sulla comunicazione client-server. Il codice per la pagina ASP.NET è il seguente:
<%@ Page Language="vb" CodeBehind="params.aspx.vb" AutoEventWireup="false" Inherits="ConsoleApplication1.params" %>
<script runat="server">
Private Sub Page_Init(Byval Sender as Object, Byval e as System.EventArgs)
' save the query
saveRequest
end sub
Private Sub saveRequest
' saves the current query in request.txt of the page folder
dim requestFileName as String=Me.MapPath(Me.TemplateSourceDirectory)+"\request.txt"
Me.Request.SaveAs(requestFileName,true)
end sub
</script>
<html>
<head>
<title>balises</title>
<script language="JavaScript">
function effacer(){
alert("Vous avez cliqué sur le bouton Effacer");
}//effacer
</script>
</head>
<body background="/images/standard.jpg">
....
</body>
</html>
Al contenuto HTML della pagina in esame, aggiungiamo una sezione di codice VB.NET. Non commenteremo questo codice, se non per dire che ogni volta che il documento sopra riportato viene richiamato, il server web salverà la richiesta del client web nel file [request.txt] nella cartella del documento richiamato.
2.7.2.1. Metodo GET
Eseguiamo un test iniziale, in cui nel codice HTML del documento il tag FORM è definito come segue:
<form method="get">
Il documento precedente (codice HTML+VB) si chiama [params.aspx]. Si trova nella struttura di directory di un server web .NET (IIS/Cassini) ed è accessibile tramite l'URL http://localhost/aspnet/chap1/params.aspx:

Il browser ha appena effettuato una richiesta e sappiamo che è stata salvata nel file [request.txt]. Diamo un'occhiata al suo contenuto:
GET /aspnet/chap1/params.aspx HTTP/1.1
Connection: keep-alive
Keep-Alive: 300
Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Encoding: gzip,deflate
Accept-Language: en-us,en;q=0.5
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113
Vediamo elementi che abbiamo già incontrato con il client [curl]. Altri compaiono per la prima volta:
il client chiede al server di non chiudere la connessione dopo la sua risposta. Ciò gli consentirà di utilizzare la stessa connessione per una richiesta successiva. La connessione non rimane aperta a tempo indeterminato. Il server la chiuderà dopo un periodo prolungato di inattività. | |
durata in secondi durante la quale la connessione [Keep-Alive] rimarrà aperta | |
Set di caratteri che il client è in grado di gestire | |
Elenco delle lingue preferite dal client. |
Compiliamo il modulo come segue:

Utilizziamo il pulsante [Invia] in alto. Il suo codice HTML è il seguente:
Quando si fa clic sul pulsante [Invia], il browser invia i parametri del modulo (il tag <form>) all'URL specificato nell'attributo [action] del tag <form action="URL">, se presente. Se questo attributo non esiste, i parametri del modulo vengono inviati all'URL che ha fornito il modulo. Questo è il caso in questione. Il pulsante [Invia] dovrebbe quindi attivare una richiesta dal browser all'URL [http://localhost/aspnet/chap1/params.aspx] con i parametri del modulo inclusi. Poiché la pagina [params.aspx] memorizza la richiesta ricevuta, dovremmo essere in grado di determinare in che modo il client ha inviato questi parametri. Proviamo. Facciamo clic sul pulsante [Invia]. Riceviamo la seguente risposta dal browser:

Questa è la pagina iniziale, ma si può notare che l'URL è cambiato nel campo [Indirizzo] del browser. È diventato il seguente:
http://localhost/aspnet/chap1/params.aspx?R1=Oui&C1=un&C2=deux&txtSaisie=programmation+web&txtMdp=ceciestsecret&areaSaisie=les+bases+de+la%0D%0Aprogrammation+web&cmbValeurs=choix3&lst1=liste3&lst2=liste1&lst2=liste3&cmdRenvoyer=Envoyer&secret=uneValeur
Possiamo notare che le scelte effettuate nel modulo si riflettono nell'URL. Diamo un'occhiata al contenuto del file [request.txt], in cui è stata memorizzata la richiesta del client:
GET /aspnet/chap1/params.aspx?R1=Oui&C1=un&C2=deux&txtSaisie=programmation+web&txtMdp=ceciestsecret&areaSaisie=les+bases+de+la%0D%0Aprogrammation+web&cmbValeurs=choix3&lst1=liste3&lst2=liste1&lst2=liste3&cmdRenvoyer=Envoyer&secret=uneValeur HTTP/1.1
Connection: keep-alive
Keep-Alive: 300
Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Encoding: gzip,deflate
Accept-Language: en-us,en;q=0.5
Host: localhost
Referer: http://localhost/aspnet/chap1/params.aspx
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113
Vediamo una richiesta HTTP molto simile a quella inizialmente effettuata dal browser quando ha richiesto il documento senza inviare alcun parametro. Ci sono due differenze:
I parametri del modulo sono stati aggiunti all'URL del documento nel formato ?param1=val1¶m2=val2&... | |
Il client utilizza questa intestazione HTTP per indicare l'URL del documento che stava visualizzando quando ha effettuato la richiesta |
Diamo un'occhiata più da vicino a come sono stati passati i parametri nella richiesta GET URL?param1=value1¶m2=value2&... HTTP/1.1, dove param1, param2, ecc. sono i nomi dei controlli del modulo web e value1, value2, ecc. sono i valori ad essi associati. Di seguito è riportata una tabella a tre colonne:
- Colonna 1: mostra la definizione di un controllo HTML dell'esempio
- Colonna 2: mostra come questo controllo appare in un browser
- Colonna 3: mostra il valore inviato al server dal browser per il controllo della Colonna 1, nella forma che assume nella richiesta GET dell'esempio
Controllo HTML | Valore | Valori restituiti |
<input type="radio" value="Yes" name="R1">Yes <input type="radio" name="R1" value="no" checked>No | - il valore dell'attributo value del pulsante di opzione selezionato dall'utente. | |
<input type="checkbox" name="C1" value="one">1 <input type="checkbox" name="C2" value="due" checked>2 <input type="checkbox" name="C3" value="three">3 | C1=uno C2=due - valori degli attributi "value" delle caselle di controllo selezionate dall'utente | |
<input type="text" name="txtInput" size="20" value="alcune parole"> | txtInput=web+programmazione - testo digitato dall'utente nel campo di immissione. Gli spazi sono stati sostituiti dal segno + | |
<input type="password" name="txtMdp" size="20" value="aPassword"> | txtPassword=thisIsSecret - testo digitato dall'utente nel campo di immissione | |
<textarea rows="2" name="inputArea" cols="20"> riga1 riga2 riga3 </textarea> | areaSaisie=le+basi+del+web%0D%0A programmazione+web - testo digitato dall'utente nel campo di immissione. %OD%OA è il marcatore di fine riga. Gli spazi sono stati sostituiti dal segno + | |
<select size="1" name="cmbValues"> <option>scelta1</option> <option selected>scelta2</option> <option>scelta3</option> </select> | cmbValues=opzione3 - valore selezionato dall'utente dall'elenco a selezione singola | |
<select size="3" name="lst1"> <option selected>list1</option> <option>list2</option> <option>list3</option> <option>elenco4</option> <option>elenco5</option> </select> | ![]() | lst1=list3 - valore selezionato dall'utente dall'elenco a selezione singola |
<select size="3" name="lst2" multiple> <option selected>list1</option> <option>list2</option> <option selected>list3</option> <option>list4</option> <option>list5</option> </select> | ![]() | lst2=list1 lst2=list3 - valori selezionati dall'utente dall'elenco a selezione multipla |
<input type="submit" value="Invia" name="cmdSubmit"> | cmdSubmit=Invia - attributi name e value del pulsante utilizzato per inviare i dati del modulo al server | |
<input type="hidden" name="secret" value="aValue"> | secret=aValue - attributo value del campo nascosto |
Potresti chiederti cosa abbia fatto il server con i parametri che gli sono stati passati. In realtà, nulla. Una volta ricevuta la richiesta
GET /aspnet/chap1/params.aspx?R1=Oui&C1=un&C2=deux&txtSaisie=programmation+web&txtMdp=ceciestsecret&areaSaisie=les+bases+de+la%0D%0Aprogrammation+web&cmbValeurs=choix3&lst1=liste3&lst2=liste1&lst2=liste3&cmdRenvoyer=Envoyer&secret=uneValeur HTTP/1.1
Il server web ha passato i parametri nell'URL al documento http://localhost/aspnet/chap1/params.aspx, cioè al documento che abbiamo creato inizialmente. Non abbiamo scritto alcun codice per recuperare ed elaborare i parametri che il client ci invia. Quindi tutto avviene come se la richiesta del client fosse semplicemente:
Ecco perché, in risposta al nostro pulsante [Submit], abbiamo ricevuto la stessa pagina ottenuta inizialmente richiedendo l'URL [http://localhost/aspnet/chap1/params.aspx] senza parametri.
2.7.2.2. Metodo POST
Il documento HTML è ora configurato in modo che il browser utilizzi il metodo POST per inviare i valori del modulo al server web:
Richiediamo il nuovo documento tramite l'URL [http://localhost/aspnet/chap1/params.aspx], compiliamo il modulo come abbiamo fatto per il metodo GET e inviamo i parametri al server utilizzando il pulsante [Invia]. Riceviamo la seguente pagina di risposta dal server:

Otteniamo quindi lo stesso risultato del metodo GET, ovvero la pagina iniziale. Notiamo una differenza: nel campo [Indirizzo] del browser, i parametri trasmessi non compaiono. Ora, diamo un'occhiata alla richiesta inviata dal client e salvata nel file [request.txt]:
POST /aspnet/chap1/params.aspx HTTP/1.1
Connection: keep-alive
Keep-Alive: 300
Content-Length: 210
Content-Type: application/x-www-form-urlencoded
Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Encoding: gzip,deflate
Accept-Language: en-us,en;q=0.5
Host: localhost
Referer: http://localhost/aspnet/chap1/params.aspx
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113
R1=Oui&C1=un&C2=deux&txtSaisie=programmation+web&txtMdp=ceciestsecrey&areaSaisie=les+bases+de+la%0D%0Aprogrammation+web&cmbValeurs=choix3&lst1=liste3&lst2=liste1&lst2=liste3&cmdRenvoyer=Envoyer&secret=uneValeur
Nella richiesta HTTP del client compaiono nuovi elementi:
La richiesta GET è stata sostituita da una richiesta POST. I parametri non sono più presenti nella prima riga della richiesta. Possiamo vedere che ora sono posizionati dopo la richiesta HTTP, a seguito di una riga vuota. La loro codifica è identica a quella della richiesta GET. | |
numero di caratteri "pubblicati", ovvero il numero di caratteri che il server web deve leggere dopo aver ricevuto le intestazioni HTTP per recuperare il documento inviato dal client. Il documento in questione qui è l'elenco dei valori del modulo. | |
specifica il tipo di documento che il client invierà dopo le intestazioni HTTP. Il tipo [application/x-www-form-urlencoded] indica che si tratta di un documento contenente i valori del modulo. |
Esistono due metodi per trasmettere dati a un server web: GET e POST. Un metodo è migliore dell'altro? Abbiamo visto che se i valori di un modulo fossero inviati dal browser utilizzando il metodo GET, il browser visualizzerebbe l'URL richiesto nella barra degli indirizzi nel formato URL?param1=val1¶m2=val2&.... Questo può essere visto sia come un vantaggio che come uno svantaggio:
- un vantaggio se si desidera consentire all'utente di salvare questo URL parametrizzato nei propri segnalibri
- uno svantaggio se non si desidera che l'utente abbia accesso a determinate informazioni del modulo, come i campi nascosti
D'ora in poi, useremo quasi esclusivamente il metodo POST nei nostri moduli.
2.8. Conclusione
Questo capitolo ha introdotto vari concetti di base dello sviluppo web:
- i vari strumenti e tecnologie disponibili (Java, ASP, ASP.NET, PHP, Perl, VBScript, JavaScript)
- la comunicazione client-server tramite il protocollo HTTP
- progettazione di un documento utilizzando l'HTML
- la progettazione di moduli di input
Abbiamo visto un esempio di come un client possa inviare informazioni al server web. Non abbiamo trattato il modo in cui il server possa
- recuperare queste informazioni
- elaborarle
- inviare al client una risposta dinamica basata sul risultato dell'elaborazione
Questo è il campo della programmazione web, un argomento che tratteremo nel prossimo capitolo con un'introduzione alla tecnologia ASP.NET.


