The origin of this question is the flask tutorial at http://blog.miguelgrinberg.com/post/designing-a-restful-api-with-python-and-flask. While reading this tutorial, I came across this function:
@app.route('/todo/api/v1.0/tasks/<int:task_id>', methods = ['PUT'])
def update_task(task_id):
task = filter(lambda t: t['id'] == task_id, tasks)
if len(task) == 0:
abort(404)
if not request.json:
abort(400)
if 'title' in request.json and type(request.json['title']) != unicode:
abort(400)
if 'description' in request.json and type(request.json['description']) is not unicode:
abort(400)
if 'done' in request.json and type(request.json['done']) is not bool:
abort(400)
task[0]['title'] = request.json.get('title', task[0]['title'])
task[0]['description'] = request.json.get('description', task[0]['description'])
task[0]['done'] = request.json.get('done', task[0]['done'])
return jsonify( { 'task': task[0] } )
This line uses value comparison:
if 'title' in request.json and type(request.json['title']) != unicode:
But this line uses identity comparison:
if 'description' in request.json and type(request.json['description']) is not unicode:
Is there a reason that the author was not consistent? Will both versions provide the same level of security? If so, what is the more pythonic approach?
I think better use json schema instead:
from jsonschema import validate, ValidationError
schema = {
'type': 'object',
'properties': {
'title': {
'type': 'string',
},
'description': {
'type': 'string',
},
'done': {
'type': 'boolean',
},
},
}
try:
validate(request.get_json(), schema)
except ValidationError:
abort(400)
Also request.json
is deprecated if you use flask>=0.10
, and better use request.get_json()
: http://flask.pocoo.org/docs/api/#flask.Request.json.