p3c-f: add Routing, APIRouter, Request, Responses API reference pages

swadhinbiswas committed 3 months ago
29908fb
1 parent ddf0c91
commit 29908fb
4 files changed
+464 -0
▼docs_site/src/content/docs/api-reference/apirouter.md
+92-0
1
+---
2
+title: APIRouter
3
+description: Modular router for grouping related routes in separate files.
4
+---
5
+
6
+`APIRouter` lets you organize routes into modular groups, then include them in the main application.
7
+
8
+## Constructor
9
+
10
+```python
11
+from justapi import APIRouter
12
+
13
+router = APIRouter(
14
+ prefix="/api/v1",
15
+ tags=["API v1"],
16
+)
17
+```
18
+
19
+### Parameters
20
+
21
+| Parameter | Type | Default | Description |
22
+|---|---|---|---|
23
+| `prefix` | `str` | `""` | URL prefix applied to all routes |
24
+| `tags` | `list[str]` | `None` | OpenAPI tags for all routes |
25
+
26
+## Methods
27
+
28
+`APIRouter` supports the same route decorators as `JustAPIApp`:
29
+
30
+| Method | Signature |
31
+|---|---|
32
+| `get(path, dependencies, tags)` | Same as `JustAPIApp.get()` |
33
+| `post(path, body_schema, schema, dependencies, tags, native)` | Same as `JustAPIApp.post()` |
34
+| `put(path, body_schema, schema, dependencies, tags, native)` | Same as `JustAPIApp.put()` |
35
+| `patch(path, body_schema, schema, dependencies, tags, native)` | Same as `JustAPIApp.patch()` |
36
+| `delete(path, dependencies, tags)` | Same as `JustAPIApp.delete()` |
37
+| `websocket(path)` | Same as `JustAPIApp.websocket()` |
38
+
39
+## Including Routers
40
+
41
+```python
42
+from justapi import JustAPIApp
43
+from app.routers.users import router as users_router
44
+from app.routers.products import router as products_router
45
+
46
+app = JustAPIApp()
47
+app.include_router(users_router, prefix="/api/v1")
48
+```
49
+
50
+### `include_router()` Parameters
51
+
52
+| Parameter | Type | Default | Description |
53
+|---|---|---|---|
54
+| `router` | `APIRouter` | required | The router to include |
55
+| `prefix` | `str` | `""` | Additional prefix applied on top of the router's own prefix |
56
+
57
+## URL Construction
58
+
59
+The final URL for each route is: `include_router_prefix` + `router.prefix` + `route_path`
60
+
61
+```python
62
+router = APIRouter(prefix="/users")
63
+
64
+@router.get("/{user_id}")
65
+def get_user(request, user_id: int): ...
66
+
67
+app.include_router(router, prefix="/api/v1")
68
+
69
+# Final URL: /api/v1/users/{user_id}
70
+```
71
+
72
+## Router-Level Dependencies
73
+
74
+```python
75
+from justapi import APIRouter, Depends, Header, HTTPException
76
+
77
+def require_token(authorization: str = Header(...)):
78
+ if not authorization.startswith("Bearer "):
79
+ raise HTTPException(401)
80
+
81
+admin_router = APIRouter(prefix="/admin", tags=["Admin"])
82
+
83
+@admin_router.get("/users", dependencies=[Depends(require_token)])
84
+def list_users(request):
85
+ return [{"id": 1}]
86
+```
87
+
88
+## See Also
89
+
90
+- [Routing API](/api-reference/routing/) — Route decorator reference
91
+- [JustAPIApp](/api-reference/justapiapp/) — Main application reference
92
+- [Routing & Sub-routers Tutorial](/tutorials/routing-subrouters/) — Step-by-step guide
0
93
▼docs_site/src/content/docs/api-reference/request.md
+124-0
1
+---
2
+title: Request Object
3
+description: Access incoming HTTP request data through the Request object.
4
+---
5
+
6
+The `Request` object provides zero-copy access to the incoming HTTP request. It's passed as the first parameter to every route handler.
7
+
8
+## Request Properties
9
+
10
+```python
11
+@app.get("/items/{item_id}")
12
+def handler(request, item_id: int):
13
+ method = request.method # str: GET, POST, etc.
14
+ path = request.path # str: /items/42
15
+ url = request.url # URL object
16
+ headers = request.headers # Headers object
17
+ query_params = request.query_params # QueryParams object
18
+ state = request.state # State object (per-request storage)
19
+```
20
+
21
+### `request.method`
22
+
23
+The HTTP method as a string: `"GET"`, `"POST"`, `"PUT"`, `"PATCH"`, `"DELETE"`.
24
+
25
+### `request.path`
26
+
27
+The URL path: `"/items/42"`.
28
+
29
+### `request.url`
30
+
31
+A `URL` object with:
32
+
33
+| Attribute | Type | Description |
34
+|---|---|---|
35
+| `scheme` | `str` | `"http"` or `"https"` |
36
+| `host` | `str` | Hostname |
37
+| `port` | `int` | Port number |
38
+| `path` | `str` | URL path |
39
+
40
+### `request.headers`
41
+
42
+A `Headers` object providing dict-like access to HTTP headers. All header names are lowercased.
43
+
44
+```python
45
+@app.get("/")
46
+def handler(request):
47
+ user_agent = request.headers.get("user-agent")
48
+ content_type = request.headers.get("content-type")
49
+ auth = request.headers.get("authorization")
50
+ return {"ua": user_agent}
51
+```
52
+
53
+| Method | Description |
54
+|---|---|
55
+| `.get(key)` | Get header value (case-insensitive) |
56
+| `.items()` | Iterate over `(key, value)` pairs |
57
+
58
+### `request.query_params`
59
+
60
+A `QueryParams` object providing dict-like access to query string parameters.
61
+
62
+```python
63
+@app.get("/search")
64
+def handler(request):
65
+ q = request.query_params.get("q")
66
+ page = request.query_params.get("page", "1")
67
+ return {"query": q, "page": int(page)}
68
+```
69
+
70
+| Method | Description |
71
+|---|---|
72
+| `.get(key, default)` | Get query parameter |
73
+| `.items()` | Iterate over `(key, value)` pairs |
74
+
75
+### `request.state`
76
+
77
+A `State` object for per-request storage. Useful for passing data between middleware and handlers:
78
+
79
+```python
80
+@app.middleware("http")
81
+def set_user(request, call_next):
82
+ request.state.user = {"id": 42, "role": "admin"}
83
+ return call_next(request)
84
+
85
+@app.get("/profile")
86
+def profile(request):
87
+ user = request.state.user
88
+ return {"user_id": user["id"]}
89
+```
90
+
91
+## Request Body Methods
92
+
93
+```python
94
+@app.post("/data")
95
+def handler(request):
96
+ # Parse JSON body
97
+ data = request.json() # dict | list
98
+
99
+ # Raw bytes
100
+ body = request.body() # bytes
101
+
102
+ # Parse form data
103
+ form = request.form() # dict
104
+```
105
+
106
+| Method | Returns | Description |
107
+|---|---|---|
108
+| `request.json()` | `dict` or `list` | Parse body as JSON |
109
+| `request.body()` | `bytes` | Raw request body bytes |
110
+| `request.form()` | `dict` | Parse as URL-encoded form |
111
+
112
+## Zero-Copy Architecture
113
+
114
+The `Request` object uses PyO3's buffer protocol to provide **zero-copy** access to request data:
115
+
116
+- Headers and query parameters are parsed in Rust and exposed as read-only memory views
117
+- No data is copied between Rust and Python
118
+- Body reading triggers a one-time copy from the network buffer
119
+
120
+## See Also
121
+
122
+- [Response Classes](/api-reference/responses/) — Returning responses
123
+- [Dependency Injection](/api-reference/dependency-injection/) — Extracting request components with Depends
124
+- [Zero-GIL Architecture](/advanced/zero-gil-architecture/) — How the GIL is released during request processing
0
125
▼docs_site/src/content/docs/api-reference/responses.md
+130-0
1
+---
2
+title: Response Classes
3
+description: Return responses with different content types, status codes, and streaming capabilities.
4
+---
5
+
6
+JustAPI provides several response classes optimized for zero-copy data transfer from Rust to Python.
7
+
8
+## `Response`
9
+
10
+Base response class:
11
+
12
+```python
13
+from justapi.responses import Response
14
+
15
+return Response(
16
+ content="Hello",
17
+ status_code=200,
18
+ headers={"X-Custom": "value"},
19
+)
20
+```
21
+
22
+| Parameter | Type | Default | Description |
23
+|---|---|---|---|
24
+| `content` | `str` | `""` | Response body text |
25
+| `status_code` | `int` | `200` | HTTP status code |
26
+| `headers` | `dict` | `None` | Additional headers |
27
+
28
+## `JSONResponse`
29
+
30
+Automatically serializes a Python object to JSON using Rust's `serde_json`:
31
+
32
+```python
33
+from justapi.responses import JSONResponse
34
+
35
+return JSONResponse({"message": "Hello", "items": [1, 2, 3]})
36
+```
37
+
38
+| Parameter | Type | Default | Description |
39
+|---|---|---|---|
40
+| `content` | `dict` or `list` | required | Python object to serialize |
41
+
42
+## `HTMLResponse`
43
+
44
+Sets `Content-Type: text/html`:
45
+
46
+```python
47
+from justapi.responses import HTMLResponse
48
+
49
+return HTMLResponse("<h1>Hello</h1>")
50
+```
51
+
52
+## `PlainTextResponse`
53
+
54
+Sets `Content-Type: text/plain`:
55
+
56
+```python
57
+from justapi.responses import PlainTextResponse
58
+
59
+return PlainTextResponse("Hello, World!")
60
+```
61
+
62
+## `RedirectResponse`
63
+
64
+Returns an HTTP redirect:
65
+
66
+```python
67
+from justapi.responses import RedirectResponse
68
+
69
+return RedirectResponse(
70
+ url="https://example.com",
71
+ status_code=307, # Temporary redirect
72
+)
73
+```
74
+
75
+| Parameter | Type | Default | Description |
76
+|---|---|---|---|
77
+| `url` | `str` | required | Redirect target URL |
78
+| `status_code` | `int` | `307` | Redirect status (307, 308, 301, 302) |
79
+
80
+## `StreamingResponse`
81
+
82
+Streams content using a Python generator:
83
+
84
+```python
85
+from justapi.responses import StreamingResponse
86
+import asyncio
87
+
88
+
89
+@app.get("/stream")
90
+async def stream(request):
91
+ async def generate():
92
+ for i in range(100):
93
+ yield f"data: {i}\n\n"
94
+ await asyncio.sleep(0.1)
95
+
96
+ return StreamingResponse(generate(), media_type="text/plain")
97
+```
98
+
99
+| Parameter | Type | Default | Description |
100
+|---|---|---|---|
101
+| `generator` | async generator | required | Content generator |
102
+| `media_type` | `str` | `"text/plain"` | Content-Type header |
103
+
104
+## Dict Return (Shortcut)
105
+
106
+When a route handler returns a plain dict, it's automatically converted to `JSONResponse`:
107
+
108
+```python
109
+@app.get("/")
110
+def handler(request):
111
+ return {"message": "Hello"} # Equivalent to JSONResponse(...)
112
+```
113
+
114
+## Setting Status Codes
115
+
116
+Use tuples or the `status` key in the response dict for non-200 status codes:
117
+
118
+```python
119
+@app.post("/items")
120
+def create_item(request):
121
+ return {"status": 201, "body": {"id": 1, "name": "Item"}}
122
+```
123
+
124
+The `status` key sets the HTTP status code, while `body` contains the response body.
125
+
126
+## See Also
127
+
128
+- [Request Object](/api-reference/request/) — Accessing request data
129
+- [Streaming Output](/advanced/streaming-output/) — Validated streaming with `@app.stream_json`
130
+- [Error Handling](/tutorials/error-handling/) — Error response patterns
0
131
▼docs_site/src/content/docs/api-reference/routing.md
+118-0
1
+---
2
+title: Routing API
3
+description: Complete reference for HTTP method decorators and route registration.
4
+---
5
+
6
+## Method Decorators
7
+
8
+Each HTTP method decorator registers a route handler in the radix-trie router.
9
+
10
+### `@app.get()`
11
+
12
+```python
13
+@app.get(
14
+ path: str,
15
+ dependencies: list | None = None,
16
+ tags: list[str] | None = None,
17
+)
18
+```
19
+
20
+### `@app.post()`
21
+
22
+```python
23
+@app.post(
24
+ path: str,
25
+ body_schema: type[Schema] | None = None,
26
+ schema: type[Schema] | None = None,
27
+ dependencies: list | None = None,
28
+ tags: list[str] | None = None,
29
+ native: bool = False,
30
+)
31
+```
32
+
33
+### `@app.put()`
34
+
35
+```python
36
+@app.put(
37
+ path: str,
38
+ body_schema: type[Schema] | None = None,
39
+ schema: type[Schema] | None = None,
40
+ dependencies: list | None = None,
41
+ tags: list[str] | None = None,
42
+ native: bool = False,
43
+)
44
+```
45
+
46
+### `@app.patch()`
47
+
48
+```python
49
+@app.patch(
50
+ path: str,
51
+ body_schema: type[Schema] | None = None,
52
+ schema: type[Schema] | None = None,
53
+ dependencies: list | None = None,
54
+ tags: list[str] | None = None,
55
+ native: bool = False,
56
+)
57
+```
58
+
59
+### `@app.delete()`
60
+
61
+```python
62
+@app.delete(
63
+ path: str,
64
+ dependencies: list | None = None,
65
+ tags: list[str] | None = None,
66
+)
67
+```
68
+
69
+## Route Parameters
70
+
71
+| Parameter | Applies To | Type | Description |
72
+|---|---|---|---|
73
+| `path` | All | `str` | URL pattern with `{param}` placeholders |
74
+| `body_schema` | POST, PUT, PATCH | `Schema` subclass | Validate body against this schema in Rust |
75
+| `schema` | POST, PUT, PATCH | `Schema` subclass | Alias for `body_schema` |
76
+| `dependencies` | All | `list[Depends]` | Route-level dependency injection |
77
+| `tags` | All | `list[str]` | OpenAPI operation tags |
78
+| `native` | POST, PUT, PATCH | `bool` | Execute entirely in Rust (724k+ RPS) |
79
+
80
+## Path Parameter Types
81
+
82
+| Type | Example | Valid Input |
83
+|---|---|---|
84
+| `str` | `/hello/{name}` | Any string |
85
+| `int` | `/items/{id}` | `42` |
86
+| `float` | `/price/{val}` | `19.99` |
87
+| `bool` | `/flag/{val}` | `true`, `1`, `yes` |
88
+| `UUID` | `/users/{uid}` | `550e8400-...` |
89
+| `datetime` | `/events/{ts}` | `2026-07-24T12:00:00Z` |
90
+
91
+## Native Fast Path
92
+
93
+When `native=True`, the handler executes entirely in Rust:
94
+
95
+- Request body is validated against the schema in Rust
96
+- The handler runs as a Rust callback
97
+- The response is serialized in Rust
98
+- Zero GIL acquisition for the entire request lifecycle
99
+
100
+```python
101
+@app.post("/fast-items", body_schema=ItemSchema, native=True)
102
+def create_item(request):
103
+ return {"status": "ok"}
104
+```
105
+
106
+## Route Resolution
107
+
108
+Routes are resolved in O(1) time using a radix-trie (matchit). The route-lookup cache memoizes repeated lookups for the same path.
109
+
110
+## OpenAPI Generation
111
+
112
+All registered routes automatically generate OpenAPI 3.1 documentation available at `/openapi.json`, `/docs` (Swagger UI), `/redoc` (ReDoc), and `/scalar` (Scalar UI).
113
+
114
+## See Also
115
+
116
+- [APIRouter](/api-reference/apirouter/) — Modular route grouping
117
+- [JustAPIApp](/api-reference/justapiapp/) — App configuration reference
118
+- [Native Fast Path](/advanced/native-fast-path/) — Deep dive on Rust-native execution
0
119