From 8c13e3db9da9b03dad983dd7ca0171c0e6675547 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Thu, 27 Aug 2026 13:47:07 -0700 Subject: [PATCH] Add flask documentation --- .../workers/framework-guides/apis/flask.mdx | 8 + .../languages/python/packages/fastapi.mdx | 40 +++- .../languages/python/packages/flask.mdx | 173 ++++++++++++++++++ 3 files changed, 211 insertions(+), 10 deletions(-) create mode 100644 src/content/docs/workers/framework-guides/apis/flask.mdx create mode 100644 src/content/docs/workers/languages/python/packages/flask.mdx diff --git a/src/content/docs/workers/framework-guides/apis/flask.mdx b/src/content/docs/workers/framework-guides/apis/flask.mdx new file mode 100644 index 00000000000..92b4d5d7f4b --- /dev/null +++ b/src/content/docs/workers/framework-guides/apis/flask.mdx @@ -0,0 +1,8 @@ +--- +pcx_content_type: navigation +title: Flask +description: Deploy Flask applications on Cloudflare Workers with Python support. +external_link: /workers/languages/python/packages/flask/ +products: + - workers +--- diff --git a/src/content/docs/workers/languages/python/packages/fastapi.mdx b/src/content/docs/workers/languages/python/packages/fastapi.mdx index a8b09a35662..fd29c73c615 100644 --- a/src/content/docs/workers/languages/python/packages/fastapi.mdx +++ b/src/content/docs/workers/languages/python/packages/fastapi.mdx @@ -11,21 +11,23 @@ products: import { Render, WranglerConfig } from "~/components"; -The FastAPI package is supported in Python Workers. +[FastAPI](https://fastapi.tiangolo.com/) 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/). The ASGI server handles all of the raw sockets on the application’s behalf. -The Python Workers provide [an ASGI server](https://github.com/cloudflare/workers-py/blob/main/packages/runtime-sdk/src/asgi.py) +The Python Workers provide [an ASGI server](https://github.com/cloudflare/workers-py/blob/main/packages/runtime-sdk/src/workers/asgi.py) that you can use directly in your Python Worker, which lets you use FastAPI in Python Workers. ## Quick Start To get started with FastAPI in Python Workers, follow these steps: -2. Create a `src/main.py` file with your FastAPI application: + + +1. Create a `src/main.py` file with your FastAPI application: ```python from fastapi import FastAPI @@ -39,12 +41,13 @@ from workers import asgi Default = asgi.entrypoint(app) ``` -3. Create a `wrangler.jsonc` file to configure your Worker: +2. Create a `wrangler.jsonc` file to configure your Worker: ```jsonc { + "$schema": "node_modules/wrangler/config-schema.json", "name": "my-fastapi-app", "main": "src/main.py", "compatibility_date": "$today", @@ -53,7 +56,7 @@ Default = asgi.entrypoint(app) ``` -4. Create a `pyproject.toml` file to manage your dependencies: +3. Create a `pyproject.toml` file to manage your dependencies: ```toml [project] name = "my-fastapi-app" @@ -70,18 +73,36 @@ dev = [ ] ``` -5. Run your Worker locally: +4. Run your Worker locally: ```bash uv run pywrangler dev ``` +5. In another terminal, send a request to the Worker: + + ```sh + curl http://localhost:8787/ + ``` + + The Worker returns: + + ```json output + {"Hello": "World"} + ``` + + + ## Serve a frontend -You can serve a single-page application (SPA) or any static frontend alongside your FastAPI backend by using [Workers Static Assets](/workers/static-assets/). +You can serve 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. +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: @@ -143,8 +164,7 @@ async def frontend(path: str, request: Request): asset_url = f"https://assets.local/{path}" resp = await env.ASSETS.fetch(asset_url) body = await resp.bytes() - headers = dict(resp.headers) - return Response(content=body, status_code=resp.status, headers=headers) + return Response(content=body, status_code=resp.status, headers=resp.headers) ``` You can run this worker locally using `uv run pywrangler dev`. diff --git a/src/content/docs/workers/languages/python/packages/flask.mdx b/src/content/docs/workers/languages/python/packages/flask.mdx new file mode 100644 index 00000000000..0e39043f653 --- /dev/null +++ b/src/content/docs/workers/languages/python/packages/flask.mdx @@ -0,0 +1,173 @@ +--- +pcx_content_type: reference +title: Flask +description: Run Flask applications in Python Workers. +head: + - tag: title + content: Flask +products: + - workers +--- + +import { Steps, WranglerConfig } from "~/components"; + +[Flask](https://flask.palletsprojects.com/) is supported in Python Workers. + +Flask applications rely on a protocol called the Web Server Gateway Interface +(WSGI). This means that Flask never directly reads or writes to a socket, +instead relying on the WSGI server to communicate. + +Python Workers include a [WSGI server](https://github.com/cloudflare/workers-py/blob/main/packages/runtime-sdk/src/workers/wsgi.py) +which you can use with Flask applications. + +## Create a Flask Worker + +Use this quick start to run a minimal Flask application. + + + +1. Create `src/worker.py` with your flask application: + + ```python title="src/worker.py" + from flask import Flask + from workers import wsgi + + app = Flask(__name__) + + @app.get("/") + def index(): + return {"message": "Hello from Flask"} + + Default = wsgi.entrypoint(app) + ``` + +2. In the project root, create `wrangler.jsonc`: + + + + ```jsonc + { + "$schema": "node_modules/wrangler/config-schema.json", + "name": "my-flask-worker", + "main": "src/worker.py", + "compatibility_date": "$today", + "compatibility_flags": ["python_workers"] + } + ``` + + + +3. Create a `pyproject.toml` to declare dependencies: + + ```toml title="pyproject.toml" + [project] + name = "flask-worker" + version = "0.1.0" + requires-python = ">=3.12" + dependencies = [ + "flask", + ] + + [dependency-groups] + dev = [ + "workers-py", + "workers-runtime-sdk", + ] + ``` + +4. Start the local development server: + + ```sh + uv run pywrangler dev + ``` + +5. In another terminal, send a request to the Worker: + + ```sh + curl http://localhost:8787/ + ``` + + The Worker returns: + + ```json output + {"message":"Hello from Flask"} + ``` + + + +## Serve a frontend + +You can serve any static frontend alongside your flask backend by using [Workers Static Assets](/workers/static-assets/). +Using Static Assets means your frontend files are not bundled inside the Worker itself, keeping the bundle small. + +Place your static 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. + + + +```jsonc +{ + "$schema": "node_modules/wrangler/config-schema.json", + "name": "my-flask-worker", + "main": "src/worker.py", + "compatibility_date": "$today", + "compatibility_flags": ["python_workers"], + "assets": { + "directory": "./public/", + "binding": "ASSETS", + "run_worker_first": true + } +} +``` + + + +The following Worker handles an API route before forwarding other requests. The catch-all handlers return each asset's body, status, and headers: + +```python title="src/worker.py" +from flask import Flask, Response, request +from pyodide.ffi import run_sync +from workers import wsgi + + +app = Flask(__name__) + + +@app.get("/api/hello") +def api_hello(): + return {"message": "Hello from the API"} + + +@app.get("/") +@app.get("/") +def frontend(path=""): + assets = request.environ["workers.env"].ASSETS + asset_response = run_sync(assets.fetch(f"https://assets.local/{path}")) + body = run_sync(asset_response.bytes()) + return Response( + body, + status=asset_response.status, + headers=asset_response.headers, + ) + + +Default = wsgi.entrypoint(app) +``` + +`run_sync` bridges both asynchronous asset operations into Flask's synchronous +handler. API routes take priority, and unmatched paths are served from +`./public/`. + + +## More examples + +Clone the `cloudflare/python-workers-examples` repository and run the flask-todo +example there: + +```bash +git clone https://github.com/cloudflare/python-workers-examples +cd python-workers-examples/flask-todo +# See README.md for instructions +```