apigenie-generatorOpenAPI serversserver fastapi

server fastapi

Generate a Python FastAPI server from an OpenAPI document.

Usage

apigenie-generator server fastapi [...OPTIONS] INPUT_FILE

Description

The generated project has the layout of the python-fastapi generator of openapi-generator and accepts its options, so a project generated by openapi-generator can be generated again by API Genie. The code itself is written for FastAPI 0.115+, pydantic 2.7+ and Python 3.10+:

pyproject.toml, requirements.txt, README.md, Dockerfile, docker-compose.yaml, openapi.yaml
src/openapi_server/
    main.py                 the application: includes the routers, loads the implementation
    apis/pets_api.py        the routes of the "pets" API (one module per tag)
    apis/pets_api_base.py   BasePetsApi: the methods to implement
    impl/__init__.py        the implementation package, yours
    models/                 pydantic models, one module per schema
    security_api.py         the dependencies checking credentials
tests/                      pytest tests with FastAPI's TestClient

Routes validate requests, then call the methods of the base class of their API, which answer 501 Not Implemented. Implement them in a subclass, in a module of the implementation package:

from openapi_server.apis.pets_api_base import BasePetsApi
from openapi_server.models import Pet


class PetsApi(BasePetsApi):
    async def show_pet_by_id(self, *, pet_id: str) -> Pet:
        return Pet(id=1, name="Rex")

The application imports the modules of the implementation package when it starts, and the first subclass of a base class serves its requests. Tests can replace it with app.dependency_overrides[get_pets_api]. Credentials are validated the same way, by a subclass of BaseSecurity of security_api.py.

The generated code covers:

  • routes with the status code, response class, documented responses (including default, ranges like 4XX and headers), tags, summary, description, operation ID and deprecation of operations; routes of concrete paths come before the routes of templates matching them
  • path, query, header and cookie parameters with their aliases, defaults and constraints, JSON, text and binary request bodies, forms and file uploads (UploadFile)
  • models: classes with aliases for names that aren’t valid Python names, constraints, defaults and descriptions; enums; allOf merged into one class; oneOf/anyOf as unions, with discriminators where the document has them; nullable types of OpenAPI 3.0 and 3.1; recursive and mutually referencing models
  • security: API keys (header, query, cookie), HTTP basic, bearer and other HTTP schemes, OAuth2 (all flows, with scopes) and OpenID Connect, with global security, alternatives (a request needs to meet one of the security requirements) and anonymous access ({})

Files are generated again on every run, except the implementation package, the tests of the APIs, tests/conftest.py and .openapi-generator-ignore, which are generated only when they don’t exist. Files listed in .openapi-generator-ignore (which uses the syntax of .gitignore) aren’t written. .openapi-generator/FILES lists the generated files.

Differences from openapi-generator:

  • routes declare their status code and response class, e.g. 201 or 204 without a body, instead of documenting every response as 200
  • the implementation is one instance of the subclass, resolved by a FastAPI dependency, instead of an instance per request; the tokens of security schemes are passed to it
  • models are idiomatic pydantic 2 models: oneOf/anyOf are unions (discriminated where possible) instead of wrapper classes, constraints use pattern= instead of the deprecated regex=, and there are no to_dict()/from_dict() helpers
  • OAuth2 schemes of the same flow don’t collide, and OpenID Connect schemes are supported
  • mutual TLS security schemes are reported and left out, since FastAPI can’t check them
  • unknown options are errors, not ignored
  • the input must be an OpenAPI 3.0, 3.1 or 3.2 document; convert Swagger 2.0 documents with apigenie convert, and bundle documents referencing other files with apigenie bundle

Constructs that FastAPI can’t express are reported as warnings and simplified: object query parameters (e.g. deepObject) are left out and the route receives the request instead; arrays in headers, cookies and non-exploded query parameters are received as strings; nested objects in forms are received as strings.

Not supported: callbacks, webhooks and response links, which the served OpenAPI document leaves out, and x-internal, whose operations stay in it.

Extensions

Extension Effect
x-apigenie.codegen.controller-name on an operation or its path item: the API module of the operation, instead of its first tag
x-apigenie.codegen.action-name name of the function of an operation, instead of its operationId
x-apigenie.codegen.disabled true on an operation or its path item leaves the operation out, with skipDisabled
x-codegen-request-body-name on an operation or its request body: the name of the body parameter
x-defaultMapping defaultMapping of a discriminator in OpenAPI 3.0 and 3.1 documents: the schema of the values whose discriminator value isn’t mapped

The extensions can live in an overlay for this target instead of in the document, e.g. fastapi.overlay.yaml:

overlay: 1.0.0
info:
  title: FastAPI names
  version: 1.0.0
actions:
  - target: $.paths['/pets'].post
    update:
      x-codegen-request-body-name: pet
      x-apigenie:
        codegen:
          action-name: add_pet
apigenie-generator server fastapi openapi.yaml --overlay fastapi.overlay.yaml -o out

Options

-c, –config

Path to the configuration file to use. See the “Configuration” section for more information.

–overlay OVERLAY

Path to an OpenAPI Overlay (1.0 to 1.2) applied to the input before generating, e.g. one setting the extensions of the “Extensions” section. Can be repeated: the overlays apply in order, after those listed under commands.generate.server_fastapi.overlay in the configuration file (with paths relative to it). Warnings and errors about a value an overlay set point to the overlay.

–strict

Makes an overlay action whose target selects nothing an error (exit status 2, nothing is generated) instead of a warning (OVERLAY:LINE:COL: action #N (TARGET) selects no nodes.).

-o, –output

Directory where the project is generated.

–package-name

Python package of the generated code (packageName), e.g. pet_store or acme.pet_store. Defaults to openapi_server.

–package-version

Version of the generated project (packageVersion). Defaults to the version of the API when pip accepts it, otherwise to 1.0.0.

-p, –property NAME=VALUE

Sets a generator option (see below), e.g. -p serverPort=8000. Options given on the command line take precedence over the configuration file. Mapping options take comma-separated lists, e.g. -p 'nameMappings=_links=links,$type=kind'.

Configuration

Options can also be set in the configuration file, either directly or in an additionalProperties section, like in configuration files of openapi-generator:

version: '1.0'
commands:
  generate:
    server_fastapi:
      packageName: pet_store
      serverPort: 8000
      nameMappings:
        _links: links
Option Description
packageName Python package of the generated code (default openapi_server)
packageVersion Version of the project (defaults to the version of the API when pip accepts it, otherwise 1.0.0)
serverPort Port the server listens to (defaults to the port of the first server, or 8080)
sourceFolder Directory of the package, relative to the output directory (default src)
fastapiImplementationPackage Package of the implementation of the APIs (default impl), inside the generated package unless useExternalImplementationPackage is set
useExternalImplementationPackage The implementation package is outside the generated package and isn’t generated (default false)
generateTests Generate tests (tests/) (default true)
generateDocker Generate a Dockerfile and docker-compose.yaml (default true)
generatorVersion Version of the generator written into generated files
sortParamsByRequiredFlag Put required parameters before optional ones (default true)
skipDeprecated Don’t generate code for deprecated operations (default false)
skipDisabled Don’t generate code for operations disabled with x-apigenie (default false)
modelsLayout Where models are written: modules (a module per model, the default) or single (one module)
disallowAdditionalPropertiesIfNotPresent Models of schemas without additionalProperties reject unknown properties (extra=“forbid”) (default false)
hideGenerationTimestamp Accepted for compatibility with openapi-generator; generated files have no timestamps
modelNamePrefix Prefix of model names
modelNameSuffix Suffix of model names
modelNameMappings Mappings of schema names to model names (Schema=Model,…)
nameMappings Mappings of property names to field names (name=field_name,…)
parameterNameMappings Mappings of parameter names to Python names (name=python_name,…)
enumNameMappings Mappings of enum values to member names (value=NAME,…)