Python 3 - Programmazione CGI

Common Gateway Interface, o CGI, è un insieme di standard che definiscono il modo in cui le informazioni vengono scambiate tra il server Web e uno script personalizzato. Le specifiche CGI sono attualmente mantenute dall'NCSA.

Cos'è la CGI?

  • Common Gateway Interface, o CGI, è uno standard per i programmi gateway esterni per interfacciarsi con i server di informazioni come i server HTTP.

  • La versione corrente è CGI / 1.1 e CGI / 1.2 è in fase di elaborazione.

Navigare su Internet

Per comprendere il concetto di CGI, vediamo cosa succede quando facciamo clic su un collegamento ipertestuale per esplorare una particolare pagina web o URL.

  • Il browser contatta il server Web HTTP e richiede l'URL, ovvero il nome del file.

  • Il server Web analizza l'URL e cerca il nome del file. Se trova quel file, lo rimanda al browser, altrimenti invia un messaggio di errore che indica che hai richiesto un file sbagliato.

  • Il browser Web riceve la risposta dal server Web e visualizza il file ricevuto o il messaggio di errore.

Tuttavia, è possibile impostare il server HTTP in modo che ogni volta che viene richiesto un file in una determinata directory, quel file non viene restituito; invece viene eseguito come un programma e tutto ciò che il programma emette viene rispedito al browser per la visualizzazione. Questa funzione è chiamata Common Gateway Interface o CGI ei programmi sono chiamati script CGI. Questi programmi CGI possono essere uno script Python, uno script PERL, uno script shell, un programma C o C ++, ecc.

Diagramma di architettura CGI

Supporto e configurazione del server Web

Prima di procedere con la programmazione CGI, assicurati che il tuo server Web supporti CGI e che sia configurato per gestire i programmi CGI. Tutti i programmi CGI che devono essere eseguiti dal server HTTP sono conservati in una directory preconfigurata. Questa directory è chiamata CGI Directory e per convenzione è chiamata / var / www / cgi-bin. Per convenzione, i file CGI hanno l'estensione come.cgi, ma puoi mantenere i tuoi file con estensione python .py anche.

Per impostazione predefinita, il server Linux è configurato per eseguire solo gli script nella directory cgi-bin in / var / www. Se vuoi specificare qualsiasi altra directory per eseguire i tuoi script CGI, commenta le seguenti righe nel file httpd.conf -

<Directory "/var/www/cgi-bin">
   AllowOverride None
   Options ExecCGI
   Order allow,deny
   Allow from all
</Directory>

<Directory "/var/www/cgi-bin">
Options All
</Directory>

Qui, assumiamo che tu abbia il server Web attivo e funzionante con successo e che tu sia in grado di eseguire qualsiasi altro programma CGI come Perl o Shell, ecc.

Primo programma CGI

Ecco un semplice collegamento, che è collegato a uno script CGI chiamato hello.py . Questo file è conservato nella directory / var / www / cgi-bin e ha il seguente contenuto. Prima di eseguire il programma CGI, assicurati di aver modificato la modalità di utilizzo del filechmod 755 hello.py Comando UNIX per rendere eseguibile il file.

#!/usr/bin/python

print ("Content-type:text/html\r\n\r\n")
print ('<html>')
print ('<head>')
print ('<title>Hello Word - First CGI Program</title>')
print ('</head>')
print ('<body>')
print ('<h2>Hello Word! This is my first CGI program</h2>')
print ('</body>')
print ('</html>')

Note- La prima riga nello script deve essere il percorso dell'eseguibile Python. In Linux dovrebbe essere #! / Usr / bin / python3

Inserisci il seguente URL nel tuo browser

http://localhost:8080/cgi-bin/hello.py

Hello Word! This is my first CGI program

Questo script hello.py è un semplice script Python, che scrive il suo output sul file STDOUT, cioè schermo. C'è una caratteristica importante ed extra disponibile che è la prima riga da stampareContent-type:text/html\r\n\r\n. Questa riga viene rinviata al browser e specifica il tipo di contenuto da visualizzare sullo schermo del browser.

A questo punto devi aver compreso il concetto di base di CGI e puoi scrivere molti programmi CGI complicati usando Python. Questo script può interagire con qualsiasi altro sistema esterno anche per scambiare informazioni come RDBMS.

Intestazione HTTP

La linea Content-type:text/html\r\n\r\nfa parte dell'intestazione HTTP che viene inviata al browser per comprendere il contenuto. Tutta l'intestazione HTTP avrà la seguente forma:

HTTP Field Name: Field Content

For Example
Content-type: text/html\r\n\r\n

Ci sono poche altre importanti intestazioni HTTP, che userete frequentemente nella vostra programmazione CGI.

Sr.No. Intestazione e descrizione
1

Content-type:

Una stringa MIME che definisce il formato del file restituito. L'esempio è Content-type: text / html

2

Expires: Date

La data in cui le informazioni diventano non valide. Viene utilizzato dal browser per decidere quando una pagina deve essere aggiornata. Una stringa di data valida è nel formato 01 gen 1998 12:00:00 GMT.

3

Location: URL

L'URL restituito al posto dell'URL richiesto. È possibile utilizzare questo campo per reindirizzare una richiesta a qualsiasi file.

4

Last-modified: Date

La data dell'ultima modifica della risorsa.

5

Content-length: N

La lunghezza, in byte, dei dati restituiti. Il browser utilizza questo valore per segnalare il tempo di download stimato per un file.

6

Set-Cookie: String

Imposta il cookie passato attraverso la stringa

Variabili d'ambiente CGI

Tutti i programmi CGI hanno accesso alle seguenti variabili d'ambiente. Queste variabili svolgono un ruolo importante durante la scrittura di qualsiasi programma CGI.

Sr.No. Nome e descrizione della variabile
1

CONTENT_TYPE

Il tipo di dati del contenuto. Utilizzato quando il client invia il contenuto allegato al server. Ad esempio, caricamento di file.

2

CONTENT_LENGTH

La lunghezza delle informazioni sulla query. È disponibile solo per richieste POST.

3

HTTP_COOKIE

Restituisce i cookie impostati sotto forma di coppia chiave e valore.

4

HTTP_USER_AGENT

Il campo dell'intestazione della richiesta dell'agente utente contiene informazioni sull'agente utente che ha originato la richiesta. È il nome del browser web.

5

PATH_INFO

Il percorso per lo script CGI.

6

QUERY_STRING

Le informazioni con codifica URL inviate con la richiesta del metodo GET.

7

REMOTE_ADDR

L'indirizzo IP dell'host remoto che effettua la richiesta. Questo è utile per la registrazione o per l'autenticazione.

8

REMOTE_HOST

Il nome completo dell'host che effettua la richiesta. Se queste informazioni non sono disponibili, è possibile utilizzare REMOTE_ADDR per ottenere l'indirizzo IR.

9

REQUEST_METHOD

Il metodo utilizzato per effettuare la richiesta. I metodi più comuni sono GET e POST.

10

SCRIPT_FILENAME

Il percorso completo dello script CGI.

11

SCRIPT_NAME

Il nome dello script CGI.

12

SERVER_NAME

Il nome host o l'indirizzo IP del server

13

SERVER_SOFTWARE

Il nome e la versione del software in esecuzione sul server.

Ecco un piccolo programma CGI per elencare tutte le variabili CGI. Fare clic su questo collegamento per visualizzare il risultato Ottieni ambiente

#!/usr/bin/python

import os

print ("Content-type: text/html\r\n\r\n");
print ("<font size=+1>Environment</font><\br>");
for param in os.environ.keys():
   print ("<b>%20s</b>: %s<\br>" % (param, os.environ[param]))

Metodi GET e POST

Devi esserti imbattuto in molte situazioni in cui hai bisogno di passare alcune informazioni dal tuo browser al server web e, infine, al tuo programma CGI. Il più delle volte, il browser utilizza due metodi, due trasmettono queste informazioni al server web. Questi metodi sono il metodo GET e il metodo POST.

Passaggio di informazioni utilizzando il metodo GET

Il metodo GET invia le informazioni utente codificate aggiunte alla richiesta della pagina. La pagina e le informazioni codificate sono separate dal? carattere come segue -

http://www.test.com/cgi-bin/hello.py?key1=value1&key2=value2
  • Il metodo GET è il metodo predefinito per passare le informazioni dal browser al server web e produce una lunga stringa che appare nella casella Posizione: del browser.

  • Non utilizzare mai il metodo GET se si dispone di password o altre informazioni sensibili da passare al server.

  • Il metodo GET ha limiti di dimensione: solo 1024 caratteri possono essere inviati in una stringa di richiesta.

  • Il metodo GET invia le informazioni utilizzando l'intestazione QUERY_STRING e sarà accessibile nel programma CGI tramite la variabile d'ambiente QUERY_STRING.

È possibile passare le informazioni semplicemente concatenando coppie di chiavi e valori insieme a qualsiasi URL oppure è possibile utilizzare i tag HTML <FORM> per passare le informazioni utilizzando il metodo GET.

Esempio di URL semplice: metodo Get

Ecco un semplice URL, che passa due valori al programma hello_get.py utilizzando il metodo GET.

/cgi-bin/hello_get.py?first_name=ZARA&last_name=ALI

Sotto è hello_get.pyscript per gestire l'input fornito dal browser web. Useremocgi modulo, che rende molto facile accedere alle informazioni passate -

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
first_name = form.getvalue('first_name')
last_name  = form.getvalue('last_name')

print ("Content-type:text/html\r\n\r\n")
print ("<html>")
print ("<head>")
print ("<title>Hello - Second CGI Program</title>")
print ("</head>")
print ("<body>")
print ("<h2>Hello %s %s</h2>" % (first_name, last_name))
print ("</body>")
print ("</html>")

Ciò genererebbe il seguente risultato:

Hello ZARA ALI

Esempio di FORM semplice: metodo GET

Questo esempio trasmette due valori utilizzando HTML FORM e il pulsante di invio. Usiamo lo stesso script CGI hello_get.py per gestire questo input.

<form action = "/cgi-bin/hello_get.py" method = "get">
   First Name: <input type = "text" name = "first_name">  <br />

   Last Name: <input type = "text" name = "last_name" />
   <input type = "submit" value = "Submit" />
</form>

Ecco l'output effettivo del modulo sopra, inserisci Nome e Cognome e quindi fai clic sul pulsante Invia per vedere il risultato.

Passaggio di informazioni utilizzando il metodo POST

Un metodo generalmente più affidabile per passare informazioni a un programma CGI è il metodo POST. Questo impacchetta le informazioni esattamente allo stesso modo dei metodi GET, ma invece di inviarle come stringa di testo dopo un? nell'URL lo invia come messaggio separato. Questo messaggio arriva nello script CGI sotto forma di input standard.

Di seguito è riportato lo stesso script hello_get.py che gestisce GET e il metodo POST.

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
first_name = form.getvalue('first_name')
last_name  = form.getvalue('last_name')

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Hello - Second CGI Program</title>"
print "</head>"
print "<body>"
print "<h2>Hello %s %s</h2>" % (first_name, last_name)
print "</body>"
print "</html>"

Riprendiamo lo stesso esempio di cui sopra che trasmette due valori utilizzando il FORM HTML e il pulsante di invio. Usiamo lo stesso script CGI hello_get.py per gestire questo input.

<form action = "/cgi-bin/hello_get.py" method = "post">
First Name: <input type = "text" name = "first_name"><br />
Last Name: <input type = "text" name = "last_name" />

<input type = "submit" value = "Submit" />
</form>

Ecco l'output effettivo del modulo sopra. Immettere Nome e Cognome e quindi fare clic sul pulsante Invia per vedere il risultato.

Passaggio dei dati della casella di controllo al programma CGI

Le caselle di controllo vengono utilizzate quando è necessario selezionare più di un'opzione.

Ecco un esempio di codice HTML per un modulo con due caselle di controllo:

<form action = "/cgi-bin/checkbox.cgi" method = "POST" target = "_blank">
   <input type = "checkbox" name = "maths" value = "on" /> Maths
   <input type = "checkbox" name = "physics" value = "on" /> Physics
   <input type = "submit" value = "Select Subject" />
</form>

Il risultato di questo codice è il seguente modulo:

Di seguito è riportato lo script checkbox.cgi per gestire l'input fornito dal browser Web per il pulsante della casella di controllo.

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('maths'):
   math_flag = "ON"
else:
   math_flag = "OFF"

if form.getvalue('physics'):
   physics_flag = "ON"
else:
   physics_flag = "OFF"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Checkbox - Third CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> CheckBox Maths is : %s</h2>" % math_flag
print "<h2> CheckBox Physics is : %s</h2>" % physics_flag
print "</body>"
print "</html>"

Passaggio dei dati del pulsante di opzione al programma CGI

I pulsanti di opzione vengono utilizzati quando è necessario selezionare una sola opzione.

Ecco un esempio di codice HTML per un modulo con due pulsanti di opzione:

<form action = "/cgi-bin/radiobutton.py" method = "post" target = "_blank">
   <input type = "radio" name = "subject" value = "maths" /> Maths
   <input type = "radio" name = "subject" value = "physics" /> Physics
   <input type = "submit" value = "Select Subject" />
</form>

Il risultato di questo codice è il seguente modulo:

Di seguito è riportato lo script radiobutton.py per gestire l'input fornito dal browser Web per il pulsante di opzione -

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('subject'):
   subject = form.getvalue('subject')
else:
   subject = "Not set"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Radio - Fourth CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> Selected Subject is %s</h2>" % subject
print "</body>"
print "</html>"

Passaggio dei dati dell'area di testo al programma CGI

L'elemento TEXTAREA viene utilizzato quando è necessario passare del testo su più righe al programma CGI.

Ecco un esempio di codice HTML per un modulo con una casella TEXTAREA -

<form action = "/cgi-bin/textarea.py" method = "post" target = "_blank">
   <textarea name = "textcontent" cols = "40" rows = "4">
      Type your text here...
   </textarea>
   <input type = "submit" value = "Submit" />
</form>

Il risultato di questo codice è il seguente modulo:

Di seguito è riportato lo script textarea.cgi per gestire l'input fornito dal browser web -

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('textcontent'):
   text_content = form.getvalue('textcontent')
else:
   text_content = "Not entered"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>";
print "<title>Text Area - Fifth CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> Entered Text Content is %s</h2>" % text_content
print "</body>"

Passaggio dei dati della casella a discesa al programma CGI

La casella a discesa viene utilizzata quando abbiamo molte opzioni disponibili ma ne verranno selezionate solo una o due.

Ecco un esempio di codice HTML per un modulo con una casella a discesa:

<form action = "/cgi-bin/dropdown.py" method = "post" target = "_blank">
   <select name = "dropdown">
      <option value = "Maths" selected>Maths</option>
      <option value = "Physics">Physics</option>
   </select>
   <input type = "submit" value = "Submit"/>
</form>

Il risultato di questo codice è il seguente modulo:

Di seguito è riportato lo script dropdown.py per gestire l'input fornito dal browser web.

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('dropdown'):
   subject = form.getvalue('dropdown')
else:
   subject = "Not entered"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Dropdown Box - Sixth CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> Selected Subject is %s</h2>" % subject
print "</body>"
print "</html>"

Utilizzo dei cookie in CGI

Il protocollo HTTP è un protocollo senza stato. Per un sito web commerciale, è necessario mantenere le informazioni sulla sessione tra le diverse pagine. Ad esempio, la registrazione di un utente termina dopo aver completato molte pagine. Come conservare le informazioni sulla sessione dell'utente in tutte le pagine web?

In molte situazioni, l'utilizzo dei cookie è il metodo più efficiente per ricordare e tracciare preferenze, acquisti, commissioni e altre informazioni necessarie per una migliore esperienza dei visitatori o statistiche del sito.

Come funziona?

Il tuo server invia alcuni dati al browser del visitatore sotto forma di cookie. Il browser può accettare il cookie. In caso affermativo, viene memorizzato come record di testo normale sul disco rigido del visitatore. Ora, quando il visitatore arriva a un'altra pagina del tuo sito, il cookie è disponibile per il recupero. Una volta recuperato, il tuo server sa / ricorda cosa è stato memorizzato.

I cookie sono un record di dati di testo semplice di 5 campi di lunghezza variabile -

  • Expires- La data in cui scadrà il cookie. Se questo è vuoto, il cookie scadrà quando il visitatore chiude il browser.

  • Domain - Il nome di dominio del tuo sito.

  • Path- Il percorso della directory o della pagina web che imposta il cookie. Questo può essere vuoto se desideri recuperare il cookie da qualsiasi directory o pagina.

  • Secure- Se questo campo contiene la parola "secure", il cookie può essere recuperato solo con un server sicuro. Se questo campo è vuoto, non esiste alcuna restrizione di questo tipo.

  • Name = Value - I cookie vengono impostati e recuperati sotto forma di coppie chiave e valore.

Impostazione dei cookie

È molto semplice inviare cookie al browser. Questi cookie vengono inviati insieme all'intestazione HTTP prima del campo Tipo di contenuto. Supponendo che si desideri impostare UserID e Password come cookie. L'impostazione dei cookie avviene come segue:

#!/usr/bin/python
print "Set-Cookie:UserID = XYZ;\r\n"
print "Set-Cookie:Password = XYZ123;\r\n"
print "Set-Cookie:Expires = Tuesday, 31-Dec-2007 23:12:40 GMT;\r\n"
print "Set-Cookie:Domain = www.tutorialspoint.com;\r\n"
print "Set-Cookie:Path = /perl;\n"
print "Content-type:text/html\r\n\r\n"
...........Rest of the HTML Content....

Da questo esempio, devi aver capito come impostare i cookie. Noi usiamoSet-Cookie Intestazione HTTP per impostare i cookie.

È facoltativo impostare gli attributi dei cookie come Expires, Domain e Path. È da notare che i cookie vengono impostati prima dell'invio di magic line"Content-type:text/html\r\n\r\n.

Recupero dei cookie

È molto facile recuperare tutti i cookie impostati. I cookie sono memorizzati nella variabile d'ambiente CGI HTTP_COOKIE e avranno la seguente forma:

key1 = value1;key2 = value2;key3 = value3....

Ecco un esempio di come recuperare i cookie.

#!/usr/bin/python

# Import modules for CGI handling 
from os import environ
import cgi, cgitb

if environ.has_key('HTTP_COOKIE'):
   for cookie in map(strip, split(environ['HTTP_COOKIE'], ';')):
      (key, value ) = split(cookie, '=');
      if key == "UserID":
         user_id = value

      if key == "Password":
         password = value

print "User ID  = %s" % user_id
print "Password = %s" % password

Questo produce il seguente risultato per i cookie impostati dallo script precedente:

User ID = XYZ
Password = XYZ123

Esempio di caricamento di file

Per caricare un file, il modulo HTML deve avere l'attributo enctype impostato su multipart/form-data. Il tag di input con il tipo di file crea un pulsante "Sfoglia".

<html>
   <body>
      <form enctype = "multipart/form-data" action = "save_file.py" method = "post">
      <p>File: <input type = "file" name = "filename" /></p>
      <p><input type = "submit" value = "Upload" /></p>
      </form>
   </body>
</html>

Il risultato di questo codice è il seguente modulo:

L'esempio sopra è stato disabilitato intenzionalmente per salvare le persone che caricano file sul nostro server, ma puoi provare il codice sopra con il tuo server.

Ecco il copione save_file.py per gestire il caricamento dei file -

#!/usr/bin/python

import cgi, os
import cgitb; cgitb.enable()

form = cgi.FieldStorage()

# Get filename here.
fileitem = form['filename']

# Test if the file was uploaded
if fileitem.filename:
   # strip leading path from file name to avoid 
   # directory traversal attacks
   fn = os.path.basename(fileitem.filename)
   open('/tmp/' + fn, 'wb').write(fileitem.file.read())

   message = 'The file "' + fn + '" was uploaded successfully'
   
else:
   message = 'No file was uploaded'
   
print """\
Content-Type: text/html\n
<html>
   <body>
      <p>%s</p>
   </body>
</html>
""" % (message,)

Se esegui lo script precedente su Unix / Linux, devi occuparti di sostituire il separatore di file come segue, altrimenti sulla tua macchina Windows sopra l'istruzione open () dovrebbe funzionare bene.

fn = os.path.basename(fileitem.filename.replace("\\", "/" ))

Come aprire una finestra di dialogo "Download file"?

A volte, si desidera offrire un'opzione in cui un utente può fare clic su un collegamento e verrà visualizzata una finestra di dialogo "Download file" per l'utente invece di visualizzare il contenuto effettivo. Questo è molto semplice e può essere ottenuto tramite l'intestazione HTTP. Questa intestazione HTTP è diversa dall'intestazione menzionata nella sezione precedente.

Ad esempio, se vuoi creare un file FileName file scaricabile da un determinato collegamento, la sua sintassi è la seguente:

#!/usr/bin/python

# HTTP Header
print "Content-Type:application/octet-stream; name = \"FileName\"\r\n";
print "Content-Disposition: attachment; filename = \"FileName\"\r\n\n";

# Actual File Content will go here.
fo = open("foo.txt", "rb")

str = fo.read();
print str

# Close opend file
fo.close()

Spero ti sia piaciuto questo tutorial. Se sì, inviami il tuo feedback a: Contattaci