Matraz – los encabezados no se convierten a Unicode?

Estoy desarrollando un pequeño servicio web en python usando:

  • Frasco (v. 0.8)
  • tormenta ORM (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 fragmento (ligeramente reescrito para simplificar) con el que tengo problemas:

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

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

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

El código anterior falla 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 : '00000000-0000-0000-0000-000000000009' 

Realmente no entiendo por qué sucede esto y qué puedo hacer al respecto. Pensé que Flask era 100% unicode .

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

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

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

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

Las clases de Request y Response subclasifican las clases BaseRequest y BaseResponse e implementan todos los mixins que Werkzeug proporciona:

La palabra BaseRequest enlaza con http://werkzeug.pocoo.org/docs/wrappers/#werkzeug.wrappers.BaseRequest donde leemos

encabezados
Los encabezados del EnvironHeaders WSGI como EnvironHeaders inmutables.

La palabra EnvironHeaders enlaza con http://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.EnvironHeaders donde leemos

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

La palabra Encabezados es … no, no está vinculada, pero debería haberse vinculado a http://pocoo.org/docs/datastructures/#werkzeug.datastructures.Headers donde leemos

Los encabezados son mayormente compatibles con la clase Python wsgiref.headers.Headers

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

Cree un objeto similar a la asignación que encabeza los encabezados, que debe ser una lista de tuplas de nombre / valor del encabezado como se describe en PEP 3333 .

La frase PEP 3333 enlaza con http://www.python.org/dev/peps/pep-3333/ donde no hay una definición explícita de qué tipo de encabezados deben ser, pero después de buscar encabezados de palabras por un tiempo encontramos esta afirmació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 (eg POST/PUT input data and HTML page outputs). 

Es por eso que en Python 2 obtienes los encabezados como str no unicode .

Ahora vamos a pasar a la deencoding.

Ni su .decode('utf-8') ni el mensi .decode('ascii') (ni esperar ciegamente ninguna otra encoding) es universalmente bueno porque, en teoría, los valores de campo del encabezado HTTP pueden transportar cualquier cosa; la parte difícil es lograr que todas las partes (remitente, receptor e intermedios) estén de acuerdo con la encoding. . Dicho esto, creo que deberías actuar de acuerdo con el consejo de Julian Reshke.

Por lo tanto, la forma segura de hacerlo es apegarse a ASCII y elegir una encoding además de eso, como la definida en RFC 5987.

después de verificar que los Agentes de Usuario (navegadores) que soporta lo han implementado.

El título de RFC 5987 es Conjunto de caracteres y encoding de idioma para los parámetros de campo del encabezado del Protocolo de transferencia de hipertexto (HTTP)

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

Lo que puede hacer aquí es decodificarlo manualmente como lo hizo (aunque debería usar uuid.decode('ascii') y no utf-8) o cambiar su campo para que sea RawStr lugar de Unicode