diff --git a/tests/test_strict_content_type_app_level.py b/tests/test_strict_content_type_app_level.py new file mode 100644 index 0000000000..42a0821a47 --- /dev/null +++ b/tests/test_strict_content_type_app_level.py @@ -0,0 +1,44 @@ +from fastapi import FastAPI +from fastapi.testclient import TestClient + +app_default = FastAPI() + + +@app_default.post("/items/") +async def app_default_post(data: dict): + return data + + +app_lax = FastAPI(strict_content_type=False) + + +@app_lax.post("/items/") +async def app_lax_post(data: dict): + return data + + +client_default = TestClient(app_default) +client_lax = TestClient(app_lax) + + +def test_default_strict_rejects_no_content_type(): + response = client_default.post("/items/", content='{"key": "value"}') + assert response.status_code == 422 + + +def test_default_strict_accepts_json_content_type(): + response = client_default.post("/items/", json={"key": "value"}) + assert response.status_code == 200 + assert response.json() == {"key": "value"} + + +def test_lax_accepts_no_content_type(): + response = client_lax.post("/items/", content='{"key": "value"}') + assert response.status_code == 200 + assert response.json() == {"key": "value"} + + +def test_lax_accepts_json_content_type(): + response = client_lax.post("/items/", json={"key": "value"}) + assert response.status_code == 200 + assert response.json() == {"key": "value"} diff --git a/tests/test_strict_content_type_nested.py b/tests/test_strict_content_type_nested.py new file mode 100644 index 0000000000..922d01571a --- /dev/null +++ b/tests/test_strict_content_type_nested.py @@ -0,0 +1,91 @@ +from fastapi import APIRouter, FastAPI +from fastapi.testclient import TestClient + +# Lax app with nested routers, inner overrides to strict + +app_nested = FastAPI(strict_content_type=False) # lax app +outer_router = APIRouter(prefix="/outer") # inherits lax from app +inner_strict = APIRouter(prefix="/strict", strict_content_type=True) +inner_default = APIRouter(prefix="/default") + + +@inner_strict.post("/items/") +async def inner_strict_post(data: dict): + return data + + +@inner_default.post("/items/") +async def inner_default_post(data: dict): + return data + + +outer_router.include_router(inner_strict) +outer_router.include_router(inner_default) +app_nested.include_router(outer_router) + +client_nested = TestClient(app_nested) + + +def test_strict_inner_on_lax_app_rejects_no_content_type(): + response = client_nested.post("/outer/strict/items/", content='{"key": "value"}') + assert response.status_code == 422 + + +def test_default_inner_inherits_lax_from_app(): + response = client_nested.post("/outer/default/items/", content='{"key": "value"}') + assert response.status_code == 200 + assert response.json() == {"key": "value"} + + +def test_strict_inner_accepts_json_content_type(): + response = client_nested.post("/outer/strict/items/", json={"key": "value"}) + assert response.status_code == 200 + + +def test_default_inner_accepts_json_content_type(): + response = client_nested.post("/outer/default/items/", json={"key": "value"}) + assert response.status_code == 200 + + +# Strict app -> lax outer router -> strict inner router + +app_mixed = FastAPI(strict_content_type=True) +mixed_outer = APIRouter(prefix="/outer", strict_content_type=False) +mixed_inner = APIRouter(prefix="/inner", strict_content_type=True) + + +@mixed_outer.post("/items/") +async def mixed_outer_post(data: dict): + return data + + +@mixed_inner.post("/items/") +async def mixed_inner_post(data: dict): + return data + + +mixed_outer.include_router(mixed_inner) +app_mixed.include_router(mixed_outer) + +client_mixed = TestClient(app_mixed) + + +def test_lax_outer_on_strict_app_accepts_no_content_type(): + response = client_mixed.post("/outer/items/", content='{"key": "value"}') + assert response.status_code == 200 + assert response.json() == {"key": "value"} + + +def test_strict_inner_on_lax_outer_rejects_no_content_type(): + response = client_mixed.post("/outer/inner/items/", content='{"key": "value"}') + assert response.status_code == 422 + + +def test_lax_outer_accepts_json_content_type(): + response = client_mixed.post("/outer/items/", json={"key": "value"}) + assert response.status_code == 200 + + +def test_strict_inner_on_lax_outer_accepts_json_content_type(): + response = client_mixed.post("/outer/inner/items/", json={"key": "value"}) + assert response.status_code == 200 diff --git a/tests/test_strict_content_type_router_level.py b/tests/test_strict_content_type_router_level.py new file mode 100644 index 0000000000..72a02d6c91 --- /dev/null +++ b/tests/test_strict_content_type_router_level.py @@ -0,0 +1,61 @@ +from fastapi import APIRouter, FastAPI +from fastapi.testclient import TestClient + +app = FastAPI() + +router_lax = APIRouter(prefix="/lax", strict_content_type=False) +router_strict = APIRouter(prefix="/strict", strict_content_type=True) +router_default = APIRouter(prefix="/default") + + +@router_lax.post("/items/") +async def router_lax_post(data: dict): + return data + + +@router_strict.post("/items/") +async def router_strict_post(data: dict): + return data + + +@router_default.post("/items/") +async def router_default_post(data: dict): + return data + + +app.include_router(router_lax) +app.include_router(router_strict) +app.include_router(router_default) + +client = TestClient(app) + + +def test_lax_router_on_strict_app_accepts_no_content_type(): + response = client.post("/lax/items/", content='{"key": "value"}') + assert response.status_code == 200 + assert response.json() == {"key": "value"} + + +def test_strict_router_on_strict_app_rejects_no_content_type(): + response = client.post("/strict/items/", content='{"key": "value"}') + assert response.status_code == 422 + + +def test_default_router_inherits_strict_from_app(): + response = client.post("/default/items/", content='{"key": "value"}') + assert response.status_code == 422 + + +def test_lax_router_accepts_json_content_type(): + response = client.post("/lax/items/", json={"key": "value"}) + assert response.status_code == 200 + + +def test_strict_router_accepts_json_content_type(): + response = client.post("/strict/items/", json={"key": "value"}) + assert response.status_code == 200 + + +def test_default_router_accepts_json_content_type(): + response = client.post("/default/items/", json={"key": "value"}) + assert response.status_code == 200