2012-05-18 41 views
6

Estoy usando Python Flask + nginx con FCGI.Python Flask + nginx fcgi - ¿salida de respuesta grande?

En algunas solicitudes, tengo que generar respuestas grandes. Por lo general, esas respuestas se obtienen de un socket. Actualmente estoy respondiendo así:

response = [] 
while True: 
    recv = s.recv(1024) 
    if not recv: break 
    response.append(recv) 
s.close() 
response = ''.join(response) 

return flask.make_response(response, 200, { 
              'Content-type': 'binary/octet-stream', 
              'Content-length': len(response), 
              'Content-transfer-encoding': 'binary', 
              }) 

El problema es que en realidad no necesito los datos. También tengo una manera de determinar la longitud exacta de respuesta que se debe obtener del socket. Por lo tanto, necesito una buena forma de enviar los encabezados HTTP, y luego comenzar a producir directamente desde el socket, en lugar de recopilarlo en la memoria y luego suministrarlo a nginx (probablemente por algún tipo de transmisión).

No he podido encontrar la solución a este problema aparentemente común. ¿Cómo se lograría eso?

¡Gracias!

Respuesta

10

si response en flask.make_response es iterable, se repetirá para generar la respuesta, y cada cadena se escribirá en la secuencia de salida por sí misma.

lo que esto significa es que también puede devolver un generador que producirá la salida cuando se repita. si conoce la longitud del contenido, puede (y debe) pasarlo como encabezado.

un ejemplo sencillo:

from flask import Flask 
app = Flask(__name__) 
import sys 
import time 
import flask 

@app.route('/') 
def generated_response_example(): 
    n = 20 
    def response_generator(): 
     for i in range(n): 
      print >>sys.stderr, i 
      yield "%03d\n" % i 
      time.sleep(.2) 

    print >>sys.stderr, "returning generator..." 
    gen = response_generator() 

    # the call to flask.make_response is not really needed as it happens imlicitly 
    # if you return a tuple. 
    return flask.make_response(gen ,"200 OK", {'Content-length': 4*n}) 

if __name__ == '__main__': 
    app.run() 

si ejecuta este y probarlo en un navegador, debería ver un buen número de incemental ...

(el tipo de contenido no se ajusta porque parece si lo hago, mi navegador espera hasta que se haya transmitido todo el contenido antes de mostrar la página. wget -qO - localhost:5000 no tiene este problema.

Cuestiones relacionadas