Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 126 additions & 37 deletions src/content/docs/workers/languages/python/packages/fastapi.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,116 @@ import { Render } from "~/components";

The FastAPI package is supported in Python Workers.

FastAPI applications use a protocol called the [Asynchronous Server Gateway Interface (ASGI)](https://asgi.readthedocs.io/en/latest/). This means that FastAPI never reads from or writes to a socket itself. An ASGI application expects to be hooked up to an ASGI server, typically [uvicorn](https://uvicorn.dev/).
FastAPI applications use a protocol called the [Asynchronous Server Gateway Interface (ASGI)](https://asgi.readthedocs.io/en/latest/).
This means that FastAPI never reads from or writes to a socket itself. An ASGI application expects to be hooked up to an ASGI server,
typically [uvicorn](https://uvicorn.dev/).
The ASGI server handles all of the raw sockets on the application’s behalf.

The Python Workers provides [an ASGI server](https://github.com/cloudflare/workers-py/blob/main/packages/runtime-sdk/src/asgi.py)
that you can use directly in your Python Worker, which lets you use FastAPI in Python Workers.

## Get Started
## Quick Start

Clone the `cloudflare/python-workers-examples` repository and run the FastAPI example:
To get started with FastAPI in Python Workers, follow these steps:

2. Create a `src/main.py` file with your FastAPI application:
```python
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
return {"Hello": "World"}

import asgi
from workers import WorkerEntrypoint

class Default(WorkerEntrypoint):
async def fetch(self, request):
return await asgi.fetch(app, request, self.env)
```

3. Create a `wrangler.jsonc` file to configure your Worker:
```jsonc
{
"name": "my-fastapi-app",
"main": "src/main.py",
"compatibility_date": "$today",
"compatibility_flags": ["python_workers"],
}
```

4. Create a `pyproject.toml` file to manage your dependencies:
```toml
[project]
name = "my-fastapi-app"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = [
"fastapi",
]

[dependency-groups]
dev = [
"workers-py",
"workers-runtime-sdk"
]
```

5. Run your Worker locally:
```bash
git clone https://github.com/cloudflare/python-workers-examples
cd python-workers-examples/03-fastapi
uv run pywrangler dev
```

### Example code
## Serve a frontend

```python
You can serve a single-page application (SPA) or any static frontend alongside your FastAPI backend by using [Workers Static Assets](/workers/static-assets/).

This is equivalent to FastAPI's native [`app.frontend()`](https://fastapi.tiangolo.com/tutorial/frontend/) method, which serves a static build directory as low-priority routes so that API path operations are checked first. The difference is where the files live: `app.frontend()` reads files from the local filesystem, while on Workers the static assets are served from Cloudflare's globally distributed asset store through the `ASSETS` binding. This means your frontend files are not bundled inside the Worker itself, keeping the bundle small.

Place your frontend build output (for example, HTML, CSS, and JavaScript files) in a directory such as `./public/`. Then configure your Wrangler file with an `assets` block that includes a `binding` and sets `run_worker_first` to `true`. This ensures every request reaches your FastAPI Worker first, so your API routes take priority over static files.

Add a catch-all route at the end of your FastAPI app that proxies unmatched requests to the assets binding:

```jsonc title="wrangler.jsonc"
{
"name": "my-fastapi-app",
"main": "src/worker.py",
"compatibility_date": "$today",
"compatibility_flags": ["python_workers"],
"assets": {
"directory": "./public/",
"binding": "ASSETS",
"run_worker_first": true
}
}
```

Be sure to create a `pyproject.toml` file to manage your dependencies:

```toml
[project]
name = "my-fastapi-app"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = [
"fastapi",
]

[dependency-groups]
dev = [
"workers-py",
"workers-runtime-sdk"
]
```

Then write your worker:

```python title="src/worker.py"
from workers import WorkerEntrypoint
from fastapi import FastAPI, Request
from pydantic import BaseModel
from fastapi.responses import Response
import asgi

class Default(WorkerEntrypoint):
Expand All @@ -43,33 +131,34 @@ class Default(WorkerEntrypoint):

app = FastAPI()

@app.get("/")
async def root():
return {"message": "Hello, World!"}

@app.get("/env")
async def root(req: Request):
env = req.scope["env"]
return {"message": "Here is an example of getting an environment variable: " + env.MESSAGE}

class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None

@app.post("/items/")
async def create_item(item: Item):
return item

@app.put("/items/{item_id}")
async def create_item(item_id: int, item: Item, q: str | None = None):
result = {"item_id": item_id, **item.dict()}
if q:
result.update({"q": q})
return result

@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}
@app.get("/api/hello")
async def api_hello():
return {"message": "Hello from the API"}

# Catch-all: proxy everything else to Workers Static Assets.
# This is the Workers equivalent of app.frontend("/", directory="dist").
@app.get("/{path:path}")
async def frontend(path: str, request: Request):
env = request.scope["env"]
asset_url = f"https://assets.local/{path}"
resp = await env.ASSETS.fetch(asset_url)
Comment thread
dom96 marked this conversation as resolved.
body = await resp.bytes()
headers = dict(resp.headers)
return Response(content=body, status_code=resp.status, headers=headers)
```

You can run this worker locally using `uv run pywrangler dev`.

With this setup, a request to `/api/hello` is handled by FastAPI, while a request to `/index.html` or any other path is served from the `./public/` directory through the assets binding.

For more information on configuring static assets, refer to the [Workers Static Assets documentation](/workers/static-assets/).

## More examples

Clone the `cloudflare/python-workers-examples` repository and run the FastAPI examples there:

```bash
git clone https://github.com/cloudflare/python-workers-examples
cd python-workers-examples/03-fastapi
uv run pywrangler dev
```