Homepage di Marco Buzzo
Python
Python
Introduzione
Documentazione
Pubblicazioni
Faq CGI
Slides Seminario
Tkinter
Supporto Emacs
Link
Argomenti
Circuit Macros
Varie
 Chia
Contatti
marcobuzzo@tiscalinet.it
 

CGI FAQ


1. Configurazione del Server Server ed alternative al CGI


2. Domande specifiche su CGI


1. Configurazione del Server ed alternative al CGI


1.1. Come configurare il server web per eseguire i miei script?

Hai due possibilità per eseguire i tuoi script in Python: puoi configurare il server per eseguirli SOLO nella directory cgi-bin, oppure puoi impostare il server in modo da gestirli da qualunque percorso. Esistono buoni motivi per scegliere l'una o l'altra possibilità; per ora non ne terremo conto. Le istruzioni che seguono sono specifiche per l'uso del server Apache 1.1.bx.

A) Se vuoi eseguire gli script SOLO dalla directory cgi-bin, cambia nel file access.conf la seguente riga; da:

<Directory /usr/local/etc/httpd/cgi-bin> Options Indexes FollowSymLinks </Directory>

a:

<Directory /usr/local/etc/httpd/cgi-bin> Options FollowSymLinks ExecCGI </Directory> (sostiruisci il VERO percorso della tua directory cgi-bin)

B) Se vuoi che gli script siano eseguibili da qualunque percorso nell'albero che parte da /html/, nel file access.conf elimina il cancelletto # nella sezione che segue:

<Directory /usr/local/etc/httpd/htdocs> Options All </Directory>

(anche adesso, al posto del percorso segnato, inserisci il percorso del document root)

Inoltre, aggiungi la linea:

AddHandler cgi-script .py

al file srm.conf.

A questo punto, controlla che il tuo script sia universalmente leggibile ed eseguibile facendo chmod ugo+rx miofile.py.


1.2.Come operare il debug dei miei script?

Io utilizzo due metodi -

Fai un "tail -f" nel file logs/error_log. Questo ti permette di vedere continuamente il log degli errori, che é il luogo ove vengono memorizzati gli output delle tue chiamate al sys.sterr.write().

Prova ad eseguire il tuo script dal prompt della shell. In molti casi é facile localizzare un errore di sintassi dall'esecuzione diretta dello script. Può essere necessario impostare svariate variabili di ambiente CGI per permettere al tuo script CGI di lavorare senza errori. Il tuo programma dovrebbe avere la seguente

 if (__name__ == "__main__"): 
   main()
porzione di codice, in modo da importare il tuo modulo e testarlo interattivamente. Spesso può accadere che l'esecuzione manuale esponga il tuo script ad errori come il tentativo di importare un modulo che non é nel percorso delle librerie dello script.

Se il tuo script usa la classe cgi.FieldStorage per la form di input, avrai bisogno di impostare le variabili di ambiente REQUEST_METHOD e QUERY_STRING in maniera appropriata prima di eseguire lo script. D'altro canto lo script sembrerà attendere se lo esegui in maniera interattiva, ma quando premi control-c, verrà visualizzato un messaggio simile al seguente:

 Traceback (innermost last):
   File "./letter.py", line 93, in ?
     main()
   File "./letter.py", line 23, in main
     form = cgi.FieldStorage()
   File "/usr/local/lib/python1.4/cgi.py", line 822, in __init__
     self.read_single()
   File "/usr/local/lib/python1.4/cgi.py", line 901, in read_single
     self.read_lines()
   File "/usr/local/lib/python1.4/cgi.py", line 925, in read_lines
     self.read_lines_to_eof()
   File "/usr/local/lib/python1.4/cgi.py", line 930, in read_lines_to_eof
     line = self.fp.readline()
 KeyboardInterrupt
Ad esempio, se il tuo script é in attesa che qualcuno gli passi una form chiamata "page", e tu vuoi impostarla come "info", imposta l'ambiente come segue:
  setenv REQUEST_METHOD "GET"
  setenv QUERY_STRING "page=info"
Questo ovviamente vale solo per lo Unix!

Vedi anche la domanda 2.4.


1.3. Usare Python per il CGI sotto Microsoft Windows

[Grazie ad Aaron Watters] Nel server Microsoft IIS o in Win95 MS Personal Web Server, devi impostare Python allo stesso modo di un qualunque altro motore di script.

Chiama regedt32 e vai a:

  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W3SVC\Parameters\ScriptMap
and enter the following line (making any specific changes that your system may need)
  .py :REG_SZ: c:\<path to python>\python.exe -u %s %s
Questa riga ti permetterà di chiamare il tuo script con un semplice riferimento, come: http://yourserver/scripts/yourscript.py "scripts" é una directory "eseguibile" per il tuo server (di solito é impostata di default).L'opzione "-u" specifica la modalità binaria e senza buffer per stdin - necessaria quando si lavora con dati binari.

In aggiunta, per chi non lo sapesse é interessante notare che ".py" può non essere una buona idea come estensione di un file usato in questo contesto (puoi riservare *.py per i moduli di supporto ed usare *.cgi o *.cgp per gli script principali). Comunque anche questo appartiene alla FAQ Windows.

Netscape Servers: Information on this topic exists at: http://home.netscape.com/comprod/server_central/support/fasttrack_man/programs.htm#1010870

------------------------------------------------------------------------

[addendum by Carl Feynmann]

Se usi Personal Web Server sotto Windows 95, si può trattare di una versione che non supporta l'esecuzione degli script CGI. Esistono due versioni di Personal Web Server: Front Page Personal Web Server e Microsoft Personal Web Server. Il primo non esegue file dalla directory 'scripts'; termina con un oscuro messaggio del tipo "directory non accessibile o illeggibile". Puoi controllare se la tua versione é quella giusta tramite la taskbar, nella tray a fianco all'orologio. Se l'icona dice "Personal Web Server" quando ci passi sopra col mouse, allora si tratta di quella buona.

Ci sono due modi per i quali ti trovi davanti al server non buono: hai installato la versione 1.1 o precedente di Front Page, oppure in fase di installazione, non hai controllato le caselle 'Server Extension'. Il primo caso può essere risolto prendendo il CD-ROM Front Page 98 e controllare nella dir \PWS\UPGRADE gli aggiornamenti. Ho trovato qualcosa in questa dir ma non ne ho testato l'effettivo funzionamento. Nel secondo caso é necessario reinstallare Front Page 98, scegliendo l'opzione 'custom installation', ed abilitando le opzioni 'Server Extensions Resource Kit' e 'Server Extensions Administration Pages'.


1.4. E' possibile usare FastCGI con Python?

Si. Il miglior indirizzo per il supporto di Python a FastCGI é http://www.digicool.com/releases/fcgi/.

Se non sei proprio sicuro di cosa sia FastCGI, dai uno sguardo a http://www.fastcgi.com.

C'é anche una implementazione in Python (non é richiesto alcun modulo di estensione) dell'interfaccia dell'applicazione FastCGI presso http://starship.skyport.net/crew/robind/python/.


1.5. E' possibile scrivere applicazioni Netscape WAI in Python?

Si! Prova il modulo Netscape WAI per Python, che é disponibile presso python.org http://www.python.org/ftp/python/contrib/Web/waimodule-0.1.tar.gz

Wai per Netscape é il successore del meccanismo di estensione NSAPI. Questo permette alle applicazioni del server di essere eseguite internamente o esternamente al processo, e di essere attivate automaticamente o manualmente quando richiesto dal server stesso.

Due interessanti caratteristiche delle applicazioni WAI sono:

  1- Le applicazioni possono essere eseguite su macchine diverse dal web server
(Questo argomento concerno la sicurezza chiaramente. Netscape raccomanda di pensarci bene prima di adottare una simile soluzione). Ho usate questa particolarità per eseguire applicazioni "snoop" su 'SGI Indys around Magnet', cosicché potevo controllare ognuna di quattro telecamere, attraverso diversi url nello stesso web browser.
  2- Attraverso lo strumento "osagent", possono essere avviate multiple applicazioni,
visto che é supportata la loro ridondanza. Se una termina, una richiesta verrà automaticamente inoltrata ad un'altra istanza. Non ho ancora provato questa possibilità [...].

Netscape ha incluso il binding per C, C++, e Java con Enterprise-3.0.L'interfaccia Python WAI fornisce un sistema di binding identico a quello di Java implementato in C. Sfortunatamente non sono stato in grado di compilare una versione funzionale di modulo condiviso di questo tipo, così il Makefile incluso restituisce un nuovo interprete Python con una versione statica del modulo. Se qualcuno é in grado di ottenere una versione condivisa funzionante, sarei felice di esserne informato!

L'idea fondamentale per scrivere una applicazione WAI é che tu hai una sottoclasse da wai.WebApplicationInterface, e fornisce un metodo Run() nella tua classe. Questo metodo é chiamato ad ogni richiesta proveniente dal web e riceve un oggetto HTTPServiceRequest, contenente le varie informazioni richieste, come intestazioni e variabili cgi. Un oggetto WAIFieldStorage é fornito nel modulo waicgi.py che passa le informazioni inserite in una form, in un oggetto reale cgi.FieldStorage che puoi gestire nella vecchia maniera dei cgi.

Perciò la conversione di un programma cgi in una (molto più veloce) applicazione WAI, é generalmente solo una questione legata allo spostamento delle chiamate di inizializzazione nel metodo __init__() della classe della tua applicazione, ed alla chiamata del tuo vecchio metodo main() dal metodo Run() della classe dell'applicazione dopo aver creato il nuovo oggetto WAIFieldStorage.

Sfortunatamente sino ad ora ho avuto dei problemi cercando di cambiare il codice http risultante nell'applicazione WAI in qualcosa fino a 200. Se lo imposto su qualcos'altro tramite il metodo HTTPServiceRequest.setResponseStatus(), allora viene iniziato un nuovo processo per ogni richiesta, fino a quando non ne appaiono una dozzina, momento in cui il server termina di rispondere. Ho analizzato il problema, ma non sono stato in grado di risolverlo. Un programma per il testing usando l'interfaccia C ha funzionato correttamente, ma non altrettanto ha fatto quello in Python... :( Ancora una volta, se qualcuno risolve il problema, me lo faccia sapere.


1.6. Cosa e' questo Bob di cui si sente parlare?

(estratta dalla mailing list Python)

C'é qualcuno che ha avuto esperienze usando Bobo o Persistant CGI di > Digital Creations (http://www.digicool.com). Avete qualche suggerimento ? - danny.

Ho utilizzato Bobo nell'arco di circa un anno per progetti commerciali e posso sicuramente dire che ha cambiato la mia vita ;-) Bobo é semplice e potente e fornisce un antidoto contro la goffa, convulsa e fragile programmazione CGI. Bobo ti permette di porre l'attenzione sulla programmazione agli oggetti senza preoccuparti dei dettagli CGI.

Se ti é mai capitato di scrivere un programma CGI in Python che sia più lungo di 25 righe devi necessariamente dare uno sguardo a Bobo. Un buon punto i partenza é l'introduzione a Bobo scritta in occasione della quarta edizione del Quick Python Book da Ken McDonald's per Manning Pubblications. (http://www.digicool.com/releases/bobo/intro/)

Dopodiché, controlla il tutorial di Jim Fulton (http://www.digicool.com/releases/bobo/Tutorial/). Una cosa importante da ricordare quando inizi é che Bobo é un ORB, non un framework per CGI.

Iniziare con Bobo é semplice, ma può diventare molto complesso se lo desideri, specialmente se decidi di usare DocumentTemplate (una possibilità veramente completa per generare HTML), BoboPOS (un oggetto per archiviare molto flessibile), o l'esecuzione di processi lunghi.

Detto questo, alcune cose sono molto ben documentate, ma devono essere tralasciate. L'Apache ha qualche piccolo problema con gli schemi di autenticazione di Bobo; questi sono stati risolti dalla versione 1.3 ma le precedenti versioni richiedono una patch (non ne hai bisogno se non ti interessa l'autenticazione).La patch può essere scaricata presso ftp://ftp.digicool.com/pub/releases/ServerPatches/ Ancora, Bobo richiede qualche aggiustamento per lavorare con Windows, dal momento che lavora normalmente con link simbolici. Comunque esistono un paio di semplici soluzioni a questo problema. (http://www.digicool.com/releases/bobo/Win32/)

Una buona sorgente di informazioni su Bobo é la Bobo mailing list, ospitata presso findmail (http://www.findmail.com/listsaver/bobo/)

(grazie a Amos Latteier 3/5/1998)


1.7. E' possibile scrivere script CGI in Python per Apache/Win32?

Si, una breve descrizione é disponibile presso:
  http://starship.skyport.net/crew/jbauer/apachenotes/
E' estremamente importante essere certi di usare Python in modalità priva di buffer (SetEnv PYTHONUNBUFFERED 1) ed impostare PYTHONPATH come una variabile di ambiente del sistema. Dimenticarsi di impostare questi parametri é la più comune fonte di errori del tipo "premature end of header".


1.8. Come e' possibile eseguire file .pyc come CGI?H

Ho configurato il mio server Apache in modo da eseguire i file ".pyc" come script CGI. E' una soluzione semplice dal momento che non hai bisogno di rendere eseguibili i file .py. Si tratta semplicemente di file che non verranno eseguiti.

La loro versione eseguibile sarà quella con estensione ".pyc".

Vantaggi: Sei obbligato a compilare il file .py prima di qualcosa del tipo ...: python -c "import mymodule", e il codice del file .pyc é garantito essere sintatticamente a posto. La velocità di esecuzione potrebbe essere maggiore quando hai a che fare con script lunghi. Diventa più semplice avere file col permesso di lettura e di esecuzione nella medesima directory.

Inoltre puoi estendere le capacità degli script facendo vari controlli addizionali prima di eseguire lo script in questione.

Modifiche per Apache:

 1) In /httpd/conf/mime.types, inserisci la seguente riga

 application/x-python-compiled  pyc

 2) In /httpd/conf/srm.conf, inserisci una riga:

 Action application/x-python-compiled /cgi-bin/pyc_exec
Questo dice di avviare sempre lo script "pyc_exec" quando viene richiamato un file .pyc. Questo script potrebbe essere lo script di una shell che richiama Python con il .pyc come parametro della riga di comando, ma credo che sia più efficiente caricare il .pyc da uno script Python. Come azione di default quando lo script da errore, stampo tutte le variabili di ambiente. Qualunque tipo di commento é benvenuto.

Ecco uno script Python "pyc_exec" che entra nel cgi-bin:

 ------------------------------------------------------------
 #! /usr/bin/python

 import os, imp
 try :
        _script_ = "no script given"
        _script_ = os.environ["PATH_TRANSLATED"]
        try :
                _mode_ = "rb"
                _file_ = open(_script_, _mode_)
                imp.load_module("__main__", _file_, _script_, \
                        ("pyc", _mode_, imp.PY_COMPILED) )
        finally :
                _file_.close()
 except :
        print "Content-type: text/html\n"
        print "<html><title>Error encountered during Script execution</title>"
        print "<body>"
        print "<H2>Script = '%s'</H2>" % _script_
        print "<pre>"
        for name, value in os.environ.items():
                print "%s\t= %s" % (name, value)
        print "</pre></body></html>"
 ------------------------------------------------------------

1.9. Problemi con le librerie condivise e gli script CGI

Ogni tanto alcune persone si trovano nei guai con il CGI per Python usando moduli che richiedono specifiche librerie condivise. Di solito il problema si manifesta con lo script che non é in grado di localizzare la libreria condivisa (il file .so o .sl).

Dopo qualche discussione nel newsgroup, abbiamo concluso che un semplice script di shell, che imposta alcune variabili di ambiente per il linker (di solito LD_LIBRARY_PATH) e che poi avvia uno script per Python é la soluzione più semplice.

Nota che potrebbe anche essere possibile impostare delle variabili di ambiente usando alcune direttive nel setup del demone httpd. Per Apache, questo é supportato dal modulo env; controlla la documentazione presso http://www.apache.org/docs/mod/mod_env.html per ulteriori dettagli .


2. CGI Issues


2.1. Come scrivo un CGI "Hello, World?"

Il seguente script CGI fa apparire nel tuo browser la scritta "Hello, World!".
 #!/usr/local/bin/python
 # for unix of course

 def main():
   print "Content-type: text/html"
   print
   print "<TITLE> Hello, World!</TITLE>"
   print "Hello, World!"

 if (__name__ == "__main__"):
   main()

2.2. Cosa sono le templates e come si usano?

Le templates HTML rappresentano un sistema per lasciare il codice HTML al di fuori del tuo programma e metterlo in un file separato.

(grazie a Skip Montanaro per l'ispirazione)

Probabilmente il modo più semplice per usare le template HTML in uno script CGI Python é quello di usare il meccanismo di sostituzione delle chiavi di un dizionario per le stringhe.

Il modo per farlo é quello di usare l'operatore % per le stringhe che si comporta come printf() in C. La documentazione per questo può essere trovata presso http://www.python.org/doc/tut/node45.html#SECTION008100000000000000000

Brevemente, il tuo file template, ad esempio "template.txt" dovrà sembrare una cosa del tipo:

     <pre>
      Dear %(name)s,
        We really like your %(feature)s, and have awarded you the 
      %(feature)s-of-the-month award for %(month)s %(year)s. From all 
      of us here at Acme Awards, Congratulations!

                                              %(closing)s,
                                              Dave Mitchell
     </pre>
Ed il tuo dizionario dovrà essere del tipo:
        def_dict = {'name': 'J.Q. Studmeyer',\
                      'feature': 'long nose',\
                      'month':        'April',\
                      'year':         '1996',\
                      'closing':      'very truly yours'}
Più avanti quando nel tuo codice scrivi
  templ = open("template.txt").read()
  print templ%(def_dict)
Il tuo programma stamperà:
     <pre>
      Dear J.Q. Studmeyer,
        We really like your long nose, and have awarded you the 
      long nose-of-the-month award for April 1996. From all 
      of us here at Acme Awards, Congratulations!

                                              very truly yours,
                                              Dave Mitchell
     </pre>
Stupefacente, no?


2.3. Cosa sono i cookies e come li uso nei miei script?

Cookies, o netscape-cookies come alcune volte vengono chiamati, implementano uno schema per applicazioni web tale da immagazzinare lo stato del programma nel client.

Ogni cookie contiene diversi bit di informazione come nomi di variabili, valori, una data entro la quale sopravvivere ed un percorso.

Ecco come lavorano i cookie: quando richiedi un url da un sito, ogni cookie disponibile nel tuo browser, e inviato al server assieme alla richiesta. Questo permette al programma che risiede nel server di fare cose come rintracciare il percorso dell'utente o avviare una autenticazione come user-id. Chiaramente ci sono anche delle questioni legate alla sicurezza, per cui non racchiuderai nel cookie informazioni che vuoi che restino segrete.

Il nome della variabile ed il valore sono quello che aspetteresti. Ci sono chiaramente limiti alla dimensioni del nome e del valore. Ritengo che il valore debba essere minore di 2k, e la dimensione del cookie debba essere minore di 20k complessivamente. (correggetemi se questo non é esatto).

Il percorso determina la locazione del sito mentre il cookie resta valido. Per esempio, se la tua applicazione é localizzata presso "/cgi-bin/myapp/myapp.cgi", e nel cookie viene impostato il percorso "/", allora quel cookie verrà mandato quando visiti ogni url dall'intero sito.

Per quanto concerne la data, dice per quanto tempo il cookie resta valido.

Per una completa spiegazione di cosa sia il protocollo cookie e di come si usa, controlla la documentazione di Netscape presso http://devedge.netscape.com/library/documentation/communicator/jsguide4/cookies.htm

Per usare i cookies nel tuo script CGI Python, Tim O'Malley si occupa del modulo "Cookie.py" che può essere prelevato presso ftp://ftp.bbn.com/pub/timo/python/Cookie.py

L'uso di Cookie.py é estremamente semplice. Qui, i cookies lavorano come dei dizionari o la classe cgi FieldStorage. Per creare un nuovo cookie, devi fare una cosa del tipo:

x = Cookie.Cookie()

Per impostare i valori del nuovo cookie, devi solo assegnarli:

x['dave'] = "great"

Per mandare questi cookie al browser dell'utente, devi solo "stamparli" prima del titolo "Content-type". Se lo fai dopo, appariranno assieme all'output dello script. Se ti capiterà sai già che non funzionerà;)

print C

Set-Cookie: dave="great";

A questo punto un po' di aiuto: l'opinione pubblica é stata ingiustamente spaventata da articoli allarmistici relativamente ai cookies, i quali ti priverebbero della tua privacy o sarebbe in grado di "rubare" i numeri della carta di credito... Non é vero. I cookies possono solo contenere informazioni necessarie ad un server e che tu inserisci in un apposito form. Non possono prendere la tua carta di credito e leggerne il numero. Un'altra cosa da sapere é che molte persone attivano gli avvertimenti all'uso dei cookies nei loro browser solo per pochi giorni, per poi disabilitarli in quanto risulta noioso clickare sul bottone "confirm". Piuttosto sarebbe meglio disabilitarne l'uso.


2.4. Il mio script CGI non funziona, anche se gira dalla riga di comando

(Vedi anche la domanda 1.2 sul debugging.)

In altre parole, lo stesso comando o lo stesso script, funziona se testato manualmente, e non funziona se preso come CGI.

Alcune delle possibili cause:

- Lo script CGI é eseguito come utente "nobody". IN genere questo utente ha permessi minimi. Se lo script deve leggere file o directory, potrebbe non avere il permesso di farlo.

- Il tuo ISP sta eseguendo un CGI su una macchina diversa, quindi entri in una shell dove Python non é installato correttamente.

Per risolvere questa situazione, sarebbe enormemente di aiuto se se tu avessi accesso al file error_log del server httpd (per Apache di solito si trova in /usr/local/etc/httpd/logs/error_log o simile).

Inoltre assicurati di aver aletto la sezione dedicata al debugging nel manuale per il modulo cgi, o la docstring di cgi.py: contiene alcuni suggerimenti a proposito del debugging sistematico degli script CGI.


2.5. Come eseguo un comando ritardato da uno script CGI?

Ad esempio, vuoi eseguire un comando che aggiorna un database dopo che hai verificato l'input dell'utente, ma é così lento che vuoi che lo script completi il lavoro in background.

Se provi questa soluzione ingenua

    os.system("some_command &")
noterai che alcuni browser aspettano che venga completato il comando, perciò il contrario del risultato voluto.

Il motivo é che il comando in background ha ancora stdout e stderr aperti. La soluzione é chiuderli. Nell'esempio che segue, questo dovrebbe funzionare (usando la sintassi della shell di Bourne):

    os.system(" some_command >/dev/null 2>&1 & ")
Se stai usando os.fork(), prova os.close(1); os.close(2).


2.6. Esiste un tutorial CGI?

Si possono trovare semplice script presso http://www.vex.net/py_examples/ che mostrano come Python possa essere usato per semplici applicazioni come una form modellata sullo script per Perl mailer.cgi by Matt Kruse (<mkruse@saunix.sau.edu>). I siti che seguono contengono informazioni generiche sulla programmazione CGI.
   http://hoohoo.ncsa.uiuc.edu/cgi/
   http://www.cgi-resources.com/ - resources, docs, books, examples
   http://www.worldwidemart.com/scripts/ - a good deal of scripts
   http://nswt.tuwien.ac.at/
   http://nswt.tuwien.ac.at/htdocs/
   http://nswt.tuwien.ac.at/htdocs/www-security-faq/

2.7. Come posso controllare un indirizzo di email dal mio script?

Se vuoi sapere con certezza se hai ottenuto un indirizzo di email esistente, é mandarvi una email e vedere se ottieni una risposta!

Se d'altro canto vuoi sapere se l'indirizzo é stato scritto correttamente, o se sembra un valido indirizzo di email, sei su una strada migliore.

Per questo compito ho scritto un modulo chiamato email.py, che utilizza un sicuro regex per controllare la parte della riga in cui l'utente scrive il proprio indirizzo. Non c’è molto altro da fare quando lui inserisce

  http://members.aol.com/clueless/newbie.html
come sua email, ma quando si tratta di qualcosa di più ragionevole come
  in%"<davem@magnet.com>"
come potrebbe apparire su un VAX, questo programma si comporta degnamente.

Fino a quando non lo metterò su python.org, lo puoi prelevare presso la mia homepage http://people.magnet.com/~davem/python/email.py

Il suo uso é semplice. Tutto quello che devi fare é:

   import email
  >>> email.validate_email_addr('in%"<davem@magnet.com>"')
  '<davem@magnet.com>'
  >>> email.validate_email_addr("<bogus@aol>")
  ''
In altre parole, se si rende conto dell'indirizzo di email, lo restituisce "pulito". Differentemente restituisce la stringa null

2.8. Come faccio l'upload di un file via CGI?

Una breve descrizione con relativo codice é disponibile presso:
  http://starship.skyport.net/crew/jbauer/cgiupload/
Anche Bobo fornisce un meccanismo per fare upload tramite CGI.


2.9. Come può uno script CGI mostrare il nome del browser e l'indirizzo IP?

Gli script CGI possono ottenere informazioni di questo tipo attraverso le variabili di ambiente, perciò devi controllare i valori nel dizionario os.environ. Prova ad eseguire il seguente listato come script CGI per vedere una lista completa di ciò di cui il tuo server dispone.
    #!/usr/local/bin/python
    import os
    print 'Content-type: text/plain\n\n'
    for k,v in os.environ.items():
        print k, v
Alcuni degli output di questo CGI sono del tipo:
    SERVER_PORT 80
    REMOTE_ADDR 10.27.10.38
    SERVER_SOFTWARE Apache/1.3.1 (Unix)
    GATEWAY_INTERFACE CGI/1.1
    HTTP_ACCEPT_LANGUAGE en
    REMOTE_PORT 54319
    HTTP_USER_AGENT Mozilla/4.5 [en] (X11; I; SunOS 5.6 sun4u)
    SERVER_PROTOCOL HTTP/1.0
    SCRIPT_NAME /cgi-bin/t.cgi
      ...
Quindi, per il browser devi esaminare os.environ['HTTP_USER_AGENT'], e per l'indirizzo IP os.environ['REMOTE_ADDR'].

(Nota che qualcuno potrebbe usare un browser il quale non invia un messaggio User-Agent HTTP, per cui potresti non essere in grado di usare os.environ['HTTP_USER_AGENT']; é importante saperlo per scrivere degli script esenti da problemi...


2.10. Come posso gestire la grafica da un file CGI, ad esempio mostrare un file GIF?

Devi solo comunicare al browser che tu stai inviando una immagine, specificando il corretto tipo MIME:
    import sys
    image = open('my.gif','rb').read()
    # HTTP Headers
    sys.stdout.write('Content-type: image/gif\r\n')
    # End-of-headers
    sys.stdout.write('\r\n')
    # Start of content
    sys.stdout.write(image)
Fai attenzione al fatto che che non puoi usare 'print image' perché verrebbe agganciata ad una linea nuova o vuota (proprio nel caso in cui usi 'print image,') che potrebbe non "piacere" al browser.

Questo esempio legge una GIF da un file; é anche possibile produrre immagini tramite codice Python, usando un package come Python Imaging Library (http://www.python.org/sigs/image-sig/Imaging.html).

(M.A. Lemburg.) 



Traduzione a cura di Marco Buzzo