Flask or Werkzeug/0.9.4 breaking POST data

846 views Asked by At

I have found some behaviour of Flask-restful caused I think by Werkzeug/0.9.4 that I do not understand. It seems that the use of Multidict is breaking my data when I try to POST valid JSON that contains a "=".

Here's my test JSON:

{
    "alert": {
        "@id": "90",
        "action": "hoojimaflip",
        "fruit": {
            "@bowl": "bananas",
            "@protocol": "tcp"
        },
        "url": "https://this-is-a-sample/paramer?id=90"
    }
}

Here is the POST method.

def post(self):
    f1=open("./log", 'w+')
    data = request.json
    if not data:
        # I know this is not equivalent to the JSON above. 
        # Just troubleshooting by dumping it all out.
        data = request.form
    print >>f1, data
    return ('', 201)

If I POST using cURL with application/json it's fine. I get the POSTed JSON correctly in request.data. I will need to render it back to JSON later, but no issue.

{
    u'alert': {
        u'@id': u'90'
        u'action': u'hoojimaflip', 
        u'fruit': {
              u'@bowl': u'bananas', 
              u'@protocol': u'tcp'
        },
        u'url': u'https://this-is-a-sample/paramer?id=90', 
    }
}

If I post via cURL with application/x-www-form-urlencoded, then I should be able to get the data in request.form. But, it seems that something is breaking my data.

ImmutableMultiDict([('
   { "alert": { 
         "@id": "90",
         "action": "hoojimaflip",
         "fruit": {
             "@bowl": "bananas",
             "@protocol": "tcp"
         },
         "url": "https://this-is-a-sample/paramer?id', u'90"    
     }
 }'
 )])

The "=" sign is being used as some kind of record separator and breaking the POSTed JSON.

Does anyone have any ideas? Am I missing something obvious?

Thanks!

1

There are 1 answers

0
Martijn Pieters On BEST ANSWER

If an external application is stubbornly POST-ing with an alternative mime-type, you can force Flask to treat the data as JSON anyway by using the request.get_json() method instead, setting the force argument to True:

data = request.get_json(force=True)

Don't try to treat a JSON payload as form data, that'll never work.