Showcase
FastAPI
Fern has a first-class integration with FastAPI. Fern automatically 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 is auto-generated by Fern under the hood.
Repos:
- Venus is a Python FastAPI server that uses Fern under the hood.
- The Fern FastAPI Starter is a simple example of a Fern-powered FastAPI server.
Example
Let’s walk through the Fern FastAPI Starter.
Step 1: Define the API
fern/api/definition/imdb.yml
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/.
$ 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
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:
backend/src/fern_fastapi_starter/server.py
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.
If you change the signature of the endpoint method, you’ll get an error:
You can use the command line to check for compile errors:
$ poetry run mypy
Success: no issues found in 24 source files
Step 5: Run the server
$ 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 🚀
$ 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"
}