0
# OpenAPI Integration
1
2
Automatic API documentation generation with Swagger UI, route documentation, schema definitions, and custom OpenAPI specification support for comprehensive API documentation.
3
4
## Capabilities
5
6
### OpenAPI Generator
7
8
Main class for managing OpenAPI specification generation and documentation.
9
10
```python { .api }
11
class OpenAPI:
12
def add_openapi_path_obj(
13
self,
14
route_type,
15
endpoint: str,
16
openapi_name: str,
17
openapi_tags: Optional[list],
18
handler
19
):
20
"""
21
Add a route to the OpenAPI specification.
22
23
Args:
24
route_type: HTTP method type
25
endpoint: URL endpoint pattern
26
openapi_name: Name for the operation in OpenAPI docs
27
openapi_tags: List of tags for grouping operations
28
handler: Route handler function
29
"""
30
31
def get_openapi_docs_page(self) -> str:
32
"""
33
Generate Swagger UI HTML page for API documentation.
34
35
Returns:
36
HTML string containing Swagger UI interface
37
"""
38
39
def get_openapi_config(self) -> dict:
40
"""
41
Get the complete OpenAPI specification as a dictionary.
42
43
Returns:
44
OpenAPI specification dictionary following OpenAPI 3.0 standard
45
"""
46
47
def override_openapi(self, openapi_json_spec_path: str):
48
"""
49
Override auto-generated OpenAPI spec with custom specification.
50
51
Args:
52
openapi_json_spec_path: Path to custom OpenAPI JSON specification file
53
"""
54
```
55
56
### Route Documentation
57
58
Use decorators with OpenAPI parameters to document routes automatically.
59
60
```python { .api }
61
# HTTP method decorators support OpenAPI documentation parameters
62
@app.get(
63
endpoint="/users/{user_id}",
64
openapi_name="Get User by ID",
65
openapi_tags=["Users"]
66
)
67
def get_user(request):
68
"""Route handler with OpenAPI documentation"""
69
70
@app.post(
71
endpoint="/users",
72
openapi_name="Create User",
73
openapi_tags=["Users", "Management"]
74
)
75
def create_user(request):
76
"""Route handler with multiple OpenAPI tags"""
77
```
78
79
## Usage Examples
80
81
### Basic OpenAPI Setup
82
83
```python
84
from robyn import Robyn, OpenAPI
85
86
# Create app with OpenAPI support
87
app = Robyn(__file__, openapi=OpenAPI())
88
89
# Document routes with OpenAPI metadata
90
@app.get("/", openapi_name="Get Root", openapi_tags=["General"])
91
def root(request):
92
"""Root endpoint returning welcome message"""
93
return {"message": "Welcome to the API"}
94
95
@app.get("/users", openapi_name="List Users", openapi_tags=["Users"])
96
def list_users(request):
97
"""Get list of all users"""
98
return {"users": ["alice", "bob", "charlie"]}
99
100
@app.get("/users/<user_id>", openapi_name="Get User", openapi_tags=["Users"])
101
def get_user(request):
102
"""Get specific user by ID"""
103
user_id = request.path_params["user_id"]
104
return {"user_id": user_id, "name": f"User {user_id}"}
105
106
@app.post("/users", openapi_name="Create User", openapi_tags=["Users", "Management"])
107
def create_user(request):
108
"""Create a new user"""
109
user_data = request.json()
110
return {"message": "User created", "data": user_data}
111
112
# Serve OpenAPI documentation
113
@app.get("/docs")
114
def docs(request):
115
return app.openapi.get_openapi_docs_page()
116
117
@app.get("/openapi.json")
118
def openapi_spec(request):
119
return app.openapi.get_openapi_config()
120
121
app.start()
122
```
123
124
### Custom OpenAPI Specification
125
126
```python
127
from robyn import Robyn, OpenAPI
128
import json
129
130
app = Robyn(__file__)
131
132
# Create custom OpenAPI specification
133
custom_spec = {
134
"openapi": "3.0.0",
135
"info": {
136
"title": "My Custom API",
137
"description": "A comprehensive API for managing users and resources",
138
"version": "1.0.0",
139
"contact": {
140
"name": "API Support",
141
"url": "https://example.com/support",
142
"email": "support@example.com"
143
},
144
"license": {
145
"name": "MIT",
146
"url": "https://opensource.org/licenses/MIT"
147
}
148
},
149
"servers": [
150
{
151
"url": "https://api.example.com/v1",
152
"description": "Production server"
153
},
154
{
155
"url": "https://staging-api.example.com/v1",
156
"description": "Staging server"
157
}
158
],
159
"paths": {
160
"/users": {
161
"get": {
162
"summary": "List all users",
163
"description": "Retrieve a paginated list of all users in the system",
164
"tags": ["Users"],
165
"parameters": [
166
{
167
"name": "page",
168
"in": "query",
169
"description": "Page number for pagination",
170
"required": False,
171
"schema": {
172
"type": "integer",
173
"minimum": 1,
174
"default": 1
175
}
176
},
177
{
178
"name": "limit",
179
"in": "query",
180
"description": "Number of users per page",
181
"required": False,
182
"schema": {
183
"type": "integer",
184
"minimum": 1,
185
"maximum": 100,
186
"default": 20
187
}
188
}
189
],
190
"responses": {
191
"200": {
192
"description": "List of users",
193
"content": {
194
"application/json": {
195
"schema": {
196
"type": "object",
197
"properties": {
198
"users": {
199
"type": "array",
200
"items": {"$ref": "#/components/schemas/User"}
201
},
202
"pagination": {
203
"$ref": "#/components/schemas/Pagination"
204
}
205
}
206
}
207
}
208
}
209
}
210
}
211
},
212
"post": {
213
"summary": "Create a new user",
214
"description": "Create a new user account with the provided information",
215
"tags": ["Users"],
216
"requestBody": {
217
"required": True,
218
"content": {
219
"application/json": {
220
"schema": {"$ref": "#/components/schemas/CreateUserRequest"}
221
}
222
}
223
},
224
"responses": {
225
"201": {
226
"description": "User created successfully",
227
"content": {
228
"application/json": {
229
"schema": {"$ref": "#/components/schemas/User"}
230
}
231
}
232
},
233
"400": {
234
"description": "Invalid input data",
235
"content": {
236
"application/json": {
237
"schema": {"$ref": "#/components/schemas/Error"}
238
}
239
}
240
}
241
}
242
}
243
}
244
},
245
"components": {
246
"schemas": {
247
"User": {
248
"type": "object",
249
"required": ["id", "username", "email"],
250
"properties": {
251
"id": {
252
"type": "integer",
253
"description": "Unique user identifier"
254
},
255
"username": {
256
"type": "string",
257
"description": "Username for the account",
258
"minLength": 3,
259
"maxLength": 50
260
},
261
"email": {
262
"type": "string",
263
"format": "email",
264
"description": "User's email address"
265
},
266
"full_name": {
267
"type": "string",
268
"description": "Full name of the user"
269
},
270
"created_at": {
271
"type": "string",
272
"format": "date-time",
273
"description": "Account creation timestamp"
274
}
275
}
276
},
277
"CreateUserRequest": {
278
"type": "object",
279
"required": ["username", "email", "password"],
280
"properties": {
281
"username": {
282
"type": "string",
283
"minLength": 3,
284
"maxLength": 50
285
},
286
"email": {
287
"type": "string",
288
"format": "email"
289
},
290
"password": {
291
"type": "string",
292
"minLength": 8,
293
"description": "User password (will be hashed)"
294
},
295
"full_name": {
296
"type": "string"
297
}
298
}
299
},
300
"Pagination": {
301
"type": "object",
302
"properties": {
303
"page": {
304
"type": "integer",
305
"description": "Current page number"
306
},
307
"limit": {
308
"type": "integer",
309
"description": "Items per page"
310
},
311
"total": {
312
"type": "integer",
313
"description": "Total number of items"
314
},
315
"has_next": {
316
"type": "boolean",
317
"description": "Whether there are more pages"
318
}
319
}
320
},
321
"Error": {
322
"type": "object",
323
"required": ["message"],
324
"properties": {
325
"message": {
326
"type": "string",
327
"description": "Error message"
328
},
329
"code": {
330
"type": "string",
331
"description": "Error code"
332
},
333
"details": {
334
"type": "object",
335
"description": "Additional error details"
336
}
337
}
338
}
339
},
340
"securitySchemes": {
341
"BearerAuth": {
342
"type": "http",
343
"scheme": "bearer",
344
"bearerFormat": "JWT"
345
},
346
"ApiKeyAuth": {
347
"type": "apiKey",
348
"in": "header",
349
"name": "X-API-Key"
350
}
351
}
352
},
353
"security": [
354
{"BearerAuth": []},
355
{"ApiKeyAuth": []}
356
]
357
}
358
359
# Save custom spec to file
360
with open("custom_openapi.json", "w") as f:
361
json.dump(custom_spec, f, indent=2)
362
363
# Use custom specification
364
openapi = OpenAPI()
365
openapi.override_openapi("custom_openapi.json")
366
app = Robyn(__file__, openapi=openapi)
367
368
# Implement the actual routes
369
@app.get("/users")
370
def list_users(request):
371
page = int(request.query_params.get("page", "1"))
372
limit = int(request.query_params.get("limit", "20"))
373
374
# Simulate user data
375
users = [
376
{"id": i, "username": f"user{i}", "email": f"user{i}@example.com"}
377
for i in range((page-1)*limit + 1, page*limit + 1)
378
]
379
380
return {
381
"users": users,
382
"pagination": {
383
"page": page,
384
"limit": limit,
385
"total": 1000,
386
"has_next": page * limit < 1000
387
}
388
}
389
390
@app.post("/users")
391
def create_user(request):
392
user_data = request.json()
393
394
# Validate required fields
395
if not all(field in user_data for field in ["username", "email", "password"]):
396
return Response(400, {}, {
397
"message": "Missing required fields",
398
"code": "MISSING_FIELDS",
399
"details": {"required": ["username", "email", "password"]}
400
})
401
402
# Simulate user creation
403
new_user = {
404
"id": 1001,
405
"username": user_data["username"],
406
"email": user_data["email"],
407
"full_name": user_data.get("full_name"),
408
"created_at": "2023-12-01T12:00:00Z"
409
}
410
411
return Response(201, {}, new_user)
412
413
# Documentation endpoints
414
@app.get("/docs")
415
def swagger_ui(request):
416
return app.openapi.get_openapi_docs_page()
417
418
@app.get("/openapi.json")
419
def openapi_json(request):
420
return app.openapi.get_openapi_config()
421
422
app.start()
423
```
424
425
### Advanced OpenAPI with Authentication
426
427
```python
428
from robyn import Robyn, OpenAPI, AuthenticationHandler, BearerGetter
429
430
class SimpleAuthHandler(AuthenticationHandler):
431
def __init__(self):
432
super().__init__(BearerGetter())
433
434
def authenticate(self, request):
435
token = self.token_getter.get_token(request)
436
if token == "valid-token":
437
return Identity(claims={"user_id": "123", "role": "admin"})
438
return None
439
440
app = Robyn(__file__)
441
442
# Configure authentication
443
auth_handler = SimpleAuthHandler()
444
app.configure_authentication(auth_handler)
445
446
# Public endpoints
447
@app.get("/", openapi_name="API Info", openapi_tags=["General"])
448
def api_info(request):
449
"""Get API information and status"""
450
return {
451
"name": "My Secure API",
452
"version": "1.0.0",
453
"status": "healthy"
454
}
455
456
@app.post("/auth/login", openapi_name="Login", openapi_tags=["Authentication"])
457
def login(request):
458
"""Authenticate user and get access token"""
459
credentials = request.json()
460
# Simplified login logic
461
if credentials.get("username") == "admin":
462
return {"token": "valid-token", "expires_in": 3600}
463
return Response(401, {}, {"error": "Invalid credentials"})
464
465
# Protected endpoints
466
@app.get("/profile", auth_required=True, openapi_name="Get Profile", openapi_tags=["User"])
467
def get_profile(request):
468
"""Get current user's profile (requires authentication)"""
469
return {
470
"user_id": request.identity.claims["user_id"],
471
"role": request.identity.claims["role"]
472
}
473
474
@app.get("/admin/stats", auth_required=True, openapi_name="Get Admin Stats", openapi_tags=["Admin"])
475
def admin_stats(request):
476
"""Get administrative statistics (requires authentication)"""
477
if request.identity.claims.get("role") != "admin":
478
return Response(403, {}, {"error": "Admin access required"})
479
480
return {
481
"total_users": 150,
482
"active_sessions": 23,
483
"server_uptime": "5 days"
484
}
485
486
# Custom documentation with authentication info
487
@app.get("/docs")
488
def docs_with_auth(request):
489
"""Swagger UI with authentication support"""
490
html = app.openapi.get_openapi_docs_page()
491
492
# You could customize the HTML here to add authentication instructions
493
auth_info = """
494
<div style="background: #f8f9fa; padding: 15px; margin: 10px 0; border-radius: 5px;">
495
<h4>Authentication</h4>
496
<p>This API requires authentication for protected endpoints.</p>
497
<p>To authenticate:</p>
498
<ol>
499
<li>Call POST /auth/login with {"username": "admin"}</li>
500
<li>Copy the returned token</li>
501
<li>Click "Authorize" button and enter: Bearer YOUR_TOKEN</li>
502
</ol>
503
</div>
504
"""
505
506
# Insert auth info after the body tag
507
html = html.replace("<body>", f"<body>{auth_info}")
508
509
return html
510
511
app.start()
512
```
513
514
### OpenAPI with Multiple Routers
515
516
```python
517
from robyn import Robyn, SubRouter, OpenAPI
518
519
# Create app with OpenAPI
520
app = Robyn(__file__, openapi=OpenAPI())
521
522
# Create sub-routers with different purposes
523
api_v1 = SubRouter(__file__, prefix="/api/v1", openapi=OpenAPI())
524
admin_router = SubRouter(__file__, prefix="/admin", openapi=OpenAPI())
525
526
# API v1 routes
527
@api_v1.get("/users", openapi_name="List Users V1", openapi_tags=["Users", "V1"])
528
def list_users_v1(request):
529
"""List users - API Version 1"""
530
return {"users": [], "version": "v1"}
531
532
@api_v1.post("/users", openapi_name="Create User V1", openapi_tags=["Users", "V1"])
533
def create_user_v1(request):
534
"""Create user - API Version 1"""
535
return {"message": "User created", "version": "v1"}
536
537
# Admin routes
538
@admin_router.get("/dashboard", openapi_name="Admin Dashboard", openapi_tags=["Admin"])
539
def admin_dashboard(request):
540
"""Administrative dashboard overview"""
541
return {"dashboard": "admin", "stats": {"users": 100}}
542
543
@admin_router.get("/logs", openapi_name="View Logs", openapi_tags=["Admin", "Logs"])
544
def view_logs(request):
545
"""View system logs"""
546
return {"logs": ["Log entry 1", "Log entry 2"]}
547
548
# Include routers
549
app.include_router(api_v1)
550
app.include_router(admin_router)
551
552
# Main app routes
553
@app.get("/", openapi_name="Root", openapi_tags=["General"])
554
def root(request):
555
"""Root endpoint with API information"""
556
return {
557
"api": "My Multi-Router API",
558
"version": "1.0.0",
559
"endpoints": {
560
"docs": "/docs",
561
"openapi": "/openapi.json",
562
"api_v1": "/api/v1",
563
"admin": "/admin"
564
}
565
}
566
567
# Consolidated documentation
568
@app.get("/docs")
569
def comprehensive_docs(request):
570
"""Comprehensive API documentation"""
571
return app.openapi.get_openapi_docs_page()
572
573
@app.get("/openapi.json")
574
def full_openapi_spec(request):
575
"""Complete OpenAPI specification"""
576
return app.openapi.get_openapi_config()
577
578
app.start()
579
```