Posting a json data with "Content-Type: application/x-www-form-urlencoded" header and can't get data from req. Tried req.params, req.media and req.stream.read() - all empty.
auto_parse_form_urlencoded is set to True.
cURL request:
curl 'http://127.0.0.1:8000/' -H 'Accept: application/json, text/plain, */*' --compressed -H 'Content-Type: application/x-www-form-urlencoded' --data '{ "param1": 1 , "param2": "2" }'
I know that it is unusual situation, but that is how a third party app currently works and I'm trying to write a middleware that will convert data to json (already did one for multipart/form-data).
Hi @mastizada !
Yes, it is very unusual to masquerade JSON as application/x-www-form-urlencoded indeed, but knowing it is a third party app, and not your choice, I will refrain from judgement.
The answer is that it should just work out of the box, unless I misunderstood anything.
Just set auto_parse_form_urlencoded to False instead (False should already be default in recent Falcon versions, but it does not hurt to be explicit):
import json
import falcon
class Responder:
def on_post(self, req, resp):
data = req.bounded_stream.read()
resp.media = json.loads(data.decode())
api = falcon.API()
api.req_options.auto_parse_form_urlencoded = False
api.add_route('/', Responder())
Then, running this with gunicorn, I could perform your cURL:
curl 'http://127.0.0.1:8000/' -H 'Accept: application/json, text/plain, */*' --compressed -H 'Content-Type: application/x-www-form-urlencoded' --data '{ "param1": 1 , "param2": "2" }'
{"param1": 1, "param2": "2"}
(Setting it to True would have parsed the form as URL-encoded automatically, silencing the errors etc, exactly as you have observed)
What is more, you actually do not even need to use any middleware.
Even though it would look odd, you could also install JSON media handler to handle application/x-www-form-urlencoded, then you could just access your payload as req.media:
import json
import falcon
import falcon.media
class Responder:
def on_post(self, req, resp):
resp.media = req.media
api = falcon.API()
api.req_options.auto_parse_form_urlencoded = False
api.req_options.media_handlers = falcon.media.Handlers({
'application/x-www-form-urlencoded': falcon.media.JSONHandler(),
})
api.add_route('/', Responder())
Hope this helps, but do not hesitate to ask should you still have any issue with the above!
Thanks @vytas7 it works.
Most helpful comment
Hi @mastizada !
Yes, it is very unusual to masquerade JSON as
application/x-www-form-urlencodedindeed, but knowing it is a third party app, and not your choice, I will refrain from judgement.The answer is that it should just work out of the box, unless I misunderstood anything.
Just set
auto_parse_form_urlencodedtoFalseinstead (Falseshould already be default in recent Falcon versions, but it does not hurt to be explicit):Then, running this with
gunicorn, I could perform your cURL:(Setting it to
Truewould have parsed the form as URL-encoded automatically, silencing the errors etc, exactly as you have observed)What is more, you actually do not even need to use any middleware.
Even though it would look odd, you could also install JSON media handler to handle
application/x-www-form-urlencoded, then you could just access your payload asreq.media:Hope this helps, but do not hesitate to ask should you still have any issue with the above!