Browse Source

Fix UnboundLocalError in OpenAPI generation for custom response classes

In `get_openapi_path`, `status_code` is assigned only inside the branches:

    if route.status_code is not None:
        status_code = str(route.status_code)
    else:
        response_signature = inspect.signature(current_response_class.__init__)
        status_code_param = response_signature.parameters.get("status_code")
        if status_code_param is not None:
            if isinstance(status_code_param.default, int):
                status_code = str(status_code_param.default)
    operation.setdefault("responses", {}).setdefault(status_code, {})["description"] = ...

When `route.status_code is None` and the response class's `__init__` has no
`status_code` parameter (or its default is not an `int`), `status_code` is
never bound, but the following line uses it as a dict key -> `UnboundLocalError`.

This is reachable with a common pattern: a custom `response_class` whose
`__init__` is `def __init__(self, *args, **kwargs)` (or types `status_code`
as `int | None = None`). Because `get_openapi_path` -> `get_openapi` ->
`Application.openapi()`, a single such route makes `app.openapi()` raise,
taking down `/openapi.json`, `/docs`, and `/redoc` for the whole app.

Initialize `status_code` to "200" (FastAPI's default route status) before the
branches so it is always bound; the working paths are unchanged.
pull/16025/head
Osamaali313 21 hours ago
parent
commit
da3cd29314
  1. 1
      fastapi/openapi/utils.py

1
fastapi/openapi/utils.py

@ -337,6 +337,7 @@ def get_openapi_path(
)
callbacks[callback.name] = {callback.path: cb_path}
operation["callbacks"] = callbacks
status_code = "200"
if route.status_code is not None:
status_code = str(route.status_code)
else:

Loading…
Cancel
Save