Получите исходное тело POST в Python Flask независимо от заголовка Content-Type
Ранее я спросил Как получить данные, полученные в запросе 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
Ответы
Ответ 1
Используйте 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
в этом случае будут пустыми.
Ответ 2
Там request.stream
, когда тип mime не распознается.
data = request.stream.read()
Ответ 3
У меня была эта проблема, и я думаю, что некоторые из вас могут извлечь выгоду из моего решения. Я создал класс промежуточного ПО WSGI, который сохраняет исходный корпус POST из сокета. Я сохранил значение в переменной WSGI 'environ', поэтому я мог ссылаться на него как request.environ ['body_copy'] в моем приложении Flask.
Вам нужно быть осторожным, чтобы почтовые данные были не слишком большими или у вас могут быть проблемы с памятью на вашем сервере.
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
Ответ 4
Наконец-то я понял, что сделаю это:
request.environ['CONTENT_TYPE'] = 'application/something_Flask_ignores'
Тогда request.data
будет фактически иметь данные сообщения. Это значит, что вы не можете контролировать запрос клиента и хотите просто переопределить его на сервере.