Cookie - Cookie HTTP

Scopo Il modulo Cookie definisce le classi per l'analisi e la creazione di intestazioni cookie HTTP.
Versione Python 2.1 e superiore

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.

Creare ed Impostare un Cookie

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

Morsel

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:

  • expires
  • path
  • comment
  • domain
  • max-age
  • secure
  • version

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.

Valori Codificati

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=5 
  valore codificato=5

stringa_con_apici
  Set-Cookie: stringa_con_apici="Disse, \"Salve, Mondo!\""
  valore=Disse, "Salve, Mondo!" 
  valore codificato="Disse, \"Salve, Mondo!\""

Ricevere ed Analizzare le Intestazioni Cookie

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!\""

Formati Alternativi di Output

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()

Classi Deprecate

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.

Vedere anche:

Cookie
La documenazione della libreria standard per questo modulo
cookielib
Il modulo cookielib, per lavorare con i cookie dal lato client.
RFC 2109
Meccanismo di gestione dello stato HTTP