-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplugins_example.py
More file actions
123 lines (98 loc) · 3.68 KB
/
plugins_example.py
File metadata and controls
123 lines (98 loc) · 3.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
"""
Plugins and Exception Handling Example
This example demonstrates:
- Creating and using plugins (middleware)
- Custom exception handlers
- Advanced routing with nested paths
"""
import time
from webspark.core import Plugin, View, WebSpark, path
from webspark.http import Context
from webspark.utils import HTTPException
# Simple logging plugin
class LoggingPlugin(Plugin):
def apply(self, handler):
def wrapped_handler(ctx: Context):
start_time = time.time()
print(f"[LOG] {ctx.method} {ctx.path} - Start")
try:
handler(ctx)
duration = time.time() - start_time
print(
f"[LOG] {ctx.method} {ctx.path} - Completed in {duration:.4f}s with status {ctx.status}"
)
except Exception as e:
duration = time.time() - start_time
print(
f"[LOG] {ctx.method} {ctx.path} - Failed in {duration:.4f}s with error: {e}"
)
raise
return wrapped_handler
# Authentication plugin (simulated)
class AuthPlugin(Plugin):
def apply(self, handler):
def wrapped_handler(ctx: Context):
# In a real app, you would check a token or session
auth_header = ctx.headers.get("Authorization")
if not auth_header or not auth_header.startswith("Bearer "):
raise HTTPException("Unauthorized", status=401)
# Extract token (in a real app, you would validate it)
token = auth_header[7:] # Remove "Bearer "
if token != "secret-token":
raise HTTPException("Invalid token", status=401)
# Add user info to request for use in views
ctx.state["user"] = {"id": 1, "username": "admin"}
handler(ctx)
return wrapped_handler
# Views
class PublicView(View):
def handle_get(self, ctx: Context):
ctx.json({"message": "This is a public endpoint", "timestamp": time.time()})
class ProtectedView(View):
def handle_get(self, ctx: Context):
ctx.json(
{
"message": "This is a protected endpoint",
"user": ctx.state.get("user"),
"timestamp": time.time(),
}
)
class ErrorView(View):
def handle_get(self, request):
# Simulate an error
raise HTTPException("Something went wrong", status=500)
# Create the app with global plugins
app = WebSpark(debug=True, plugins=[LoggingPlugin()])
# Add custom exception handler
@app.handle_exception(500)
def handle_server_error(ctx: Context, exc):
"""Custom handler for 500 Internal Server Error."""
if app.debug:
ctx.text(f"Server Error: {str(exc)}", status=500)
else:
ctx.json({"error": "Internal server error"}, status=500)
@app.handle_exception(401)
def handle_unauthorized(ctx: Context, exc):
"""Custom handler for 401 Unauthorized."""
ctx.json({"error": "Unauthorized access"}, status=401)
# Add routes with nested paths and specific plugins
app.add_paths(
[
path("/", view=PublicView.as_view()),
path(
"/api",
children=[
path("/public", view=PublicView.as_view()),
path(
"/protected", view=ProtectedView.as_view(), plugins=[AuthPlugin()]
),
path("/error", view=ErrorView.as_view()),
],
),
]
)
if __name__ == "__main__":
# For development purposes, you can run this with a WSGI server like:
# gunicorn examples.plugins_example:app
print("Plugins and Exception Handling Example")
print("Run with: gunicorn examples.plugins_example:app")