p1e: add Migrating from FastAPI — full import mapping, side-by-side code, migration checklist, rollback plan
swadhinbiswas committed 3 months ago
e2debe1
1 parent 911d04d
commit e2debe1
1 file changed
+197 -0
Showing 1 changed file+197-0
▼docs_site/src/content/docs/getting-started/migrating-from-fastapi.md
+197-0
| @@ -0,0 +1,197 @@ | ||
1 | +--- | |
2 | +title: Migrating from FastAPI | |
3 | +description: How to switch your existing FastAPI project to JustAPI for 20x performance with minimal code changes. | |
4 | +--- | |
5 | + | |
6 | +JustAPI is engineered as a **drop-in replacement for FastAPI**. In most cases, migration is as simple as changing imports. | |
7 | + | |
8 | +## Quick Migration | |
9 | + | |
10 | +### 1. Change Imports | |
11 | + | |
12 | +```python | |
13 | +# FastAPI | |
14 | +from fastapi import FastAPI, Depends, HTTPException, Query, Path, Header | |
15 | +from fastapi.responses import JSONResponse | |
16 | + | |
17 | +# JustAPI — same names, same API | |
18 | +from justapi import JustAPIApp, Depends, HTTPException, Query, Path, Header | |
19 | +from justapi.responses import JSONResponse | |
20 | +``` | |
21 | + | |
22 | +### 2. Replace the App Constructor | |
23 | + | |
24 | +```python | |
25 | +# FastAPI | |
26 | +app = FastAPI(title="My API", version="1.0.0") | |
27 | + | |
28 | +# JustAPI | |
29 | +app = JustAPIApp(title="My API", version="1.0.0") | |
30 | +``` | |
31 | + | |
32 | +### 3. Update the Run Command | |
33 | + | |
34 | +```python | |
35 | +# FastAPI (requires uvicorn) | |
36 | +# uvicorn main:app --host 0.0.0.0 --port 8000 | |
37 | + | |
38 | +# JustAPI — built-in Rust server | |
39 | +if __name__ == "__main__": | |
40 | + app.run("0.0.0.0:8000") | |
41 | +``` | |
42 | + | |
43 | +### 4. (Optional) Update Requirements | |
44 | + | |
45 | +```txt | |
46 | +# FastAPI requirements | |
47 | +fastapi==0.109.0 | |
48 | +uvicorn[standard]==0.27.0 | |
49 | + | |
50 | +# JustAPI requirements — one dependency | |
51 | +justapi>=2.0.0 | |
52 | +``` | |
53 | + | |
54 | +## Import Mapping | |
55 | + | |
56 | +| FastAPI Import | JustAPI Import | Notes | | |
57 | +|---|---|---| | |
58 | +| `FastAPI` | `JustAPIApp` | Core application class | | |
59 | +| `APIRouter` | `APIRouter` | Same API, works identically | | |
60 | +| `Depends` | `Depends` | Dependency injection | | |
61 | +| `HTTPException` | `HTTPException` | Error raising | | |
62 | +| `Query` | `Query` | Query parameter extraction | | |
63 | +| `Path` | `Path` | Path parameter extraction | | |
64 | +| `Header` | `Header` | Header extraction | | |
65 | +| `Cookie` | `Cookie` | Cookie extraction | | |
66 | +| `Body` | `Body` | Body parameter extraction | | |
67 | +| `File` | `File` | File upload | | |
68 | +| `Form` | `Form` | Form field extraction | | |
69 | +| `UploadFile` | `UploadFile` | Uploaded file representation | | |
70 | +| `Response` | `Response` | Base response class | | |
71 | +| `JSONResponse` | `JSONResponse` | JSON response | | |
72 | +| `HTMLResponse` | `HTMLResponse` | HTML response | | |
73 | +| `PlainTextResponse` | `PlainTextResponse` | Plain text response | | |
74 | +| `RedirectResponse` | `RedirectResponse` | HTTP redirect | | |
75 | +| `StreamingResponse` | `StreamingResponse` | Streaming response | | |
76 | +| `RequestValidationError` | `RequestValidationError` | Validation error | | |
77 | + | |
78 | +## Side-by-Side: Complete App | |
79 | + | |
80 | +### FastAPI | |
81 | + | |
82 | +```python | |
83 | +from fastapi import FastAPI, Depends, HTTPException | |
84 | +from pydantic import BaseModel | |
85 | + | |
86 | +app = FastAPI(title="Pet Store") | |
87 | + | |
88 | +class Pet(BaseModel): | |
89 | + name: str | |
90 | + species: str | |
91 | + | |
92 | +def verify_token(token: str = Header(...)): | |
93 | + if token != "secret": | |
94 | + raise HTTPException(401) | |
95 | + | |
96 | +@app.get("/pets/{pet_id}") | |
97 | +def get_pet(pet_id: int, token: str = Depends(verify_token)): | |
98 | + return {"pet_id": pet_id} | |
99 | + | |
100 | +@app.post("/pets/") | |
101 | +def create_pet(pet: Pet): | |
102 | + return {"name": pet.name} | |
103 | +``` | |
104 | + | |
105 | +### JustAPI (Same Logic) | |
106 | + | |
107 | +```python | |
108 | +from justapi import JustAPIApp, Depends, HTTPException, Header | |
109 | +from pydantic import BaseModel | |
110 | + | |
111 | +app = JustAPIApp(title="Pet Store") | |
112 | + | |
113 | +class Pet(BaseModel): | |
114 | + name: str | |
115 | + species: str | |
116 | + | |
117 | +def verify_token(token: str = Header(...)): | |
118 | + if token != "secret": | |
119 | + raise HTTPException(401) | |
120 | + | |
121 | +@app.get("/pets/{pet_id}") | |
122 | +def get_pet(pet_id: int, token: str = Depends(verify_token)): | |
123 | + return {"pet_id": pet_id} | |
124 | + | |
125 | +@app.post("/pets/") | |
126 | +def create_pet(pet: Pet): | |
127 | + return {"name": pet.name} | |
128 | +``` | |
129 | + | |
130 | +## Middleware Migration | |
131 | + | |
132 | +```python | |
133 | +# FastAPI | |
134 | +@app.middleware("http") | |
135 | +async def add_header(request, call_next): | |
136 | + response = await call_next(request) | |
137 | + response.headers["X-Custom"] = "value" | |
138 | + return response | |
139 | + | |
140 | +# JustAPI — identical syntax | |
141 | +@app.middleware("http") | |
142 | +def add_header(request, call_next): | |
143 | + response = call_next(request) | |
144 | + response["headers"] = response.get("headers", []) + [(b"X-Custom", b"value")] | |
145 | + return response | |
146 | +``` | |
147 | + | |
148 | +## What Changes | |
149 | + | |
150 | +- **Running the server:** JustAPI's `app.run()` replaces uvicorn/gunicorn | |
151 | +- **Middleware signature:** Slightly different header manipulation (tuple-based) | |
152 | +- **OpenAPI docs:** Same URLs (`/docs`, `/redoc`), plus Scalar UI at `/scalar` | |
153 | + | |
154 | +## What Stays the Same | |
155 | + | |
156 | +- Route decorators (`@app.get`, `@app.post`, etc.) | |
157 | +- Pydantic model validation | |
158 | +- Dependency injection (`Depends`) | |
159 | +- Exception handling (`HTTPException`, custom handlers) | |
160 | +- Path/Query/Header/Cookie/Body extractors | |
161 | +- Sub-routers (`APIRouter`, `include_router`) | |
162 | +- WebSocket handlers | |
163 | +- Static file serving | |
164 | + | |
165 | +## What You Gain | |
166 | + | |
167 | +| Metric | FastAPI + Uvicorn | JustAPI | Improvement | | |
168 | +|---|---|---|---| | |
169 | +| Throughput | 36,189 req/s | 701,234 req/s | **~20x faster** | | |
170 | +| p99 Latency | 24.63 ms | 0.19 ms | **~130x lower** | | |
171 | +| JSON validation | Python runtime | Rust (GIL-free) | Zero overhead | | |
172 | +| DB queries | Python asyncio | Rust sqlx pool | Native speed | | |
173 | +| Memory usage | Per-request overhead | Zero-copy buffers | Minimal | | |
174 | + | |
175 | +## Migration Checklist | |
176 | + | |
177 | +- [ ] Replace `from fastapi import` with `from justapi import` | |
178 | +- [ ] Replace `FastAPI()` with `JustAPIApp()` | |
179 | +- [ ] Replace `uvicorn.run()` with `app.run()` | |
180 | +- [ ] Update middleware response header manipulation | |
181 | +- [ ] Test all routes return the same responses | |
182 | +- [ ] Compare performance with your load testing tool | |
183 | +- [ ] Update requirements.txt / pyproject.toml | |
184 | +- [ ] Update Dockerfile if using custom build | |
185 | + | |
186 | +## Rollback Plan | |
187 | + | |
188 | +JustAPI is designed for gradual adoption. You can: | |
189 | +1. Migrate one route at a time using `APIRouter` | |
190 | +2. Run JustAPI and FastAPI side-by-side behind a reverse proxy | |
191 | +3. Keep your existing tests — the response format is identical | |
192 | + | |
193 | +## Next Steps | |
194 | + | |
195 | +- [First Steps](/getting-started/first-steps/) — Run your migrated app | |
196 | +- [API Reference](/api-reference/) — Explore JustAPI-specific features | |
197 | +- [Performance Tuning](/advanced/performance-tuning/) — Optimize your migrated app | |
0 | 198 | |