mirror of https://github.com/tiangolo/fastapi.git
🔒 Fix constraining return values to model
This commit is contained in:
parent
e2e573166e
commit
da166b7967
|
|
@ -1,6 +1,6 @@
|
||||||
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
|
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
|
||||||
|
|
||||||
__version__ = "0.1.2"
|
__version__ = "0.1.3"
|
||||||
|
|
||||||
from .applications import FastAPI
|
from .applications import FastAPI
|
||||||
from .routing import APIRouter
|
from .routing import APIRouter
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import inspect
|
import inspect
|
||||||
|
import logging
|
||||||
from typing import Any, Callable, List, Optional, Type
|
from typing import Any, Callable, List, Optional, Type
|
||||||
|
|
||||||
from fastapi import params
|
from fastapi import params
|
||||||
|
|
@ -47,21 +48,30 @@ def get_app(
|
||||||
is_body_form = body_field and isinstance(body_field.schema, params.Form)
|
is_body_form = body_field and isinstance(body_field.schema, params.Form)
|
||||||
|
|
||||||
async def app(request: Request) -> Response:
|
async def app(request: Request) -> Response:
|
||||||
body = None
|
try:
|
||||||
if body_field:
|
body = None
|
||||||
if is_body_form:
|
if body_field:
|
||||||
raw_body = await request.form()
|
if is_body_form:
|
||||||
body = {}
|
raw_body = await request.form()
|
||||||
for field, value in raw_body.items():
|
body = {}
|
||||||
if isinstance(value, UploadFile):
|
for field, value in raw_body.items():
|
||||||
body[field] = await value.read()
|
if isinstance(value, UploadFile):
|
||||||
else:
|
body[field] = await value.read()
|
||||||
body[field] = value
|
else:
|
||||||
else:
|
body[field] = value
|
||||||
body = await request.json()
|
else:
|
||||||
values, errors = await solve_dependencies(
|
body = await request.json()
|
||||||
request=request, dependant=dependant, body=body
|
except Exception:
|
||||||
)
|
raise HTTPException(
|
||||||
|
status_code=400, detail="There was an error parsing the body"
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
values, errors = await solve_dependencies(
|
||||||
|
request=request, dependant=dependant, body=body
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error("Error solving dependencies", e)
|
||||||
|
raise HTTPException(status_code=400, detail="Error processing request")
|
||||||
if errors:
|
if errors:
|
||||||
errors_out = ValidationError(errors)
|
errors_out = ValidationError(errors)
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -77,7 +87,10 @@ def get_app(
|
||||||
return raw_response
|
return raw_response
|
||||||
if isinstance(raw_response, BaseModel):
|
if isinstance(raw_response, BaseModel):
|
||||||
return content_type(
|
return content_type(
|
||||||
content=jsonable_encoder(raw_response), status_code=status_code
|
content=serialize_response(
|
||||||
|
field=response_field, response=raw_response
|
||||||
|
),
|
||||||
|
status_code=status_code,
|
||||||
)
|
)
|
||||||
errors = []
|
errors = []
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -67,87 +67,87 @@ def get_path_param_required_id(item_id: str = Path(...)):
|
||||||
|
|
||||||
|
|
||||||
@app.get("/path/param-minlength/{item_id}")
|
@app.get("/path/param-minlength/{item_id}")
|
||||||
def get_path_param_min_length(item_id: str = Path(..., min_length = 3)):
|
def get_path_param_min_length(item_id: str = Path(..., min_length=3)):
|
||||||
return item_id
|
return item_id
|
||||||
|
|
||||||
|
|
||||||
@app.get("/path/param-maxlength/{item_id}")
|
@app.get("/path/param-maxlength/{item_id}")
|
||||||
def get_path_param_max_length(item_id: str = Path(..., max_length = 3)):
|
def get_path_param_max_length(item_id: str = Path(..., max_length=3)):
|
||||||
return item_id
|
return item_id
|
||||||
|
|
||||||
|
|
||||||
@app.get("/path/param-min_maxlength/{item_id}")
|
@app.get("/path/param-min_maxlength/{item_id}")
|
||||||
def get_path_param_min_max_length(item_id: str = Path(..., max_length = 3, min_length = 2)):
|
def get_path_param_min_max_length(item_id: str = Path(..., max_length=3, min_length=2)):
|
||||||
return item_id
|
return item_id
|
||||||
|
|
||||||
|
|
||||||
@app.get("/path/param-gt/{item_id}")
|
@app.get("/path/param-gt/{item_id}")
|
||||||
def get_path_param_gt(item_id: float = Path(..., gt = 3)):
|
def get_path_param_gt(item_id: float = Path(..., gt=3)):
|
||||||
return item_id
|
return item_id
|
||||||
|
|
||||||
|
|
||||||
@app.get("/path/param-gt0/{item_id}")
|
@app.get("/path/param-gt0/{item_id}")
|
||||||
def get_path_param_gt0(item_id: float = Path(..., gt = 0)):
|
def get_path_param_gt0(item_id: float = Path(..., gt=0)):
|
||||||
return item_id
|
return item_id
|
||||||
|
|
||||||
|
|
||||||
@app.get("/path/param-ge/{item_id}")
|
@app.get("/path/param-ge/{item_id}")
|
||||||
def get_path_param_ge(item_id: float = Path(..., ge = 3)):
|
def get_path_param_ge(item_id: float = Path(..., ge=3)):
|
||||||
return item_id
|
return item_id
|
||||||
|
|
||||||
|
|
||||||
@app.get("/path/param-lt/{item_id}")
|
@app.get("/path/param-lt/{item_id}")
|
||||||
def get_path_param_lt(item_id: float = Path(..., lt = 3)):
|
def get_path_param_lt(item_id: float = Path(..., lt=3)):
|
||||||
return item_id
|
return item_id
|
||||||
|
|
||||||
|
|
||||||
@app.get("/path/param-lt0/{item_id}")
|
@app.get("/path/param-lt0/{item_id}")
|
||||||
def get_path_param_lt0(item_id: float = Path(..., lt = 0)):
|
def get_path_param_lt0(item_id: float = Path(..., lt=0)):
|
||||||
return item_id
|
return item_id
|
||||||
|
|
||||||
|
|
||||||
@app.get("/path/param-le/{item_id}")
|
@app.get("/path/param-le/{item_id}")
|
||||||
def get_path_param_le(item_id: float = Path(..., le = 3)):
|
def get_path_param_le(item_id: float = Path(..., le=3)):
|
||||||
return item_id
|
return item_id
|
||||||
|
|
||||||
|
|
||||||
@app.get("/path/param-lt-gt/{item_id}")
|
@app.get("/path/param-lt-gt/{item_id}")
|
||||||
def get_path_param_lt_gt(item_id: float = Path(..., lt = 3, gt = 1)):
|
def get_path_param_lt_gt(item_id: float = Path(..., lt=3, gt=1)):
|
||||||
return item_id
|
return item_id
|
||||||
|
|
||||||
|
|
||||||
@app.get("/path/param-le-ge/{item_id}")
|
@app.get("/path/param-le-ge/{item_id}")
|
||||||
def get_path_param_le_ge(item_id: float = Path(..., le = 3, ge = 1)):
|
def get_path_param_le_ge(item_id: float = Path(..., le=3, ge=1)):
|
||||||
return item_id
|
return item_id
|
||||||
|
|
||||||
|
|
||||||
@app.get("/path/param-lt-int/{item_id}")
|
@app.get("/path/param-lt-int/{item_id}")
|
||||||
def get_path_param_lt_int(item_id: int = Path(..., lt = 3)):
|
def get_path_param_lt_int(item_id: int = Path(..., lt=3)):
|
||||||
return item_id
|
return item_id
|
||||||
|
|
||||||
|
|
||||||
@app.get("/path/param-gt-int/{item_id}")
|
@app.get("/path/param-gt-int/{item_id}")
|
||||||
def get_path_param_gt_int(item_id: int = Path(..., gt = 3)):
|
def get_path_param_gt_int(item_id: int = Path(..., gt=3)):
|
||||||
return item_id
|
return item_id
|
||||||
|
|
||||||
|
|
||||||
@app.get("/path/param-le-int/{item_id}")
|
@app.get("/path/param-le-int/{item_id}")
|
||||||
def get_path_param_le_int(item_id: int = Path(..., le = 3)):
|
def get_path_param_le_int(item_id: int = Path(..., le=3)):
|
||||||
return item_id
|
return item_id
|
||||||
|
|
||||||
|
|
||||||
@app.get("/path/param-ge-int/{item_id}")
|
@app.get("/path/param-ge-int/{item_id}")
|
||||||
def get_path_param_ge_int(item_id: int = Path(..., ge = 3)):
|
def get_path_param_ge_int(item_id: int = Path(..., ge=3)):
|
||||||
return item_id
|
return item_id
|
||||||
|
|
||||||
|
|
||||||
@app.get("/path/param-lt-gt-int/{item_id}")
|
@app.get("/path/param-lt-gt-int/{item_id}")
|
||||||
def get_path_param_lt_gt_int(item_id: int = Path(..., lt = 3, gt = 1)):
|
def get_path_param_lt_gt_int(item_id: int = Path(..., lt=3, gt=1)):
|
||||||
return item_id
|
return item_id
|
||||||
|
|
||||||
|
|
||||||
@app.get("/path/param-le-ge-int/{item_id}")
|
@app.get("/path/param-le-ge-int/{item_id}")
|
||||||
def get_path_param_le_ge_int(item_id: int = Path(..., le = 3, ge = 1)):
|
def get_path_param_le_ge_int(item_id: int = Path(..., le=3, ge=1)):
|
||||||
return item_id
|
return item_id
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,104 +38,124 @@ response_not_valid_float = {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
response_at_least_3 = {"detail":[{"loc":["path","item_id"],"msg":"ensure this value has at least 3 characters","type":"value_error.any_str.min_length","ctx":{"limit_value":3}}]}
|
response_at_least_3 = {
|
||||||
|
"detail": [
|
||||||
|
{
|
||||||
|
"loc": ["path", "item_id"],
|
||||||
|
"msg": "ensure this value has at least 3 characters",
|
||||||
|
"type": "value_error.any_str.min_length",
|
||||||
|
"ctx": {"limit_value": 3},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
response_at_least_2 = {"detail":[{"loc":["path","item_id"],"msg":"ensure this value has at least 2 characters","type":"value_error.any_str.min_length","ctx":{"limit_value":2}}]}
|
response_at_least_2 = {
|
||||||
|
"detail": [
|
||||||
|
{
|
||||||
|
"loc": ["path", "item_id"],
|
||||||
|
"msg": "ensure this value has at least 2 characters",
|
||||||
|
"type": "value_error.any_str.min_length",
|
||||||
|
"ctx": {"limit_value": 2},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
response_maximum_3 = {"detail":[{"loc":["path","item_id"],"msg":"ensure this value has at most 3 characters","type":"value_error.any_str.max_length","ctx":{"limit_value":3}}]}
|
response_maximum_3 = {
|
||||||
|
"detail": [
|
||||||
|
{
|
||||||
|
"loc": ["path", "item_id"],
|
||||||
|
"msg": "ensure this value has at most 3 characters",
|
||||||
|
"type": "value_error.any_str.max_length",
|
||||||
|
"ctx": {"limit_value": 3},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
response_greater_than_3 = {
|
response_greater_than_3 = {
|
||||||
"detail": [
|
"detail": [
|
||||||
{
|
{
|
||||||
"loc": [
|
"loc": ["path", "item_id"],
|
||||||
"path",
|
"msg": "ensure this value is greater than 3",
|
||||||
"item_id"
|
"type": "value_error.number.not_gt",
|
||||||
],
|
"ctx": {"limit_value": 3},
|
||||||
"msg": "ensure this value is greater than 3",
|
}
|
||||||
"type": "value_error.number.not_gt",
|
]
|
||||||
"ctx": {
|
|
||||||
"limit_value": 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
response_greater_than_0 = {
|
response_greater_than_0 = {
|
||||||
"detail": [
|
"detail": [
|
||||||
{
|
{
|
||||||
"loc": [
|
"loc": ["path", "item_id"],
|
||||||
"path",
|
"msg": "ensure this value is greater than 0",
|
||||||
"item_id"
|
"type": "value_error.number.not_gt",
|
||||||
],
|
"ctx": {"limit_value": 0},
|
||||||
"msg": "ensure this value is greater than 0",
|
}
|
||||||
"type": "value_error.number.not_gt",
|
]
|
||||||
"ctx": {
|
|
||||||
"limit_value": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
response_greater_than_1 = {
|
response_greater_than_1 = {
|
||||||
"detail": [
|
"detail": [
|
||||||
{
|
{
|
||||||
"loc": [
|
"loc": ["path", "item_id"],
|
||||||
"path",
|
"msg": "ensure this value is greater than 1",
|
||||||
"item_id"
|
"type": "value_error.number.not_gt",
|
||||||
],
|
"ctx": {"limit_value": 1},
|
||||||
"msg": "ensure this value is greater than 1",
|
}
|
||||||
"type": "value_error.number.not_gt",
|
]
|
||||||
"ctx": {
|
|
||||||
"limit_value": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
response_greater_than_equal_3 = {"detail":[{"loc":["path","item_id"],"msg":"ensure this value is greater than or equal to 3","type":"value_error.number.not_ge","ctx":{"limit_value":3}}]}
|
response_greater_than_equal_3 = {
|
||||||
|
"detail": [
|
||||||
|
{
|
||||||
|
"loc": ["path", "item_id"],
|
||||||
|
"msg": "ensure this value is greater than or equal to 3",
|
||||||
|
"type": "value_error.number.not_ge",
|
||||||
|
"ctx": {"limit_value": 3},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
response_less_than_3 = {
|
response_less_than_3 = {
|
||||||
"detail": [
|
"detail": [
|
||||||
{
|
{
|
||||||
"loc": [
|
"loc": ["path", "item_id"],
|
||||||
"path",
|
"msg": "ensure this value is less than 3",
|
||||||
"item_id"
|
"type": "value_error.number.not_lt",
|
||||||
],
|
"ctx": {"limit_value": 3},
|
||||||
"msg": "ensure this value is less than 3",
|
}
|
||||||
"type": "value_error.number.not_lt",
|
]
|
||||||
"ctx": {
|
|
||||||
"limit_value": 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
response_less_than_0 = {
|
response_less_than_0 = {
|
||||||
"detail": [
|
"detail": [
|
||||||
{
|
{
|
||||||
"loc": [
|
"loc": ["path", "item_id"],
|
||||||
"path",
|
"msg": "ensure this value is less than 0",
|
||||||
"item_id"
|
"type": "value_error.number.not_lt",
|
||||||
],
|
"ctx": {"limit_value": 0},
|
||||||
"msg": "ensure this value is less than 0",
|
}
|
||||||
"type": "value_error.number.not_lt",
|
]
|
||||||
"ctx": {
|
|
||||||
"limit_value": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
response_less_than_equal_3 = {"detail":[{"loc":["path","item_id"],"msg":"ensure this value is less than or equal to 3","type":"value_error.number.not_le","ctx":{"limit_value":3}}]}
|
response_less_than_equal_3 = {
|
||||||
|
"detail": [
|
||||||
|
{
|
||||||
|
"loc": ["path", "item_id"],
|
||||||
|
"msg": "ensure this value is less than or equal to 3",
|
||||||
|
"type": "value_error.number.not_le",
|
||||||
|
"ctx": {"limit_value": 3},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue