diff --git a/fastapi/applications.py b/fastapi/applications.py index 56e1a3e60..f62143494 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -1187,6 +1187,7 @@ class FastAPI(Starlette): include_in_schema: bool = True, response_class: type[Response] | DefaultPlaceholder = Default(JSONResponse), name: str | None = None, + callbacks: list[BaseRoute] | None = None, openapi_extra: dict[str, Any] | None = None, generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( generate_unique_id @@ -1215,6 +1216,7 @@ class FastAPI(Starlette): include_in_schema=include_in_schema, response_class=response_class, name=name, + callbacks=callbacks, openapi_extra=openapi_extra, generate_unique_id_function=generate_unique_id_function, ) @@ -1316,6 +1318,7 @@ class FastAPI(Starlette): include_in_schema: bool = True, response_class: type[Response] = Default(JSONResponse), name: str | None = None, + callbacks: list[BaseRoute] | None = None, openapi_extra: dict[str, Any] | None = None, generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( generate_unique_id @@ -1345,6 +1348,7 @@ class FastAPI(Starlette): include_in_schema=include_in_schema, response_class=response_class, name=name, + callbacks=callbacks, openapi_extra=openapi_extra, generate_unique_id_function=generate_unique_id_function, ) diff --git a/tests/test_sub_callbacks.py b/tests/test_sub_callbacks.py index b8a9dd292..dc52950dd 100644 --- a/tests/test_sub_callbacks.py +++ b/tests/test_sub_callbacks.py @@ -74,6 +74,68 @@ app.include_router(subrouter, callbacks=events_callback_router.routes) client = TestClient(app) +def test_app_api_route_supports_callbacks(): + callback_router = APIRouter() + + @callback_router.post("{$callback_url}/app-api-route-callback") + def app_api_route_callback(body: InvoiceEvent): + pass # pragma: nocover + + app = FastAPI() + + @app.api_route( + "/app-api-route/", + methods=["POST"], + callbacks=callback_router.routes, + ) + def app_api_route(callback_url: HttpUrl | None = None): + return {"msg": "App API route received"} + + client = TestClient(app) + response = client.post("/app-api-route/") + assert response.status_code == 200, response.text + assert response.json() == {"msg": "App API route received"} + + schema = client.get("/openapi.json").json() + callbacks = schema["paths"]["/app-api-route/"]["post"]["callbacks"] + assert list(callbacks) == ["app_api_route_callback"] + assert "{$callback_url}/app-api-route-callback" in callbacks[ + "app_api_route_callback" + ] + + +def test_app_add_api_route_supports_callbacks(): + callback_router = APIRouter() + + @callback_router.post("{$callback_url}/app-add-api-route-callback") + def app_add_api_route_callback(body: InvoiceEvent): + pass # pragma: nocover + + app = FastAPI() + + def app_add_api_route(callback_url: HttpUrl | None = None): + return {"msg": "App add API route received"} + + app.add_api_route( + "/app-add-api-route/", + app_add_api_route, + methods=["POST"], + callbacks=callback_router.routes, + ) + + client = TestClient(app) + response = client.post("/app-add-api-route/") + assert response.status_code == 200, response.text + assert response.json() == {"msg": "App add API route received"} + + schema = client.get("/openapi.json").json() + callbacks = schema["paths"]["/app-add-api-route/"]["post"]["callbacks"] + assert list(callbacks) == ["app_add_api_route_callback"] + assert "{$callback_url}/app-add-api-route-callback" in callbacks[ + "app_add_api_route_callback" + ] + + def test_get(): response = client.post( "/invoices/", json={"id": "fooinvoice", "customer": "John", "total": 5.3}