p2b: add Path & Query Parameters tutorial — type conversion table, Path/Query options, curl examples

swadhinbiswas committed 3 months ago
b22d2ac
1 parent 2b5b9ce
commit b22d2ac
1 file changed
+166 -0
▼docs_site/src/content/docs/tutorials/path-query-params.md
+166-0
1
+---
2
+title: Path & Query Parameters
3
+description: Declare and type-validate path and query parameters in JustAPI.
4
+---
5
+
6
+Path and query parameters let you extract variables from the HTTP request URL. JustAPI handles type conversion and validation automatically using Python type hints.
7
+
8
+## Path Parameters
9
+
10
+Path parameters are declared as part of the URL path using `{param_name}` syntax:
11
+
12
+```python
13
+from justapi import JustAPIApp
14
+
15
+app = JustAPIApp()
16
+
17
+
18
+@app.get("/items/{item_id}")
19
+def read_item(request, item_id: int):
20
+ return {"item_id": item_id}
21
+```
22
+
23
+```bash
24
+curl http://127.0.0.1:8000/items/42
25
+# Output: {"item_id":42}
26
+```
27
+
28
+### Type Conversion
29
+
30
+JustAPI automatically converts path parameters based on type hints. If conversion fails, it returns **422 Unprocessable Entity** without invoking your handler:
31
+
32
+```python
33
+from uuid import UUID
34
+
35
+
36
+@app.get("/users/{user_id}")
37
+def read_user(request, user_id: UUID):
38
+ return {"user_id": str(user_id)}
39
+```
40
+
41
+```bash
42
+curl http://127.0.0.1:8000/users/550e8400-e29b-41d4-a716-446655440000
43
+# Output: {"user_id":"550e8400-e29b-41d4-a716-446655440000"}
44
+
45
+curl http://127.0.0.1:8000/users/not-a-uuid
46
+# Output: {"detail":"validation error"}
47
+```
48
+
49
+### Supported Types
50
+
51
+| Type | Example | Valid Input | Invalid Input |
52
+|---|---|---|---|
53
+| `int` | `/items/{id}` | `42` | `abc` → 422 |
54
+| `float` | `/price/{val}` | `19.99` | `abc` → 422 |
55
+| `str` | `/hello/{name}` | any string | — |
56
+| `bool` | `/flag/{val}` | `true`, `1`, `yes` | `maybe` → 422 |
57
+| `UUID` | `/users/{uid}` | `550e8400-...` | `bad-uuid` → 422 |
58
+| `datetime` | `/events/{ts}` | `2026-07-24T12:00:00Z` | `not-a-date` → 422 |
59
+
60
+## Query Parameters
61
+
62
+Query parameters are extracted from the URL query string (`?key=value&key2=value2`). They're declared as function parameters with default values:
63
+
64
+```python
65
+from typing import Optional
66
+
67
+
68
+@app.get("/items/")
69
+def list_items(
70
+ request,
71
+ skip: int = 0,
72
+ limit: int = 10,
73
+ q: Optional[str] = None,
74
+):
75
+ return {"skip": skip, "limit": limit, "q": q}
76
+```
77
+
78
+```bash
79
+curl "http://127.0.0.1:8000/items/?skip=0&limit=5&q=search"
80
+# Output: {"skip":0,"limit":5,"q":"search"}
81
+```
82
+
83
+### Optional vs Required
84
+
85
+Parameters with default values are optional query parameters. Parameters without defaults are **required**:
86
+
87
+```python
88
+@app.get("/search/")
89
+def search(request, query: str, page: int = 1):
90
+ # `query` is required (no default)
91
+ # `page` is optional (defaults to 1)
92
+ return {"query": query, "page": page}
93
+```
94
+
95
+```bash
96
+curl "http://127.0.0.1:8000/search/?query=rust"
97
+# Output: {"query":"rust","page":1}
98
+
99
+curl "http://127.0.0.1:8000/search/"
100
+# Output: {"detail":"validation error"} (missing required query)
101
+```
102
+
103
+## Combining Path and Query Parameters
104
+
105
+```python
106
+@app.get("/users/{user_id}/items/")
107
+def list_user_items(
108
+ request,
109
+ user_id: int,
110
+ skip: int = 0,
111
+ limit: int = 10,
112
+):
113
+ return {"user_id": user_id, "skip": skip, "limit": limit}
114
+```
115
+
116
+```bash
117
+curl "http://127.0.0.1:8000/users/42/items/?limit=3"
118
+# Output: {"user_id":42,"skip":0,"limit":3}
119
+```
120
+
121
+## Using `Path()` and `Query()` for Explicit Control
122
+
123
+For more control, use the `Path()` and `Query()` extractors:
124
+
125
+```python
126
+from justapi import Path, Query
127
+
128
+
129
+@app.get("/items/{item_id}")
130
+def read_item(
131
+ request,
132
+ item_id: int = Path(..., description="The item ID"),
133
+ q: str = Query(None, max_length=50, description="Search query"),
134
+):
135
+ return {"item_id": item_id, "q": q}
136
+```
137
+
138
+### `Path()` Options
139
+
140
+| Parameter | Type | Description |
141
+|---|---|---|
142
+| `default` | any | Default value (`...` means required) |
143
+| `description` | str | Field description for OpenAPI docs |
144
+
145
+### `Query()` Options
146
+
147
+| Parameter | Type | Description |
148
+|---|---|---|
149
+| `default` | any | Default value |
150
+| `description` | str | Field description for OpenAPI docs |
151
+| `max_length` | int | Maximum string length |
152
+| `min_length` | int | Minimum string length |
153
+| `regex` | str | Regular expression pattern |
154
+
155
+## How It Works Internally
156
+
157
+1. JustAPI's radix-trie router (matchit) extracts path parameters during route matching — O(1) time
158
+2. Type conversion runs in Rust before Python is called
159
+3. Query parameters are parsed in Rust via `serde_urlencoded`
160
+4. Invalid types return 422 without GIL acquisition
161
+
162
+## Next Steps
163
+
164
+- [Request Body & Validation](/tutorials/request-body/) — Validate JSON request bodies
165
+- [Dependency Injection](/tutorials/dependency-injection/) — Extract parameters with Depends
166
+- [Error Handling](/tutorials/error-handling/) — Custom error responses
0
167