Verify that the POST data is valid. Json

I am developing a JSON API with Python Flask.
I want to always return JSON with an error message indicating an error occurred.

This API also accepts only JSON data in the POST body, but Flask returns an HTML 400 error by default if it cannot read the data as JSON.

Preferably, I also don’t want the user to send a header Content-Type, but if the type rawor textcontent-type, try to parse the body as JSON nonetheless.

In short, I need a way to verify that the POST body is JSON, and handle the error myself.

I read about adding a decorator to requestfor this, but not an exhaustive example.

+4
source share
3 answers

You have three options:

  • Register a custom error handler for 400 errors in the API views. Ask for this error to return JSON instead of HTML.

  • Set a method Request.on_json_loading_failedfor something that throws a JSON subclass BadRequestexception . See User Errors in the Werkzeug Exception Documentation to see how you can create it.

  • Put a try: exceptaround the call request.get_json(), catch the exception BadRequestand throw a new exception using the JSON payload.

Personally, I would probably go with the second option:

from werkzeug.exceptions import BadRequest
from flask import json, Request, _request_ctx_stack


class JSONBadRequest(BadRequest):
    def get_body(self, environ=None):
        """Get the JSON body."""
        return json.dumps({
            'code':         self.code,
            'name':         self.name,
            'description':  self.description,
        })

    def get_headers(self, environ=None):
        """Get a list of headers."""
        return [('Content-Type', 'application/json')]


def on_json_loading_failed(self):
    ctx = _request_ctx_stack.top
    if ctx is not None and ctx.app.config.get('DEBUG', False):
        raise JSONBadRequest('Failed to decode JSON object: {0}'.format(e))
    raise JSONBadRequest()


Request.on_json_loading_failed = on_json_loading_failed

, , request.get_json() , on_json_loading_failed JSON, HTML.

+7

force=True silent=True request.get_json be None, , if .

from flask import Flask
from flask import request

@app.route('/foo', methods=['POST'])
def function(function = None):
    print "Data: ", request.get_json(force = True, silent = True);
    if request.get_json() is not None:
        return "Is JSON";
    else:
        return "Nope";

if __name__ == "__main__":
    app.run()

.

+1

You can try to decode the JSON object using the python json library. The main idea is to take a simple request body and try to convert it to JSON.Eg:

import json
...
# somewhere in view
def view():
    try:
        json.loads(request.get_data())
    except ValueError:
        # not a JSON! return error
        return {'error': '...'}
    # do plain stuff
0
source

Source: https://habr.com/ru/post/1654341/


All Articles