sanic-org / sanic

Accelerate your web app development | Build fast. Run fast.

Home Page:https://sanic.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

A question about request.json

hulaime opened this issue · comments

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe.

I have an API about this, similar to fuzzy query,

@app.route('/list', methods=['POST',])
async def get_user_api(request):
    user_name = request.json.get('name', None)
    ...
   users = await get_users(name=user_name, ...)
   return response.json(users)

Expect all results returned:
curl -X POST -H "Content-Type: application/json" http://localhost:8080/user/list

Expect results related to test to be returned:
curl -X POST -H "Content-Type: application/json" -d '{ "name": "test"}' http://localhost:8080/user

However, the reality is that when using the first curl, the system reports an error message:

user_name = request.json.get('name', None)
                ^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'get'

Describe the solution you'd like

When trying to process requst.json in middleware, it prompts: AttributeError: property 'json' of 'Request' object has no setter。

@app.middleware('request')
async def your_middleware(request):
    if request.json is None:
        request.json = {}

Is there any other good solution that does not require judging request.json to be None in app.route?

Additional context

No response

tl;dr if you do not care on the below topics, you may use request.ctx in the middleware, and add json there, and use it in all your handlers.

@app.middleware('request')
async def your_middleware(request):
    if request.json is None:
        request.ctx.json = {}
    else:
        request.ctx.json = request.json

BUT

I think your HTTP request is improper as there is no data in body (empty string is not a valid JSON, according to my knowledge).
But then, why Sanic ever accepted such invalid request?

You should send valid JSON if content is set to application/json:

curl -X POST -H "Content-Type: application/json" --data '{}' http://localhost:8080/user/list
#or
curl -X POST -H "Content-Type: application/json" --data 'null' http://localhost:8080/user/list

However if you send null, it would generate the same issue (request.json == None).

Anyway, above shows that None != {} (that is, in JSON terms: null != {}), so I think it makes sense to have this distinction.