Factory.ai

Open-Source Wikis

/

FastAPI

/

Systems

/

OpenAPI

fastapi/fastapi

OpenAPI

Purpose

fastapi/openapi/ produces the OpenAPI 3.1 description of an application and the HTML for the interactive doc UIs. It contains four files:

fastapi/openapi/
├── __init__.py     # empty
├── constants.py    # METHODS_WITH_BODY, REF_PREFIX
├── models.py       # Pydantic models that mirror the OpenAPI spec
├── docs.py         # HTML templates for Swagger UI, ReDoc, OAuth2 redirect
└── utils.py        # get_openapi() — the actual schema generator

Key abstractions

Symbol File Description
get_openapi(...) openapi/utils.py The entrypoint. Takes the app metadata, the routes list, the webhooks list, optional servers/tags, and produces the OpenAPI document as a dict[str, Any].
Info, License, Contact, Server, Tag, OpenAPI, PathItem, Operation, Parameter, RequestBody, Response, MediaType, Schema, SecurityScheme, OAuth2, OAuthFlows, APIKey, HTTPBase, OpenIdConnect, Reference openapi/models.py Pydantic models implementing the OpenAPI 3.1 spec. They are configured with extra = "allow" so spec extensions (x-...) flow through.
swagger_ui_default_parameters, get_swagger_ui_html, get_redoc_html, get_swagger_ui_oauth2_redirect_html openapi/docs.py HTML rendering helpers used by FastAPI to serve /docs, /redoc, and /docs/oauth2-redirect.
validation_error_definition, validation_error_response_definition, status_code_ranges openapi/utils.py Constants injected into the schema for validation errors.
_SSE_EVENT_SCHEMA fastapi/sse.py (cross-module) Schema fragment matching the OpenAPI 3.2 SSE addendum, used when a route's response_class=EventSourceResponse.

How get_openapi works

graph TD
    Start["get_openapi(title, version, routes, webhooks, ...)"]
    Start --> Walk["For each APIRoute / APIWebSocketRoute:"]
    Walk --> Flat["get_flat_dependant(route.dependant)"]
    Flat --> Params["_get_openapi_operation_parameters: Path/Query/Header/Cookie"]
    Flat --> Body["_get_openapi_operation_request_body: Body/Form/File + Pydantic models"]
    Flat --> Sec["get_openapi_security_definitions: from SecurityBase dependants"]
    Walk --> Resp["_get_openapi_operation_response_metadata + response_model"]
    Walk --> Op["Build Operation object"]
    Op --> Paths["paths[path][method] = Operation"]
    Walk --> SchemaGen["Collect ModelFields, generate JSON Schema via _compat.get_definitions"]
    SchemaGen --> Components["components.schemas + components.securitySchemes"]
    Components --> Final["Final dict: {openapi, info, servers, paths, webhooks, components, tags, security, externalDocs}"]
    Final --> Cache["FastAPI.openapi_schema (cached on the app instance)"]

Every APIRoute already has a Dependant tree (built by get_dependant at registration time). The schema generator reuses that, so OpenAPI generation is just projection — it never re-parses signatures.

Swagger UI and ReDoc

docs.py returns HTMLResponse objects, not assets. The HTML embeds CDN URLs to the third-party Swagger UI and ReDoc bundles by default; the URLs are configurable through swagger_ui_init_oauth, swagger_js_url, swagger_css_url, redoc_js_url, redoc_favicon_url, etc. (parameters on FastAPI.__init__). User-supplied OAuth2 client IDs and other init options pass through _html_safe_json (in docs.py) to escape HTML special characters before being injected into the page — guarding against injection if a user puts unusual characters in the OAuth2 init dict.

The OAuth2 redirect page (get_swagger_ui_oauth2_redirect_html) is the small bouncing-token page Swagger UI uses to receive the authorization code from an OAuth2 provider. It is served at /docs/oauth2-redirect by default.

Customising

  • Override FastAPI.openapi() to mutate the cached dict. Common patterns: rename schemas, add servers per environment, attach custom x- extensions.
  • Set generate_unique_id_function on FastAPI (or per-router) to control operationId generation. Default is generate_unique_id in fastapi/utils.py, which is f"{route.name}{path_format}_{method.lower()}" with non-word characters replaced by underscores.
  • Set openapi_url=None to hide /openapi.json. Set docs_url=None and redoc_url=None to hide the UIs.
  • For multiple servers (e.g. staging + production), pass servers=[{"url": "..."}] to FastAPI() or get_openapi().

Integration points

  • Up to FastAPIFastAPI.openapi() calls get_openapi(...). The schema is cached on self.openapi_schema; route table changes invalidate by setting it back to None.
  • Up to user tooling — anything that wants the schema (e.g. SDK generators) typically calls app.openapi() directly.
  • Down to _compat_get_openapi_operation_parameters calls get_schema_from_model_field from fastapi/_compat. JSON Schema generation is delegated to Pydantic.
  • Down to dependencies/ — every operation's parameters and security come from the route's flattened Dependant.

Entry points for modification

  • Adding a new top-level OpenAPI key: extend OpenAPI in models.py, populate it in get_openapi.
  • Changing how validation errors are described: edit validation_error_definition in openapi/utils.py.
  • Theming the docs UIs: tweak get_swagger_ui_html and get_redoc_html in openapi/docs.py. The CDN URLs are parameters; the markup itself is the inline string.
  • Supporting a new spec version: rename and split models.py, gate behaviour in get_openapi based on configured spec version.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

OpenAPI – FastAPI wiki | Factory