40

My understanding is that request.args in Flask contains the URL encoded parameters from a GET request while request.form contains POST data. What I'm having a hard time grasping is why when sending a POST request, trying to access the data with request.form returns a 400 error but when I try to access it with request.args it seems to work fine.

I have tried sending the request with both Postman and curl and the results are identical.

curl -X POST -d {"name":"Joe"} http://127.0.0.1:8080/testpoint --header "Content-Type:application/json"

Code:

@app.route('/testpoint', methods = ['POST'])
def testpoint():
    name = request.args.get('name', '')
    return jsonify(name = name)
Martijn Pieters
  • 963,270
  • 265
  • 3,804
  • 3,187
apardes
  • 4,012
  • 6
  • 37
  • 61

2 Answers2

60

You are POST-ing JSON, neither request.args nor request.form will work.

request.form works only if you POST data with the right content types; form data is either POSTed with the application/x-www-form-urlencoded or multipart/form-data encodings.

When you use application/json, you are no longer POSTing form data. Use request.get_json() to access JSON POST data instead:

@app.route('/testpoint', methods = ['POST'])
def testpoint():
    name = request.get_json().get('name', '')
    return jsonify(name = name)

As you state, request.args only ever contains values included in the request query string, the optional part of a URL after the ? question mark. Since it’s part of the URL, it is independent from the POST request body.

Martijn Pieters
  • 963,270
  • 265
  • 3,804
  • 3,187
3

Your json data in curl is wrong, so Flask does not parse data to form.

Send data like this: '{"name":"Joe"}'

curl -X POST -d '{"name":"Joe"}' http://example.com:8080/testpoint --header "Content-Type:application/json"
iurisilvio
  • 4,727
  • 1
  • 26
  • 31
  • 4
    The problem is that the OP is posting JSON in the first place, then using methods meant for *form data* to access the information. – Martijn Pieters Apr 29 '14 at 07:07