Skip to content

Commit ad2c5e1

Browse files
authored
Add flask documentation (#33074)
1 parent 3441bfe commit ad2c5e1

3 files changed

Lines changed: 211 additions & 10 deletions

File tree

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
pcx_content_type: navigation
3+
title: Flask
4+
description: Deploy Flask applications on Cloudflare Workers with Python support.
5+
external_link: /workers/languages/python/packages/flask/
6+
products:
7+
- workers
8+
---

‎src/content/docs/workers/languages/python/packages/fastapi.mdx‎

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,23 @@ products:
1111

1212
import { Render, WranglerConfig } from "~/components";
1313

14-
The FastAPI package is supported in Python Workers.
14+
[FastAPI](https://fastapi.tiangolo.com/) is supported in Python Workers.
1515

1616
FastAPI applications use a protocol called the [Asynchronous Server Gateway Interface (ASGI)](https://asgi.readthedocs.io/en/latest/).
1717
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,
1818
typically [uvicorn](https://uvicorn.dev/).
1919
The ASGI server handles all of the raw sockets on the application’s behalf.
2020

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

2424
## Quick Start
2525

2626
To get started with FastAPI in Python Workers, follow these steps:
2727

28-
2. Create a `src/main.py` file with your FastAPI application:
28+
<Steps>
29+
30+
1. Create a `src/main.py` file with your FastAPI application:
2931
```python
3032
from fastapi import FastAPI
3133

@@ -39,12 +41,13 @@ from workers import asgi
3941
Default = asgi.entrypoint(app)
4042
```
4143

42-
3. Create a `wrangler.jsonc` file to configure your Worker:
44+
2. Create a `wrangler.jsonc` file to configure your Worker:
4345

4446
<WranglerConfig>
4547

4648
```jsonc
4749
{
50+
"$schema": "node_modules/wrangler/config-schema.json",
4851
"name": "my-fastapi-app",
4952
"main": "src/main.py",
5053
"compatibility_date": "$today",
@@ -53,7 +56,7 @@ Default = asgi.entrypoint(app)
5356
```
5457
</WranglerConfig>
5558

56-
4. Create a `pyproject.toml` file to manage your dependencies:
59+
3. Create a `pyproject.toml` file to manage your dependencies:
5760
```toml
5861
[project]
5962
name = "my-fastapi-app"
@@ -70,18 +73,36 @@ dev = [
7073
]
7174
```
7275

73-
5. Run your Worker locally:
76+
4. Run your Worker locally:
7477
```bash
7578
uv run pywrangler dev
7679
```
7780

81+
5. In another terminal, send a request to the Worker:
82+
83+
```sh
84+
curl http://localhost:8787/
85+
```
86+
87+
The Worker returns:
88+
89+
```json output
90+
{"Hello": "World"}
91+
```
92+
</Steps>
93+
94+
7895
## Serve a frontend
7996

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

8299
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.
83100

84-
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.
101+
Place your frontend build output (for example, HTML, CSS, and JavaScript files)
102+
in a directory such as `./public/`. Then configure your Wrangler file with an
103+
`assets` block that includes a `binding` and sets `run_worker_first` to `true`.
104+
This ensures every request reaches your FastAPI Worker first, so your API routes
105+
take priority over static files.
85106

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

@@ -143,8 +164,7 @@ async def frontend(path: str, request: Request):
143164
asset_url = f"https://assets.local/{path}"
144165
resp = await env.ASSETS.fetch(asset_url)
145166
body = await resp.bytes()
146-
headers = dict(resp.headers)
147-
return Response(content=body, status_code=resp.status, headers=headers)
167+
return Response(content=body, status_code=resp.status, headers=resp.headers)
148168
```
149169

150170
You can run this worker locally using `uv run pywrangler dev`.
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
---
2+
pcx_content_type: reference
3+
title: Flask
4+
description: Run Flask applications in Python Workers.
5+
head:
6+
- tag: title
7+
content: Flask
8+
products:
9+
- workers
10+
---
11+
12+
import { Steps, WranglerConfig } from "~/components";
13+
14+
[Flask](https://flask.palletsprojects.com/) is supported in Python Workers.
15+
16+
Flask applications rely on a protocol called the Web Server Gateway Interface
17+
(WSGI). This means that Flask never directly reads or writes to a socket,
18+
instead relying on the WSGI server to communicate.
19+
20+
Python Workers include a [WSGI server](https://github.com/cloudflare/workers-py/blob/main/packages/runtime-sdk/src/workers/wsgi.py)
21+
which you can use with Flask applications.
22+
23+
## Create a Flask Worker
24+
25+
Use this quick start to run a minimal Flask application.
26+
27+
<Steps>
28+
29+
1. Create `src/worker.py` with your flask application:
30+
31+
```python title="src/worker.py"
32+
from flask import Flask
33+
from workers import wsgi
34+
35+
app = Flask(__name__)
36+
37+
@app.get("/")
38+
def index():
39+
return {"message": "Hello from Flask"}
40+
41+
Default = wsgi.entrypoint(app)
42+
```
43+
44+
2. In the project root, create `wrangler.jsonc`:
45+
46+
<WranglerConfig>
47+
48+
```jsonc
49+
{
50+
"$schema": "node_modules/wrangler/config-schema.json",
51+
"name": "my-flask-worker",
52+
"main": "src/worker.py",
53+
"compatibility_date": "$today",
54+
"compatibility_flags": ["python_workers"]
55+
}
56+
```
57+
58+
</WranglerConfig>
59+
60+
3. Create a `pyproject.toml` to declare dependencies:
61+
62+
```toml title="pyproject.toml"
63+
[project]
64+
name = "flask-worker"
65+
version = "0.1.0"
66+
requires-python = ">=3.12"
67+
dependencies = [
68+
"flask",
69+
]
70+
71+
[dependency-groups]
72+
dev = [
73+
"workers-py",
74+
"workers-runtime-sdk",
75+
]
76+
```
77+
78+
4. Start the local development server:
79+
80+
```sh
81+
uv run pywrangler dev
82+
```
83+
84+
5. In another terminal, send a request to the Worker:
85+
86+
```sh
87+
curl http://localhost:8787/
88+
```
89+
90+
The Worker returns:
91+
92+
```json output
93+
{"message":"Hello from Flask"}
94+
```
95+
96+
</Steps>
97+
98+
## Serve a frontend
99+
100+
You can serve any static frontend alongside your flask backend by using [Workers Static Assets](/workers/static-assets/).
101+
Using Static Assets means your frontend files are not bundled inside the Worker itself, keeping the bundle small.
102+
103+
Place your static files in a directory such as `./public/`. Then configure your
104+
Wrangler file with an `assets` block that includes a `binding` and sets
105+
`run_worker_first` to `true`. This ensures every request reaches your FastAPI
106+
Worker first, so your API routes take priority over static files.
107+
108+
<WranglerConfig>
109+
110+
```jsonc
111+
{
112+
"$schema": "node_modules/wrangler/config-schema.json",
113+
"name": "my-flask-worker",
114+
"main": "src/worker.py",
115+
"compatibility_date": "$today",
116+
"compatibility_flags": ["python_workers"],
117+
"assets": {
118+
"directory": "./public/",
119+
"binding": "ASSETS",
120+
"run_worker_first": true
121+
}
122+
}
123+
```
124+
125+
</WranglerConfig>
126+
127+
The following Worker handles an API route before forwarding other requests. The catch-all handlers return each asset's body, status, and headers:
128+
129+
```python title="src/worker.py"
130+
from flask import Flask, Response, request
131+
from pyodide.ffi import run_sync
132+
from workers import wsgi
133+
134+
135+
app = Flask(__name__)
136+
137+
138+
@app.get("/api/hello")
139+
def api_hello():
140+
return {"message": "Hello from the API"}
141+
142+
143+
@app.get("/")
144+
@app.get("/<path:path>")
145+
def frontend(path=""):
146+
assets = request.environ["workers.env"].ASSETS
147+
asset_response = run_sync(assets.fetch(f"https://assets.local/{path}"))
148+
body = run_sync(asset_response.bytes())
149+
return Response(
150+
body,
151+
status=asset_response.status,
152+
headers=asset_response.headers,
153+
)
154+
155+
156+
Default = wsgi.entrypoint(app)
157+
```
158+
159+
`run_sync` bridges both asynchronous asset operations into Flask's synchronous
160+
handler. API routes take priority, and unmatched paths are served from
161+
`./public/`.
162+
163+
164+
## More examples
165+
166+
Clone the `cloudflare/python-workers-examples` repository and run the flask-todo
167+
example there:
168+
169+
```bash
170+
git clone https://github.com/cloudflare/python-workers-examples
171+
cd python-workers-examples/flask-todo
172+
# See README.md for instructions
173+
```

0 commit comments

Comments
 (0)