2009-06-18 3 views
3

Предположим, у меня есть поток байтов с в нем следующее:Как построить webob.Request или WSGI 'environment' dict из необработанного потока байтов HTTP-запроса?

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

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

Есть ли способ, чтобы произвести WSGI стиле «окружат» Dict от него?

Надеюсь, я пропустил простой ответ, и его так же легко достичь, как и противоположная операция. Рассмотрим:

>>> 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"] 

ответ

5
стандартный код библиотеки

реиспользование питона для этой цели немного сложнее (он не был предназначен для повторного использования таким образом! -), но должно быть выполнимо, например:

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 

В принципе, нам нужно подклассифицировать обработчик запроса, чтобы подделать процесс построения, который обычно выполняется для него сервером (rfile и wfile, построенный из сокета клиенту и т. Д.). Я думаю, это не совсем полно, но должно быть близко, и я надеюсь, что это окажется полезным!

Обратите внимание, что я также фиксированной ваш пример запроса HTTP: без HTTP/1.0 или 1.1 в конце запроса сырьевой линии, POST считается плохо образован и вызывает исключение и сообщение в результате ошибки на handler.wfile.

+1

Alex, спасибо, он работает как рекламируемый. И я также опрокинул это снова через webob.Request .__ str__ и получил ожидаемые результаты (минус версия HTTP, класс запроса которой по какой-то причине не создается). –

+0

Я подозреваю, что «self.server = self» приводит к утечке памяти. Поэтому было бы неплохо, после выполнения «handler = FakeHandler (...)», чтобы сделать «del handler.server». – offby1

+0

@ offby1, эталонный цикл (который создает 'self.server = self') не является утечкой памяти, поскольку у Python есть сбор мусора для опорных циклов; если вы можете запрограммировать разрыв, это будет очень быстро ускорить процесс, избегая прохода 'gc'. –