2009-06-18 7 views
3

Supposons que j'ai un flux d'octets avec ce qui suit dans le:Comment construire une requête webob.Request ou une instruction WSGI 'environ' à partir d'un flux d'octets de requêtes HTTP brutes?

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

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

est-il un moyen de produire un style WSGI « environ » dict de celui-ci? Heureusement, j'ai oublié une réponse facile, et il est aussi facile à réaliser que l'opération inverse. Tenir compte:

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

Répondre

5

Réutiliser code bibliothèque standard de Python dans le but est un peu délicat (il n'a pas été conçu pour être réutilisé cette façon -), mais devrait être faisable, par exemple:

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 

Fondamentalement, nous avons besoin de sous-classer le gestionnaire de demande pour falsifier le processus de construction qui est normalement effectué par le serveur (rfile et wfile construit à partir du socket vers le client, et ainsi de suite). Ce n'est pas tout à fait complet, je pense, mais devrait être proche et j'espère que cela sera utile!

Notez que j'ai également fixé votre exemple requête HTTP: sans HTTP/1.0 ou 1,1 à la fin de la ligne de demande brute, un POST est considéré comme mal formé et provoque une exception et un message d'erreur résultant sur handler.wfile.

+1

Alex, merci, ça marche comme annoncé. Et j'ai aussi retourné cette dictée à nouveau via webob.Request .__ str__ et j'ai obtenu les résultats attendus (moins la version HTTP, quelle classe Request ne produit pas pour une raison quelconque). –

+0

Je suspecte que le "self.server = self" mène à une fuite de mémoire. Par conséquent, ce serait une bonne idée, après avoir fait "handler = FakeHandler (...)", de faire "del handler.server". – offby1

+0

@ offby1, une boucle de référence (que self.server = self' crée) n'est pas une fuite de mémoire, car Python a une récupération de place pour les boucles de référence; Si vous pouvez casser la boucle à bon escient, cela accélérera les choses en évitant la passe 'gc'. –

Questions connexes