Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse raw HTTP request with Werkzeug

I'm writing a fuzzer for a Flask application. I have example requests stored as text files, like this get.txt:

GET /docs/index.html HTTP/1.1
Host: www.w3.org

Ideally, I'd parse this to a werkzeug.wrappers.Request object, something like this (psuedo-code):

from werkzeug.wrappers import Request

req = Request()

with open('get.txt') as f:
    req.parse_raw(f.read())

However, it looks like the raw HTTP parsing isn't happening in Werkzeug. Instead, Werkzeug takes a WSGI environ from BaseHTTPServer.BaseHTTPRequestHandler, and that requires a BaseHTTPServer.HTTPServer instance to parse the request. That seems like overkill for something this simple.

I also came across http-parser, which is closer to what I want, but it duplicates most of Werkzeug's data structures with incompatible types. I'd have to transform the data from one to another.

Is there a simpler way to go from raw HTTP request to WSGI environ in Werkzeug (or using BaseHTTPRequestHandler without an HTTP server)?

like image 298
nathancahill Avatar asked Sep 26 '22 10:09

nathancahill


1 Answers

Didn't find an easy way to do this, so I wrote a library called Werkzeug-Raw to parse raw HTTP requests to WSGI environments (or even to open requests on test clients).

It works like this:

from flask import Flask, request
import werkzeug_raw

app = Flask(__name__)

environ = werkzeug_raw.environ('GET /foo/bar?tequila=42 HTTP/1.1')

with app.request_context(environ):
    print request.args  # ImmutableMultiDict([('tequila', u'42')])

To open a raw HTTP request on a test client:

client = app.test_client()
rv = werkzeug_raw.open(client, 'GET /foo/bar?tequila=42 HTTP/1.1')
like image 199
nathancahill Avatar answered Sep 30 '22 06:09

nathancahill