[python] Content-Type 헤더에 관계없이 Python Flask에서 원시 POST 본문 가져 오기

이전에는 비어 있기 때문에 플라스크 요청에서 데이터를받는 방법을 물었 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-urlencodedapplication/x-url-encoded)는 원시 데이터가 소모 될 것이다. request.data그리고 request.json이 경우 빈 나타납니다.


답변

request.streamWSGI 서버가 애플리케이션에 전달한 원시 데이터 스트림입니다. 읽을 때는 일반적으로 구문 분석이 수행되지 않습니다 request.get_data().

data = request.stream.read()

이전에 읽은 스트림 request.data또는 다른 속성 인 경우 스트림이 비어 있습니다 .


답변

environ['wsgi.input']스트림 에서 원시 본문을 저장하는 WSGI 미들웨어를 작성했습니다 . WSGI 환경에 값을 저장하여 request.environ['body_copy']앱 내 에서 액세스 할 수 있습니다 .

request.get_data()컨텐츠 유형에 관계없이 원시 데이터를 가져 오지만 HTTP 및 WSGI 동작을보다 잘 처리 하므로 Werkzeug 또는 Flask에서는 필요하지 않습니다 .

이것은 전체 본문을 메모리로 읽습니다. 예를 들어 큰 파일이 게시되면 문제가됩니다. 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.datarequest.headers["Content-Type"]양식 데이터로 인식 되면로 비워 지며로 분석됩니다 request.form. 컨텐츠 유형에 관계없이 원시 데이터를 얻으려면을 사용하십시오 request.get_data().

request.data전화 request.get_data(parse_form_data=True), 폼 데이터에 대한 다른 행동의 결과.


답변