Skip to content

Commit ad292b7

Browse files
Add API transformer documentation (#1317)
* Add API transformer documentation to replace API routes overview Co-Authored-By: Alek Petuskey <[email protected]> * Fix callable transformer example to correctly return transformed ASGI app Co-Authored-By: Alek Petuskey <[email protected]> * Change code blocks from 'python box' to 'python' Co-Authored-By: Alek Petuskey <[email protected]> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Alek Petuskey <[email protected]>
1 parent 8b1ad1d commit ad292b7

File tree

1 file changed

+121
-12
lines changed

1 file changed

+121
-12
lines changed

docs/api-routes/overview.md

Lines changed: 121 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,151 @@
22
import reflex as rx
33
```
44

5-
# Backend API Routes
5+
# API Transformer
66

7-
In addition to your frontend app, Reflex also uses a FastAPI backend to serve your app.
7+
In addition to your frontend app, Reflex uses a FastAPI backend to serve your app. The API transformer feature allows you to transform or extend the ASGI app that serves your Reflex application.
88

9-
To add additional endpoints to the backend API, you can use `app.add_api_route` and add a route that returns JSON.
9+
## Overview
10+
11+
The API transformer provides a way to:
12+
13+
1. Integrate existing FastAPI or Starlette applications with your Reflex app
14+
2. Apply middleware or transformations to the ASGI app
15+
3. Extend your Reflex app with additional API endpoints
16+
17+
This is useful for creating a backend API that can be used for purposes beyond your Reflex app, or for integrating Reflex with existing backend services.
18+
19+
## Using API Transformer
20+
21+
You can set the `api_transformer` parameter when initializing your Reflex app:
1022

1123
```python
12-
async def api_test(item_id: int):
13-
return \{"my_result": item_id}
24+
import reflex as rx
25+
from fastapi import FastAPI, Depends
26+
from fastapi.security import OAuth2PasswordBearer
27+
28+
# Create a FastAPI app
29+
fastapi_app = FastAPI(title="My API")
1430

15-
app = rx.App()
16-
app.api.add_api_route("/items/\{item_id}", api_test)
31+
# Add routes to the FastAPI app
32+
@fastapi_app.get("/api/items")
33+
async def get_items():
34+
return dict(items=["Item1", "Item2", "Item3"])
35+
36+
# Create a Reflex app with the FastAPI app as the API transformer
37+
app = rx.App(api_transformer=fastapi_app)
1738
```
1839

19-
Now you can access the endpoint at `localhost:8000/items/23` and get the result.
40+
## Types of API Transformers
41+
42+
The `api_transformer` parameter can accept:
43+
44+
1. A Starlette or FastAPI instance
45+
2. A callable that takes an ASGIApp and returns an ASGIApp
46+
3. A sequence of the above
47+
48+
### Using a FastAPI or Starlette Instance
2049

21-
This is useful for creating a backend API that can be used for purposes other than your Reflex app.
50+
When you provide a FastAPI or Starlette instance as the API transformer, Reflex will mount its internal API to your app, allowing you to define additional routes:
51+
52+
```python
53+
import reflex as rx
54+
from fastapi import FastAPI, Depends
55+
from fastapi.security import OAuth2PasswordBearer
56+
57+
# Create a FastAPI app with authentication
58+
fastapi_app = FastAPI(title="Secure API")
59+
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
60+
61+
# Add a protected route
62+
@fastapi_app.get("/api/protected")
63+
async def protected_route(token: str = Depends(oauth2_scheme)):
64+
return dict(message="This is a protected endpoint")
65+
66+
# Create a token endpoint
67+
@fastapi_app.post("/token")
68+
async def login(username: str, password: str):
69+
# In a real app, you would validate credentials
70+
if username == "user" and password == "password":
71+
return dict(access_token="example_token", token_type="bearer")
72+
return dict(error="Invalid credentials")
73+
74+
# Create a Reflex app with the FastAPI app as the API transformer
75+
app = rx.App(api_transformer=fastapi_app)
76+
```
77+
78+
### Using a Callable Transformer
79+
80+
You can also provide a callable that transforms the ASGI app:
81+
82+
```python
83+
import reflex as rx
84+
from starlette.middleware.cors import CORSMiddleware
85+
86+
# Create a transformer function that returns a transformed ASGI app
87+
def add_cors_middleware(app):
88+
# Wrap the app with CORS middleware and return the wrapped app
89+
return CORSMiddleware(
90+
app=app,
91+
allow_origins=["https://example.com"],
92+
allow_methods=["*"],
93+
allow_headers=["*"],
94+
)
95+
96+
# Create a Reflex app with the transformer
97+
app = rx.App(api_transformer=add_cors_middleware)
98+
```
99+
100+
### Using Multiple Transformers
101+
102+
You can apply multiple transformers by providing a sequence:
103+
104+
```python
105+
import reflex as rx
106+
from fastapi import FastAPI
107+
from starlette.middleware import Middleware
108+
from starlette.middleware.cors import CORSMiddleware
109+
110+
# Create a FastAPI app
111+
fastapi_app = FastAPI(title="My API")
112+
113+
# Add routes to the FastAPI app
114+
@fastapi_app.get("/api/items")
115+
async def get_items():
116+
return dict(items=["Item1", "Item2", "Item3"])
117+
118+
# Create a transformer function
119+
def add_logging_middleware(app):
120+
# This is a simple example middleware that logs requests
121+
async def middleware(scope, receive, send):
122+
# Log the request path
123+
path = scope["path"]
124+
print("Request:", path)
125+
await app(scope, receive, send)
126+
return middleware
127+
128+
# Create a Reflex app with multiple transformers
129+
app = rx.App(api_transformer=[fastapi_app, add_logging_middleware])
130+
```
22131

23132
## Reserved Routes
24133

25134
Some routes on the backend are reserved for the runtime of Reflex, and should not be overridden unless you know what you are doing.
26135

27-
## Ping
136+
### Ping
28137

29138
`localhost:8000/ping/`: You can use this route to check the health of the backend.
30139

31140
The expected return is `"pong"`.
32141

33-
## Event
142+
### Event
34143

35144
`localhost:8000/_event`: the frontend will use this route to notify the backend that an event occurred.
36145

37146
```md alert error
38147
# Overriding this route will break the event communication
39148
```
40149

41-
## Upload
150+
### Upload
42151

43152
`localhost:8000/_upload`: This route is used for the upload of file when using `rx.upload()`.

0 commit comments

Comments
 (0)