# server fastapi

Source: https://apigenie.pl/techdocs/reference/cli-generate_server_fastapi

Generate a Python [FastAPI](https://fastapi.tiangolo.com) server from an OpenAPI document.

## Usage

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

## Description

The generated project has the layout of the `python-fastapi` generator of
[openapi-generator](https://openapi-generator.tech) 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:

```python
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`:

```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
```

```sh
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:

```yaml
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,...) |
