Flask request and application/json content type
Solution 1
Use request.get_json()
and set force
to True
:
@menus.route('/', methods=["PUT", "POST"])
def new():
return jsonify(request.get_json(force=True))
From the documentation:
By default this function will only load the json data if the mimetype is
application/json
but this can be overridden by the force parameter.Parameters:
- force – if set to True the mimetype is ignored.
For older Flask versions, < 0.10, if you want to be forgiving and allow for JSON, always, you can do the decode yourself, explicitly:
from flask import json
@menus.route('/', methods=["PUT", "POST"])
def new():
return jsonify(json.loads(request.data))
Solution 2
the request
object already has a method get_json
which can give you the json regardless of the content-type if you execute it with force=True
so your code would be something like the following:
@menus.route('/', methods=["PUT", "POST"])
def new():
return jsonify(request.get_json(force=True))
in fact, the flask documentation says that request.get_json
should be used instead of request.json
: http://flask.pocoo.org/docs/api/?highlight=json#flask.Request.json
danielrvt
Computer Engineer graduated from Universidad Simon Bolivar, currently living in Caracas, Venezuela. GIS, Mobile and Web app developer... Web is my favorite. Always thinking about user experience and passionate about Python and JavaScript (There is something sexy about dynamic languages...). I also love using GIT and developing Augmented Reality applications with ARToolkit. My account on GitHub is this: https://github.com/danielrvt. See you on SO!!!
Updated on March 02, 2020Comments
-
danielrvt about 4 years
I have a flask app with the following view:
@menus.route('/', methods=["PUT", "POST"]) def new(): return jsonify(request.json)
However, this only works if the request's content type is set to
application/json
, otherwise the dictrequest.json
is None.I know that
request.data
has the request body as a string, but I don't want to be parsing it to a dict everytime a client forgets to set the request's content-type.Is there a way to assume that every incoming request's content-type is
application/json
? All I want is to always have access to a validrequest.json
dict, even if the client forgets to set the application content-type to json. -
danielrvt over 11 yearsThats what I ended up doing :)
-
Martijn Pieters almost 11 years@RonReiter: Why doesn't it? We take the
request.data
regardless of the content type specified by the client. Sure, if the client sent invalid request data (e.g. not (valid) JSON), nothing can be done. -
Ron Reiter almost 11 years@MartijnPieters request.data is an empty string when using www/form-url-encoded because it parses it as a form. From the documentation: data - Contains the incoming request data as string in case it came with a mimetype Flask does not handle.
-
Martijn Pieters almost 11 yearsRight, in narrow cases, where a client completely mislabeled the request, the above will fail. How likely is that case, and isn't that true for many other cases where a client malformed the request?
-
Tony Chou about 6 yearsIs it a bad idea or not recommended to make any coming data to json? I mean always use
request.get_json(force=True)
any where in back-end to extract data. -
Martijn Pieters about 6 years@TonyChou: gating on the Content-Type header is one way of blocking bad clients early. If you use
force=True
just because some clients may have forgotten to set the header, then your server will have to do more work (because now all requests could contain JSON and time is spent trying to decode it all). -
dinvlad about 3 yearsThis is actually a way to protect your app against CSRF attacks. If someone makes a POST to your app from another site, and your app uses auth cookies that are not
SameSite
, then these cookies will be automatically attached to the request, and withoutContent-Type: application/json
header present, the request would be considered "simple" and thus submitted to the server. So this ends up making your app vulnerable to CSRF, unless you check Content-Type (this happens irregardless of if/how you set CORS headers btw, the POST request would still be submitted for a "simple" request).