Python Flask'ta Content-Type başlığından bağımsız olarak ham POST gövdesini alın


131

Daha önce, boş olduğu için Flask isteğinde alınan verilerin nasıl alınacağını sordum request.data. Yanıt request.data, ham yazı gövdesi olduğunu ancak form verileri ayrıştırılırsa boş olacağını açıkladı. Ham post gövdesini koşulsuz olarak nasıl alabilirim?

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

Yanıtlar:


218

request.get_data()İçerik türünden bağımsız olarak ham verileri almak için kullanın . Veri önbelleğe alınır ve ardından siz erişemez request.data, request.json, request.formirade.

request.dataÖnce erişirseniz, önce get_dataform verilerini ayrıştırmak için bir bağımsız değişkenle birlikte arayacaktır . İstek bir şekilde içerik türü varsa ( multipart/form-data, application/x-www-form-urlencodedya da application/x-url-encoded) daha sonra ham veri tükenir. request.datave request.jsonbu durumda boş görünecektir.


2
Bu, raven-python (Sentry), hata ve geçici çözümleri kullanırken kırılıyor
dequis

34

request.streamWSGI sunucusu tarafından uygulamaya aktarılan ham veri akışıdır. Okurken hiçbir ayrıştırma yapılmaz, request.get_data()bunun yerine genellikle isteseniz de .

data = request.stream.read()

Daha önce request.dataveya başka bir öznitelik tarafından okunmuşsa akış boş olacaktır .


15

environ['wsgi.input']Akıştan ham gövdeyi depolayan bir WSGI ara yazılımı oluşturdum . Değeri WSGI ortamında kaydettim, böylece request.environ['body_copy']uygulamamdan ona erişebildim .

Bu, request.get_data()içerik türüne bakılmaksızın ham verileri alacağı için Werkzeug veya Flask'ta gerekli değildir , ancak HTTP ve WSGI davranışının daha iyi işlenmesiyle.

Bu, tüm gövdeyi belleğe okur ve bu, örneğin büyük bir dosya gönderildiğinde sorun olur. Bu, Content-Lengthbaşlık eksikse hiçbir şey okumaz , bu nedenle akış isteklerini işlemez.

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']

7

request.datarequest.headers["Content-Type"]ayrıştırılacak form verisi olarak tanınırsa boş olacaktır request.form. Ham veriyi içerik türünden bağımsız olarak almak için kullanın request.get_data().

request.datarequest.get_data(parse_form_data=True)form verileri için farklı davranışa neden olan çağrılar .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.