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

generators.yml
1- name: fernapi/fern-fastapi-server
2 version: 0.7.7
3 output:
4 location: local-file-system
5 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

fern/api/definition/imdb.yml
1service:
2 auth: false
3 base-path: /movies
4 endpoints:
5 getMovie:
6 method: GET
7 path: /{movieId}
8 path-parameters:
9 movieId: MovieId
10 response: Movie
11 errors:
12 - MovieDoesNotExistError
13
14types:
15 MovieId: string
16
17 Movie:
18 properties:
19 id: MovieId
20 title: string
21 rating:
22 type: double
23 docs: The rating scale is one to five stars
24
25 CreateMovieRequest:
26 properties:
27 title: string
28 rating: double
29
30errors:
31 MovieDoesNotExistError:
32 status-code: 404
33 type: MovieId

Step 2: Run fern generate

This generates all the boilerplate code into generated/.

terminal
$$ 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.

backend/src/fern_fastapi_starter/movies_service.py
1from .generated.fern import AbstractMoviesService, Movie, MovieDoesNotExistError, MovieId
2
3class MoviesService(AbstractMoviesService):
4 def get_movie(self, *, movie_id: str) -> Movie:
5 if movie_id == "titanic":
6 return Movie(
7 id=MovieId.from_str("titantic"),
8 title="Titanic",
9 rating=9.8,
10 )
11 raise MovieDoesNotExistError(MovieId.from_str(movie_id))

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

backend/src/fern_fastapi_starter/server.py
1from fastapi import FastAPI
2
3from .generated.fern.register import register
4from .movies_service import MoviesService
5
6app = FastAPI()
7
8register(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:

terminal
$$ poetry run mypy
>Success: no issues found in 24 source files

Step 5: Run the server

terminal
$$ 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 🚀

terminal
$$ 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"
>}