3

Is it possible to access the raw, unparsed request data from within a Flask app?

2 Answers 2

3

After digging through the source for a little bit, I think I might be able to answer your question.

Flask's request object subclasses Werkzeug's request object and does a little bit of wrapping. After looking over Werkzeug's request object, it is obviously not the intention of the programmers to let you access the unparsed request object, but you might be able to do it anyway.

Recall that Flask and Werkzeug are WSGI-compatible. Therefore, you might be able to access the unparsed data like this:

Request.environ['wsgi.input']

The problem with this is you would have to manually seek the input stream yourself, which might prove difficult. Also, I think the Request object might process the stream and leave wsgi.input empty.

We need to subclass Flask's Request object:

class newRequest(Request):
    # here is the cool part!
    def _load_form_data(self):
        super(newRequest, self)._load_form_data()
        # stream is a local variable in Werkzeug's _load_form_data() method
        self.UNPARSED_STREAM = stream
        # now we should be able to access the request through Request.UNPARSED_STREAM

# now, we need to tell Flask to use our Request object
app.request_class = newRequest

Note that we are messing with class internals. This is a dangerous hack. I also have not tested this solution at all, but it seems like it should work to me.

Sign up to request clarification or add additional context in comments.

6 Comments

Nice digging around! Not working for me unfortunately. This is the code I'm trying: hastebin.com/4gb6c8za64.py - I'm getting AttributeError: 'NewRequest' object has no attribute 'UNPARSED_STREAM'
That makes me think that our _load_form_data() method never ran. Otherwise, even if UNPARSED_STREAM was empty, it would stil exist. In that case, forget about the subclassing for a second and try accessing Request.environ['wsgi.input'] directly.
It contains a socket._fileobject object. Not sure what I can do with that, trying to .read() results in the script hanging.
After playing around on my own system, my best guess is that the original input stream in consumed once a request is recieved, making it impossible for you to the access the unprocessed request. I worked a little more with the socket._fileobject object, and it appears to be empty. If there is a way to do it, I can't figure it out!
Seems like the only way to go is to find out where Werkzeug consumes the raw request and modify it to save a copy, like you were trying with _load_form_data(). I'll try and do a bit more exploration of the source code :)
|
0

The question is a bit outdated, but someone can get here as I did. =)

I've managed to do it, but for the whole app. So it becomes your responsibility to decode all data of the request, in all routes.

You can basically disable all encoding by setting the request charset to None. It can be done subclassing the werkzeug's BaseRequest class or simply:

application = Flask('api')
application.request_class.charset = None
[...]

This did the job for me.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.