Browse Source

fix(routing): thread stream_item_type through include_router()

When a typed SSE or JSONL streaming endpoint is registered via a router,
the OpenAPI schema loses the stream item type because include_router()
re-creates routes via add_api_route() without passing stream_item_type.

This fix threads stream_item_type through add_api_route() and include_router(),
following the strict_content_type pattern.

Fixes #15077
pull/15214/head
BillionClaw 4 months ago
parent
commit
a1a7e1f7b6
  1. 7
      fastapi/routing.py

7
fastapi/routing.py

@ -840,11 +840,12 @@ class APIRoute(routing.Route):
generate_unique_id_function: Callable[["APIRoute"], str] generate_unique_id_function: Callable[["APIRoute"], str]
| DefaultPlaceholder = Default(generate_unique_id), | DefaultPlaceholder = Default(generate_unique_id),
strict_content_type: bool | DefaultPlaceholder = Default(True), strict_content_type: bool | DefaultPlaceholder = Default(True),
stream_item_type: type[Any] | None = None,
) -> None: ) -> None:
self.path = path self.path = path
self.endpoint = endpoint self.endpoint = endpoint
self.stream_item_type: Any | None = None self.stream_item_type: Any | None = stream_item_type
if isinstance(response_model, DefaultPlaceholder): if self.stream_item_type is None and isinstance(response_model, DefaultPlaceholder):
return_annotation = get_typed_return_annotation(endpoint) return_annotation = get_typed_return_annotation(endpoint)
if lenient_issubclass(return_annotation, Response): if lenient_issubclass(return_annotation, Response):
response_model = None response_model = None
@ -1364,6 +1365,7 @@ class APIRouter(routing.Router):
generate_unique_id_function: Callable[[APIRoute], str] generate_unique_id_function: Callable[[APIRoute], str]
| DefaultPlaceholder = Default(generate_unique_id), | DefaultPlaceholder = Default(generate_unique_id),
strict_content_type: bool | DefaultPlaceholder = Default(True), strict_content_type: bool | DefaultPlaceholder = Default(True),
stream_item_type: type[Any] | None = None,
) -> None: ) -> None:
route_class = route_class_override or self.route_class route_class = route_class_override or self.route_class
responses = responses or {} responses = responses or {}
@ -1793,6 +1795,7 @@ class APIRouter(routing.Router):
router.strict_content_type, router.strict_content_type,
self.strict_content_type, self.strict_content_type,
), ),
stream_item_type=route.stream_item_type,
) )
elif isinstance(route, routing.Route): elif isinstance(route, routing.Route):
methods = list(route.methods or []) methods = list(route.methods or [])

Loading…
Cancel
Save