docs: add comprehensive JustAPI Developer Handbook (docs/HANDBOOK.md)
swadhinbiswas committed 3 months ago
379ad5d
1 parent 42f4f11
commit 379ad5d
2 files changed
+508 -2
Showing 2 changed files+508-2
βΌdocs/HANDBOOK.md
+498-0
| @@ -0,0 +1,498 @@ | ||
1 | +# π JustAPI Developer Handbook & Master Reference Guide | |
2 | + | |
3 | +Welcome to the official handbook for **JustAPI** β a modern, high-performance Python web framework powered by a native **Rust core**. | |
4 | + | |
5 | +JustAPI is designed as a **drop-in, Rust-accelerated replacement for FastAPI**. It combines FastAPIβs beloved developer experience (decorators, type annotations, Pydantic/Schema validation, automatic OpenAPI docs) with a multi-threaded Rust networking and routing engine that delivers **up to 20Γ the throughput of FastAPI+Uvicorn**. | |
6 | + | |
7 | +--- | |
8 | + | |
9 | +## Table of Contents | |
10 | + | |
11 | +1. [Architecture & Philosophy](#1-architecture--philosophy) | |
12 | +2. [Installation & Setup](#2-installation--setup) | |
13 | +3. [Quickstart & Project Generator](#3-quickstart--project-generator) | |
14 | +4. [Routing & Request Handling](#4-routing--request-handling) | |
15 | +5. [Schemas & Request Validation](#5-schemas--request-validation) | |
16 | +6. [Multi-Protocol APIs (REST, GraphQL, gRPC, JSON-RPC)](#6-multi-protocol-apis) | |
17 | +7. [Database Backend & Fast-Path I/O](#7-database-backend--fast-path-io) | |
18 | +8. [Dependency Injection & Middleware](#8-dependency-injection--middleware) | |
19 | +9. [WebSockets, SSE & Real-Time Streaming](#9-websockets-sse--real-time-streaming) | |
20 | +10. [Resilience & Security Safeguards](#10-resilience--security-safeguards) | |
21 | +11. [Observability & Monitoring](#11-observability--monitoring) | |
22 | +12. [Production Deployment & CI/CD](#12-production-deployment--cicd) | |
23 | + | |
24 | +--- | |
25 | + | |
26 | +## 1. Architecture & Philosophy | |
27 | + | |
28 | +### Rust-First Performance Thesis | |
29 | + | |
30 | +In standard ASGI frameworks like FastAPI + Uvicorn or Starlette, every incoming connection, HTTP header parse, route match, JSON validation, and response serialization is executed inside Python under the **Global Interpreter Lock (GIL)**. | |
31 | + | |
32 | +JustAPI moves 95%+ of the request lifecycle out of Python entirely: | |
33 | + | |
34 | +``` | |
35 | +[ Client Connection ] | |
36 | + β | |
37 | + βΌ | |
38 | +βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
39 | +β RUST RUNTIME (justapi-core) β | |
40 | +β β’ Socket I/O (tokio) & TLS termination (rustls) β | |
41 | +β β’ HTTP/1.1 & HTTP/2 Parsing (hyper) β | |
42 | +β β’ Radix Trie Routing (matchit) β | |
43 | +β β’ Middleware (Auth/JWT, CORS, GCRA Rate Limiting) β π’ GIL RELEASED | |
44 | +β β’ Precompiled JSON Schema Validation (jsonschema-rs) β (Zero GIL Lock!) | |
45 | +β β’ Connection Pool & Database Queries (sqlx / AnyPool) β | |
46 | +β β’ JSON Serialization (serde_json / simd-json) β | |
47 | +ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ | |
48 | + β | |
49 | + Invoked only for Python application logic: | |
50 | + βΌ | |
51 | +ββββββββββββββββββββββββββββββββββββββββββββ βββββββββββββββββββ | |
52 | +β PYTHON APPLICATION LAYER (justapi-py) β | |
53 | +β β’ Business logic execution inside dedicated gil_pool β π‘ PyO3 GIL Thread | |
54 | +βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
55 | +``` | |
56 | + | |
57 | +### Zero-GIL Fast Path Mechanics | |
58 | +* **Python 3.11 & 3.12:** PyO3 releases the GIL via `py.allow_threads` during all I/O, routing, DB queries, and JSON processing. | |
59 | +* **Python 3.13t & 3.14t (Free-Threaded):** Full support for PEP 703 free-threading β Python handler execution runs concurrently across all CPU cores without GIL locks. | |
60 | + | |
61 | +--- | |
62 | + | |
63 | +## 2. Installation & Setup | |
64 | + | |
65 | +### Installing via pip | |
66 | + | |
67 | +```bash | |
68 | +pip install justapi | |
69 | +``` | |
70 | + | |
71 | +To install optional dependencies (e.g. Pydantic v2, Jinja2): | |
72 | + | |
73 | +```bash | |
74 | +pip install "justapi[full]" | |
75 | +``` | |
76 | + | |
77 | +### Building from Source | |
78 | + | |
79 | +Requirements: **Python 3.11+** and **Rust 1.85+**. | |
80 | + | |
81 | +```bash | |
82 | +git clone https://github.com/swadhinbiswas/JustAPI.git | |
83 | +cd JustAPI | |
84 | +maturin develop --release --manifest-path crates/justapi-py/Cargo.toml | |
85 | +``` | |
86 | + | |
87 | +--- | |
88 | + | |
89 | +## 3. Quickstart & Project Generator | |
90 | + | |
91 | +### Hello World Application (`app.py`) | |
92 | + | |
93 | +```python | |
94 | +from justapi import JustAPIApp | |
95 | + | |
96 | +app = JustAPIApp(title="My First JustAPI App", version="0.1.0") | |
97 | + | |
98 | + | |
99 | +@app.get("/") | |
100 | +def root(request): | |
101 | + return {"message": "Welcome to JustAPI!"} | |
102 | + | |
103 | + | |
104 | +@app.get("/items/{item_id}") | |
105 | +def read_item(request, item_id: int): | |
106 | + return {"item_id": item_id, "status": "active"} | |
107 | +``` | |
108 | + | |
109 | +Run directly in Python: | |
110 | + | |
111 | +```bash | |
112 | +python app.py | |
113 | +``` | |
114 | + | |
115 | +### Interactive Project Scaffolder CLI | |
116 | + | |
117 | +JustAPI includes a project generator supporting multiple database backends and API architecture templates: | |
118 | + | |
119 | +```bash | |
120 | +# Interactive project generator (prompts for DB and API protocol choice): | |
121 | +justapi create my_app | |
122 | + | |
123 | +# Or pass explicit configuration flags: | |
124 | +justapi create analytics_service --db duckdb --api-type rest | |
125 | +justapi create graph_service --db postgres --api-type graphql | |
126 | +justapi create rpc_service --db redis --api-type grpc | |
127 | +justapi create jsonrpc_service --db sqlite --api-type jsonrpc | |
128 | +``` | |
129 | + | |
130 | +### Hot-Reload Development Server | |
131 | + | |
132 | +```bash | |
133 | +cd my_app | |
134 | +justapi serve --reload | |
135 | +``` | |
136 | + | |
137 | +--- | |
138 | + | |
139 | +## 4. Routing & Request Handling | |
140 | + | |
141 | +### HTTP Method Decorators | |
142 | + | |
143 | +JustAPI supports standard HTTP verb decorators: | |
144 | + | |
145 | +```python | |
146 | +@app.get("/users") | |
147 | +def list_users(request): | |
148 | + ... | |
149 | + | |
150 | +@app.post("/users") | |
151 | +def create_user(request): | |
152 | + ... | |
153 | + | |
154 | +@app.put("/users/{user_id}") | |
155 | +def update_user(request, user_id: int): | |
156 | + ... | |
157 | + | |
158 | +@app.patch("/users/{user_id}") | |
159 | +def patch_user(request, user_id: int): | |
160 | + ... | |
161 | + | |
162 | +@app.delete("/users/{user_id}") | |
163 | +def delete_user(request, user_id: int): | |
164 | + ... | |
165 | +``` | |
166 | + | |
167 | +### Sub-Routers (`APIRouter`) | |
168 | + | |
169 | +Organize routes across modular files: | |
170 | + | |
171 | +```python | |
172 | +# app/routers/products.py | |
173 | +from justapi import APIRouter | |
174 | + | |
175 | +router = APIRouter(prefix="/products", tags=["Products"]) | |
176 | + | |
177 | +@router.get("/") | |
178 | +def list_products(request): | |
179 | + return [{"id": 1, "name": "Rust Book"}] | |
180 | +``` | |
181 | + | |
182 | +Include routers in the main application: | |
183 | + | |
184 | +```python | |
185 | +# app/main.py | |
186 | +from justapi import JustAPIApp | |
187 | +from app.routers.products import router as products_router | |
188 | + | |
189 | +app = JustAPIApp() | |
190 | +app.include_router(products_router) | |
191 | +``` | |
192 | + | |
193 | +--- | |
194 | + | |
195 | +## 5. Schemas & Request Validation | |
196 | + | |
197 | +### Defining Schemas (`justapi.Schema`) | |
198 | + | |
199 | +JustAPI provides a lightweight, type-safe schema class: | |
200 | + | |
201 | +```python | |
202 | +from justapi import JustAPIApp, Schema | |
203 | +from pydantic import Field | |
204 | + | |
205 | +app = JustAPIApp() | |
206 | + | |
207 | + | |
208 | +class ItemCreate(Schema): | |
209 | + name: str = Field(..., min_length=1, description="Item name") | |
210 | + price: float = Field(..., gt=0, description="Item price") | |
211 | + qty: int = Field(0, ge=0, description="Stock quantity") | |
212 | + | |
213 | + | |
214 | +@app.post("/items", body_schema=ItemCreate) | |
215 | +def create_item(request): | |
216 | + data = request.json() | |
217 | + return {"message": "Item validated & created", "item": data} | |
218 | +``` | |
219 | + | |
220 | +### Native Rust Fast-Path (`native=True`) | |
221 | + | |
222 | +For ultimate throughput (**724,000+ RPS**), pass `native=True` to execute body validation and response generation **100% inside Rust** without touching Python: | |
223 | + | |
224 | +```python | |
225 | +@app.post("/fast-items", body_schema=ItemCreate, native=True) | |
226 | +def fast_create_item(request): | |
227 | + return {"status": "ok"} | |
228 | +``` | |
229 | + | |
230 | +--- | |
231 | + | |
232 | +## 6. Multi-Protocol APIs | |
233 | + | |
234 | +JustAPI natively supports four API architecture styles out of the box: | |
235 | + | |
236 | +### 1. REST API (OpenAPI 3.1 & Docs) | |
237 | +Auto-generated interactive API documentation available at: | |
238 | +* **Swagger UI:** `http://localhost:8080/docs` | |
239 | +* **ReDoc:** `http://localhost:8080/redoc` | |
240 | +* **Scalar UI:** `http://localhost:8080/scalar` | |
241 | +* **OpenAPI Spec:** `http://localhost:8080/openapi.json` | |
242 | + | |
243 | +### 2. GraphQL API | |
244 | +Mount GraphiQL UI and execution engine in one line: | |
245 | + | |
246 | +```python | |
247 | +app.graphql(path="/graphql") | |
248 | +# Interactive GraphiQL UI available at http://localhost:8080/graphql | |
249 | +``` | |
250 | + | |
251 | +### 3. gRPC / Protobuf RPC | |
252 | +High-performance RPC endpoints: | |
253 | + | |
254 | +```python | |
255 | +class RPCRequest(Schema): | |
256 | + method: str | |
257 | + params: dict | |
258 | + | |
259 | +@app.post("/rpc", body_schema=RPCRequest) | |
260 | +def handle_rpc(request): | |
261 | + data = request.json() | |
262 | + return {"status": "OK", "method": data["method"]} | |
263 | +``` | |
264 | + | |
265 | +### 4. JSON-RPC 2.0 Protocol | |
266 | +Standard JSON-RPC 2.0 endpoint: | |
267 | + | |
268 | +```python | |
269 | +class JSONRPCRequest(Schema): | |
270 | + jsonrpc: str = "2.0" | |
271 | + method: str | |
272 | + params: list | dict = [] | |
273 | + id: int | str = 1 | |
274 | + | |
275 | +@app.post("/jsonrpc", body_schema=JSONRPCRequest) | |
276 | +def handle_jsonrpc(request): | |
277 | + req = request.json() | |
278 | + if req["method"] == "ping": | |
279 | + return {"jsonrpc": "2.0", "result": "pong", "id": req["id"]} | |
280 | +``` | |
281 | + | |
282 | +--- | |
283 | + | |
284 | +## 7. Database Backend & Fast-Path I/O | |
285 | + | |
286 | +JustAPI provides a Rust-native connection pool manager (`app.db` / `AnyPool`) achieving **177,000+ RPS** query reads. | |
287 | + | |
288 | +### Configuring Database Connection | |
289 | + | |
290 | +```python | |
291 | +app = JustAPIApp() | |
292 | + | |
293 | +# Wire PostgreSQL | |
294 | +app.set_database( | |
295 | + "postgres://postgres:password@localhost:5432/mydb", | |
296 | + init_sql=""" | |
297 | + CREATE TABLE IF NOT EXISTS items ( | |
298 | + id SERIAL PRIMARY KEY, | |
299 | + name TEXT NOT NULL, | |
300 | + qty INT DEFAULT 0 | |
301 | + ) | |
302 | + """, | |
303 | +) | |
304 | + | |
305 | +@app.get("/items") | |
306 | +def list_items(request): | |
307 | + # Runs inside Rust database connection pool | |
308 | + return app.db.query("SELECT * FROM items ORDER BY id") | |
309 | + | |
310 | +@app.post("/items") | |
311 | +def add_item(request): | |
312 | + data = request.json() | |
313 | + app.db.execute("INSERT INTO items (name, qty) VALUES ($1, $2)", [data["name"], data["qty"]]) | |
314 | + return {"message": "Inserted"} | |
315 | +``` | |
316 | + | |
317 | +### Supported Database Engines | |
318 | + | |
319 | +| Engine | Scheme | Library / Driver | Usage | | |
320 | +|---|---|---|---| | |
321 | +| **PostgreSQL** | `postgres://` | Rust `sqlx-postgres` | High-throughput relational OLTP | | |
322 | +| **MySQL** | `mysql://` | Rust `sqlx-mysql` | Scalable relational OLTP | | |
323 | +| **SQLite** | `sqlite://` | Rust `sqlx-sqlite` | Zero-config embedded DB | | |
324 | +| **DuckDB** | `duckdb://` | Python `duckdb` | Fast in-process analytical SQL & Parquet | | |
325 | +| **ClickHouse**| `clickhouse://`| Python `clickhouse-driver` | High-volume analytical column store | | |
326 | +| **MongoDB** | `mongodb://` | Python `pymongo` | NoSQL document storage | | |
327 | +| **Redis** | `redis://` | Python `redis` | Key-value caching & rate limiting | | |
328 | + | |
329 | +--- | |
330 | + | |
331 | +## 8. Dependency Injection & Middleware | |
332 | + | |
333 | +### Dependency Injection (`Depends`) | |
334 | + | |
335 | +Declare reusable dependencies: | |
336 | + | |
337 | +```python | |
338 | +from justapi import JustAPIApp, Depends, HTTPException | |
339 | + | |
340 | +app = JustAPIApp() | |
341 | + | |
342 | +def verify_token(request): | |
343 | + token = request.headers.get("authorization") | |
344 | + if not token or token != "Bearer secret-token": | |
345 | + raise HTTPException(status_code=401, detail="Invalid token") | |
346 | + return {"user_id": 42, "role": "admin"} | |
347 | + | |
348 | +@app.get("/protected") | |
349 | +def protected_route(request, user: dict = Depends(verify_token)): | |
350 | + return {"message": "Access granted", "user": user} | |
351 | +``` | |
352 | + | |
353 | +### Starlette / FastAPI Middleware Parity | |
354 | + | |
355 | +Add middleware using standard Starlette/FastAPI syntax: | |
356 | + | |
357 | +```python | |
358 | +# Configure CORS | |
359 | +app.add_cors( | |
360 | + allow_origins=["https://example.com"], | |
361 | + allow_methods=["GET", "POST", "PUT", "DELETE"], | |
362 | + allow_headers=["*"], | |
363 | + allow_credentials=True, | |
364 | +) | |
365 | + | |
366 | +# Custom HTTP middleware | |
367 | +@app.middleware("http") | |
368 | +def custom_middleware(request, call_next): | |
369 | + print(f"Before request: {request.path}") | |
370 | + response = call_next(request) | |
371 | + print(f"After request: status {response.status_code}") | |
372 | + return response | |
373 | +``` | |
374 | + | |
375 | +--- | |
376 | + | |
377 | +## 9. WebSockets, SSE & Real-Time Streaming | |
378 | + | |
379 | +### WebSockets | |
380 | + | |
381 | +Full-duplex WebSocket communication: | |
382 | + | |
383 | +```python | |
384 | +@app.websocket("/ws") | |
385 | +async def websocket_handler(ws): | |
386 | + await ws.accept() | |
387 | + while True: | |
388 | + msg = await ws.receive_text() | |
389 | + await ws.send_text(f"Echo: {msg}") | |
390 | +``` | |
391 | + | |
392 | +### Server-Sent Events (SSE) | |
393 | + | |
394 | +Stream events to browser clients: | |
395 | + | |
396 | +```python | |
397 | +import asyncio | |
398 | +from justapi.responses import StreamingResponse | |
399 | + | |
400 | +@app.get("/events") | |
401 | +async def event_stream(request): | |
402 | + async def generate(): | |
403 | + for i in range(10): | |
404 | + yield f"data: Event message #{i}\n\n" | |
405 | + await asyncio.sleep(1) | |
406 | + return StreamingResponse(generate(), media_type="text/event-stream") | |
407 | +``` | |
408 | + | |
409 | +--- | |
410 | + | |
411 | +## 10. Resilience & Security Safeguards | |
412 | + | |
413 | +JustAPI incorporates enterprise resilience primitives directly inside the Rust engine: | |
414 | + | |
415 | +### Circuit Breakers (`enable_circuit_breaker`) | |
416 | + | |
417 | +Automatically open circuit breakers when failure thresholds are exceeded: | |
418 | + | |
419 | +```python | |
420 | +# Open circuit after 5 consecutive failures, reset after 10,000 ms | |
421 | +app.enable_circuit_breaker(failure_threshold=5, reset_timeout_ms=10000) | |
422 | +``` | |
423 | + | |
424 | +### Request Coalescing (`enable_request_coalescing`) | |
425 | + | |
426 | +Deduplicate concurrent identical requests so only 1 request hits the backend while all callers share the response: | |
427 | + | |
428 | +```python | |
429 | +app.enable_request_coalescing(headers=["accept"]) | |
430 | +``` | |
431 | + | |
432 | +### Security Headers (`enable_secure_headers`) | |
433 | + | |
434 | +Apply `X-Content-Type-Options`, `X-Frame-Options`, `X-XSS-Protection`, and `Content-Security-Policy`: | |
435 | + | |
436 | +```python | |
437 | +app.enable_secure_headers(with_hsts=True) | |
438 | +``` | |
439 | + | |
440 | +--- | |
441 | + | |
442 | +## 11. Observability & Monitoring | |
443 | + | |
444 | +### OpenTelemetry Distributed Tracing | |
445 | + | |
446 | +Initialize OTLP gRPC span exporter: | |
447 | + | |
448 | +```python | |
449 | +from justapi.tracing import init_otlp_tracing, shutdown_tracing | |
450 | + | |
451 | +init_otlp_tracing(endpoint="http://localhost:4317", service_name="my_service") | |
452 | +``` | |
453 | + | |
454 | +### Prometheus Metrics & Health Probes | |
455 | + | |
456 | +Built-in system endpoints: | |
457 | +* `/health` β Returns JSON application status | |
458 | +* `/ready` β Executes readiness probes | |
459 | +* `/live` β Executes liveness probes | |
460 | +* `/metrics` β Prometheus metrics text format | |
461 | + | |
462 | +### OpenTelemetry Compose Stack | |
463 | + | |
464 | +Project templates generated by `justapi create` include `docker-compose.otel.yml` for Jaeger, Prometheus, and Grafana. | |
465 | + | |
466 | +--- | |
467 | + | |
468 | +## 12. Production Deployment & CI/CD | |
469 | + | |
470 | +### Multi-Worker CLI Execution | |
471 | + | |
472 | +Utilize all available CPU cores: | |
473 | + | |
474 | +```bash | |
475 | +justapi serve --host 0.0.0.0 --port 8080 --workers 4 | |
476 | +``` | |
477 | + | |
478 | +### Optimized Dockerfile | |
479 | + | |
480 | +```dockerfile | |
481 | +FROM python:3.12-slim | |
482 | + | |
483 | +WORKDIR /app | |
484 | + | |
485 | +COPY requirements.txt . | |
486 | +RUN pip install --no-cache-dir -r requirements.txt | |
487 | + | |
488 | +COPY . . | |
489 | + | |
490 | +EXPOSE 8080 | |
491 | +ENV HOST=0.0.0.0 PORT=8080 | |
492 | + | |
493 | +CMD ["justapi", "serve", "--host", "0.0.0.0", "--port", "8080"] | |
494 | +``` | |
495 | + | |
496 | +--- | |
497 | + | |
498 | +*JustAPI Runtime Manual β Version 2.0.0* | |
0 | 499 | |
βΌdocs/index.md
+10-2
| @@ -31,9 +31,17 @@ JustAPI obliterates traditional frameworks under load. Measured on an Intel Core | ||
31 | 31 | |
32 | 32 | *(Note: JustAPI achieves these numbers in a single process without multi-worker fan-out.)* |
33 | 33 | |
34 | +## Master Developer Handbook | |
35 | + | |
36 | +For a comprehensive end-to-end tutorial, architecture deep-dive, database guides, and production deployment handbook: | |
37 | + | |
38 | +π **[Read the JustAPI Developer Handbook (HANDBOOK.md)](HANDBOOK.md)** | |
39 | + | |
34 | 40 | ## Where to go next? |
35 | 41 | |
42 | +- **[Developer Handbook](HANDBOOK.md):** Complete end-to-end tutorial & master reference. | |
36 | 43 | - **[Getting Started](getting_started.md):** Build your first JustAPI application in minutes. |
37 | 44 | - **[Migrating from FastAPI](migrating_from_fastapi.md):** See how easy it is to switch your existing FastAPI project to JustAPI. |
38 | -- **[API Reference](api_reference.md):** Detailed information about all the classes and functions available. | |
39 | -- **[Plugins](plugins.md):** Learn how to extend JustAPI using Python or Rust. | |
45 | +- **[API Reference](api_reference.md):** Detailed documentation of classes, functions, and kwargs. | |
46 | +- **[Plugins](plugins.md):** Learn how to extend JustAPI using Python or Rust WASM plugins. | |
47 | + | |
40 | 48 | |