|
1 | | -# Examples |
2 | | - |
3 | | -Middleware |
4 | | -```python |
5 | | -from socketify import App, middleware |
6 | | - |
7 | | - |
8 | | -async def get_user(authorization): |
9 | | - if authorization: |
10 | | - # you can do something async here |
11 | | - return {"greeting": "Hello, World"} |
12 | | - return None |
13 | | - |
14 | | - |
15 | | -async def auth(res, req, data=None): |
16 | | - user = await get_user(req.get_header("authorization")) |
17 | | - if not user: |
18 | | - res.write_status(403).end("not authorized") |
19 | | - # returning Falsy in middlewares just stop the execution of the next middleware |
20 | | - return False |
21 | | - |
22 | | - # returns extra data |
23 | | - return user |
24 | | - |
25 | | - |
26 | | -def another_middie(res, req, data=None): |
27 | | - # now we can mix sync and async and change the data here |
28 | | - if isinstance(data, dict): |
29 | | - gretting = data.get("greeting", "") |
30 | | - data["greeting"] = f"{gretting} from another middie ;)" |
31 | | - return data |
32 | | - |
33 | | - |
34 | | -def home(res, req, user=None): |
35 | | - res.cork_end(user.get("greeting", None)) |
36 | | - |
37 | | - |
38 | | -app = App() |
39 | | -app.get("/", middleware(auth, another_middie, home)) |
40 | | -app.listen( |
41 | | - 3000, |
42 | | - lambda config: print("Listening on port http://localhost:%d now\n" % config.port), |
43 | | -) |
44 | | -app.run() |
45 | | - |
46 | | -# You can also take a loop on MiddlewareRouter in middleware_router.py ;) |
47 | | -``` |
48 | | - |
49 | | -Broadcast |
50 | | -```python |
51 | | -from socketify import App, AppOptions, OpCode, CompressOptions |
52 | | - |
53 | | - |
54 | | -def ws_open(ws): |
55 | | - print("A WebSocket got connected!") |
56 | | - # Let this client listen to topic "broadcast" |
57 | | - ws.subscribe("broadcast") |
58 | | - |
59 | | - |
60 | | -def ws_message(ws, message, opcode): |
61 | | - # Broadcast this message |
62 | | - ws.publish("broadcast", message, opcode) |
63 | | - |
64 | | -app = App() |
65 | | -app.ws( |
66 | | - "/*", |
67 | | - { |
68 | | - "compression": CompressOptions.SHARED_COMPRESSOR, |
69 | | - "max_payload_length": 16 * 1024 * 1024, |
70 | | - "idle_timeout": 60, |
71 | | - "open": ws_open, |
72 | | - "message": ws_message, |
73 | | - # The library guarantees proper unsubscription at close |
74 | | - "close": lambda ws, code, message: print("WebSocket closed"), |
75 | | - "subscription": lambda ws, topic, subscriptions, subscriptions_before: print(f'subscription/unsubscription on topic {topic} {subscriptions} {subscriptions_before}'), |
76 | | - }, |
77 | | -) |
78 | | -app.any("/", lambda res, req: res.end("Nothing to see here!")) |
79 | | -app.listen( |
80 | | - 3000, |
81 | | - lambda config: print("Listening on port http://localhost:%d now\n" % (config.port)), |
82 | | -) |
83 | | -app.run() |
84 | | -``` |
85 | | - |
86 | | -HTTPS |
87 | | -```python |
88 | | -from socketify import App, AppOptions |
89 | | - |
90 | | -app = App( |
91 | | - AppOptions( |
92 | | - key_file_name="./misc/key.pem", |
93 | | - cert_file_name="./misc/cert.pem", |
94 | | - passphrase="1234", |
95 | | - ) |
96 | | -) |
97 | | -app.get("/", lambda res, req: res.end("Hello World socketify from Python!")) |
98 | | -app.listen( |
99 | | - 54321, |
100 | | - lambda config: print("Listening on port https://localhost:%d now\n" % config.port), |
101 | | -) |
102 | | -app.run() |
103 | | - |
104 | | -# mkdir misc |
105 | | -# openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -passout pass:1234 -keyout ./misc/key.pem -out ./misc/cert.pem |
106 | | -``` |
107 | | - |
108 | | -Backpressure |
109 | | -```python |
110 | | -from socketify import App, AppOptions, OpCode, CompressOptions |
111 | | - |
112 | | -# Number between ok and not ok |
113 | | -backpressure = 1024 |
114 | | - |
115 | | -# Used for statistics |
116 | | -messages = 0 |
117 | | -message_number = 0 |
118 | | - |
119 | | - |
120 | | -def ws_open(ws): |
121 | | - print("A WebSocket got connected!") |
122 | | - # We begin our example by sending until we have backpressure |
123 | | - global message_number |
124 | | - global messages |
125 | | - while ws.get_buffered_amount() < backpressure: |
126 | | - ws.send("This is a message, let's call it %i" % message_number) |
127 | | - message_number = message_number + 1 |
128 | | - messages = messages + 1 |
129 | | - |
130 | | - |
131 | | -def ws_drain(ws): |
132 | | - # Continue sending when we have drained (some) |
133 | | - global message_number |
134 | | - global messages |
135 | | - while ws.get_buffered_amount() < backpressure: |
136 | | - ws.send("This is a message, let's call it %i" % message_number) |
137 | | - message_number = message_number + 1 |
138 | | - messages = messages + 1 |
139 | | - |
140 | | - |
141 | | -app = App() |
142 | | -app.ws( |
143 | | - "/*", |
144 | | - { |
145 | | - "compression": CompressOptions.DISABLED, |
146 | | - "max_payload_length": 16 * 1024 * 1024, |
147 | | - "idle_timeout": 60, |
148 | | - "open": ws_open, |
149 | | - "drain": ws_drain, |
150 | | - }, |
151 | | -) |
152 | | -app.any("/", lambda res, req: res.end("Nothing to see here!")) |
153 | | -app.listen( |
154 | | - 3000, |
155 | | - lambda config: print("Listening on port http://localhost:%d now\n" % (config.port)), |
156 | | -) |
157 | | -app.run() |
158 | | -``` |
| 1 | +## 📚 Examples |
| 2 | + |
| 3 | +All examples are located in the [`examples`](https://github.com/cirospaciari/socketify.py/tree/main/examples) directory. |
| 4 | + |
| 5 | +### 🚀 Getting Started |
| 6 | + |
| 7 | +- [`hello_world.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/hello_world.py) - Basic HTTP server setup |
| 8 | +- [`hello_world_cli.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/hello_world_cli.py) - Command-line interface example |
| 9 | +- [`hello_world_cli_ws.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/hello_world_cli_ws.py) - CLI with WebSocket support |
| 10 | +- [`hello_world_unix_domain.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/hello_world_unix_domain.py) - Unix domain socket example |
| 11 | + |
| 12 | +### 🔒 Security & HTTPS |
| 13 | + |
| 14 | +- [`https.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/https.py) - HTTPS server with SSL/TLS configuration |
| 15 | + |
| 16 | +### 🌐 WebSocket Examples |
| 17 | + |
| 18 | +- [`websockets.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/websockets.py) - Basic WebSocket implementation |
| 19 | +- [`ws_close_connection.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/ws_close_connection.py) - WebSocket connection management |
| 20 | +- [`chat/`](https://github.com/cirospaciari/socketify.py/tree/main/examples/chat) - Real-time chat application |
| 21 | +- [`broadcast.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/broadcast.py) - Broadcasting messages to multiple clients |
| 22 | +- [`backpressure.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/backpressure.py) - Handling WebSocket backpressure |
| 23 | + |
| 24 | +### ⚙️ Middleware & Routing |
| 25 | + |
| 26 | +- [`middleware.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/middleware.py) - Basic middleware implementation |
| 27 | +- [`middleware_async.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/middleware_async.py) - Asynchronous middleware |
| 28 | +- [`middleware_sync.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/middleware_sync.py) - Synchronous middleware |
| 29 | +- [`middleware_router.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/middleware_router.py) - Router-based middleware |
| 30 | +- [`router_and_basics.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/router_and_basics.py) - Routing fundamentals |
| 31 | + |
| 32 | +### 🔄 Async/Sync Programming |
| 33 | + |
| 34 | +- [`async.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/async.py) - Asynchronous request handling |
| 35 | +- [`upgrade.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/upgrade.py) - Protocol upgrade examples |
| 36 | +- [`upgrade_async.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/upgrade_async.py) - Asynchronous protocol upgrades |
| 37 | + |
| 38 | +### 📁 File Handling & Static Content |
| 39 | + |
| 40 | +- [`static_files.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/static_files.py) - Serving static files |
| 41 | +- [`file_stream.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/file_stream.py) - File streaming capabilities |
| 42 | +- [`upload_or_post.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/upload_or_post.py) - File uploads and POST data handling |
| 43 | + |
| 44 | +### 🎨 Template Engines |
| 45 | + |
| 46 | +- [`template_jinja2.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/template_jinja2.py) - Jinja2 template integration |
| 47 | +- [`template_mako.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/template_mako.py) - Mako template integration |
| 48 | +- [`templates/`](https://github.com/cirospaciari/socketify.py/tree/main/examples/templates) - Template examples and resources |
| 49 | + |
| 50 | +### 🛠️ Advanced Features |
| 51 | + |
| 52 | +- [`custom_json_serializer.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/custom_json_serializer.py) - Custom JSON serialization |
| 53 | +- [`http_request_cache.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/http_request_cache.py) - HTTP request caching |
| 54 | +- [`proxy.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/proxy.py) - Proxy server implementation |
| 55 | +- [`automatic_port_selection.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/automatic_port_selection.py) - Dynamic port selection |
| 56 | + |
| 57 | +### 🔧 Server Configuration |
| 58 | + |
| 59 | +- [`listen_options.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/listen_options.py) - Server listening options |
| 60 | +- [`graceful_shutdown.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/graceful_shutdown.py) - Graceful server shutdown |
| 61 | +- [`forks.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/forks.py) - Multi-process server setup |
| 62 | + |
| 63 | +### 📊 GraphQL Integration |
| 64 | + |
| 65 | +- [`graphiql.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/graphiql.py) - GraphiQL interface setup |
| 66 | +- [`graphiql_raw.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/graphiql_raw.py) - Raw GraphQL implementation |
| 67 | + |
| 68 | +### 🐳 Development & Deployment |
| 69 | + |
| 70 | +- [`docker/`](https://github.com/cirospaciari/socketify.py/tree/main/examples/docker) - Docker containerization examples |
| 71 | +- [`requirements.txt`](https://github.com/cirospaciari/socketify.py/tree/main/examples/requirements.txt) - Example dependencies |
| 72 | + |
| 73 | +### 🛡️ Error Handling & Logging |
| 74 | + |
| 75 | +- [`error_handler.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/error_handler.py) - Error handling strategies |
| 76 | +- [`better_logging.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/better_logging.py) - Advanced logging setup |
| 77 | +- [`not_found.py`](https://github.com/cirospaciari/socketify.py/tree/main/examples/not_found.py) - Custom 404 error pages |
| 78 | + |
| 79 | +### 🔨 Utilities & Helpers |
| 80 | + |
| 81 | +- [`helpers/`](https://github.com/cirospaciari/socketify.py/tree/main/examples/helpers) - Utility functions and helper modules |
0 commit comments