Summary
Recent FastAPI versions added strict_content_type and now pass it through APIRouter.add_api_route() into the configured route_class. This breaks custom APIRoute subclasses that define an explicit constructor matching the previous public APIRoute.__init__ signature.
Subclasses that only override get_route_handler() still work, and subclasses using **kwargs still work. The regression affects subclasses that pinned the previously accepted constructor parameters and delegate them to super().__init__().
Reproducer
from enum import Enum
from typing import Any, Callable, Sequence
from fastapi import APIRouter, FastAPI, params
from fastapi.datastructures import Default, DefaultPlaceholder
from fastapi.responses import JSONResponse, Response
from fastapi.routing import APIRoute
from fastapi.types import IncEx
from fastapi.utils import generate_unique_id
from starlette.routing import BaseRoute
class LegacyRoute(APIRoute):
def __init__(
self,
path: str,
endpoint: Callable[..., Any],
*,
response_model: Any = Default(None),
status_code: int | None = None,
tags: list[str | Enum] | None = None,
dependencies: Sequence[params.Depends] | None = None,
summary: str | None = None,
description: str | None = None,
response_description: str = "Successful Response",
responses: dict[int | str, dict[str, Any]] | None = None,
deprecated: bool | None = None,
name: str | None = None,
methods: set[str] | list[str] | None = None,
operation_id: str | None = None,
response_model_include: IncEx | None = None,
response_model_exclude: IncEx | None = None,
response_model_by_alias: bool = True,
response_model_exclude_unset: bool = False,
response_model_exclude_defaults: bool = False,
response_model_exclude_none: bool = False,
include_in_schema: bool = True,
response_class: type[Response] | DefaultPlaceholder = Default(JSONResponse),
dependency_overrides_provider: Any | None = None,
callbacks: list[BaseRoute] | None = None,
openapi_extra: dict[str, Any] | None = None,
generate_unique_id_function: Callable[[APIRoute], str]
| DefaultPlaceholder = Default(generate_unique_id),
) -> None:
super().__init__(
path,
endpoint,
response_model=response_model,
status_code=status_code,
tags=tags,
dependencies=dependencies,
summary=summary,
description=description,
response_description=response_description,
responses=responses,
deprecated=deprecated,
name=name,
methods=methods,
operation_id=operation_id,
response_model_include=response_model_include,
response_model_exclude=response_model_exclude,
response_model_by_alias=response_model_by_alias,
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
include_in_schema=include_in_schema,
response_class=response_class,
dependency_overrides_provider=dependency_overrides_provider,
callbacks=callbacks,
openapi_extra=openapi_extra,
generate_unique_id_function=generate_unique_id_function,
)
app = FastAPI()
router = APIRouter(route_class=LegacyRoute)
@router.get("/items")
def read_items():
return {"ok": True}
app.include_router(router)
Current Behavior
Route registration fails with:
TypeError: LegacyRoute.__init__() got an unexpected keyword argument 'strict_content_type'
Expected Behavior
Existing custom route classes that mirrored the previous APIRoute.__init__ signature should continue to work, or FastAPI should make this breaking change explicit and document that custom route constructors must accept future keyword arguments.
Environment
- FastAPI: current
master at e89a37e50
- Python: 3.13
- Starlette: 1.0.0
Summary
Recent FastAPI versions added
strict_content_typeand now pass it throughAPIRouter.add_api_route()into the configuredroute_class. This breaks customAPIRoutesubclasses that define an explicit constructor matching the previous publicAPIRoute.__init__signature.Subclasses that only override
get_route_handler()still work, and subclasses using**kwargsstill work. The regression affects subclasses that pinned the previously accepted constructor parameters and delegate them tosuper().__init__().Reproducer
Current Behavior
Route registration fails with:
Expected Behavior
Existing custom route classes that mirrored the previous
APIRoute.__init__signature should continue to work, or FastAPI should make this breaking change explicit and document that custom route constructors must accept future keyword arguments.Environment
masterate89a37e50