2013-01-03 17 views
9

Stiamo provando a far funzionare un servizio Web Flask e stiamo riscontrando alcuni problemi con i post di streaming, ad esempio quando l'intestazione include Transfer-Encoding: chunked.Flask e Transfer-Encoding: chunked

Sembra che il pallone predefinito non supporti HTTP 1.1. C'è un lavoro in giro per questo?

Ci sono in esecuzione questo comando:

$ curl -v -X PUT --header "Transfer-Encoding: chunked" -d @pylucene-3.6.1-2-src.tar.gz "http://localhost:5000/async-test" 

Contro questo codice:

@app.route("/async-test", methods=['PUT']) 
def result(): 
    print '------->'+str(request.headers)+'<------------' 
    print '------->'+str(request.data)+'<------------' 
    print '------->'+str(request.form)+'<------------' 
    return 'OK' 

ecco l'output ricciolo:

$ curl -v -X PUT --header "Transfer-Encoding: chunked" -d @pylucene-3.6.1-2-src.tar.gz "http://localhost:5000/async-test" 
* About to connect() to localhost port 5000 (#0) 
* Trying ::1... Connection refused 
* Trying 127.0.0.1... connected 
* Connected to localhost (127.0.0.1) port 5000 (#0) 
> PUT /async-test HTTP/1.1 
> User-Agent: curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8r zlib/1.2.5 
> Host: localhost:5000 
> Accept: */* 
> Transfer-Encoding: chunked 
> Content-Type: application/x-www-form-urlencoded 
> Expect: 100-continue 
> 
* HTTP 1.0, assume close after body 
< HTTP/1.0 200 OK 
< Content-Type: text/html; charset=utf-8 
< Content-Length: 2 
< Server: Werkzeug/0.8.3 Python/2.7.1 
< Date: Wed, 02 Jan 2013 21:43:24 GMT 
< 

Ed ecco l'output del server Flask:

* Running on 0.0.0.0:5000/ 
------->Transfer-Encoding: chunked 
Content-Length: 
User-Agent: curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8r zlib/1.2.5 
Host: localhost:5000 
Expect: 100-continue 
Accept: */* 
Content-Type: application/x-www-form-urlencoded 

<------------ 
-------><------------ 
------->ImmutableMultiDict([])<------------ 
+0

Hai mai trovato una soluzione a questo aggiungere? –

+0

Non devo avere le notifiche attivate, quindi non ho visto questo commento fino ad ora. La risposta di Waqas è corretta; abbiamo spostato il codice di test su Java. –

risposta

3

Non è il Flask Python, è il mod_wsgi. Solo le versioni mod_wsgi 3.0+ hanno iniziato a supportare i trasferimenti HTTP chunked. Flask Python usa internamente Werkzeug tool-kit come interfaccia per mod_wsgi. Se lo hai installato dalle fonti apt potrebbe essere una vecchia versione.

Provare a compilare l'ultima versione di mod_wsgi e quindi installare il framework Flask, potrebbe risolvere il problema.

1

Questo funziona per me, ma non è il modo più elegante di sfogliare l'analisi parzializzata. Ho usato il metodo di incollare il corpo nell'ambiente della risposta.

Get raw POST body in Python Flask regardless of Content-Type header

Ma il codice a che fare con l'analisi Chunked

class WSGICopyBody(object): 
    def __init__(self, application): 
     self.application = application 

    def __call__(self, environ, start_response): 
     from cStringIO import StringIO 
     input = environ.get('wsgi.input') 
     length = environ.get('CONTENT_LENGTH', '0') 
     length = 0 if length == '' else int(length) 
     body = '' 
     if length == 0: 
      environ['body_copy'] = '' 
      if input is None: 
       return 
      if environ.get('HTTP_TRANSFER_ENCODING','0') == 'chunked': 
       size = int(input.readline(),16) 
       while size > 0: 
        body += input.read(size+2) 
        size = int(input.readline(),16) 
     else: 
      body = environ['wsgi.input'].read(length) 
     environ['body_copy'] = body 
     environ['wsgi.input'] = StringIO(body) 

     # Call the wrapped application 
     app_iter = self.application(environ, 
            self._sr_callback(start_response)) 

     # Return modified response 
     return app_iter 

    def _sr_callback(self, start_response): 
     def callback(status, headers, exc_info=None): 

      # Call upstream start_response 
      start_response(status, headers, exc_info) 
     return callback 


app.wsgi_app = WSGICopyBody(app.wsgi_app) 

uso questo per ottenere a esso

request.environ['body_copy']