Lo strato applicativo di Internet
L'aspetto di Internet, per come è noto ai più, si basa essenzialmente sulla navigazione del World Wide Web (trad. lett. ragnatela mondiale), fondata su tre meccanismi per rendere le informazioni prontamente disponibili:
A questo semplice trittico, si sono via via aggiunte sempre più tecnologie (CSS, Javascript, CGI, CMS, RSS, CDN, Web Services, Web Semantico), a cui in questa e nella prossima sezione tenteremo di dare un ordinamento.
Nel 1991 Tim
Berners-Lee, durante il suo lavoro al CERN
di Ginevra, affrontò il problema di visualizzare congiuntamente i
grafici e le tabelle prodotti come risultati di esperimenti
scientifici, condotti su macchine diverse ed in laboratori differenti.
Per questo, realizzò (assieme al collega Robert
Cailliau)
un meccanismo di condivisione delle documentazione scientifica in
formato elettronico, tale da renderla accessibile in modo indipendente
dal particolare tipo di computer dell'utente. Successivamente, accettò
l'offerta di trasferirsi al Massachusetts
Institute of Technology (MIT) di Boston, presso cui nel 1994
fondò il World Wide
Web Consortium (W3C).
Il linguaggio con cui si definisce il contenuto della presentazione è l'HTML, con cui sono scritte le pagine definite statiche, visualizzabili mediante una applicazione browser, detta anche User Agent. Queste pagine sono richieste, mediante il protocollo HTTP, ad un sistema remoto dove è in esecuzione un Web Server. La URL è un indirizzo di livello applicativo, che consente di individuare contemporaneamente il protocollo, il computer che ospita il web server, e la specifica pagina richiesta.
Il World Wide Web Consortium (W3C) è l'organizzazione nata allo scopo di studiare, migliorare e definire nuove tecnologie relative al WWW, con il fine di conseguire il massimo delle potenzialità offerte da questo mezzo. Non è un ente di standardizzazione, ed i suoi documenti sono delle raccomandazioni a cui i produttori di software sono invitati ad attenersi. D'altra parte, tra i membri del W3C compaiono gli stessi produttori a cui le raccomandazioni sono indirizzate, oltre ad aziende telefoniche, istituzioni di ricerca, e società strategicamente interessate alla crescita del Web. Infine, il W3C mette a disposizione una serie di validatori della sintassi usata nella redazione delle pagine web.
Un linguaggio di marcatura (markup) ha lo scopo di indicare il modo in cui alcune parti di un testo devono essere visualizzate, mediante l'uso di descrittori appositi detti TAG (etichette) che compaiono a coppie, elimitando gli elementi dell'HTML. Mentre i linguaggi di tipo procedurale (es. LaTeX) contengono le istruzioni da eseguire per la visualizzazione desiderata, i linguaggi descrittivi lasciano al visualizzatore il compito di stabilire il risultato finale effettivo, e danno solo delle indicazioni di tipo semantico sulla natura delle singole parti di testo. In questa seconda categoria, troviamo SGML, XML, HTML.
Lo Standard Generalized Markup Language (SGML) è un metalinguaggio standardizzato (ISO 8879), discendente dal Generalized Markup Language (GML) sviluppato in IBM, ed è basato sul concetto di definizione del tipo di documento o Document Type Definition (DTD), che a sua volta stabilisce quali sono i TAG permessi in un determinato documento SGML, in modo che questo possa essere verificato formalmente, prima di procedere alla sua visualizzazione, in accordo al markup.
L'eXtensible Markup Language (XML) è una semplificazione e adattamento dell'SGML, da cui è nato, e permette di definire la grammatica di diversi linguaggi specifici derivati. Il suo scopo primario è quello dello scambio di dati strutturati, come ad esempio quelli prelevati da un database, che potrebbero essere descritti nel seguente modo:
<?xml version="1.0" encoding="ISO-8859-1"?> <utenti> <utente> <nome>Luca</nome> <cognome>Ruggiero</cognome> </utente> <utente> <nome>Max</nome> <cognome>Rossi</cognome> </utente> </utenti> |
Nella prima riga, detta prologo, si indica la versione, la codifica dei caratteri, e se esiste, il DTD che ne definisce i tag (anche se per questo scopo, si preferisce fare uso di XML Schema Definition - XSD). Ogni tag può essere corredato da attributi, e la sezione contenuta tra un tag di apertura ed uno di chiusura prende il nome di nodo; il nodo più esterno, che racchiude tutti gli altri, prende il nome di Elemento Radice. Un file XML può essere visualizzato da parte di un browser così come si trova, oppure in associazione con un foglio di stile (CSS o XSL) che ne definisce l'aspetto. In particolare, l'XHTML è un file XML che usa un insieme ridotto dei tag di HTML, ed una sintassi più rigida, e che può essere visualizzato da un browser web solo se accompagnato da un foglio di stile CSS.
L'Hyper Text Mark-Up Language
è stato sviluppato alla fine degli anni '80 da Tim Berners-Lee come
semplificazione dell'SGML, e la sua sintassi, definita
dal W3C, è praticamente ferma dal
1999 alla versione 4.01 e non
più modificata, perché in un qualche futuro, l'HTML verrà soppiantato da XHTML e XML, o da HTML5.
Un file HTML è composto di elementi racchiusi
tra una coppia di tag
(tag significa etichetta, qui con la funzione
di descrivere
l'aspetto che dovrà avere l'elemento), uno di apertura ed uno di
chiusura, e quest'ultimo, per certi elementi, è opzionale. Ad esempio,
l'elemento <b>testo testo
testo</b> verrà visualizzato in grassetto, come testo
testo testo.
Molto spesso nel tag di apertura di un elemento vengono specificati, oltre al suo tipo, anche uno o più attributi, con lo scopo di arricchire e/o specializzare la semantica standard del tag, assegnando ad una o più proprietà, dei valori definiti in modo esplicito. Per questo, il formato di un elemento HTML avrà il generico aspetto
<tipo attr1=valore1 attr2=valore2 ... > testo al quale si applica la semantica del tag </tipo> |
Volendo fare un esempio che non c'entra nulla, è come se un documento HTML fosse un banco per la vendita di ortofrutta, esposta in cassette (elementi), ognuno recante una etichetta (tag) con su scritto il tipo del prodotto (pere, pomodori, carote...) assieme a degli attributi (provenienza, prezzo, tasto bilancia...).
Si può inoltre dire che un file HTML è un file SGML che adotta il DTD
di HTML. La prima riga di un documento HTML contiene infatti l'indicazione
della DTD adottata, indicando così al browser
qual'è la versione di HTML che stiamo utilizzando. Il documento HTML vero
e proprio è quindi racchiuso tra i tag <html>
e </html>, all'interno
dei quali troviamo due sezioni:
Ad esempio, il listato seguente raffigura come si presenta il sorgente
della pagina che stiamo leggendo, che usa il DTD
4.01 Transitional
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML
4.01 Transitional//EN"> <html lang="it"> <head> <meta content="text/html; charset=ISO-8859-1" http-equiv="content-type"> <title>World Wide Web</title> <link rel="stylesheet" type="text/css" href="../corso.css"> <meta content="Alessandro Falaschi" name="author"> </head> <body> <a href="../index.html">Lo strato applicativo di Internet</a> <br> . . . </body> </html> |
Come mostrato dall'esempio, i tag possono essere nidificati,
nel senso che all'interno di un tag di apertura/chiusura se ne può
inserire un altro, e li dentro, un altro ancora. Questo determina la possibilità di interpretare
un documento HTML come una struttura ad albero,
in cui tutti i tag interni ad un altro, sono rappresentati come
discendenti dal primo. Il risultato è il cosiddetto albero DOM (Document
Object Model),
che ad esempio, nel caso del semplice codice HTML mostrato appresso, dà
luogo all'albero mostrato a fianco. Nel caso in cui invece dell'HTML si
debba analizzare allo stesso modo un documento XML, allora il parser da
impiegare è SAX (Simple
API for XML).
<!-- My document
--> <html> <head> <title>My Document</title> </head> <body> <h1>Header</h1> <p> Paragraph </p> </body> </html> |
Sebbene inizialmente l'HTML fosse stato pensato per essere scritto
a mano, attualmente è abbastanza comune ricorrere a strumenti wysiwyg, come ad esempio
(video),
con
cui sono realizzate queste pagine; ciononostante, può accadere di dover
modificare manualmente una pagina preesistente, e conoscere qualcosa
dei possibili elementi può essere molto utile (ma altri editor wysiwyg
sono, ad esempio Amaya, Bluegriffon,
Sigil).
Questo corso non ha nessuna pretesa di includere, tra le altre cose, un corso di HTML. Ma chi volesse approfondire l'argomento, può prendere come ottimo punto di partenza questo sito con le traduzioni italiane del sito di W3C, e che presenta diverso materiale utile, come un tutorial di HTML e CSS, la raccomandazione HTML 4.01, e la tabella degli elementi da questa definiti, che è riportata qui sotto.
Legenda: Facoltativo, Proibito, Vuoto, Disapprovato, DTD Transitoria, DTD Frameset
|
Per ogni elemento della tabella si possono individuare gli attributi supportati, che hanno lo scopo di modificare e/o specificare meglio la funzione dell'elemento, come ad es. href e target, usati con l'elemento <a>, che specificano rispettivamente il collegamento da seguire, e dove aprire la nuova pagina:
<p>Avete visto le nostre <a href="../gabbie/uccelli.gif" target="_top">gabbie per uccelli</a>?</p> |
che produrrà il risultato:
Avete visto le nostre gabbie per uccelli?
Gli elementi che si usano più di frequente, sono
Un elenco un pò più dettagliato, è presente presso Wikipedia.
I fogli di
stile a cascata (CSS = Cascading Style Sheets)
contengono le dichiarazioni necessarie a definire lo stile (per es.
tipo di carattere, colori e spaziature) da applicare ai documenti HTML e XHTML, e la
definizione di queste regole è ancora una volta emanata dal W3C.
In questo modo, i contenuti possono essere sviluppati in modo
indipendente dalla loro modalità di visualizzazione, rendendo in
definitiva più omogenee le diverse pagine di uno stesso sito. Ad
esempio, non occorre ripetere una specifica di colore per tutti gli
elementi simili, con il rischio che qualora si desideri cambiarla,
occorra ripetere ovunque la stessa operazione: al contrario, la
specifica del colore viene eseguita una sola volta, nel foglio di stile.
Sebbene il W3C abbia pubblicato nel 2006 la versione 2.01 delle specifiche CSS, e si stia lavorando alla versione 3.0, la traduzione italiana che riportiamo è quella della versione 2.0 del 1998, che pure è molto diffusa. Il foglio di stile viene associato alla pagina HTML nella sua sezione <head> in uno dei due modi seguenti: usando un file separato, eventualmente ri-usabile a partire da pagine HTML differenti
<html> <head> <title>Esempio</title> <link rel="stylesheet" type="text/css" href="foglio_di_stile.css"> </head> . . |
oppure in-linea nella stessa pagina per la quale se ne desidera l'applicazione
<html> <head> <title>Esempio</title> <style type="text/css"> ...codice css... ...codice css... ...codice css... </style> </head> . . |
Il codice CSS consiste in una serie di regole, ciascuna caratterizzata da un selettore che individua quando applicarla, seguito da una o più istruzioni di assegnazione di uno o più valori a una determinata proprietà:
selettore { proprietà1: valore1; proprietà2: valore2, valore3; } |
Il selettore può corrispondere a
Alcuni esempi di uso dei selettori, possono essere trovati presso HTML.it.
Qui ci limitiamo invece ad esemplificare i concetti esposti mediante l'esempio pratico delle pagine di questo stesso testo, che usa un CSS specifico allo scopo di non ripetere i comandi relativi al colore dello sfondo, ed alla dimensione dei caratteri, per tutti i riquadri di codice. Ciò è ottenuto realizzando i riquadri come una tabella ad una sola cella, ed usando per gli elementi <table> e <td>, un attributo class=pre, al quale sono associati i seguenti selettori nel file corso.css utilizzato:
table.pre { border: 1pt solid rgb(253, 152, 253); width: auto; background-color: rgb(244, 255, 252); } td.pre { font-weight: normal; font-size: small; font-family: monospace,Courier New,Courier; } |
Nell'esempio su riportato, la proprietà border è utilizzata per impostare (qualora all'elemento table sia assegnato un attributo di valore pre) il bordo della tabella che delimita il riquadro ad uno spessore di un pixel, a linea continua, e di colore viola, mentre per lo sfondo (proprietà background-color) è scelto il colore celeste, e la larghezza (width) del riquadro dipenderà da quella del contenuto. Quindi, il selettore td.pre determina l'applicazione delle proprietà sui caratteri contenuti all'interno della colonna, stabilendone il peso, la dimensione, ed il tipo di carattere. Pertanto, un riquadro (vuoto!) sarà realizzato mediante un codice HTML pari a
<table class="pre"
cellpadding="10" cellspacing="0"> <tbody> <tr> <td class="pre"> --- inserire qui il contentuto del riquadro! --- </td> </tr> </tbody> </table> |
Un elenco delle proprietà esistenti, assieme ai loro possibili valori, ed a degli esempi di utilizzo, è fornita assieme alla raccomandazione di W3C, ed è replicata su diversi siti in rete. Tra i riferimenti, elenchiamo alcuni siti dove scegliere liberamente un template di stile (template letteralmente significa sagoma) da usare per dare un aspetto gradevole alle proprie pagine.
Ora che abbiamo (un minimo) più chiaro cosa si intende per style sheet (foglio di stile), evidenziamo che il termine cascading rappresenta il fatto che alcuni selettori possono essere in conflitto tra loro, causando per uno stesso elemento la possibilità di dover applicare regole diverse dagli effetti contrastanti. Per derimere questa contesa, viene applicata una scala di priorità, che attribuisce una maggiore importanza al CSS impostato tra le preferenze da parte dell'umano che sta effettuando la navigazione, rispetto a quello applicato di default dal browser, mentre il CSS impostato dall'autore della pagina prodomina su entrambi. Quindi, predomina la regola più specifica, riconoscendo ad un selettore legato ad un identificatore la priorità rispetto a quello associato ad una classe, e quest'ultimo a sua volta prende il sopravvento su di un selettore relativo ad un elemento HTML.
Ora che abbiamo preparato le pagine che il server web dovrà fornire, su richiesta, al browser, resta il passaggio di come depositarle presso il server. A questo scopo esistono tutta una serie di possibilità, che elenchiamo.
Il File Transfert Protocol è uno tra i protocolli più anziani di Internet, specificato nella RFC 959, e permette ad un programma client di colloquiare con un server in ascolto sulla porta TCP 21, al fine di leggere/scrivere/navigare tra i files del suo filesystem. Può essere invocato da linea di comando, impartendo manualmente i comandi di cui dispone, oppure può essere utilizzata una interfaccia grafica, ormai incorporata nelle stesse applicazioni genericamente usate per navigare nel filesystem locale (ossia, del proprio computer), permettendo in questo caso, operazioni di tipo drag and drop.
In una prima fase del collegamento, l'utente che sta usando il
client si autentica presso il server, trasmettendo la password in
chiaro,
e questa circostanza è uno dei principali motivi per cui l'uso dell'FTP
è sconsigliato/scoraggiato. E' da notare, tuttavia, che esiste anche
una modalità anonima di collegamento, in cui
il client usa con nome utente anonymous, e
come password tipicamente invia il proprio indirizzo email. Vedi, come
esempio, questo file di capture.
Quando ancora il web non esisteva, questo era il modo in cui venivano
messi
pubblicamente a disposizione dati e programmi, ed è tuttora in uso, ad
esempio come meccanismo di default utilizzato dai browser web, per
accedere ad una URI il cui schema
è ftp:, come ad esempio ftp://ftp.debian.org/debian/.
Due ulteriori possibilità sono quelle relative ad un collegamento attivo o passivo. La differenza nasce dal fatto che l'FTP utilizza in effetti due diverse connessioni TCP, la prima detta di controllo, su cui avviene l'autenticazione, e dove poi sono inviati i comandi di sessione, ed una seconda connessione, instaurata sotto il controllo della prima, su cui avviene il trasferimento dati vero e proprio.
Nel caso della modalità attiva, la connessione dati è creata su iniziativa del server, in quanto è quest'ultimo a contattare il client, un pò per meglio gestire le richieste di servizio nel caso di elevato traffico, ed un pò per essere sicuro di stare parlando con chi si è presentato con l'IP sorgente. In questo caso, il server usa la porta 20 come sorgente del canale dati, e contatta il client sul numero di porta da esso usato in uscita, incrementato di uno.
L'ultima delle figure a fianco, prelevate da un articolo pubblicato su qcipc,
mostra il risultato finale di un setup attivo. Questa tecnica dà però
luogo a problemi, ogni volta in cui tra client e server sia interposto
un dispositivo NAT,
ovvero quando il client posside un indirizzo IP privato, ed il server
uno pubblico. Infatti in questo caso, il server non è in grado di
aprire una connessione verso il client, e il trasferimento non può
avere luogo.
Nel caso specificato (presenza di un NAT), si ricorre allora alla modalità di FTP passivo, mostrata nella figura seguente. In questo caso anche la connessione dati viene aperta su iniziativa del client, e nella prima fase, il server comunica al client un nuovo numero di porta effimera, su cui aprire la connessione dati. Quindi nel caso passivo, è sempre il client ad aprire entrambi i canali (di controllo e dati), e non si presenta nessun problema, anche in presenza di NAT.
A volte, per garantire una maggiore sicurezza e confidenzialità, il
client si trova ad operare in una modalità cosiddetta chrooted,
cioè a dire, come se sul server fosse stato eseguito il comando chroot, abbreviazione di change
root.
In tal caso, il client non può più navigare per tutto il filesystem del
server, ma solo a partire (e poi, in giù) da quella che sarebbe stata
la sua home directory, se si fosse collegato
come terminale, sullo stesso computer che ospita il server FTP.
Esistono molte implementazioni di client e server FTP.
Lo SSH File Transfer Protocol non è ancora uno standard Internet (l'ultimo Draft è scaduto), ma è utilizzato estensivamente come un vero e proprio protocollo di accesso remoto ad un filesystem. Non consiste nella esecuzione di FTP su di una connessione resa sicura via SSH, ma è un protocollo sviluppato ex-novo, che sfrutta i meccanismi di sicurezza offerti da uno strato che assicura tale funzione, ma l'accoppiata con SSH è particolamente diffusa e utilizzata.
Il Network File system venne inizialmente sviluppato nel 1984 da Sun Microsystem, e da allora ha subito diverse evoluzioni, fino alla ultima versione normativa definita dalla RFC 3530. Prevede che un computer -server NFS- offra parte del suo filesystem, per essere montato da altri computer -client NFS-, i quali da quel momento in poi, accedono al disco remoto come se fosse il proprio. E' utilizzato in special modo per realizzare delle stazioni di lavoro diskless, oppure per condividere dati e programmi su più macchine, senza doverli replicare.
Il Server Message Block è il protocollo usato dai prodotti Microsoft per condividere in rete files, stampanti, porte seriali e comunicazioni di varia natura, e include un meccanismo di comunicazione autenticata tra processi. Nato per essere usato principalmente su rete locale in associazione al NetBIOS, funziona anche su TCP/IP. Come per il caso precedente, sebbene possa ben essere usato per salvare le pagine web sul disco del server, ha degli scopi più articolati.
L'Internet Message Acces Protocol, sebbene nato per la gestione dell'email, può altrettanto bene essere usato per trasferire file da/verso il proprio computer locale ed un computer remoto!
Il Web Distributed Authoring and Versioning è una estensione di HTTP definita nella RFC 4918 per facilitare la collaborazione tra utenti nella gestione di documenti e file presenti su server HTTP. Consiste in un insieme di nuovi metodi ed intestazioni di HTTP che permettono oltre che di leggere, anche di scrivere, spostare, gestire la proprietà ed i diritti, e permettere la modifica delle pagine da parte di un gruppo di autori. Il supporto offerto dai sistemi operativi a Webdav permette in generale di vedere una URI HTTP come un filesystem esterno.
Un indirizzo di livello applicativo che identifica una risorsa accessibile mediante HTTP è chiamata URI (Uniform Resource Identifier), come definito nella RFC 3986, ed estende i concetti di URL (Uniform Resource Locator, utilizzato per indicare anche dove trovare la risorsa, e come utilizzarla) ed URN (Uniform Resource Name, utilizzato esclusivamente per dare un nome univoco alla risorsa) precedentemente usati. La generica sintassi di una URI
<scheme>:<scheme-specific-part> |
ne
permette l'uso per identificare non solo un indirizzo web, ma anche (ad
es.) un indirizzo email, un identificativo VoIP, un codice ISBN,
o tante altre cose, in base al tipo di schema
che vi compare, in accordo a quelli registrati presso lo IANA.
Lo schema è indicativo del namespace
sotto cui ricade la risorsa, e la sintassi della parte scheme-specific-part
dipende dallo schema usato, ma per parecchi di questi, ci si può riferire
a questo generico esempio relativo ad una URL HTTP:
in cui
Quando una URI compare come valore di un attributo href di un elemento anchor in una pagina HTML, il browser tenta di dereferenziare l'indirizzo, intraprendendo una azione legata allo schema che compare nella URI. Se ad esempio si tratta di un'altra pagina web, ne farà richiesta al server che la ospita, e visualizzerà il body della risposta, mentre se ad esempio si tratta di uno schema mailto (es. mailto:jsmith@example.com), manderà in esecuzione l'applicazione-client email (user agent) predefinita, impostando il destinatario a quello che compare nella URI.
L'HyperText Transfer Protocol è definito nella sua versione attuale (1.1) dalla RFC 2616, che descrive la sintassi dei suoi messaggi per mezzo di un formalismo noto come forma aumentata di Backus-Naur (ABNF).
Un breve parentesi, per illustrare come la ABNF è una sintassi formale orientata alla descrizione di grammatiche context-free, e che funziona mediante l'applicazione ripetuta di regole di produzione del tipo
simbolo = espressione |
che indicano come dei simboli non terminali (a sinistra dell'uguale) possono essere riscritti in termini di sequenze di altri (terminali o meno). Partendo da un simbolo non terminale, si applicano ripetutamente le regole, finché non restano solo simboli terminali, per i quali non esistono regole di riscrittura, ed il risultato forma una frase appartenente al linguaggio che si sta descrivendo. L'espressione può indicare il semplice concatenamento di altre regole e simboli terminali, oppure l'alternativa tra essi
terno = numero numero numero / ambo numero ambo = numero numero numero = 1 / 2 / 3 / 4 / 5 / 6 / 7 / 8 / 9 / 0 |
mentre altre notazioni hanno altri significati, come ad esempio un [elemento] tra parentesi quadre è
opzionale, ed un asterisco come in *ALPHA
indica la ripetizione di un qualsiasi numero
di ALPHA.
L'ABNF è spesso usata per descrivere i linguaggi di programmazione, e i formati dei protocolli Internet, e per questo, è documentata nella RFC 5234, ed è stata ulteriormente riassunta, nello stesso documento che descrive l'HTTP.
La figura che segue mostra il meccanismo di richiesta/risposta (client/server), a partire da un click su di una pagina, che determina il prelievo dei files dal sever web, che a sua volta provoca la comparsa del risultato sullo schermo. Lo User Agent (browser) nel ruolo di client, invia una richiesta HTTP su di una connessione TCP aperta verso l'indirizzo di trasporto corrispondente alla porta 80, ed il server restituisce la risposta sulla stessa connessione.
Vi sono quindi due tipi di messaggi HTTP: di richiesta e di risposta.
Tanto che la ABNF per l'HTTP, inizia così:
generic-message = start-line *(message-header CRLF) CRLF [ message-body ] start-line = Request-Line | Status-Line |
Nelle prime versioni del protocollo, la connessione veniva chiusa immediatamente dopo che una richiesta era stata soddisfatta, in accordo alla natura senza stato (stateless) del protocollo: il server non mantiene memoria delle richieste precedenti, anche se provenienti dallo stesso client, ma le tratta tutte in modo indipendente l'una dall'altra. D'altra parte, nel caso in cui nella pagina ricevuta siano presenti elementi HTML (come ad es. di tipo <img>), che referenziano oggetti (immagini) da inserire nella pagina da visualizzare, queste vengono allora richieste subito di seguito alla pagina ricevuta. Per riassumere, un video.
In accordo alla descrizione ABNF su riportata, un messaggio di richiesta HTTP è composto da tre parti:
La riga di richiesta ha l'aspetto generico descritto dalla ABNF, a cui è affiancato un esempio reale
Request-Line = Method SP Request-URI SP
HTTP-Version CRLF es. GET /wiki/Pagina_principale HTTP/1.1 |
ed è composta dal metodo (qui, GET), dal nome della risorsa oggetto della richiesta (/wiki/Pagina_principale) così come compare nella URL che ha prodotto la richiesta stessa, e dal nome del protocollo con la sua versione. In generale, la risposta viene generata interpretando la risorsa come il nome di un file, completo di path relativo, che giace sul disco del computer che ospita il server, sotto una apposita directory.
Dei metodi possibili descritti dalla RFC, i più frequentemente usati sono
Il formato delle righe di intestazione HTTP segue quello specificato per il caso delle email, ossia il nome dell'header, seguito da due punti, e poi una stringa che ne specifica il valore. Mentre nelle email, però, gli header sono a prevalente beneficio del ricevente, nell'HTTP sono realmente funzionali al protocollo, e sono presenti sia nelle richieste, che nelle risposte. L'insieme completo dei Request Header che possono comparire nelle richieste è specificato nella RFC. A partire da un esempio concreto, possiamo discutere di
E' composta di tre parti:
Il body è presente nel caso in cui il codice di risposta indichi un successo, ed è posto di seguito alla sezione degli header, separato da questi da una linea vuota, come per l'email.
La prima riga della risposta ha un aspetto del tipo
HTTP/1.1 200 OK |
ed il codice di risposta (nell'esempio, 200 OK) segue le convenzioni già viste per l'email, in cui la prima cifra dà una indicazione relativa all'esito della richiesta, in accordo allo schema. La descrizione dei casi d'uso dei diversi codici è contenuta nella RFC 2616, e wikipedia ne presenta un elenco sintetico. Alcuni codici di risposta particolarmente significativi sono
Commentiamo assieme il capture relativo alla richiesta ripetuta della URI http://infocom.uniroma1.it/alef/tesi/.
In definitiva, una richiesta o risposta HTTP che entrasse per intero in uno stesso segmento TCP, e nel caso fosse una risposta, contenesse una pagina HTML, avrebbe la composizione mostrata di seguito:
Ethernet | IP | TCP |
|
Nella navigazione web sono presenti una o più cache intermedie, che hanno lo scopo di alleggerire il carico dei server. Una prima cache è interna al browser, ma in rete possono esserne dislocate altre, che prendono il nome di Proxy, a cui il client può indirizzare tutte le richieste (dovunque dirette), e che si fa carico di effettuare le richieste per suo conto, e di fornire la risposta.
Se
le risorse richieste giacciono già nella cache (del proxy, o del
browser), queste possono essere restituite direttamente, senza
recuperarle nuovamente dal server di origine, che quindi riduce
l'occupazione di banda di uscita. Se diversi client usano lo stesso
proxy, e referenziano le stesse pagine, il risparmio di banda può
diventare considerevole, e può convenire dislocare un proxy interno ad
una sottorete, da far condividere a tutti i client di quella sottorete.
Un meccanismo che consente l'accesso diretto alle repliche presenti in cache è quello di validazione, ottenuto rendendo i metodi di richiesta condizionali, mediante l'inserimento degli header
In questo modo, se il server verifica che l'oggetto è sempre uguale
(ossia, la data è la stessa, e/o l'Etag
coincide), risponde con un codice 304 Not Modified,
ed il browser (il proxy) visualizza (invia) il contenuto della propria
cache. Un esempio di tale comportamento, può essere riscontrato nel
file di capture già
analizzato.
Un secondo meccanismo di gestione delle cache si basa invece su di una logica di obsolescenza (expiration), fondata sull'uso di alcuni header specifici, come
Quando un client sta per effettuare una richiesta di un oggetto che ha in cache, ma che non è ancora spirato, può scegliere di rinunciare ad effettuare la richiesta, e visualizzare la sua copia locale. Al contrario, un server può tentare di impedire che un oggetto da esso inviato venga memorizzato nelle cache, usando i valori no-cache, no-store, must-revalidate, come ad esempio avviene nel caso di pagine dinamiche ottenute mediante l'esecuzione di CGI.
Mentre tutti i browser hanno la possibilità di configurare volontariamente un proxy a cui inoltrare le richieste, può succedere che i router della LAN o del provider provvedano di loro iniziativa a reinstradare i pacchetti IP associati a comunicazioni HTTP, in modo che attraversino un Proxy. Questa funzionalità prende il nome di Transparent o Intercepting Proxy.
Un Reverse Proxy al contrario, invece di essere usato per uscire, è usato per smistare il traffico in ingresso ad una lan, verso una pluralità di web server interni, ognuno che serve pagine per un diverso dominio, e potenzialmente configurati con un IP privato. Questo ha lo scopo di migliorare la sicurezza, di permettere il bilanciamento del carico, oltre naturalmente a realizzare il caching delle pagine in uscita.
Le
risorse associate agli URI presenti su determinate pagine web, e dalle
quali possono essere richieste, possono nel frattempo essere state
trasferite su computer differenti e cambiare la componente dominio
della URI, oppure possono essere state ri-nominate, e pur rimanendo
sullo stesso server (e dominio), prendere un URI diverso. In tal caso,
le richieste che citano il vecchio indirizzo si vedrebbero restituire
una risposta del tipo 404 Not Found, producendo
disappunto e frustrazione. La soluzione offerta da HTTP si basa su di un
meccanismo di redirezione, che usa i codici di
risposta 301-303
e 307, e che comunica il nuovo indirizzo come valore associato
all'header Location
presente nella risposta. La differenza tra i diversi codici di risposta
risiede nelle possibilità che il nuovo indirizzo sia temporaneo o
permanente (nel qual caso, i collegamenti preferiti
dovrebbero aggiornarsi automaticamente), e nella possibilità che il
browser segua automaticamente il nuovo indirizzo, oppure chieda prima
conferma all'operatore umano.
Affinché il server verso cui sono dirette le richieste per risorse che non ci sono più, risponda con un codice di tipo 3xx Moved anziché 404 Not Found, il server stesso deve essere debitamente configurato in tal senso.
L'HTTP permette la negoziazione dei contenuti, ossia consente allo User Agent di esprimere le proprie preferenze a riguardo delle diverse possibili versioni degli oggetti richiesti, delegando poi al server di decidere. Oppure, al contrario, si consente al Server di offrire una scelta di possibilità, ed allo UA di decidere quale utilizzare. Queste preferenze vengono espresse mediante l'uso di appositi header nella richiesta, come Accept, Accept-Charset, Accept-Encoding, Accept-Language, e User-Agent. Il server quindi, utilizza l'header di risposta Vary per specificare su quali dimensioni si è effettuata la scelta del tipo di contentenuto da inviare. Per una descrizione dei metodi usati per gestire la fase di negoziazione dei contenuti, ci si può riferire alla documentazione relativa al server Web Apache.
Quando uno UA invia più richieste consecutive verso uno stesso server, come nel caso, ad esempio, in cui si vogliano scaricare tutte le immagini contenute in una determinata pagina appena ricevuta, è molto più sensato ri-utilizzare sempre la stessa connessione TCP, piuttosto che aprirne una diversa per ogni diverso oggetto richiesto. In tal modo, oltre a risparmiare sui tempi necessari al Round Trip Time necessario per l'apertura e la chiusura delle connessioni, si riduce l'occupazione di memoria necessaria ai buffer del TCP, e la gestione del controllo di congestione attuata dal TCP può evolvere su di un intervallo temporale più ampio.
![]() |
Nel caso si adottino connessioni persistenti, un client può inviare le richieste in pipeline, ossia una di seguito all'altra, senza attendere la fine della risposta alla richiesta precedente; in tutti i modi, è prescritto che il server invii le risposte nello stesso ordine con cui sono pervenute le richieste.
Nella versione 1.1 di HTTP, le connessioni
persistenti
sono il funzionamento di default, che può essere sovvertito qualora il
client (il server), invii assieme alla richiesta (risposta) l'header Connection:
Close.
Viceversa, per compatibilità con versioni precedenti del protocollo, il
desiderio esplicito di usare connessioni persistenti può essere
segnalato mediante l'header Connection:
KeepAlive.
Un esempio di utilizzo delle conessioni persistenti, è dato dal file di capture relativoalla richiesta
della URI http://www.ubuntu-it.org/index.php?page=Filosofia.
Qualora la richiesta lo permetta (dichiarando tramite l'header Accept-Encoding della richiesta, uno o più algoritmi scelti tra gzip, compress, e deflate), il body della risposta HTTP può contenere un oggetto che è memorizzato, e trasmesso, in forma compressa, ed in tal caso l'header Content-Encoding esprimerà quale sia stato l'algoritmo di compressione scelto. D'altra parte, l'oggetto richiesto può essere memorizzato presso il server in formato nativo, e compresso solo al momento della trasmissione: questa circostanza, viene segnalata per mezzo dell'header Transfer-Encoding, che oltre ai valori prima elencati, prevede anche la codifica chunked.
Più codifiche di trasferimento possono essere applicate in cascata, ma chunked deve essere applicata per ultima, perchè questa anziché realizzare una trasformazione dell'oggetto richiesto, lo segmenta in blocchi (chunks). Questa tecnica è usata quando il server non conosce a priori la dimensione dell'oggetto inviato, perché questo è il risultato di un calcolo ancora in corso, oppure perché si tratta di un contenuto audio/video generato in tempo reale. Al fine di evitare di dover dichiarare una dimensione ignota nell'header Content-length della risposta, l'oggetto viene inviato in modalità chunked, e all'inizio di ogni chunk viene dichiarata l'estensione dello stesso. Come esempio, possiamo esaminare il traffico catturato durante la visita al sito di HttpWatch.
Nei termini definiti al capitolo precedente, la sicurezza in http è volta ad offrire uno o più dei seguenti servizi:
Mentre per gli ultimi due punti si ricorre essenzialmente alla attivazione del TLS, il primo punto, anche se potenzialmente gestibile con meccanismi appositamente definiti per l'HTTP, viene generalmente implementato a cura di uno strato applicativo ancora superiore all'HTTP, mediante le tecniche dei CGI, dei cookie, o del javascript. Ma iniziamo, comunque, dal meccanismo basato sul solo HTTP.
Il meccanismo di autenticazione previsto da HTTP si basa su di uno schema challenge-response, in cui il server dopo aver ricevuto la richiesta di un oggetto per il quale è stato ristretto l'accesso, anziché inviare la risposta contenente l'oggetto, emette una risposta con la quale sfida il client ad autenticarsi; questi sottomette quindi una nuova richiesta, a cui allega le proprie credenziali. Sono previste due modalità di autenticazione, dette Basic e Digest, descritte nella RFC 2617, entrambe basate sulla conoscenza di un segreto (ossia, di una coppia username-password) condiviso tra client e server.
Questo schema è da considerare assolutamente insicuro, e da usare solo in un ambito del tutto fidato, in quanto la password è inviata in chiaro, seppur con codifica base64. La prima risposta (di sfida) del server, che riporta un codice 401 Unauthorized, contiene un header
WWW-Authenticate: Basic realm="Laboratorio Internet" |
In tal caso il browser presenta all'utente una nuova finestra, in cui cita il valore del Realm (in modo che l'utente possa ricordare quali credenziali usare), e richiede l'immissione di una coppia utente-password. Ad esempio, l'identità dell'utente "Aladdin" con password "open sesame" saranno combinati assieme come "Aladdin:open sesame", e quindi rappresentati con codifica base64, come QWxhZGRpbjpvcGVuIHNlc2FtZQ== (come verifica, eseguire da terminale il comando echo QWxhZGRpbjpvcGVuIHNlc2FtZQ== | base64 -d). Pertanto, dopo l'immissione di utente e password da parte di chi siede di fronte al computer, il browser reitera la richiesta precedente, aggiungendo alla stessa una intestazione
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
che questa volta produce nel server l'invio della pagina protetta. Un esempio del comportamento descritto, si può ottenere visitando questa pagina protetta, (username/password = labint/lablint) a cui corrisponde questo file di capture.
Dal punto di vista dell'utente, il funzionamento di questo schema è del tutto identico al precedente; al contrario di quello, però, la password viene inviata in una forma crittograficamente sicura. Anche ora il server risponde alla prima richiesta, con una risposta che riporta il codice 401 Unauthorized, ma che stavolta contiene un header di sfida del tipo
WWW-Authenticate: Digest realm="testrealm@host.com", qop="auth,auth-int", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="5ccc069c403ebaf9f0171e9517f40e41 |
Mentre il realm ha come prima lo scopo di essere mostrato all'utente, il nonce viene usato assieme al nome utente, alla password, al realm, al metodo, all'URI della risorsa, ad un contatore di richiesta (nc), al codice di quality of protection (qop) prescelto, e ad un nonce del client (cnonce), per calcolare (mediante il calcolo ripetuto di un hash MD5), il valore della response da inserire nell'header Authorization da restituire al server:
Authorization: Digest username="Mufasa", realm="testrealm@host.com", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", uri="/dir/index.html", qop=auth, nc=00000001, cnonce="0a4f113b", response="6629fae49393a05397450978507c4ef1", opaque="5ccc069c403ebaf9f0171e9517f40e41" |
Il server usa la stessa password (o meglio, una sua versione crittografata) per effettuare lo stesso calcolo, ed autenticare l'utente.
Qualora si desideri un livello di sicurezza maggiore di quello offerto dal semplice uso della autenticazione HHTP, si può ricorrere al Secure Sockets Layer (SSL), ovvero alla sua più recente denominazione TLS. In tal caso, la URI presenta una schema di tipo https, che causa l'apertura di una connessione TCP verso la porta 443 anziché la 80. A quel punto, un messaggio di Client_Hello (capture) determina l'inizio dell'handshake protocol, al termine del quale l'applicazione prosegue come se si trattasse di una normale connessione HTTP su TCP, mentre invece tutto il traffico si svolge in modalità crittografata, come descritto nella RFC 2818. Nelle esercitazioni, troviamo la descrizione di come dotare il nostro server web Apache di un certificato X.509, ed attivare un host virtuale che risponda all'HTTPS.
Anzichè usare una diversa porta come per il caso dell'https, la RFC 2817 descrive l'uso del codice di risposta 426 Upgrade Required, e dell'header Upgrade posto nella nuova richiesta, tali da permettere ad una connessione HTTP normale, di passare in una modalità protetta da TLS, sempre usando la stessa porta 80. Questo, oltre che permette di risparmiare un indirizzo di trasporto, consente di ospitare dei server virtuali sicuri su di un medesimo computer, senza necessità di assegnare allo stesso molteplici indirizzi IP. Infatti, se il TLS si attiva prima dell'HTTP, il certificato da inviare ai client è scelto solo in base all'indirizzo IP dal lato server del socket, mentre se parte prima l'HTTP, la scelta può tener conto anche del nome a dominio che compare nell'intestazione Host.
Dopo aver illustrato molti dettagli dell'HTTP, svolgiamo un approfondimento di ciò che accade ai due estremi della navigazione web, iniziando da quando una risposta giunge al browser, e come possano entrare in gioco meccanismi differenti dalla semplice visualizzazione della pagina ricevuta. Quindi, illustriamo come possono essere gestiti gli schemi della URI diversi da http. Infine, discutiamo come si possano inviare, assieme ad una richiesta HTTP, anche alcuni dati intenzionalmente immessi dall'operatore umano.
La risposta HTTP contiene, tra gli altri, l'header Content-Type, che identifica il documento trasportato nel body, come aderente ad uno dei tipi MIME registrati presso IANA. Alcuni di questi sono direttamente visualizzabili dal browser, mentre per altri, viene invocata una Helper Application, posta in corrispondenza al tipo di file dal sistema operativo stesso, oppure memorizzata a seguito di una domanda a riguardo, posta all'utente. Ma non sempre un server web invia un header Content-Type (perchè ciò avvenga, deve essere opportunamente configurato), e così a volte il browser deve tentare di assegnare per suo conto un Mime Type al file ricevuto, in base all'estensione del file, oppure analizzando l'inizio dello stesso. Se tutti i tentativi falliscono, il file viene trattato come application/octet-stream, e viene suggerito di salvarlo su disco.
Un volta determinato con successo il Mime-Type dell'oggetto ricevuto, e individuata l'applicazione Helper idonea a visualizzare/riprodurre lo stesso, questa può essere eseguita in modo indipendente, o esterno al browser, oppure direttamente all'interno della finestra del browser. In questo secondo caso, il programma Helper prende il nome di plugin, in quanto non può essere eseguito in modo indipendente, dipendendo dai servizi offerti dal browser stesso, come ad esempio l'interfaccia grafica. A volte invece, un plugin ha il solo scopo di far eseguire una applicazione preesistente, che altrimenti verrebbe eseguita esternamente al browser, all'interno dello stesso. La configurazione attuale dei plugin del browser Firefox, ad esempio, può essere visualizzata immettendo l'indirizzo about:plugins nella sua barra degli indirizzi.
A
volte il programma da usare per visualizzare/riprodurre un oggetto
richiesto mediante web, non è determinato al momento dell'arrivo della
risposta, bensì al momento in cui viene cliccata la URI
presente in una pagina web. Se la URI fa riferimento ad uno schema
che non è http, allora il
browser non invierà nessuna richiesta http,
ed invocherà invece un programma apposito, passandogli la URI come
argomento, delegando a questo il compito di procedere, in accordo al
protocollo associato alla URI.
Ad esempio, cliccando una URI per la quale lo schema è mailto:, verrà mandato in esecuzione lo UserAgent di invio email, nella cui finestra di composizione troveremo pre-impostate le informazioni relative all'indirizzo di destinazione, come desunte dal resto della URI (vedi anche RFC2368). Come ulteriore esempio, nel caso di uno schema ftp://, è il browser stesso ad effettuare una connessione anonima e permettere la navigazione nel file system remoto: provare ad es. con ftp://ftp.debian.org/debian/.
In Firefox, le preferenze per quanto riguarda le modalità di navigazione e di gestione delle informazioni ricevute possono essere impostate inserendo l'indirizzo about:config nella barra degli indirizzi; l'effetto di tale azione, oltre a mostrare i valori impostati agendo sul menù delle preferenze, ne visualizza anche molti altri, definiti in accordo a queste regole di configurazione. In particolare,
A volte la risposta HTTP, anziché contenere un oggetto (come ad es. una pagina HTML, una immagine, od un contenuto multimediale) che deve essere semplicemente mostrato dal browser (o da un plugin, o da una helper application), consegna allo UA del vero e proprio codice eseguibile, rendendo così il web un meccanismo di distribuzione di applicazioni, ossia un application server. Fin qui nulla di straordinario, tranne per il fatto che il codice ricevuto deve essere eseguito indipendentemente dal S.O. presente sul computer presso il quale è utilizzato il browser, ed a questo fine, sono state sviluppate le soluzioni proposte con Java, Javascript e Flash, brevissimamente descritte appresso.
Il linguaggio
Java è stato definito da Sun
Microsystem (ora propretà di Oracle),
che recentemente l'ha rilasciato con licenza
GPL, ma che fin dal 1998 ha adottato un modello di sviluppo aperto
indicato come Java
Community Process. Java è basato su oggetti, e presenta una sintassi
abbastanza simile al c++ (video
corso in italiano).
La compilazione del codice sorgente Java produce un eseguibile detto bytecode
che, anziché essere legato ad un particolare tipo di ambiente
hardware/software, deve essere eseguito da un altro programma,
denominato Java
Virtual Machine (JVM),
che costituisce lo strato software che effettivamente interagisce con
il computer ospite. Pertanto, se il bytecode è uno, di macchine
virtuali ce ne sono tante, quante sono le architetture alternative.
Le versioni di JVM più recenti prevedono un ulteriore passo di elaborazione del bytecode, detto compilazione Just In Time (JIT), e che produce il codice macchina relativo alla architettura ospite, direttamente al momento della esecuzione. In una pagina HTML possono essere presenti diverse applet java, inserite nella stessa mediante l'elemento HTML <object>. Il nutrito insieme di librerie di classi disponibili per Java, permette di scrivere applicazioni (applet) di ogni tipo, anche con accesso alla rete, e che una volta ricevute tramite web, sono eseguite in una cosiddetta sandbox, in modo da limitare al minimo indispensabile i diritti di uso ed accesso alle risorse del computer ospite.
La Java Micro Edition
è la specifica di un sottoinsieme della piattaforma Java, idoneo per lo
sviluppo di applicazioni da utilizzare nell'ambito di dispositivi con
prestazioni ridotte, come ad es. i telefoni cellulari, ed il cui codice
sorgente è stato rilasciato sotto licenza GPL con il nome di PhoneMe;
dato che l'ambiente può essere emulato su computer, lo sviluppo di nuove applicazioni mobili è particolarmente facilitato.
Le funzionalità di cui una applicazione JME può usufruire sono descritte dalla applicazione di un particolare profilo, identificato al momento della configurazione della JME di cui è equipaggiato il dispositivo su cui l'applicazione dovrà essere eseguita. Ad esempio, la Connected Limited Device Configuration (CLDC) contiene un sotto-insieme minimo di librerie di classi Java, e quando accoppiata alla Mobile Information Device Profile (MIDP), viene definito un ambiente dotato di una API alla interfaccia grafica (GUI), e di una API orientata alla esecuzione di giochi bi-dimensionali: le applicazioni scritte per questo profilo, sono dette MIDlets.
Mentre per Java, il bytecode ricevuto deve essere eseguito da una JVM (che non è detto sia installata), il codice Javascript è inviato in forma di sorgente, è molto semplificato rispetto a Java (con cui non ha neanche molto a vedere, se è per quello), e viene eseguito direttamente dal browser. Il sorgente viene così interpretato riga per riga dallo UA stesso; per mantenere compatibilità tra i diversi UA, Javascript è stato sottoposto ad un processo di standardizzazione da parte di ECMA, riconosciuto anche da ISO, e che gli ha portato il secondo nome di ECMAscript. Ciononostante, le implementazioni di Javascript su browser diversi sono parzialmente incompatibili, ed il codice Javascript deve fare del suo meglio per tentare di capire dove si trova, ed evitare di eseguire istruzioni che potrebbero essere interpretate per il verso sbagliato. Queste tecniche sono state poi incorporate nelle svariate librerie (o framework) che offrono funzioni di più alto livello, realizzate mediante funzioni scritte in javascript.
L'uso tradizionale di
Javascript
è stato quello di produrre particolari effetti grafici non ottenibili
con il solo HTML, ma che attualmente sono possibili utilizzando il CSS.
Javascript viene altresì usato per modificare al volo
una pagina HTML ricevuta prima che questa venga visualizzata,
intervenendo direttamente su di una sua rappresentazione interna al
Browser, nota con il nome di Document
Object Model (DOM).
Presso la sezione dei riferimenti troviamo alcuni interessanti links a siti che consentono di sperimentare la programmazione Javascript modificando direttamente degli esempi già pronti.
Rappresenta l'acronimo di Asynchronous JavaScript and XML, e individua l'utilizzo congiunto di diverse tecnologie per realizzare pagine web interattive che si comportano in maniera sensibilmente più pronta di quelle tradizionali, in quanto il ciclo richiesta-risposta non avviene più solo ad opera dell'utente, ma è il browser stesso, eseguendo del codice javascipt, a condurre una dialogo asincrono con il Server, mentre l'utente interagisce con la rappresentazione dei dati mostrata dal browser. Ad esempio, nel caso in cui si clicchi per poter vedere delle informazioni aggiuntive, qualora venga mostrato un indicatore di avanzamento, significa che il browser è in attesa dei dati mancanti, e richiesti al server mediante l'oggetto XMLHttpRequest(), usati poi per modificare il DOM della pagina visualizzata. Ad esempio, è questa la tecnologia usata da siti popolari come facebook e google.
La X di AJAX sta per XML, in ossequio al formato di serializzazione dei dati che sono richiesti da Javascript via HTTP, come usato nelle prime implementazioni: in tal caso infatti i dati sono rappresentati come dei frammenti XML, consentendo così di esprimere anche informazioni complesse e strutturate.
Acronimo di JavaScript Object Notation, si pone in alternativa ad XML per la serializzazione dei dati ricevuti tramite una richiesta HTTP, come dichiarato nel Content-type di risposta, pari a application/json. La RFC 4627 descrive la sintassi usata per esprimere questa rappresentazione dei dati, che può essere riassunta in poche semplici regole, e che sostanzialmente coincide con la notazione usata da Javascript per rappresentare le proprie strutture dati: infatti, lo stesso oggetto JSON ricevuto può essere eseguito dall'interprete javascript mediante la funzione eval(), che trasforma le strutture dati ricevute, in dati direttamente disponibili al programma. D'altra parte, se nel JSON ricevuto fosse presente anche del codice eseguibile (sempre javascript), questo sarebbe effettivamente eseguito, ponendo problemi di sicurezza. Perciò, questo semplice modo di procedere è stato sostituito dall'utilizzo di una diversa funzione, JSON.parse(), che è stata introdotta nelle versioni più recenti dei borowser, e chi si limita ad interpretare unicamente le strutture dati permesse da JSON, e non qualsiasi possibile costrutto di Javascript, come invece avviene per la eval().
Dato che i dati codificati in json possono in linea di principio essere utilizzati da un qualunque altro linguaggio di programmazione, e non solo da javascript, sono state sviluppate una serie di librerie (vedi a metà pagina di json.org) che effettuano il parsing di una stringa json in praticamente qualunque linguaggio di programmazione, rendendono così la codifica json un metodo universale per lo scambio dati.
Nel 1995 viene distributo FutureSplash, un plugin capace di produrre grafica vettoriale animata all'interno del browser. La ditta originaria viene acquisita nel '96 da Macromedia, sviluppatrice del concorrente Shockwave, e i due prodotti vengono fusi in Macromedia Flash; a partire dal 2005, i diritti sulla tecnologia sono acquisiti da Adobe Systems.
Il plugin Flash viene prodotto per architetture Windows, Macintosh e
Linux, e rappresenta una sorta di browser nel browser. Le animazioni
Flash vengono definite per mezzo del linguaggio interpretato ActionScript,
molto simile al Javascript, e che viene eseguito da una Actionscript
Virtual Machine, che nella sua realizzazione più recente dispone
anche di un compilatore Just In Time.
La grande diffusione di Flash in moltissimi siti web ne ha favorito la crescita, ed attualmente è la tecnologia in assoluto più usata per la diffusione di contenuti multimediali via web.
In HTML è definito l'elemento <form> (modulo o modello), tra i cui tag di apertura e chiusura, oltre ad altri elementi HTML qualsiasi, si possono inserire elementi particolari detti controlli, che vengono visualizzati dal browser come campi di inserimento all'interno di moduli. Per fissare fin da subito le idee, qui appresso è mostrata la visualizzazione corrispondente al codice mostrato a fianco, in cui compaiono i campi di inserimento prodotti dai controlli <input> con attributo type pari a text, radio, checkbox, submit, oltre ai controlli select e textarea, da verificare con l'aiuto della descrizione semantica dei controlli.
L'elemento <form> presenta un attributo particolare, denominato action, che identifica una URI da invocare quando l'utente aziona un pulsante di inoltro, a cui corrisponde un programma (che come vedremo prende il nome di CGI) da eseguire presso il server HTTP, URI che viene citata nella corrispondente richiesta HTTP, effettuata usando il metodo definito dall'attributo (sempre di form) method.
La particolarità della URI che compare nell'attributo action è che anziché rappresentare una risorsa statica, individua un programma CGI, invocato con argomenti impostati in base ai contenuti inseriti mediante i campi di inserimento offerti dai controlli: per ogni campo (controllo) della form, è specificato infatti un attributo name, che rappresenta un nome di variabile, a cui viene associato il valore immesso dall'utente in corrispondenza di quel campo, oppure preimpostato mediante l'attributo value.
codice HTML | risultato visualizzato |
<FORM
method="get" action="bar.php"> <TABLE border="1"> <TR bgcolor="#CCCCFF"> <TH>Nome</TH> <TH>Valore</TH> </TR> <TR> <TD>Ti chiami</TD> <TD><input name="tichiami" type="text" size="25"></TD> </TR> <TR> <TD>Genere</TD> <TD> <input type="radio" name="sex" value="uomo"> Maschile<BR> <input type="radio" name="sex" value="donna" checked> Femminile</TD> </TR> <TR> <TD>Colore occhi</TD> <TD> <select name="occhi"> <option selected>blu</option> <option>castani</option> <option>verdi</option> <option>altro</option> </select> </TD> </TR> <TR> <TD>Altre caratteristiche</TD> <TD> <input type="checkbox" name="altezza" value="1"> Alto più di 1,80</input><BR> <input type="checkbox" name="peso" value="1"> peso più di 80 Kg</input> </TD> </TR> <TR> <TD colspan="2">Descrivi le tue attitudini atletiche:<BR> <textarea name="athletic" cols="50" rows="4"> </textarea> </TD> </TR> <TR> <TD colspan="2" align="center"> <input type="submit" value="Invia le tue informazioni"> </TD> </TR> </TABLE> </FORM> |
|
Descriviamo la semantica di un sotto-insieme essenziale di controlli HTML, rimandando alla normativa ufficiale per la loro definizione completa, e ad altri siti per la loro sperimentazione interattiva.
Ti chiami |
Alto più di 1,80 peso più di 80 Kg |
Maschile Femminile |
Colore occhi |
Per sperimentare l'effetto della esecuzione di questo e dei prossimi esempi, occorre installare sul proprio computer il server web Apache e configurarlo come indicato nella esercitazione collegata a questo capitolo, e quindi installare nella propria directory public_html gli esempi forniti e che consistono nei programmi CGI invocati mediante l'attibuto action delle form illustrate nel seguito. Il primo esempio di form, consiste nel seguente codice HTML:
<form method="get"
action="http://127.0.0.1/labint/primocgi.cgi"> <table style="background-color: rgb(255, 247, 229); width: 85%; margin-left: auto; margin-right: auto;" border="1" cellpadding="4" cellspacing="2"> <caption><i>Esempio di Inserimento</i></caption> <tbody> <tr> <td align=right width=30%>email:</td> <td><input type="text" maxlength="50" name="email"></td> </tr> <tr> <td align=right>ordine:</td> <td> <table align=left cellpadding="2" cellspacing="2"> <tbody> <tr> <td> <input name="ordine" value="pizza" type="radio">pizza</td> </tr> <tr> <td><input checked="checked" name="ordine" value="lasagna" type="radio"> lasagna</td> </tr> <tr> <td><input name="ordine" value="tiramisu" type="radio">tiramisu</td> </tr> <tr> <td><input name="ordine" value="pinta" type="radio">pinta</td> </tr> </tbody> </table> </td> </tr> <tr> <td align=right><input name="ok" value="ok" type="submit"></td> <td align=left><input name="reset" value="reset" type="reset"></td> </tr> </tbody> </table> </form> |
che produce la visualizzazione seguente:
e che, quando viene premuto (nella versione on-line del testo) il tasto ok, condiziona il browser ad
effettuare una richiesta HTTP (con il metodo GET) della URI http://127.0.0.1/labint/primocgi.cgi indicata
nell'attributo action
dell'elemento form, e che
(avendo configurato Apache ed installato il
codice) produce come risultato una pagina HTML, che il server web ci
invierà come risposta.
Dato che l'esistenza del meccanismo dei CGI ha reso il WWW classico (ossia, il trittico composto da URI, HTTP e HTML) una sorta di sottostrato su cui realizzare vere e proprie applicazioni di elaborazione distribuita, dedichiamo a questi ulteriori aspetti (e non solo) il prossimo capitolo.
Dal TCP al VoIP, dal DNS all'Email alla crittografia, tutto ciò che accade
dietro le quinte di Internet, completo di cattura del traffico.
Scopri
come effettuare il download,
ricevere gli aggiornamenti,
e contribuire!