Server boilerplate

FastAPI

Source code
A starter repo for FastAPI, using Fern

Latest version: 0.7.7

The FastAPI generator generates types and networking logic for your FastAPI server. This saves you time and add compile-time safety that you are serving the exact API that you specified in your API Definition.

Available on the open source plan.

What Fern generates

  • Pydantic models for your API types
  • Exceptions that you can throw for non-200 responses
  • Abstract classes for you to define your business logic
  • All the networking/HTTP logic to call your API

Adding the FastAPI generator

1
2
3
4
5
- name: fernapi/fern-fastapi-server
  version: 0.7.7
  output:
    location: local-file-system
    path: ../generated/server-boilerplate/fastapi

Example server

Venus is a FastAPI microservice in production that manages Fern's auth (i.e. users, organizations, tokens).

Demo Video

Getting started

Let's walk through the Fern FastAPI Starter.

Step 1: Define the API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
service:
  auth: false
  base-path: /movies
  endpoints:
    getMovie:
      method: GET
      path: /{movieId}
      path-parameters:
        movieId: MovieId
      response: Movie
      errors:
        - MovieDoesNotExistError

types:
  MovieId: string

  Movie:
    properties:
      id: MovieId
      title: string
      rating:
        type: double
        docs: The rating scale is one to five stars

  CreateMovieRequest:
    properties:
      title: string
      rating: double

errors:
  MovieDoesNotExistError:
    status-code: 404
    type: MovieId

Step 2: Run fern generate

This generates all the boilerplate code into generated/.

1
2
3
4
5
$ fern generate
[api]: fernapi/fern-fastapi-starter Downloaded to backend/src/fern_fastapi_starter/api/generated
┌─
│ ✓  fernapi/fern-fastapi-server
└─

Step 3: Implement the server

Notice you only need to provide the business logic. Just implement the function, and Fern takes care of the rest.

1
2
3
4
5
6
7
8
9
10
11
from .generated.fern import AbstractMoviesService, Movie, MovieDoesNotExistError, MovieId

class MoviesService(AbstractMoviesService):
    def get_movie(self, *, movie_id: str) -> Movie:
        if movie_id == "titanic":
            return Movie(
                id=MovieId.from_str("titantic"),
                title="Titanic",
                rating=9.8,
            )
        raise MovieDoesNotExistError(MovieId.from_str(movie_id))

And register your endpoints with Fern, which registers them with FastAPI under the hood:

1
2
3
4
5
6
7
8
from fastapi import FastAPI

from .generated.fern.register import register
from .movies_service import MoviesService

app = FastAPI()

register(app, imdb=MoviesService())

Step 4: Compile

The type checker will warn you if you make mistakes implementing your API:

Invalid return value

If you change the signature of the endpoint method, you'll get an error:

Invalid signature

You can use the command line to check for compile errors:

1
2
$ poetry run mypy
Success: no issues found in 24 source files

Step 5: Run the server

1
2
3
4
5
6
$ poetry run start
INFO:     Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
INFO:     Started reloader process [32816] using StatReload
INFO:     Started server process [32829]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

Step 6: Hit the API 🚀

1
2
3
4
5
6
7
8
9
10
11
12
13
$ curl --location --request GET --silent 'localhost:8080/movies/titanic' | jq .
{
  "id": "titantic",
  "title": "Titanic",
  "rating": 9.8
}

$ curl --location --request GET --silent 'localhost:8080/movies/oceans-11' | jq .
{
  "error": "MovieDoesNotExistError",
  "errorInstanceId": "f6e1d69c-bf97-42d5-bc89-5e42773e3880",
  "content": "oceans-11"
}