![](/img/trans.png)
[英]Python requests not sending {"Content-Type":"application/json"} header or is just ignoring body in HTTP POST
[英]Get raw POST body in Python Flask regardless of Content-Type header
之前問過如何獲取 Flask 請求中收到的數據,因為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
無論內容類型如何,都使用request.get_data()
獲取原始數據。 數據被緩存,隨后您可以隨意訪問request.data
、 request.json
、 request.form
。
如果您首先訪問request.data
,它將首先調用帶有參數的get_data
來解析表單數據。 如果請求具有表單內容類型( multipart/form-data
、 application/x-www-form-urlencoded
或application/x-url-encoded
),則將使用原始數據。 在這種情況下request.data
和request.json
將顯示為空。
request.stream
是 WSGI 服務器傳遞給應用程序的原始數據流。 讀取時不進行解析,盡管您通常需要request.get_data()
代替。
data = request.stream.read()
如果之前由request.data
或其他屬性讀取,則該流將為空。
我創建了一個 WSGI 中間件,用於存儲來自environ['wsgi.input']
流的原始正文。 我將值保存在 WSGI 環境中,以便我可以從我的應用程序中的request.environ['body_copy']
訪問它。
這在 Werkzeug 或 Flask 中不是必需的,因為request.get_data()
將獲取原始數據而不管內容類型如何,但可以更好地處理 HTTP 和 WSGI 行為。
這會將整個正文讀入內存,如果例如發布大文件,這將是一個問題。 如果缺少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.headers["Content-Type"]
被識別為表單數據, request.data
將為空,它將被解析為request.form
。 無論內容類型如何,都要獲取原始數據,請使用request.get_data()
。
request.data
調用request.get_data(parse_form_data=True)
,這導致表單數據的不同行為。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.