41

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
  • 1,048,767
  • 296
  • 4,058
  • 3,343
apardes
  • 4,272
  • 7
  • 40
  • 66

3 Answers3

65

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
  • 1,048,767
  • 296
  • 4,058
  • 3,343
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,868
  • 1
  • 30
  • 36
  • 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
0

just change args for form and it will work

@app.route('/testpoint', methods = ['POST'])
def testpoint():
    name = request.form.get('name', '')`enter code here`
    return jsonify(name = name)