2009-11-23 5 views
7

En WSGI, los datos de la publicación se consumen al leer el objeto similar al archivo environ['wsgi.input']. Si un segundo elemento en la pila también quiere leer datos de publicaciones, puede colgar el programa leyendo cuando no hay nada más que leer.¿Cómo copio wsgi.input si quiero procesar datos POST más de una vez?

¿Cómo debo copiar los datos POST para que puedan procesarse varias veces?

Respuesta

7

Go eche un vistazo al paquete WebOb. Proporciona funcionalidad que le permite a uno designar que wsgi.input debe hacerse buscable. Esto tiene el efecto de permitirle rebobinar el flujo de entrada de modo que el contenido pueda reproducirse a través de un controlador diferente. Incluso si no usa WebOb, la forma en que lo hace debe ser instructiva, ya que podría confiar en que Ian lo haya hecho de manera adecuada. Para obtener resultados de búsqueda en la documentación, vaya al here.

1

Si vas a leer de una sola vez, siempre se puede leer en, crear un archivo como objeto cStringIO de las cosas que ha leído y luego asignar de nuevo, como esto:

import cStringIO 
import copy 
lines = [] 
for line in environ['wsgi.input']: 
    lines.append(line) 
newlines = copy.copy(lines) 
environ['wsgi.input'] = cStringIO.StringIO(''.join(newlines)) 

Hay muy probablemente una manera más eficiente de hacer esto, pero en cosas generales post hallazgo de wsgi bastante frágil si desea hacer cualquier cosa no trivial (como los tiempos de lectura de correos Muptiple datos) ...

+0

Y, bobince _es_ la manera más eficiente de hacer eso :) –

+0

El uso de un bucle for/in en wsgi.input así podría ser muy ineficaz en memoria/tiempo. Esto se debe a que, en el peor de los casos, si tenía un archivo grande en el que todos los datos constaban de líneas vacías, terminaría creando una lista muy grande en la que cada entrada es un solo carácter. Además, no estoy seguro de por qué te molestas con copy.copy() dado que te unes de nuevo de inmediato de todos modos. –

10

usted podría intente volver a poner una réplica de archivo de la secuencia en el entorno:

from cStringIO import StringIO 

length = int(environ.get('CONTENT_LENGTH', '0')) 
body = StringIO(environ['wsgi.input'].read(length)) 
environ['wsgi.input'] = body 

Sin embargo, hacer esto es un poco oloroso. Idealmente, solo una parte del código debe analizar la cadena de consulta y el cuerpo de la publicación, y entregar los resultados a otros componentes.

+0

No debe confiar en que la longitud predeterminada del contenido sea -1. No hay nada en la especificación WSGI que diga que una implementación debe aceptar -1 como argumento para leer() para significar leer todas las entradas. Una implementación puede decidir lanzar una excepción en esa circunstancia. De hecho, la especificación probablemente incluso dice que si CONTENT_LENGTH no está presente o vacío, debe interpretarse en el sentido de '0' o no está disponible la entrada. –

+0

Ah yeh ... no estoy muy seguro de por qué lo puse, mi código actual usa 0 :-) Sin embargo, su intención es cambiar este comportamiento en WSGI, ¿no? – bobince

+0

Tengo alguna duda de que WSGI verá algún cambio ahora. –

Cuestiones relacionadas