FastAPI Internals

@marcelotryle

The Speaker

bg:60%

Marcelo Trylesinski

@marcelotryle

OSS Maintainer

Uvicorn

Starlette

@marcelotryle

What is FastAPI?

@marcelotryle

How do I run FastAPI?

uvicorn main:app or...

www.uvicorn.org

@marcelotryle

How do I run FastAPI?

hypercorn main:app or...

github.com/pgjones/hypercorn

@marcelotryle

How do I run FastAPI?

granian main:app

github.com/emmett-framework/granian

@marcelotryle

How the interactions happen?

@marcelotryle

Let's focus on...

@marcelotryle

But... How it really happens?

@marcelotryle

ASGI application

Scope = Dict[str, Any]
Receive = Callable[[], Awaitable[Dict[str, Any]]]
Send = Callable[[Dict[str, Any]], Awaitable[None]]

async def app(scope: Scope, receive: Receive, send: Send):
    ...
@marcelotryle

Simplest ASGI application

async def app(scope, receive, send):
    body = b"Hello world!"
    headers = [(b"content-type", b"text/plain"), (b"content-length", str(len(body)).encode())]

    await send({"type": "http.response.start", "status": 200, "headers": headers})
    await send({"type": "http.response.body", "body": body})
@marcelotryle

After the connection is established...

@marcelotryle

If the client sends a body...

@marcelotryle

Then... It's the application's turn!

@marcelotryle

Middleware Stack

@marcelotryle

Middleware Stack

from fastapi import FastAPI
from src.middleware import CustomMiddleware, AnotherCustomMiddleware

app = FastAPI()
app.add_middleware(CustomMiddleware)
app.add_middleware(AnotherCustomMiddleware)
@marcelotryle

Middleware Stack

@marcelotryle

Routing

@marcelotryle

Routing

@marcelotryle

Dependency Injection

@marcelotryle

Dependency Injection

@marcelotryle

Dependency Injection

Async

async def dependency():
    return "Hello, World!"

Sync

def dependency():
    return "Hello, World!"
@marcelotryle

Input/Output Validation

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Input(BaseModel):
    name: str
    age: int

class Output(Input):
    id: int

@app.post("/")
async def read_item(input: Input) -> Output:
    return await database_insert(input)
@marcelotryle

Input/Output Validation

@marcelotryle

WebSockets

@marcelotryle

WebSockets

@marcelotryle

Async vs Sync

When should I use...

@marcelotryle

Bonus: FastAPI Tips

https://github.com/Kludex/fastapi-tips

@marcelotryle

Try Logfire! 🚀

@marcelotryle

Thank You!

www.fastapiexpert.com

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" referrerpolicy="no-referrer" />

Marcelo Trylesinski
@marcelotryle
Kludex

@marcelotryle

![bg:40% 80% right](assets/marcelo.png) ![bg:40% 80% left](assets/marcelo.png)

Reference: https://github.com/koddr/starlette-logo

FastAPI is a web framework.

Uvicorn was built by Tom Christie, the same author as MkDocs, Starlette, HTTPX and Django Rest Framework.

Hypercorn was built by Phil Jones, one of the Flask maintainers.

Granian was built by an Italian - which is in the room.

The client initiates the communication, and the server parses the HTTP request. Then the server sends the information to the application in a specific format.

ASGI is the interface between the server and the application.

And the request line is read...

The middleware intercepts the messages sent by the server, and the application.

It comes from Starlette.

When to use non-async code? - CPU bound that can escape the GIL - Thread blocking IO