Scopo | Il modulo Cookie definisce le classi per l'analisi e la creazione di intestazioni cookie HTTP. |
Versione Python | 2.1 e superiore |
A partire dal 1 gennaio 2021 le versioni 2.x di Python non sono piu' supportate. Ti invito a consultare la corrispondente versione 3.x dell'articolo per le versioni 3.x di Python
I cookie fanno parte del protocollo HTTP da lungo tempo. Tutti le moderne infrastrutture di sviluppo web forniscono un semplice accesso ai cookie in modo che un programmatore quasi mai debba preoccuparsi di come formattarli oppure assicurarsi che le intestazioni vengano inviate propriamente. Può comunque essere istruttivo capire come funzionano i cookie, e le opzioni che supportano.
Il modulo Cookie implementa un parser per i cookie che è per la maggior parte rispondente alle specifiche RFC 2109 . E' un poco meno rigido dello standard poichè MSIE 3.0x non supporta l'intero standard.
I cookie sono usati come gestione dello stato, e come tali sono in genere impostati dal server per essere salvati e restituiti dal client. L'esempio più semplice per la creazione di un cookie potrebbe essere qualcosa come questo:
import Cookie
c = Cookie.SimpleCookie()
c['ilmiocookie'] = 'valore_del_cookie'
print c
Il risultato è un header Set-Cookie valido pronto per essere passato al client come parte della risposta HTTP:
$ python Cookie_setheaders.py Set-Cookie: ilmiocookie=valore_del_cookie
E' anche possibile controllare gli altri aspetti di un cookie, tipo la scadenza, il percoso ed il dominio. In effetti, tutti gli attributi RFC per i cookie possono essere gestiti tramite l'oggetto
Morsel
che rappresenta il valore del cookie.
import Cookie
import datetime
def show_cookie(c):
print c
for key, morsel in c.iteritems():
print
print 'key =', morsel.key
print ' value =', morsel.value
print ' coded_value =', morsel.coded_value
for name in morsel.keys():
if morsel[name]:
print ' %s = %s' % (name, morsel[name])
c = Cookie.SimpleCookie()
# Un cookie con un valore che deve essere codificato per potere entrare nell'intestazione
c['encoded_value_cookie'] = '"cookie_value"'
c['encoded_value_cookie']['comment'] = 'Si noti che il valore di questo cookie ha degli apici racchiusi in una sequenza di escape'
# Un cookie che si applica solo a parti del sito
c['restricted_cookie'] = 'cookie_value'
c['restricted_cookie']['path'] = '/sub/path'
c['restricted_cookie']['domain'] = 'PyMOTW'
c['restricted_cookie']['secure'] = True
# Un cookie che scade in 5 minuti
c['with_max_age'] = 'scade in 5 minutei'
c['with_max_age']['max-age'] = 300 # secondi
# Un cookie che scade ad un tempo specifico
c['expires_at_time'] = 'cookie_value'
expires = datetime.datetime(2009, 2, 14, 18, 30, 14) + datetime.timedelta(hours=1)
c['expires_at_time']['expires'] = expires.strftime('%a, %d %b %Y %H:%M:%S') # Wdy, DD-Mon-YY HH:MM:SS GMT
show_cookie(c)
L'esempio di cui sopra comprende due diversi metodi per impostare dei cookie salvati che scadono. Si può impostare max-age ad un numero di secondi, oppure ad una data ed ora alla quale il cookie dovrebbe essere scaricato.
$ python Cookie_Morsel.py Set-Cookie: encoded_value_cookie="\"cookie_value\""; Comment=Si noti che il valore di questo cookie ha degli apici racchiusi in una sequenza di escape Set-Cookie: expires_at_time=cookie_value; expires=Sat, 14 Feb 2009 19:30:14 Set-Cookie: restricted_cookie=cookie_value; Domain=PyMOTW; Path=/sub/path; secure Set-Cookie: with_max_age="scade in 5 minutei"; Max-Age=300 key = restricted_cookie value = cookie_value coded_value = cookie_value domain = PyMOTW secure = True path = /sub/path key = with_max_age value = scade in 5 minutei coded_value = "scade in 5 minuti" max-age = 300 key = encoded_value_cookie value = "cookie_value" coded_value = "\"cookie_value\"" comment = Si noti che il valore di questo cookie ha degli apici racchiusi in una sequenza di escape key = expires_at_time value = cookie_value coded_value = cookie_value expires = Sat, 14 Feb 2009 19:30:14
Sia l'oggetto
Cookie
che
Morsel
sono come dei dizionari. Morsel risponde ad un elenco fisso di chiavi:
Le chiavi per una istanza di Cookie sono i nomi dei cookie individuali che sono stati salvati. Questa informazione è disponibile anche tramite l'attributo key di Morsel.
L'intestazione del cookie potrebbe richiedere valori da codificare in modo che possano essere analizzati correttamente.
import Cookie
c = Cookie.SimpleCookie()
c['intero'] = 5
c['stringa_con_apici'] = 'Disse, "Salve, Mondo!"'
for name in ['intero', 'stringa_con_apici']:
print c[name].key
print ' %s' % c[name]
print ' valore=%s' % c[name].value, type(c[name].value)
print ' valore codificato=%s' % c[name].coded_value
print
Il valore
Morsel.value
è sempre il valore decodificato del cookie, mentre
Morsel.coded_value
è sempre la rappresentazione da usare per trasmettere il valore al client. Entrambi i valori sono sempre stringhe. I valori salvati in un cookie che non sono stringhe vengono convertiti automaticamente.
$ python Cookie_coded_value.py intero Set-Cookie: intero=5 valore=5valore codificato=5 stringa_con_apici Set-Cookie: stringa_con_apici="Disse, \"Salve, Mondo!\"" valore=Disse, "Salve, Mondo!" valore codificato="Disse, \"Salve, Mondo!\""
Una volta che le intestazioni Set-Cookie sono ricevute dal client, esso restituirà quei cookie al server in base a susseguenti richieste usando l'intestazione del cookie. Il cookie in arrivo assomiglia a questo:
Cookie: intero=5; stringa_con_apici="Disse, \"Salve, Mondo!\""
A seconda del proprio server web ed infrastruttura, i cookie sono disponibili direttamente dalle intestazioni oppure della variabile di ambiente
HTTP_COOKIE
. Per decodficarli si passa la stringa senza il prefisso di intestazione a
SimpleCookie
quando lo si istanzia, opure si usa il metodo
load()
.
import Cookie
HTTP_COOKIE = r'intero=5; stringa_con_apici="Disse, \"Salve, Mondo!\""'
print 'Dal costruttore:'
c = Cookie.SimpleCookie(HTTP_COOKIE)
print c
print
print 'Da load():'
c = Cookie.SimpleCookie()
c.load(HTTP_COOKIE)
print c
$ python Cookie_parse.py Dal costruttore: Set-Cookie: intero=5 Set-Cookie: stringa_con_apici="Disse, \"Salve, Mondo!\"" Da load(): Set-Cookie: intero=5 Set-Cookie: stringa_con_apici="Disse, \"Salve, Mondo!\""
Oltre ad usare l'intestazione Set-Cookie, è possibile usare JavaScript per aggiungere dei cookie ad un client.
SimpleCookie
e
Mosrsel
forniscono un output JavaScript tramite il metodo
js_output()
.
import Cookie
c = Cookie.SimpleCookie()
c['ilmiocookie'] = 'valore_cookie'
c['altro_cookie'] = 'secondo valore'
print c.js_output()
Tutti questi esempi hanno usato SimpleCookie. Il modulo
Cookie
comprende anche due altri classi:
SerialCookie
e
SmartCookie
. SerialCookie puù gestire qualsiasi valore che possa essere oggetto di pickle. SmartCookie identifica se un valore debba essere estratto da pickle oppure se si tratte di un semplice valore. Visto che entrambe queste classi usano pickle, ci sono potenziali falle di sicurezza nella applicazione, quindi non dovrebbero essere usate. E' più sicuro conservare lo stato sul server, e passare al cliente una chiave di sessione.