How to allow no body in GET request while using flask-restful's reqparse.RequestParser?

Issue

I have a Flask_restful resource which I am adding as blueprint resource

class SampleAPI(Resource):
    def __init__(self):
        self.reqparse = reqparse.RequestParser(bundle_errors=True)
        self.reqparse.add_argument('name', type=str, required=False,
                                   help='No name provided',
                                   location='json')
        
        self.reqparse.add_argument('id', type=str, required=False,
                                   help='No id provided',
                                   location='args')

    def post(self):
        args = self.reqparse.parse_args()
        name = args["name"]
        # Do something with name

        return lf.to_json(), 201

    def get(self):
        args = self.reqparse.parse_args()
        ID = args["id"]
        # Do something with ID

        return lf.to_json(), 200

When I use post endpoint, every works fine as I am sending a JSON body with request. BUT when I make a GET request, I get a bad request error –

{
    "message": "The browser (or proxy) sent a request that this server could not understand."
}

I found out that, I need to send an empty JSON body – "{}" with the request to make the request working otherwise it throws the bad request error as above.

I need to understand how I can allow no body but also use reqparse.RequestParser and parse arguments using flask_restful extension of flask in this GET request!

Thanks!

Solution

In the case of the get request, the body is not present, but self.reqparse.parse_args() tries to access it to verify the correctness of the passed parameters (it accesses it since at the moment of its creation it is specified that the parameter name is contained in the json body). In a get request, the parameters are passed inside the url and not the body, consequently the error is generated.

I advise you to create two different objects:

One for the post request, when you need to get your params from the json body:

self.reqparse = reqparse.RequestParser(bundle_errors=True)
self.reqparse.add_argument('name', type=str, required=False,
                                   help='No name provided',
                                   location='json')

And one for the get request, when you need to get your params from args:
when you need to get your params from the json body:

self.reqparse = reqparse.RequestParser(bundle_errors=True)
self.reqparse.add_argument('id', type=str, required=False,
                               help='No id provided',
                               location='args')

If you need both parameters in both requests, then create two different objects of type RequestParser, and add the two required parameters to both, specifying as location 'json' in the case of the post request, and 'args' in the case of the get request

Answered By – Matteo Pasini

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published