无论Content-Type标头如何,都可以在Python Flask中获取原始POST主体

时间:2012-06-12 15:37:11

标签: python flask

之前,我问过How to get data received in Flask request,因为request.data是空的。答案解释说request.data是原始帖子正文,但如果解析表单数据则为空。如何无条件地获得原始邮政体?

@app.route('/', methods=['POST'])
def parse_request():
    data = request.data  # empty in some cases
    # always need raw data here, not parsed form data

5 个答案:

答案 0 :(得分:190)

使用request.get_data()获取原始数据,无论内容类型如何。数据已缓存,您随后可以随意访问request.datarequest.jsonrequest.form

如果您首先访问request.data,它将使用参数调用get_data来首先解析表单数据。如果请求具有表单内容类型(multipart/form-dataapplication/x-www-form-urlencodedapplication/x-url-encoded),则将使用原始数据。在这种情况下,request.datarequest.json将显示为空。

答案 1 :(得分:26)

当无法识别mime类型时,会出现request.stream

data = request.stream.read()

答案 2 :(得分:14)

我刚遇到这个问题,我想你们中的一些人可能会从我的解决方案中受益。我创建了一个WSGI中间件类,它从套接字中保存原始POST主体。我将值保存在WSGI变量'environ'中,因此我可以在Flask应用程序中将其称为request.environ ['body_copy']。

您需要注意发布数据不是太大,或者服务器上可能存在内存问题。

class WSGICopyBody(object):
    def __init__(self, application):
        self.application = application

    def __call__(self, environ, start_response):

        from cStringIO import StringIO
        length = environ.get('CONTENT_LENGTH', '0')
        length = 0 if length == '' else int(length)

        body = environ['wsgi.input'].read(length)
        environ['body_copy'] = body
        environ['wsgi.input'] = StringIO(body)

        # Call the wrapped application
        app_iter = self.application(environ, 
                                    self._sr_callback(start_response))

        # Return modified response
        return app_iter

    def _sr_callback(self, start_response):
        def callback(status, headers, exc_info=None):

            # Call upstream start_response
            start_response(status, headers, exc_info)
        return callback

app.wsgi_app = WSGICopyBody(app.wsgi_app)

request.environ['body_copy'] # This is the raw post body you can use in your flask app

答案 3 :(得分:4)

我终于弄清楚我是否这样做了:

request.environ['CONTENT_TYPE'] = 'application/something_Flask_ignores'

然后request.data实际上会有帖子数据。这是因为您无法控制客户端请求并希望在服务器上覆盖它。

答案 4 :(得分:0)

这对我有用:

@application.route("/getrawdata", methods=['POST'])
def getrawdata():
    #Your processing logic here
    return request.get_data()

我已经通过在原始数据中传递二进制字符串在Postman中成功测试了这一点。 为此,您需要在烧瓶中导入请求包:

from flask import request