AltAPI 1.1__tar.gz → 1.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- altapi-1.2.1/PKG-INFO +194 -0
- altapi-1.2.1/README.md +172 -0
- {altapi-1.1 → altapi-1.2.1}/pyproject.toml +3 -4
- {altapi-1.1 → altapi-1.2.1}/setup.py +3 -3
- altapi-1.2.1/src/AltAPI.egg-info/PKG-INFO +194 -0
- {altapi-1.1 → altapi-1.2.1}/src/altapi/app.py +406 -284
- altapi-1.1/PKG-INFO +0 -34
- altapi-1.1/README.md +0 -12
- altapi-1.1/src/AltAPI.egg-info/PKG-INFO +0 -34
- {altapi-1.1 → altapi-1.2.1}/LICENSE.txt +0 -0
- {altapi-1.1 → altapi-1.2.1}/MANIFEST.in +0 -0
- {altapi-1.1 → altapi-1.2.1}/setup.cfg +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/AltAPI.egg-info/SOURCES.txt +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/AltAPI.egg-info/dependency_links.txt +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/AltAPI.egg-info/requires.txt +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/AltAPI.egg-info/top_level.txt +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/altapi/__init__.py +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/altapi/caching/__init__.py +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/altapi/caching/cache.py +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/altapi/http/__init__.py +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/altapi/http/request.py +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/altapi/http/responses.py +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/altapi/middleware/__init__.py +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/altapi/middleware/middleware.py +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/altapi/router.c +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/altapi/router.pyx +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/altapi/templating/__init__.py +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/altapi/templating/default_templates.py +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/altapi/templating/templates.py +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/altapi/websocket/__init__.py +0 -0
- {altapi-1.1 → altapi-1.2.1}/src/altapi/websocket/ws.py +0 -0
altapi-1.2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: AltAPI
|
|
3
|
+
Version: 1.2.1
|
|
4
|
+
Summary: A simple and fast ASGI microframework for Python with WebSocket support.
|
|
5
|
+
Home-page: https://github.com/amogus-gggy/AltAPI
|
|
6
|
+
Author: amogus-gggy
|
|
7
|
+
Project-URL: Homepage, https://github.com/amogus-gggy/AltAPI
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE.txt
|
|
11
|
+
Requires-Dist: uvicorn[standard]>=0.30.0
|
|
12
|
+
Requires-Dist: anyio>=4.0.0
|
|
13
|
+
Requires-Dist: jinja2>=3.0.0
|
|
14
|
+
Requires-Dist: ujson
|
|
15
|
+
Provides-Extra: dev
|
|
16
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
17
|
+
Requires-Dist: httpx>=0.27.0; extra == "dev"
|
|
18
|
+
Requires-Dist: cython>=3.0.0; extra == "dev"
|
|
19
|
+
Dynamic: home-page
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
Dynamic: requires-python
|
|
22
|
+
|
|
23
|
+
# AltAPI
|
|
24
|
+
|
|
25
|
+
A simple and fast ASGI microframework for Python with WebSocket support.
|
|
26
|
+
|
|
27
|
+
[](https://github.com/amogus-gggy/AltAPI/blob/main/DOCS.md)
|
|
28
|
+
[](https://github.com/fedor444/AltAPI)
|
|
29
|
+
[](LICENSE.txt)
|
|
30
|
+
|
|
31
|
+
## Changelog
|
|
32
|
+
|
|
33
|
+
### v1.2.0
|
|
34
|
+
- Added `workers` parameter to `app.run()` for multi-process support (still unstable sometimes)
|
|
35
|
+
- Added `access_log` parameter to enable/disable request logging
|
|
36
|
+
- GC optimizations now apply to all workers automatically
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install altapi
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Requirements:**
|
|
47
|
+
- Python >= 3.10
|
|
48
|
+
|
|
49
|
+
## Quick Start
|
|
50
|
+
|
|
51
|
+
### Minimal Example
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
from altapi import AltAPI
|
|
55
|
+
from altapi.http import JSONResponse
|
|
56
|
+
|
|
57
|
+
app = AltAPI()
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@app.get("/")
|
|
61
|
+
async def home(request):
|
|
62
|
+
return JSONResponse({"message": "Hello, World!"})
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
if __name__ == "__main__":
|
|
66
|
+
app.run(host="0.0.0.0", port=8000)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Run:
|
|
70
|
+
```bash
|
|
71
|
+
python app.py
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Or via uvicorn:
|
|
75
|
+
```bash
|
|
76
|
+
uvicorn app:app --reload
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Features
|
|
80
|
+
|
|
81
|
+
- ✅ ASGI compliant
|
|
82
|
+
- ✅ JSON, HTML, and text responses
|
|
83
|
+
- ✅ Typed path parameters (`{id:int}`, `{name:str}`, `{value:float}`)
|
|
84
|
+
- ✅ Sync and async handlers
|
|
85
|
+
- ✅ Full WebSocket support
|
|
86
|
+
- ✅ Built-in server (`app.run()`)
|
|
87
|
+
- ✅ Jinja2 templates
|
|
88
|
+
- ✅ Response caching
|
|
89
|
+
- ✅ Static file mounting
|
|
90
|
+
|
|
91
|
+
## Usage Examples
|
|
92
|
+
|
|
93
|
+
### Path Parameters
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from altapi.http import JSONResponse
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@app.get("/users/{id:int}")
|
|
100
|
+
async def get_user(request):
|
|
101
|
+
user_id = request.path_params["id"] # automatically int
|
|
102
|
+
return JSONResponse({"id": user_id, "name": f"User {user_id}"})
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@app.get("/items/{name:str}")
|
|
106
|
+
async def get_item(request):
|
|
107
|
+
name = request.path_params["name"] # str
|
|
108
|
+
return JSONResponse({"name": name})
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Handling POST Requests
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
@app.post("/api/echo")
|
|
115
|
+
async def echo(request):
|
|
116
|
+
data = await request.json()
|
|
117
|
+
return JSONResponse({"echo": data})
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### WebSocket
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from altapi.websocket import WebSocket
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@app.websocket("/ws/echo")
|
|
127
|
+
async def websocket_echo(ws: WebSocket):
|
|
128
|
+
await ws.accept()
|
|
129
|
+
while True:
|
|
130
|
+
text = await ws.receive_text()
|
|
131
|
+
await ws.send_text(f"Echo: {text}")
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Caching
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from altapi.caching import InMemoryCache, cache
|
|
138
|
+
|
|
139
|
+
app = AltAPI(
|
|
140
|
+
cache_backend=InMemoryCache(max_size=1000),
|
|
141
|
+
cache_timeout=300
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@app.get("/api/data")
|
|
146
|
+
@cache(expires=3600) # cache for 1 hour
|
|
147
|
+
async def get_data(request):
|
|
148
|
+
return JSONResponse({"data": "cached"})
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Jinja2 Templates
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
from altapi.templating import Jinja2Templates
|
|
155
|
+
|
|
156
|
+
app = AltAPI(templates_directory="templates")
|
|
157
|
+
templates = Jinja2Templates(directory="templates")
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@app.get("/")
|
|
161
|
+
async def home(request):
|
|
162
|
+
return templates.TemplateResponse(
|
|
163
|
+
"index.html",
|
|
164
|
+
{"request": request, "title": "Home Page"}
|
|
165
|
+
)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Static Files
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
# Automatically serves files at /static
|
|
172
|
+
app = AltAPI(static_directory="static")
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Response Types
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
from altapi.http import (
|
|
179
|
+
JSONResponse, # JSON response
|
|
180
|
+
HTMLResponse, # HTML response
|
|
181
|
+
PlainTextResponse, # Plain text response
|
|
182
|
+
StreamingResponse, # Streaming response
|
|
183
|
+
FileResponse, # File download
|
|
184
|
+
RedirectResponse, # Redirect
|
|
185
|
+
)
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Documentation
|
|
189
|
+
|
|
190
|
+
Full documentation is available in [DOCS.md](DOCS.md).
|
|
191
|
+
|
|
192
|
+
## License
|
|
193
|
+
|
|
194
|
+
AGPLv3, see [LICENSE.txt](LICENSE.txt) for details.
|
altapi-1.2.1/README.md
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# AltAPI
|
|
2
|
+
|
|
3
|
+
A simple and fast ASGI microframework for Python with WebSocket support.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/amogus-gggy/AltAPI/blob/main/DOCS.md)
|
|
6
|
+
[](https://github.com/fedor444/AltAPI)
|
|
7
|
+
[](LICENSE.txt)
|
|
8
|
+
|
|
9
|
+
## Changelog
|
|
10
|
+
|
|
11
|
+
### v1.2.0
|
|
12
|
+
- Added `workers` parameter to `app.run()` for multi-process support (still unstable sometimes)
|
|
13
|
+
- Added `access_log` parameter to enable/disable request logging
|
|
14
|
+
- GC optimizations now apply to all workers automatically
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install altapi
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Requirements:**
|
|
25
|
+
- Python >= 3.10
|
|
26
|
+
|
|
27
|
+
## Quick Start
|
|
28
|
+
|
|
29
|
+
### Minimal Example
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
from altapi import AltAPI
|
|
33
|
+
from altapi.http import JSONResponse
|
|
34
|
+
|
|
35
|
+
app = AltAPI()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@app.get("/")
|
|
39
|
+
async def home(request):
|
|
40
|
+
return JSONResponse({"message": "Hello, World!"})
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
if __name__ == "__main__":
|
|
44
|
+
app.run(host="0.0.0.0", port=8000)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Run:
|
|
48
|
+
```bash
|
|
49
|
+
python app.py
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Or via uvicorn:
|
|
53
|
+
```bash
|
|
54
|
+
uvicorn app:app --reload
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Features
|
|
58
|
+
|
|
59
|
+
- ✅ ASGI compliant
|
|
60
|
+
- ✅ JSON, HTML, and text responses
|
|
61
|
+
- ✅ Typed path parameters (`{id:int}`, `{name:str}`, `{value:float}`)
|
|
62
|
+
- ✅ Sync and async handlers
|
|
63
|
+
- ✅ Full WebSocket support
|
|
64
|
+
- ✅ Built-in server (`app.run()`)
|
|
65
|
+
- ✅ Jinja2 templates
|
|
66
|
+
- ✅ Response caching
|
|
67
|
+
- ✅ Static file mounting
|
|
68
|
+
|
|
69
|
+
## Usage Examples
|
|
70
|
+
|
|
71
|
+
### Path Parameters
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from altapi.http import JSONResponse
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@app.get("/users/{id:int}")
|
|
78
|
+
async def get_user(request):
|
|
79
|
+
user_id = request.path_params["id"] # automatically int
|
|
80
|
+
return JSONResponse({"id": user_id, "name": f"User {user_id}"})
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@app.get("/items/{name:str}")
|
|
84
|
+
async def get_item(request):
|
|
85
|
+
name = request.path_params["name"] # str
|
|
86
|
+
return JSONResponse({"name": name})
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Handling POST Requests
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
@app.post("/api/echo")
|
|
93
|
+
async def echo(request):
|
|
94
|
+
data = await request.json()
|
|
95
|
+
return JSONResponse({"echo": data})
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### WebSocket
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from altapi.websocket import WebSocket
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@app.websocket("/ws/echo")
|
|
105
|
+
async def websocket_echo(ws: WebSocket):
|
|
106
|
+
await ws.accept()
|
|
107
|
+
while True:
|
|
108
|
+
text = await ws.receive_text()
|
|
109
|
+
await ws.send_text(f"Echo: {text}")
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Caching
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
from altapi.caching import InMemoryCache, cache
|
|
116
|
+
|
|
117
|
+
app = AltAPI(
|
|
118
|
+
cache_backend=InMemoryCache(max_size=1000),
|
|
119
|
+
cache_timeout=300
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@app.get("/api/data")
|
|
124
|
+
@cache(expires=3600) # cache for 1 hour
|
|
125
|
+
async def get_data(request):
|
|
126
|
+
return JSONResponse({"data": "cached"})
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Jinja2 Templates
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from altapi.templating import Jinja2Templates
|
|
133
|
+
|
|
134
|
+
app = AltAPI(templates_directory="templates")
|
|
135
|
+
templates = Jinja2Templates(directory="templates")
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@app.get("/")
|
|
139
|
+
async def home(request):
|
|
140
|
+
return templates.TemplateResponse(
|
|
141
|
+
"index.html",
|
|
142
|
+
{"request": request, "title": "Home Page"}
|
|
143
|
+
)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Static Files
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
# Automatically serves files at /static
|
|
150
|
+
app = AltAPI(static_directory="static")
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Response Types
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
from altapi.http import (
|
|
157
|
+
JSONResponse, # JSON response
|
|
158
|
+
HTMLResponse, # HTML response
|
|
159
|
+
PlainTextResponse, # Plain text response
|
|
160
|
+
StreamingResponse, # Streaming response
|
|
161
|
+
FileResponse, # File download
|
|
162
|
+
RedirectResponse, # Redirect
|
|
163
|
+
)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Documentation
|
|
167
|
+
|
|
168
|
+
Full documentation is available in [DOCS.md](DOCS.md).
|
|
169
|
+
|
|
170
|
+
## License
|
|
171
|
+
|
|
172
|
+
AGPLv3, see [LICENSE.txt](LICENSE.txt) for details.
|
|
@@ -4,14 +4,13 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "AltAPI"
|
|
7
|
-
version = "1.1"
|
|
7
|
+
version = "1.2.1"
|
|
8
8
|
|
|
9
9
|
authors = [
|
|
10
|
-
{name = "amogus-gggy"}
|
|
11
|
-
{name = "vxiddev"}
|
|
10
|
+
{name = "amogus-gggy"}
|
|
12
11
|
]
|
|
13
12
|
|
|
14
|
-
description = "
|
|
13
|
+
description = "A simple and fast ASGI microframework for Python with WebSocket support."
|
|
15
14
|
readme = "README.md"
|
|
16
15
|
requires-python = ">=3.10"
|
|
17
16
|
|
|
@@ -17,9 +17,9 @@ extensions = [
|
|
|
17
17
|
|
|
18
18
|
setup(
|
|
19
19
|
name="altapi",
|
|
20
|
-
version="1.1",
|
|
21
|
-
author="
|
|
22
|
-
description="
|
|
20
|
+
version="1.2.1",
|
|
21
|
+
author="amogus-gggy",
|
|
22
|
+
description="A simple and fast ASGI microframework for Python with WebSocket support.",
|
|
23
23
|
long_description=open("README.md", encoding="utf-8").read(),
|
|
24
24
|
long_description_content_type="text/markdown",
|
|
25
25
|
url="https://github.com/amogus-gggy/AltAPI",
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: AltAPI
|
|
3
|
+
Version: 1.2.1
|
|
4
|
+
Summary: A simple and fast ASGI microframework for Python with WebSocket support.
|
|
5
|
+
Home-page: https://github.com/amogus-gggy/AltAPI
|
|
6
|
+
Author: amogus-gggy
|
|
7
|
+
Project-URL: Homepage, https://github.com/amogus-gggy/AltAPI
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE.txt
|
|
11
|
+
Requires-Dist: uvicorn[standard]>=0.30.0
|
|
12
|
+
Requires-Dist: anyio>=4.0.0
|
|
13
|
+
Requires-Dist: jinja2>=3.0.0
|
|
14
|
+
Requires-Dist: ujson
|
|
15
|
+
Provides-Extra: dev
|
|
16
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
17
|
+
Requires-Dist: httpx>=0.27.0; extra == "dev"
|
|
18
|
+
Requires-Dist: cython>=3.0.0; extra == "dev"
|
|
19
|
+
Dynamic: home-page
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
Dynamic: requires-python
|
|
22
|
+
|
|
23
|
+
# AltAPI
|
|
24
|
+
|
|
25
|
+
A simple and fast ASGI microframework for Python with WebSocket support.
|
|
26
|
+
|
|
27
|
+
[](https://github.com/amogus-gggy/AltAPI/blob/main/DOCS.md)
|
|
28
|
+
[](https://github.com/fedor444/AltAPI)
|
|
29
|
+
[](LICENSE.txt)
|
|
30
|
+
|
|
31
|
+
## Changelog
|
|
32
|
+
|
|
33
|
+
### v1.2.0
|
|
34
|
+
- Added `workers` parameter to `app.run()` for multi-process support (still unstable sometimes)
|
|
35
|
+
- Added `access_log` parameter to enable/disable request logging
|
|
36
|
+
- GC optimizations now apply to all workers automatically
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install altapi
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Requirements:**
|
|
47
|
+
- Python >= 3.10
|
|
48
|
+
|
|
49
|
+
## Quick Start
|
|
50
|
+
|
|
51
|
+
### Minimal Example
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
from altapi import AltAPI
|
|
55
|
+
from altapi.http import JSONResponse
|
|
56
|
+
|
|
57
|
+
app = AltAPI()
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@app.get("/")
|
|
61
|
+
async def home(request):
|
|
62
|
+
return JSONResponse({"message": "Hello, World!"})
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
if __name__ == "__main__":
|
|
66
|
+
app.run(host="0.0.0.0", port=8000)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Run:
|
|
70
|
+
```bash
|
|
71
|
+
python app.py
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Or via uvicorn:
|
|
75
|
+
```bash
|
|
76
|
+
uvicorn app:app --reload
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Features
|
|
80
|
+
|
|
81
|
+
- ✅ ASGI compliant
|
|
82
|
+
- ✅ JSON, HTML, and text responses
|
|
83
|
+
- ✅ Typed path parameters (`{id:int}`, `{name:str}`, `{value:float}`)
|
|
84
|
+
- ✅ Sync and async handlers
|
|
85
|
+
- ✅ Full WebSocket support
|
|
86
|
+
- ✅ Built-in server (`app.run()`)
|
|
87
|
+
- ✅ Jinja2 templates
|
|
88
|
+
- ✅ Response caching
|
|
89
|
+
- ✅ Static file mounting
|
|
90
|
+
|
|
91
|
+
## Usage Examples
|
|
92
|
+
|
|
93
|
+
### Path Parameters
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from altapi.http import JSONResponse
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@app.get("/users/{id:int}")
|
|
100
|
+
async def get_user(request):
|
|
101
|
+
user_id = request.path_params["id"] # automatically int
|
|
102
|
+
return JSONResponse({"id": user_id, "name": f"User {user_id}"})
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@app.get("/items/{name:str}")
|
|
106
|
+
async def get_item(request):
|
|
107
|
+
name = request.path_params["name"] # str
|
|
108
|
+
return JSONResponse({"name": name})
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Handling POST Requests
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
@app.post("/api/echo")
|
|
115
|
+
async def echo(request):
|
|
116
|
+
data = await request.json()
|
|
117
|
+
return JSONResponse({"echo": data})
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### WebSocket
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from altapi.websocket import WebSocket
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@app.websocket("/ws/echo")
|
|
127
|
+
async def websocket_echo(ws: WebSocket):
|
|
128
|
+
await ws.accept()
|
|
129
|
+
while True:
|
|
130
|
+
text = await ws.receive_text()
|
|
131
|
+
await ws.send_text(f"Echo: {text}")
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Caching
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from altapi.caching import InMemoryCache, cache
|
|
138
|
+
|
|
139
|
+
app = AltAPI(
|
|
140
|
+
cache_backend=InMemoryCache(max_size=1000),
|
|
141
|
+
cache_timeout=300
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@app.get("/api/data")
|
|
146
|
+
@cache(expires=3600) # cache for 1 hour
|
|
147
|
+
async def get_data(request):
|
|
148
|
+
return JSONResponse({"data": "cached"})
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Jinja2 Templates
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
from altapi.templating import Jinja2Templates
|
|
155
|
+
|
|
156
|
+
app = AltAPI(templates_directory="templates")
|
|
157
|
+
templates = Jinja2Templates(directory="templates")
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@app.get("/")
|
|
161
|
+
async def home(request):
|
|
162
|
+
return templates.TemplateResponse(
|
|
163
|
+
"index.html",
|
|
164
|
+
{"request": request, "title": "Home Page"}
|
|
165
|
+
)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Static Files
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
# Automatically serves files at /static
|
|
172
|
+
app = AltAPI(static_directory="static")
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Response Types
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
from altapi.http import (
|
|
179
|
+
JSONResponse, # JSON response
|
|
180
|
+
HTMLResponse, # HTML response
|
|
181
|
+
PlainTextResponse, # Plain text response
|
|
182
|
+
StreamingResponse, # Streaming response
|
|
183
|
+
FileResponse, # File download
|
|
184
|
+
RedirectResponse, # Redirect
|
|
185
|
+
)
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Documentation
|
|
189
|
+
|
|
190
|
+
Full documentation is available in [DOCS.md](DOCS.md).
|
|
191
|
+
|
|
192
|
+
## License
|
|
193
|
+
|
|
194
|
+
AGPLv3, see [LICENSE.txt](LICENSE.txt) for details.
|