aiohttp-openapi-helper 0.2.0__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.
- aiohttp_openapi_helper-0.2.0/.gitignore +87 -0
- aiohttp_openapi_helper-0.2.0/LICENSE +21 -0
- aiohttp_openapi_helper-0.2.0/PKG-INFO +435 -0
- aiohttp_openapi_helper-0.2.0/README.md +402 -0
- aiohttp_openapi_helper-0.2.0/docs/index.md +93 -0
- aiohttp_openapi_helper-0.2.0/pyproject.toml +80 -0
- aiohttp_openapi_helper-0.2.0/src/aiohttp_openapi_helper/__init__.py +0 -0
- aiohttp_openapi_helper-0.2.0/src/aiohttp_openapi_helper/decorators.py +138 -0
- aiohttp_openapi_helper-0.2.0/src/aiohttp_openapi_helper/middleware.py +450 -0
- aiohttp_openapi_helper-0.2.0/src/aiohttp_openapi_helper/spec.py +265 -0
- aiohttp_openapi_helper-0.2.0/tests/test_decorators.py +284 -0
- aiohttp_openapi_helper-0.2.0/tests/test_middleware.py +328 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
pip-wheel-metadata/
|
|
24
|
+
share/python-wheels/
|
|
25
|
+
*.egg-info/
|
|
26
|
+
.installed.cfg
|
|
27
|
+
*.egg
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
*.manifest
|
|
31
|
+
*.spec
|
|
32
|
+
|
|
33
|
+
# Unit test / coverage reports
|
|
34
|
+
htmlcov/
|
|
35
|
+
.tox/
|
|
36
|
+
.nox/
|
|
37
|
+
.coverage
|
|
38
|
+
.coverage.*
|
|
39
|
+
.cache
|
|
40
|
+
nosetests.xml
|
|
41
|
+
coverage.xml
|
|
42
|
+
*.cover
|
|
43
|
+
*.py,cover
|
|
44
|
+
.hypothesis/
|
|
45
|
+
.pytest_cache/
|
|
46
|
+
.pytest_cache/
|
|
47
|
+
|
|
48
|
+
# Virtual environments
|
|
49
|
+
.venv
|
|
50
|
+
venv/
|
|
51
|
+
ENV/
|
|
52
|
+
env/
|
|
53
|
+
.venv/
|
|
54
|
+
|
|
55
|
+
# IDEs
|
|
56
|
+
.idea/
|
|
57
|
+
.vscode/
|
|
58
|
+
*.swp
|
|
59
|
+
*.swo
|
|
60
|
+
*~
|
|
61
|
+
|
|
62
|
+
# Environment variables
|
|
63
|
+
.env
|
|
64
|
+
.venv
|
|
65
|
+
|
|
66
|
+
# Testing
|
|
67
|
+
.pytest_cache/
|
|
68
|
+
.coverage
|
|
69
|
+
|
|
70
|
+
# Documentation
|
|
71
|
+
docs/_build/
|
|
72
|
+
docs/.doctrees/
|
|
73
|
+
docs/*.html
|
|
74
|
+
|
|
75
|
+
# Temporary files
|
|
76
|
+
*.tmp
|
|
77
|
+
*.temp
|
|
78
|
+
*.log
|
|
79
|
+
|
|
80
|
+
# OS
|
|
81
|
+
.DS_Store
|
|
82
|
+
Thumbs.db
|
|
83
|
+
|
|
84
|
+
# Project specific
|
|
85
|
+
*.spec.snapshot
|
|
86
|
+
openapi.json
|
|
87
|
+
openapi.yaml
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alex Developer
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aiohttp-openapi-helper
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Lightweight OpenAPI 3 helper for aiohttp
|
|
5
|
+
Project-URL: Homepage, https://github.com/alexdev/aiohttp-openapi-helper
|
|
6
|
+
Project-URL: Repository, https://github.com/alexdev/aiohttp-openapi-helper
|
|
7
|
+
Project-URL: Documentation, https://github.com/alexdev/aiohttp-openapi-helper/blob/main/README.md
|
|
8
|
+
Project-URL: Issues, https://github.com/alexdev/aiohttp-openapi-helper/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/alexdev/aiohttp-openapi-helper/blob/main/CHANGELOG.md
|
|
10
|
+
Author-email: Alex Developer <alex.dev@project1997.com>
|
|
11
|
+
Maintainer-email: Alex Developer <alex.dev@project1997.com>
|
|
12
|
+
License: MIT
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Framework :: aiohttp
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
|
|
25
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
26
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
27
|
+
Classifier: Typing :: Typed
|
|
28
|
+
Requires-Python: >=3.8
|
|
29
|
+
Requires-Dist: aiohttp>=3.8.0
|
|
30
|
+
Requires-Dist: jsonschema>=4.0.0
|
|
31
|
+
Requires-Dist: pyyaml>=6.0
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# aiohttp-openapi-helper
|
|
35
|
+
|
|
36
|
+
[](https://badge.fury.io/py/aiohttp-openapi-helper)
|
|
37
|
+
[](https://pypi.org/project/aiohttp-openapi-helper/)
|
|
38
|
+
[](https://opensource.org/licenses/MIT)
|
|
39
|
+
[](https://pypi.org/project/aiohttp-openapi-helper/)
|
|
40
|
+
[](https://github.com/alexdev/aiohttp-openapi-helper/actions)
|
|
41
|
+
[](https://codecov.io/gh/alexdev/aiohttp-openapi-helper)
|
|
42
|
+
|
|
43
|
+
Lightweight OpenAPI 3.0 helper for aiohttp applications. Simplifies API development with decorator-based routes, automatic spec generation, and built-in validation.
|
|
44
|
+
|
|
45
|
+
## Features
|
|
46
|
+
|
|
47
|
+
✨ **Decorator-based Routes**: Define OpenAPI specs directly on route handlers
|
|
48
|
+
🚀 **Auto Spec Generation**: Automatically generate OpenAPI 3.0 specification
|
|
49
|
+
✅ **Request Validation**: Validate incoming requests against schemas
|
|
50
|
+
📦 **Response Validation**: Validate outgoing responses (optional)
|
|
51
|
+
🔧 **Flexible Middleware**: Easy-to-configure validation middleware
|
|
52
|
+
📝 **Type Hints**: Full type annotations for better IDE support
|
|
53
|
+
⚡ **Lightweight**: Minimal dependencies, no heavy frameworks
|
|
54
|
+
📚 **Well Documented**: Comprehensive examples and API reference
|
|
55
|
+
|
|
56
|
+
## Comparison
|
|
57
|
+
|
|
58
|
+
| Feature | aiohttp-openapi-helper | aiohttp-apispec | aiohttp-swagger3 |
|
|
59
|
+
|---------|------------------------|-----------------|------------------|
|
|
60
|
+
| Decorator-based routes | ✅ | ❌ | ✅ |
|
|
61
|
+
| Auto spec generation | ✅ | ✅ | ✅ |
|
|
62
|
+
| Request validation | ✅ | ❌ | ✅ |
|
|
63
|
+
| Response validation | ✅ | ❌ | ✅ |
|
|
64
|
+
| Lightweight | ✅ | ⚠️ | ❌ |
|
|
65
|
+
| Type hints | ✅ | ⚠️ | ✅ |
|
|
66
|
+
|
|
67
|
+
## Installation
|
|
68
|
+
|
|
69
|
+
Install via pip:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install aiohttp-openapi-helper
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Quick Start
|
|
76
|
+
### Basic Usage
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from aiohttp import web
|
|
80
|
+
from aiohttp_openapi_helper import openapi_route, generate_openapi_spec, OpenAPIMiddleware
|
|
81
|
+
|
|
82
|
+
# Create aiohttp application
|
|
83
|
+
app = web.Application()
|
|
84
|
+
|
|
85
|
+
# Add OpenAPI middleware for validation
|
|
86
|
+
app.middlewares.append(OpenAPIMiddleware().middleware)
|
|
87
|
+
|
|
88
|
+
# Define your routes with OpenAPI decorators
|
|
89
|
+
@openapi_route(
|
|
90
|
+
app,
|
|
91
|
+
"/users/{user_id}",
|
|
92
|
+
method="GET",
|
|
93
|
+
summary="Get user by ID",
|
|
94
|
+
description="Retrieve user information by user ID",
|
|
95
|
+
parameters=[
|
|
96
|
+
{"name": "user_id", "in": "path", "required": True, "schema": {"type": "integer"}},
|
|
97
|
+
{"name": "include_details", "in": "query", "schema": {"type": "boolean"}}
|
|
98
|
+
],
|
|
99
|
+
responses={
|
|
100
|
+
"200": {
|
|
101
|
+
"description": "Successful response",
|
|
102
|
+
"content": {
|
|
103
|
+
"application/json": {
|
|
104
|
+
"schema": {
|
|
105
|
+
"type": "object",
|
|
106
|
+
"properties": {
|
|
107
|
+
"id": {"type": "integer"},
|
|
108
|
+
"name": {"type": "string"},
|
|
109
|
+
"email": {"type": "string"}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"404": {"description": "User not found"}
|
|
116
|
+
}
|
|
117
|
+
)
|
|
118
|
+
async def get_user(request):
|
|
119
|
+
user_id = int(request.match_info["user_id"])
|
|
120
|
+
include_details = request.query.get("include_details") == "true"
|
|
121
|
+
|
|
122
|
+
# Your business logic here
|
|
123
|
+
user = {"id": user_id, "name": "John Doe", "email": "john@example.com"}
|
|
124
|
+
|
|
125
|
+
return web.json_response(user)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@openapi_route(
|
|
129
|
+
app,
|
|
130
|
+
"/users",
|
|
131
|
+
method="POST",
|
|
132
|
+
summary="Create a new user",
|
|
133
|
+
description="Create a new user in the system",
|
|
134
|
+
request_body={
|
|
135
|
+
"required": True,
|
|
136
|
+
"content": {
|
|
137
|
+
"application/json": {
|
|
138
|
+
"schema": {
|
|
139
|
+
"type": "object",
|
|
140
|
+
"required": ["name", "email"],
|
|
141
|
+
"properties": {
|
|
142
|
+
"name": {"type": "string"},
|
|
143
|
+
"email": {"type": "string", "format": "email"},
|
|
144
|
+
"age": {"type": "integer"}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
responses={
|
|
151
|
+
"201": {
|
|
152
|
+
"description": "User created successfully",
|
|
153
|
+
"content": {
|
|
154
|
+
"application/json": {
|
|
155
|
+
"schema": {
|
|
156
|
+
"type": "object",
|
|
157
|
+
"properties": {
|
|
158
|
+
"id": {"type": "integer"},
|
|
159
|
+
"name": {"type": "string"},
|
|
160
|
+
"email": {"type": "string"}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
"400": {"description": "Invalid input"}
|
|
167
|
+
}
|
|
168
|
+
)
|
|
169
|
+
async def create_user(request):
|
|
170
|
+
data = await request.json()
|
|
171
|
+
|
|
172
|
+
# Validation is automatic by middleware
|
|
173
|
+
# Your business logic here
|
|
174
|
+
new_user = {
|
|
175
|
+
"id": 123,
|
|
176
|
+
"name": data["name"],
|
|
177
|
+
"email": data["email"]
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return web.json_response(new_user, status=201)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
# Generate and serve OpenAPI spec
|
|
184
|
+
spec = generate_openapi_spec(
|
|
185
|
+
title="User API",
|
|
186
|
+
version="1.0.0",
|
|
187
|
+
description="API for user management",
|
|
188
|
+
routes=app.router.routes()
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
# Add route to serve the spec
|
|
192
|
+
app.router.add_get("/openapi.json", lambda r: web.json_response(spec))
|
|
193
|
+
app.router.add_get("/openapi.yaml", lambda r: web.Response(
|
|
194
|
+
text=web.yaml.dump(spec),
|
|
195
|
+
content_type="application/yaml"
|
|
196
|
+
))
|
|
197
|
+
|
|
198
|
+
# Run the application
|
|
199
|
+
if __name__ == "__main__":
|
|
200
|
+
web.run_app(app, port=8080)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Advanced Configuration
|
|
204
|
+
```python
|
|
205
|
+
from aiohttp import web
|
|
206
|
+
from aiohttp_openapi_helper import (
|
|
207
|
+
openapi_route,
|
|
208
|
+
generate_openapi_spec,
|
|
209
|
+
OpenAPIMiddleware,
|
|
210
|
+
security_scheme
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
app = web.Application()
|
|
214
|
+
|
|
215
|
+
# Configure middleware with custom options
|
|
216
|
+
middleware = OpenAPIMiddleware(
|
|
217
|
+
validate_request=True,
|
|
218
|
+
validate_response=True,
|
|
219
|
+
raise_on_error=False, # Return 400 instead of raising exception
|
|
220
|
+
log_errors=True
|
|
221
|
+
)
|
|
222
|
+
app.middlewares.append(middleware.middleware)
|
|
223
|
+
|
|
224
|
+
# Define security schemes
|
|
225
|
+
api_key_scheme = security_scheme(
|
|
226
|
+
type="apiKey",
|
|
227
|
+
name="X-API-Key",
|
|
228
|
+
in_="header"
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
bearer_scheme = security_scheme(
|
|
232
|
+
type="http",
|
|
233
|
+
scheme="bearer",
|
|
234
|
+
bearer_format="JWT"
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
# Use security schemes in routes
|
|
238
|
+
@openapi_route(
|
|
239
|
+
app,
|
|
240
|
+
"/protected",
|
|
241
|
+
method="GET",
|
|
242
|
+
summary="Protected endpoint",
|
|
243
|
+
security=[{"ApiKeyAuth": []}],
|
|
244
|
+
responses={
|
|
245
|
+
"200": {"description": "Successful response"},
|
|
246
|
+
"401": {"description": "Unauthorized"}
|
|
247
|
+
}
|
|
248
|
+
)
|
|
249
|
+
async def protected_route(request):
|
|
250
|
+
return web.json_response({"message": "Access granted"})
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
# Generate spec with security schemes
|
|
254
|
+
spec = generate_openapi_spec(
|
|
255
|
+
title="Secure API",
|
|
256
|
+
version="1.0.0",
|
|
257
|
+
security_schemes={
|
|
258
|
+
"ApiKeyAuth": api_key_scheme,
|
|
259
|
+
"BearerAuth": bearer_scheme
|
|
260
|
+
},
|
|
261
|
+
routes=app.router.routes()
|
|
262
|
+
)
|
|
263
|
+
```
|
|
264
|
+
### API Reference
|
|
265
|
+
@openapi_route(app, path, method, **kwargs)
|
|
266
|
+
Decorator to define OpenAPI-compliant routes.
|
|
267
|
+
|
|
268
|
+
Parameters:
|
|
269
|
+
|
|
270
|
+
app: aiohttp Application instance
|
|
271
|
+
path: Route path (e.g., "/users/{user_id}")
|
|
272
|
+
method: HTTP method ("GET", "POST", "PUT", "DELETE", etc.)
|
|
273
|
+
summary: Brief summary of the endpoint
|
|
274
|
+
description: Detailed description
|
|
275
|
+
tags: List of tags for grouping endpoints
|
|
276
|
+
parameters: List of parameter specifications
|
|
277
|
+
request_body: Request body schema (for POST/PUT/PATCH)
|
|
278
|
+
responses: Response schemas keyed by status code
|
|
279
|
+
security: Security requirements
|
|
280
|
+
deprecated: Mark as deprecated (bool)
|
|
281
|
+
|
|
282
|
+
generate_openapi_spec(title, version, **kwargs)
|
|
283
|
+
Generate OpenAPI 3.0 specification from registered routes.
|
|
284
|
+
Parameters:
|
|
285
|
+
|
|
286
|
+
title: API title
|
|
287
|
+
version: API version
|
|
288
|
+
description: API description
|
|
289
|
+
routes: aiohttp routes collection
|
|
290
|
+
security_schemes: Dictionary of security schemes
|
|
291
|
+
servers: List of server objects
|
|
292
|
+
tags: List of tag definitions
|
|
293
|
+
contact: Contact information
|
|
294
|
+
license: License information
|
|
295
|
+
|
|
296
|
+
Returns: Dictionary containing OpenAPI specification
|
|
297
|
+
OpenAPIMiddleware(validate_request=True, validate_response=False, raise_on_error=True, log_errors=False)
|
|
298
|
+
Middleware for request/response validation.
|
|
299
|
+
Parameters:
|
|
300
|
+
|
|
301
|
+
validate_request: Enable request validation
|
|
302
|
+
validate_response: Enable response validation
|
|
303
|
+
raise_on_error: Raise exception on validation error (otherwise return 400)
|
|
304
|
+
log_errors: Log validation errors to console
|
|
305
|
+
|
|
306
|
+
security_scheme(type, **kwargs)
|
|
307
|
+
Helper to create security scheme definitions.
|
|
308
|
+
Parameters:
|
|
309
|
+
|
|
310
|
+
type: "apiKey", "http", "oauth2", or "openIdConnect"
|
|
311
|
+
name: Header/query/cookie name (for apiKey)
|
|
312
|
+
in_: "header", "query", or "cookie" (for apiKey)
|
|
313
|
+
scheme: HTTP scheme (for http type)
|
|
314
|
+
bearer_format: Bearer token format (for bearer scheme)
|
|
315
|
+
flows: OAuth2 flows configuration
|
|
316
|
+
open_id_connect_url: OpenID Connect URL
|
|
317
|
+
|
|
318
|
+
## Testing
|
|
319
|
+
Run tests with pytest:
|
|
320
|
+
```bash
|
|
321
|
+
pytest tests/ -v
|
|
322
|
+
```
|
|
323
|
+
Run with coverage:
|
|
324
|
+
```bash
|
|
325
|
+
pytest tests/ --cov=aiohttp_openapi_helper --cov-report=html
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
# Examples
|
|
329
|
+
Complete Example
|
|
330
|
+
```python
|
|
331
|
+
from aiohttp import web
|
|
332
|
+
from aiohttp_openapi_helper import (
|
|
333
|
+
openapi_route,
|
|
334
|
+
generate_openapi_spec,
|
|
335
|
+
OpenAPIMiddleware,
|
|
336
|
+
security_scheme
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
async def init_app():
|
|
340
|
+
app = web.Application()
|
|
341
|
+
|
|
342
|
+
# Add middleware
|
|
343
|
+
app.middlewares.append(OpenAPIMiddleware(
|
|
344
|
+
validate_request=True,
|
|
345
|
+
validate_response=False
|
|
346
|
+
).middleware)
|
|
347
|
+
|
|
348
|
+
# Define routes
|
|
349
|
+
@openapi_route(
|
|
350
|
+
app,
|
|
351
|
+
"/health",
|
|
352
|
+
method="GET",
|
|
353
|
+
summary="Health check",
|
|
354
|
+
tags=["System"],
|
|
355
|
+
responses={
|
|
356
|
+
"200": {
|
|
357
|
+
"description": "Service is healthy",
|
|
358
|
+
"content": {
|
|
359
|
+
"application/json": {
|
|
360
|
+
"schema": {
|
|
361
|
+
"type": "object",
|
|
362
|
+
"properties": {
|
|
363
|
+
"status": {"type": "string"},
|
|
364
|
+
"version": {"type": "string"}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
)
|
|
372
|
+
async def health_check(request):
|
|
373
|
+
return web.json_response({
|
|
374
|
+
"status": "healthy",
|
|
375
|
+
"version": "1.0.0"
|
|
376
|
+
})
|
|
377
|
+
|
|
378
|
+
@openapi_route(
|
|
379
|
+
app,
|
|
380
|
+
"/items",
|
|
381
|
+
method="GET",
|
|
382
|
+
summary="List all items",
|
|
383
|
+
tags=["Items"],
|
|
384
|
+
parameters=[
|
|
385
|
+
{"name": "limit", "in": "query", "schema": {"type": "integer", "default": 10}},
|
|
386
|
+
{"name": "offset", "in": "query", "schema": {"type": "integer", "default": 0}}
|
|
387
|
+
],
|
|
388
|
+
responses={
|
|
389
|
+
"200": {
|
|
390
|
+
"description": "List of items",
|
|
391
|
+
"content": {
|
|
392
|
+
"application/json": {
|
|
393
|
+
"schema": {
|
|
394
|
+
"type": "array",
|
|
395
|
+
"items": {
|
|
396
|
+
"type": "object",
|
|
397
|
+
"properties": {
|
|
398
|
+
"id": {"type": "integer"},
|
|
399
|
+
"name": {"type": "string"}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
)
|
|
408
|
+
async def list_items(request):
|
|
409
|
+
limit = int(request.query.get("limit", 10))
|
|
410
|
+
offset = int(request.query.get("offset", 0))
|
|
411
|
+
|
|
412
|
+
items = [{"id": i, "name": f"Item {i}"} for i in range(offset, offset + limit)]
|
|
413
|
+
|
|
414
|
+
return web.json_response(items)
|
|
415
|
+
|
|
416
|
+
# Generate and serve spec
|
|
417
|
+
spec = generate_openapi_spec(
|
|
418
|
+
title="Demo API",
|
|
419
|
+
version="1.0.0",
|
|
420
|
+
description="Demonstration of aiohttp-openapi-helper",
|
|
421
|
+
routes=app.router.routes(),
|
|
422
|
+
tags=[
|
|
423
|
+
{"name": "System", "description": "System endpoints"},
|
|
424
|
+
{"name": "Items", "description": "Item management endpoints"}
|
|
425
|
+
]
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
app.router.add_get("/openapi.json", lambda r: web.json_response(spec))
|
|
429
|
+
|
|
430
|
+
return app
|
|
431
|
+
|
|
432
|
+
if __name__ == "__main__":
|
|
433
|
+
web.run_app(init_app(), port=8080)
|
|
434
|
+
```
|
|
435
|
+
|