Flask – How do I read the raw body in a POST request when the content type is "application/x-www-form-urlencoded"

Question:

Turns out that Flask sets request.data to an empty string if the content type of the request is application/x-www-form-urlencoded. Since I’m using a JSON body request, I just want to parse the json or force Flask to parse it and return request.json.

This is needed because changing the AJAX content type forces an HTTP OPTION request, which complicates the back-end.

How do I make Flask return the raw data in the request object?

Asked By: Ron Reiter

||

Answers:

You can get the post data via request.form.keys()[0] if content type is application/x-www-form-urlencoded.

request.form is a multidict, whose keys contain the parsed post data.

Answered By: iMom0

If you want get the JSON when request is ‘Content-Type’: ‘application/x-www-form-urlencoded’ you need “force” conversion to json like de code below:

from flask import Flask, request
import os


app = Flask(__name__)


@app.route("/my-endpoint", methods = ['POST'])
def myEndpoint():

    requestJson = request.get_json(force=True)

    //TODO: do something....

    return requestJson


if __name__ == "__main__":
    port = int(os.environ.get('PORT', 5000))
    app.run(host='0.0.0.0', port=port, debug=True, use_reloader=True)
Answered By: rafambbr

Use request.get_data() to get the POST data. This works independent of whether the data has content type application/x-www-form-urlencoded or application/octet-stream.

Answered By: Mark

try this:

f = request.form

   output = []

   user_data = {}

   user_data['email'] = f['email']

   user_data['password'] = f['password']

   user_data['key'] = f['key']

   output.append(user_data)
Answered By: s3had

main.py

import json

from flask import Flask, request

app = Flask(__name__)


@app.route('/', methods=['POST'])
def index():
    mimetype = request.mimetype
    if mimetype == 'application/x-www-form-urlencoded':
        form = json.loads(next(iter(request.form.keys())))
    elif mimetype == 'multipart/form-data':
        form = dict(request.form)
    elif mimetype == 'application/json':
        form = request.json
    else:
        form = request.data.decode()
    print(mimetype, form, type(form))
    return form


if __name__ == '__main__':
    app.run()

Test

curl -X POST http://127.0.0.1:5000/ --data "{"a":1, "b":2}"

curl -X POST http://127.0.0.1:5000/ -F a=1 -F b=2

curl -X POST -H "Content-type: application/json" http://127.0.0.1:5000/ --data "{"a":1, "b":2}"

Result

application/x-www-form-urlencoded {'a': 1, 'b': 2} <class 'dict'>
multipart/form-data {'a': '1', 'b': '2'} <class 'dict'>
application/json {'a': 1, 'b': 2} <class 'dict'>
Answered By: XerCis

You can get it that way:

@app.route("/path-to-the-post-endpoint", methods=["POST"])
def handle_post_request():
    data = request.form.to_dict()
    data['some_key_1'] = "Some Value 1"
    data['some_key_2'] = "Some Value 2"
    # ...etc.

    # DO SOMETHING HERE

    return [], 200
Answered By: Pavel Tashev
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.