2009-06-18 6 views
3

Angenommen ich ein Byte-Stream in es mit der folgenden haben:Wie erstellt man ein webob.Request oder ein WSGI 'environ' dict aus dem HTTP-Request-Byte-Stream?

 
POST /mum/ble?q=huh 
Content-Length: 18 
Content-Type: application/json; charset="utf-8" 
Host: localhost:80 

["do", "re", "mi"] 

Gibt es eine Möglichkeit, eine WSGI-Stil ‚environ‘ dict daraus zu produzieren?

Hoffentlich habe ich eine einfache Antwort übersehen, und es ist so einfach zu erreichen wie die umgekehrte Operation. Bedenken Sie:

>>> import json 
>>> from webob import Request 
>>> r = Request.blank('/mum/ble?q=huh') 
>>> r.method = 'POST' 
>>> r.content_type = 'application/json' 
>>> r.charset = 'utf-8' 
>>> r.body = json.dumps(['do', 're', 'mi']) 
>>> print str(r) # Request's __str__ method gives raw HTTP bytes back! 
POST /mum/ble?q=huh 
Content-Length: 18 
Content-Type: application/json; charset="utf-8" 
Host: localhost:80 

["do", "re", "mi"] 

Antwort

5

Standardbibliothek Code des Reusing Python zum Zweck ist ein bisschen schwierig (es nicht so wiederverwendet zu werden wurde entwickelt, -!), Sollte aber machbar sein, zB:

import cStringIO 
from wsgiref import simple_server, util 

input_string = """POST /mum/ble?q=huh HTTP/1.0 
Content-Length: 18 
Content-Type: application/json; charset="utf-8" 
Host: localhost:80 

["do", "re", "mi"] 
""" 

class FakeHandler(simple_server.WSGIRequestHandler): 
    def __init__(self, rfile): 
     self.rfile = rfile 
     self.wfile = cStringIO.StringIO() # for error msgs 
     self.server = self 
     self.base_environ = {} 
     self.client_address = ['?', 80] 
     self.raw_requestline = self.rfile.readline() 
     self.parse_request() 

    def getenv(self): 
     env = self.get_environ() 
     util.setup_testing_defaults(env) 
     env['wsgi.input'] = self.rfile 
     return env 

handler = FakeHandler(rfile=cStringIO.StringIO(input_string)) 
wsgi_env = handler.getenv() 

print wsgi_env 

Grundsätzlich müssen wir den Request-Handler von der Unterklasse ableiten, um den normalerweise vom Server ausgeführten Build-Prozess (rfile und wfile vom Socket zum Client usw.) zu fälschen. Das ist nicht ganz komplett, denke ich, sollte aber nah sein und ich hoffe es erweist sich als hilfreich!

Beachten Sie, dass ich habe auch Ihr Beispiel HTTP-Anforderung festgelegt: ohne HTTP/1.0 oder 1.1 am Ende der Roh-Anforderungsleitung, ein POST gilt als schlecht ausgebildet und verursacht eine Ausnahme und eine resultierende Fehlermeldung auf handler.wfile.

+1

Alex, danke, es funktioniert wie beworben. Und ich habe dieses Diktat erneut über webob.Request .__ str__ gerundet und die erwarteten Ergebnisse erhalten (minus HTTP-Version, die Request-Klasse aus irgendeinem Grund nicht erzeugt). –

+0

Ich vermute, dass der "self.server = self" zu einem Speicherleck führt. Daher wäre es eine gute Idee nach "handler = FakeHandler (...)" "del handler.server" zu machen. – offby1

+0

@ offby1, eine Referenzschleife (die 'self.server = self' erzeugt) ist kein Speicherleck, da Python eine Speicherbereinigung für Referenzschleifen hat; Wenn Sie die Schleife absichtlich brechen können, wird das die Dinge beschleunigen, indem Sie den 'gc'-Pass vermeiden. –

Verwandte Themen