Add better JSON decode error handling, improve feedback for client after invalid JSON requests (#1354)

* Request body error, raise RequestValidationError instead of HTTPException in case JSON decode failure

* add missing test case for body general exception
This commit is contained in:
Aviram Hassan 2020-06-13 15:33:27 +03:00 committed by GitHub
parent 5ffa18f10f
commit b13a4baf32
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 1 deletions

View file

@ -1,5 +1,6 @@
import asyncio import asyncio
import inspect import inspect
import json
from typing import Any, Callable, Dict, List, Optional, Sequence, Set, Type, Union from typing import Any, Callable, Dict, List, Optional, Sequence, Set, Type, Union
from fastapi import params from fastapi import params
@ -177,6 +178,8 @@ def get_request_handler(
body_bytes = await request.body() body_bytes = await request.body()
if body_bytes: if body_bytes:
body = await request.json() body = await request.json()
except json.JSONDecodeError as e:
raise RequestValidationError([ErrorWrapper(e, ("body", e.pos))], body=e.doc)
except Exception as e: except Exception as e:
raise HTTPException( raise HTTPException(
status_code=400, detail="There was an error parsing the body" status_code=400, detail="There was an error parsing the body"

View file

@ -1,3 +1,5 @@
from unittest.mock import patch
import pytest import pytest
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -176,5 +178,24 @@ def test_post_body(path, body, expected_status, expected_response):
def test_post_broken_body(): def test_post_broken_body():
response = client.post("/items/", data={"name": "Foo", "price": 50.5}) response = client.post("/items/", data={"name": "Foo", "price": 50.5})
assert response.status_code == 400, response.text assert response.status_code == 422, response.text
assert response.json() == {
"detail": [
{
"ctx": {
"colno": 1,
"doc": "name=Foo&price=50.5",
"lineno": 1,
"msg": "Expecting value",
"pos": 0,
},
"loc": ["body", 0],
"msg": "Expecting value: line 1 column 1 (char 0)",
"type": "value_error.jsondecode",
}
]
}
with patch("json.loads", side_effect=Exception):
response = client.post("/items/", json={"test": "test2"})
assert response.status_code == 400, response.text
assert response.json() == {"detail": "There was an error parsing the body"} assert response.json() == {"detail": "There was an error parsing the body"}