Flask is not getting any POST data from a request


Question

Within our server we've got this piece a code calling a function inside my APP like this:

data = urllib.urlencode( dict(api_key="a-key-goes-here") )
headers = {
    "User-Agent" : "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.2 Safari/537.36",
    "Accept" : "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,text/png,*/*;q=0.5",
    "Accept-Language" : "en-US,en;q=0.8",
    "Accept-Charset" : "ISO-8859-1,utf-8",
    "Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
}
request = urllib2.Request(url, data, headers)
response = urllib2.urlopen(request)
code = response.code
message = response.read()
response.close()

I know that this is not using url_for( neither other ways to call a url trough your APP but this has a reason. Our server is just testing that the call goes correctly but the url is expected to be outside our APP and so is the api key.

So, our server handling url looks like this:

@app.route('/loan_performer', methods=["GET", "POST"])
def loan_performer():
    if 'api_key' in request.form and request.form['api_key'] == API_KEY:
        ret = dict()

        # rate1 return a random number between 3.000 and 4.000 and point1 will be 0
        ret['rate_one'] = random.randint(3000, 4000)
        ret['point_one'] = 0

        # rate2 do it between 3.500 and 4.500, point2 being 0.5
        ret['rate_two'] = random.randint(3500, 4500)
        ret['point_two'] = 0.5  

        # rate3 between 4.000 and 5.000 with 1.0
        ret['rate_three'] = random.randint(4000, 5000)
        ret['point_three'] = 1.0

        return json.dumps(ret), 200

    else:
        return u"Your API Key is invalid.", 403

Our error is as the title says:

We are constantly receiving the error "Bad request (GET and HEAD requests may not contain a request body)" Which is a 404 error handled by Passenger WSGI for Apache. But in other words, for a reason request.form is empty and it shouldn't.

Is there anything I'm doing wrong or any other way to POST data from Flask to outside?

If there is needed more info I'm willing to update, just call it.

Edit 1

I switched to use requests like this:

dat = dict( api_key="a-key-goes-here" )
request = requests.post(url, data=dat)
message = request.text
code = request.status_code

And it refuses to work. This is the logger I made in the handling url function:

(08/02/2014 07:07:20 AM) INFO This is message ImmutableMultiDict([]) ImmutableMultiDict([])  and this code 403

request.args - request.form - request.data , all of them are empty, either using urllib or requests.

Update on Edit 1

After removing "GET" from methods suggested by Martin konecny I got this response:

(08/02/2014 08:35:06 AM) INFO This is message <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>405 Method Not Allowed</title>
<h1>Method Not Allowed</h1>
<p>The method is not allowed for the requested URL.</p>

and this code 405

1
1
11/25/2015 10:21:44 AM

Accepted Answer

But in other words, for a reason request.form is empty and it shouldn't.

I don't think you can infer this conclusion. What appears to be happening is you have a GET request with a POST header.

From the Python docs:

data may be a string specifying additional data to send to the server, or None if no such data is needed. Currently HTTP requests are the only ones that use data; the HTTP request will be a POST instead of a GET when the data parameter is provided. data should be a buffer in the standard application/x-www-form-urlencoded format. The urllib.urlencode() function takes a mapping or sequence of 2-tuples and returns a string in this format.

You need to remove the header

"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"

when you are sending requests with an empty data structure, or just remove it alltogether (it will be added automatically by urllib when needed)

1
8/2/2014 5:59:29 AM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon