2012-04-12 9 views
6

estoy desarrollando un pequeño servicio web en Python usando:Frasco: ¿los encabezados no se convierten a Unicode?

  • Frasco (v. 0.8)
  • ORM tormenta (v 0.19.)
  • Apache con mod_wsgi

tengo un encabezado HTTP personalizado, Unison-UUID que estoy usando en algún momento para recuperar información en mi base de datos.

aquí está el (ligeramente reescrito por simplicidad) fragmento que estoy teniendo problemas con:

uuid = flask.request.headers['Unison-UUID'] 
store = storm.locals.Store(my_database) 
user = store.get(models.User, uuid) 

La clase User es más o menos así:

class User(Storm): 
    uuid = Unicode(primary=True) 
    # Other columns.... 

El código anterior falla en De la siguiente manera:

File "/Users/lum/Documents/unison-recsys/www/api/unison/unison.py", line 27, in decorated 
    user = g.store.get(models.User, uuid) 
    File "/Users/lum/Documents/unison-recsys/venv/lib/python2.6/site-packages/storm/store.py", line 165, in get 
    variable = column.variable_factory(value=variable) 
    File "/Users/lum/Documents/unison-recsys/venv/lib/python2.6/site-packages/storm/variables.py", line 396, in parse_set 
    % (type(value), value)) 
TypeError: Expected unicode, found <type 'str'>: '00000000-0000-0000-0000-000000000009' 

Realmente no entiendo por qué esto está sucediendo y lo que puedo hacer al respecto. Pensé Flask was 100% unicode.

Una solución rápida que encontré es decodificar el valor del encabezado, es decir, uuid = uuid.decode('utf-8'). ¿Es esto realmente lo que debe hacerse? Esto parece un poco hackish. ¿No hay forma de obtener unicode directamente, sin tener que "decodificarlo" manualmente?

+3

Puede ser de interés: http://stackoverflow.com/q/818122/311220 http: // stackoverflow.com/q/7567154/311220 – Acorn

Respuesta

12

En http://flask.pocoo.org/docs/api/#flask.request leemos

El objeto de solicitud es una instancia de una subclase Request y proporciona todos los atributos que define Werkzeug.

La palabra Request enlaces a http://werkzeug.pocoo.org/docs/wrappers/#werkzeug.wrappers.Request donde leemos

Los Request y Response clases subclase de las clases BaseRequest y BaseResponse y poner en práctica todos los mixins Werkzeug ofrece:

La palabra BaseRequest enlaces a http://werkzeug.pocoo.org/docs/wrappers/#werkzeug.wrappers.BaseRequest donde leemos

encabezados
Los encabezados del entorno WSGI son inmutables EnvironHeaders.

La palabra EnvironHeaders enlaces a http://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.EnvironHeaders donde se lee

Esto proporciona la misma interfaz que Headers y se construye a partir de un entorno WSGI.

La palabra encabezados es ... no, no está vinculado pero debe se ha relacionado con http://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.Headers donde leemos

encabezados es compatible con la mayoría de la clase Python wsgiref.headers.Headers

donde la frase wsgiref.headers.Headers enlaces a http://docs.python.org/dev/library/wsgiref.html#wsgiref.headers.Headers donde leemos

Cree un encabezado de ajuste de objetos de tipo mapeo, que debe ser una lista de tuplas de nombre/valor de encabezado como se describe en PEP 3333.

La frase PEP 3333 enlaces a http://www.python.org/dev/peps/pep-3333/ donde no hay una definición explícita de qué tipo cabeceras deberían ser, pero después de buscar por palabra cabeceras por un tiempo nos encontramos con esta declaración, por lo tanto

WSGI define dos tipos de "cadena":

"Native" strings (which are always implemented using the type named str) 
that are used for request/response headers and metadata 
"Bytestrings" (which are implemented using the `bytes` type in Python 3, 
and `str` elsewhere), that are used for the bodies of requests and 
responses (e.g. POST/PUT input data and HTML page outputs). 

es por eso que en Python 2 se obtiene encabezados como str no unicode.

Ahora vayamos a la decodificación.

Ni su .decode('utf-8') ni mensi .decode('ascii') (ni esperando ciegamente ninguna otra codificación) es universalmente bueno porque In theory, HTTP header field values can transport anything; the tricky part is to get all parties (sender, receiver, and intermediates) to agree on the encoding.. Dicho esto creo que debe actuar de acuerdo a Julian Reshke advice

Por lo tanto, la manera segura de hacer esto es pegarse a ASCII, y elegir una codificación en la parte superior de que, como el que se define en el RFC 5987.

después de comprobar que los Agentes de usuario (navegadores) que admite han implementado.

Título de RFC 5987 es conjunto de caracteres y codificación de idioma para el protocolo de transferencia de hipertexto (HTTP) Parámetros campo de cabecera

+2

respuesta muy detallada, ¡muchas gracias! – lum

+0

+1 (+10 si pudiera)! –

0

Los valores de encabezado son ASCII, consulte las preguntas vinculadas de Acorn.

Lo que se puede hacer aquí es o bien decodificar de forma manual, como lo hizo (aunque se debe usar uuid.decode('ascii') y no UTF-8) o cambia su campo para ser RawStr en lugar de Unicode

+0

Los valores de encabezado son ** no ** ASCII, consulte http://stackoverflow.com/a/818188/95735 –

+0

Gracias por mencionar 'RawStr'. Esta podría ser una mejor opción en mi caso específico. – lum

Cuestiones relacionadas