简体   繁体   English

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

[英]Get raw POST body in Python Flask regardless of Content-Type header

Previously, I asked How to get data received in Flask request because request.data was empty.之前问过如何获取 Flask 请求中收到的数据,因为request.data为空。 The answer explained that request.data is the raw post body, but will be empty if form data is parsed.答案解释说request.data是原始帖子正文,但如果解析表单数据,它将为空。 How can I get the raw post body unconditionally?如何无条件获取原始帖子正文?

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

Use request.get_data() to get the raw data, regardless of content type.无论内容类型如何,都使用request.get_data()获取原始数据。 The data is cached and you can subsequently access request.data , request.json , request.form at will.数据被缓存,随后您可以随意访问request.datarequest.jsonrequest.form

If you access request.data first, it will call get_data with an argument to parse form data first.如果您首先访问request.data ,它将首先调用带有参数的get_data来解析表单数据。 If the request has a form content type ( multipart/form-data , application/x-www-form-urlencoded , or application/x-url-encoded ) then the raw data will be consumed.如果请求具有表单内容类型( multipart/form-dataapplication/x-www-form-urlencodedapplication/x-url-encoded ),则将使用原始数据。 request.data and request.json will appear empty in this case.在这种情况下request.datarequest.json将显示为空。

request.stream is the stream of raw data passed to the application by the WSGI server. request.stream是 WSGI 服务器传递给应用程序的原始数据流。 No parsing is done when reading it, although you usually want request.get_data() instead.读取时不进行解析,尽管您通常需要request.get_data()代替。

data = request.stream.read()

The stream will be empty if it was previously read by request.data or another attribute.如果之前由request.data或其他属性读取,则该流将为空。

I created a WSGI middleware that stores the raw body from the environ['wsgi.input'] stream.我创建了一个 WSGI 中间件,用于存储来自environ['wsgi.input']流的原始正文。 I saved the value in the WSGI environ so I could access it from request.environ['body_copy'] within my app.我将值保存在 WSGI 环境中,以便我可以从我的应用程序中的request.environ['body_copy']访问它。

This isn't necessary in Werkzeug or Flask, as request.get_data() will get the raw data regardless of content type, but with better handling of HTTP and WSGI behavior.这在 Werkzeug 或 Flask 中不是必需的,因为request.get_data()将获取原始数据而不管内容类型如何,但可以更好地处理 HTTP 和 WSGI 行为。

This reads the entire body into memory, which will be an issue if for example a large file is posted.这会将整个正文读入内存,如果例如发布大文件,这将是一个问题。 This won't read anything if the Content-Length header is missing, so it won't handle streaming requests.如果缺少Content-Length标头,这将不会读取任何Content-Length ,因此它不会处理流请求。

from io import BytesIO

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

    def __call__(self, environ, start_response):
        length = int(environ.get('CONTENT_LENGTH') or 0)
        body = environ['wsgi.input'].read(length)
        environ['body_copy'] = body
        # replace the stream since it was exhausted by read()
        environ['wsgi.input'] = BytesIO(body)
        return self.application(environ, start_response)

app.wsgi_app = WSGICopyBody(app.wsgi_app)
request.environ['body_copy']

request.data will be empty if request.headers["Content-Type"] is recognized as form data, which will be parsed into request.form .如果request.headers["Content-Type"]被识别为表单数据, request.data将为空,它将被解析为request.form To get the raw data regardless of content type, use request.get_data() .无论内容类型如何,都要获取原始数据,请使用request.get_data()

request.data calls request.get_data(parse_form_data=True) , which results in the different behavior for form data. request.data调用request.get_data(parse_form_data=True) ,这导致表单数据的不同行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Python 请求不发送 {"Content-Type":"application/json"} 标头或只是忽略 HTTP POST 中的正文 - Python requests not sending {"Content-Type":"application/json"} header or is just ignoring body in HTTP POST 基于Content-Type标头的Python / Django REST Framework POST - Python/Django REST Framework POST based on Content-Type header Ajax,内容类型标头和python - Ajax, content-type header and python Python HTTP标头内容类型边界 - Python HTTP Header Content-Type boundary 我无法传递 Content-Type header 并且内容在 POST python 请求中始终为 0 - I can't pass the Content-Type header and the content is always 0 on POST python request 烧瓶中没有POST请求和Content-Type“application / json”的响应 - No response with POST request and Content-Type “application/json” in flask Python:如何获取 URL 的内容类型? - Python: How to get the Content-Type of an URL? Python Flask,如何为静态文件(js)设置“Content-Type”? - Python Flask, how to set 'Content-Type' for static files (js)? Flask - 当内容类型为“application/x-www-form-urlencoded”时,如何在 POST 请求中读取原始正文 - Flask - How do I read the raw body in a POST request when the content type is "application/x-www-form-urlencoded" 如何检测和更正 python 中电子邮件标题中的 Content-Type 字符集? - How to detect and correct the Content-Type charset in email header in python?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM