p2a: add Hello World tutorial — step-by-step with code, curl tests, complete app
swadhinbiswas committed 3 months ago
ff3b99a
1 parent 424b08d
commit ff3b99a
3 files changed
+152 -69
Showing 3 changed files+152-65
▼docs_site/src/content/docs/tutorial/databases.md
+0-35
| @@ -1,37 +0,0 @@ | ||
1 | -title: Database Integration (SQL & NoSQL) | |
2 | -description: Connect to PostgreSQL, MySQL, SQLite, DuckDB, ClickHouse, Mongo, and Redis in JustAPI. | |
3 | - | |
4 | -JustAPI provides a Rust-native connection pool manager (`app.db`) that executes SQL queries in Rust with zero GIL lock. | |
5 | - | |
6 | -## PostgreSQL Integration | |
7 | - | |
8 | -```python | |
9 | -from justapi import JustAPIApp | |
10 | - | |
11 | -app = JustAPIApp() | |
12 | -app.set_database( | |
13 | - "postgres://postgres:password@localhost:5432/mydb", | |
14 | - init_sql="CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, name TEXT);" | |
15 | -) | |
16 | - | |
17 | -@app.get("/users") | |
18 | -def get_users(request): | |
19 | - return app.db.query("SELECT * FROM users ORDER BY id") | |
20 | -``` | |
21 | - | |
22 | -## Analytical Databases (DuckDB & ClickHouse) | |
23 | - | |
24 | -```python | |
25 | -import duckdb | |
26 | -from justapi import JustAPIApp | |
27 | - | |
28 | -app = JustAPIApp() | |
29 | -conn = duckdb.connect("analytics.duckdb") | |
30 | - | |
31 | -@app.get("/analytics/sales") | |
32 | -def sales_summary(request): | |
33 | - res = conn.execute("SELECT region, SUM(amount) FROM sales GROUP BY region").fetchall() | |
34 | - return {"summary": res} | |
35 | -``` | |
36 | 0 | |
▼docs_site/src/content/docs/tutorial/path-params.md
+0-30
| @@ -1,32 +0,0 @@ | ||
1 | -title: Path Parameters | |
2 | -description: Declare and type-validate path parameters in JustAPI. | |
3 | - | |
4 | -Path parameters allow you to extract variables directly from the HTTP request URL path. | |
5 | - | |
6 | -## Basic Path Parameters | |
7 | - | |
8 | -```python | |
9 | -from justapi import JustAPIApp | |
10 | - | |
11 | -app = JustAPIApp() | |
12 | - | |
13 | -@app.get("/items/{item_id}") | |
14 | -def read_item(request, item_id: int): | |
15 | - return {"item_id": item_id} | |
16 | -``` | |
17 | - | |
18 | -## Type Conversion & Automatic Validation | |
19 | - | |
20 | -JustAPI automatically converts and validates path parameter types based on Python type hints (`int`, `float`, `str`, `bool`, `UUID`): | |
21 | - | |
22 | -```python | |
23 | -from uuid import UUID | |
24 | - | |
25 | -@app.get("/users/{user_id}") | |
26 | -def read_user(request, user_id: UUID): | |
27 | - return {"user_id": str(user_id)} | |
28 | -``` | |
29 | - | |
30 | -If a client sends `/users/invalid-uuid`, JustAPI returns an automatic **HTTP 422 Unprocessable Entity** JSON error without invoking your Python code. | |
31 | 0 | |
▼docs_site/src/content/docs/tutorials/hello-world.md
+152-0
| @@ -0,0 +1,152 @@ | ||
1 | +--- | |
2 | +title: Hello World in 2 Minutes | |
3 | +description: Build and run your first JustAPI application from scratch. | |
4 | +--- | |
5 | + | |
6 | +This tutorial walks through creating a complete JustAPI application, step by step. By the end, you'll have a running API server with multiple endpoints. | |
7 | + | |
8 | +## Prerequisites | |
9 | + | |
10 | +- Python 3.11+ | |
11 | +- JustAPI installed (`pip install justapi`) | |
12 | + | |
13 | +## 1. Create the App | |
14 | + | |
15 | +Create a file named `main.py`: | |
16 | + | |
17 | +```python | |
18 | +from justapi import JustAPIApp | |
19 | + | |
20 | +app = JustAPIApp(title="Hello World", version="0.1.0") | |
21 | + | |
22 | + | |
23 | +@app.get("/") | |
24 | +def root(request): | |
25 | + return {"message": "Hello, World!"} | |
26 | +``` | |
27 | + | |
28 | +## 2. Run It | |
29 | + | |
30 | +```bash | |
31 | +python main.py | |
32 | +``` | |
33 | + | |
34 | +Expected output: | |
35 | + | |
36 | +``` | |
37 | +[Rust Tokio Runtime] Initialized with 12 worker threads | |
38 | +[Rust Tokio Runtime] Listening on http://127.0.0.1:8000 | |
39 | +[Rust Tokio Runtime] OpenAPI docs at http://127.0.0.1:8000/docs | |
40 | +``` | |
41 | + | |
42 | +## 3. Test It | |
43 | + | |
44 | +```bash | |
45 | +curl http://127.0.0.1:8000/ | |
46 | +``` | |
47 | + | |
48 | +Expected response: | |
49 | + | |
50 | +```json | |
51 | +{"message":"Hello, World!"} | |
52 | +``` | |
53 | + | |
54 | +## 4. Add More Endpoints | |
55 | + | |
56 | +Extend your `main.py` with a parameterized route: | |
57 | + | |
58 | +```python | |
59 | +@app.get("/hello/{name}") | |
60 | +def hello_name(request, name: str): | |
61 | + return {"greeting": f"Hello, {name}!"} | |
62 | +``` | |
63 | + | |
64 | +Test it: | |
65 | + | |
66 | +```bash | |
67 | +curl http://127.0.0.1:8000/hello/JustAPI | |
68 | +# Output: {"greeting":"Hello, JustAPI!"} | |
69 | +``` | |
70 | + | |
71 | +## 5. Add a POST Endpoint | |
72 | + | |
73 | +```python | |
74 | +from pydantic import BaseModel | |
75 | + | |
76 | +class Message(BaseModel): | |
77 | + content: str | |
78 | + author: str | |
79 | + | |
80 | +@app.post("/messages/") | |
81 | +def create_message(request, msg: Message): | |
82 | + return { | |
83 | + "received": msg.content, | |
84 | + "from": msg.author, | |
85 | + "length": len(msg.content), | |
86 | + } | |
87 | +``` | |
88 | + | |
89 | +Test with curl: | |
90 | + | |
91 | +```bash | |
92 | +curl -X POST http://127.0.0.1:8000/messages/ \ | |
93 | + -H "Content-Type: application/json" \ | |
94 | + -d '{"content": "Hello from JustAPI!", "author": "Alice"}' | |
95 | +``` | |
96 | + | |
97 | +Expected response: | |
98 | + | |
99 | +```json | |
100 | +{"received":"Hello from JustAPI!","from":"Alice","length":20} | |
101 | +``` | |
102 | + | |
103 | +## Complete Application | |
104 | + | |
105 | +```python | |
106 | +from justapi import JustAPIApp | |
107 | +from pydantic import BaseModel | |
108 | + | |
109 | +app = JustAPIApp(title="Hello World", version="0.1.0") | |
110 | + | |
111 | + | |
112 | +class Message(BaseModel): | |
113 | + content: str | |
114 | + author: str | |
115 | + | |
116 | + | |
117 | +@app.get("/") | |
118 | +def root(request): | |
119 | + return {"message": "Hello, World!"} | |
120 | + | |
121 | + | |
122 | +@app.get("/hello/{name}") | |
123 | +def hello_name(request, name: str): | |
124 | + return {"greeting": f"Hello, {name}!"} | |
125 | + | |
126 | + | |
127 | +@app.post("/messages/") | |
128 | +def create_message(request, msg: Message): | |
129 | + return { | |
130 | + "received": msg.content, | |
131 | + "from": msg.author, | |
132 | + "length": len(msg.content), | |
133 | + } | |
134 | + | |
135 | + | |
136 | +if __name__ == "__main__": | |
137 | + app.run("127.0.0.1:8000") | |
138 | +``` | |
139 | + | |
140 | +## Key Concepts | |
141 | + | |
142 | +- **`JustAPIApp()`** — Creates your application and initializes the Rust runtime | |
143 | +- **`@app.get()` / `@app.post()`** — Route decorators that register handlers in the radix-trie router | |
144 | +- **Path parameters** — `{name}` in the path becomes a function parameter | |
145 | +- **Pydantic models** — Auto-validated request bodies with zero-copy parsing | |
146 | +- **`app.run()`** — Starts the built-in Rust HTTP server (no uvicorn needed) | |
147 | + | |
148 | +## Next Steps | |
149 | + | |
150 | +- [Path & Query Parameters](/tutorials/path-query-params/) — URL parameters, query strings, type validation | |
151 | +- [Request Body & Validation](/tutorials/request-body/) — Deep dive into schema validation | |
152 | +- [Dependency Injection](/tutorials/dependency-injection/) — Reusable components with Depends | |
0 | 153 | |