Skip to content

Commit 353e4d1

Browse files
committed
Update the documentation to reflect the new changes
1 parent 4a7524e commit 353e4d1

2 files changed

Lines changed: 130 additions & 0 deletions

File tree

docs/server_sent_event_routing.md

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
This example demonstrates Grip’s Server-Sent Events (SSE) capabilities. It defines an SSE controller, custom middleware, pipeline-based routing, backpressure strategies, and fiber blocking to handle real-time HTTP streaming connections efficiently.
2+
3+
## Application code
4+
5+
```crystal
6+
# src/application.cr: Defines a Grip application with Server-Sent Events support and middleware.
7+
8+
# Imports the Grip framework for building the web application.
9+
require "grip"
10+
11+
# Wallet handles Server-Sent Event (SSE) streams and real-time domain events.
12+
class Wallet
13+
include Grip::Controllers::ServerSent
14+
15+
# Executed when a client establishes an SSE connection.
16+
# @param context [HTTP::Server::Context] The HTTP request context.
17+
# @return [HTTP::Server::Context] The modified context after streaming.
18+
def stream(context : Context) : Context
19+
# Initializes the SSE stream with backpressure configuration.
20+
# capacity: Sets the buffer size for pending events.
21+
# strategy: Defines how overflow is handled when the queue is full (e.g., Strategy::DropOldest).
22+
stream = context.stream(
23+
capacity: 100,
24+
strategy: Strategy::DropOldest,
25+
)
26+
27+
# 1. Send initial connection handshake frame to the client.
28+
stream.connected(connection_id: ::UUID.random.to_s)
29+
30+
# 2. Emit structured domain data payload.
31+
payload = {
32+
"amount" => 0.25,
33+
"currency" => "USD",
34+
"totalBalance" => 10.50,
35+
}
36+
37+
stream.emit(
38+
Event::Type::Data,
39+
data: payload,
40+
id: 1001,
41+
)
42+
43+
# 3. Emit a protocol error frame if an error header is present.
44+
if context.request.headers.has_key?("X-Simulate-Error")
45+
stream.error(
46+
{
47+
"message" => "Simulated error occurred",
48+
"code" => 500,
49+
}
50+
)
51+
end
52+
53+
# Blocks the fiber, sends ping responses and keeps the HTTP connection open until the client disconnects.
54+
stream.await
55+
56+
# Gracefully halts processing after stream closure.
57+
context.halt
58+
end
59+
end
60+
61+
# PoweredByHeader adds a Server header to HTTP responses.
62+
class PoweredByHeader
63+
include HTTP::Handler
64+
65+
# Adds a Server header to the response.
66+
# @param context [HTTP::Server::Context] The HTTP request context.
67+
# @return [HTTP::Server::Context] The modified context with the added header.
68+
def call(context : HTTP::Server::Context) : HTTP::Server::Context
69+
context
70+
.put_resp_header("Server", "grip") # Sets the Server header to "grip".
71+
end
72+
end
73+
74+
# SecureHeaders adds a Security header to HTTP responses.
75+
class SecureHeaders
76+
include HTTP::Handler
77+
78+
# Adds a Security header to the response.
79+
# @param context [HTTP::Server::Context] The HTTP request context.
80+
# @return [HTTP::Server::Context] The modified context with the added header.
81+
def call(context : HTTP::Server::Context) : HTTP::Server::Context
82+
context
83+
.put_resp_header("Security", "Absolutely") # Sets a custom Security header.
84+
end
85+
end
86+
87+
# Application configures and runs a Grip web application.
88+
class Application
89+
include Grip::Application
90+
91+
# Defines the array of HTTP handlers for processing requests.
92+
property handlers : Array(HTTP::Handler) = [
93+
Grip::Handlers::Pipeline.new, # Manages the request pipeline for middleware execution.
94+
Grip::Handlers::ServerSent.new, # Handles Server-Sent Events protocol logic.
95+
Grip::Handlers::HTTP.new, # Handles core HTTP protocol logic, it must be the last one as it handles all the requests.
96+
] of HTTP::Handler
97+
98+
# Initializes the application and configures routes.
99+
def initialize
100+
routes # Calls the routes method to set up routing.
101+
end
102+
103+
# Defines routing structure and pipelines for SSE streaming endpoints.
104+
def routes
105+
# Pipeline for API requests, applying the PoweredByHeader middleware.
106+
pipeline :api, [
107+
PoweredByHeader.new # Adds a Server header to responses.
108+
]
109+
110+
# Pipeline for web requests, applying the SecureHeaders middleware.
111+
pipeline :web, [
112+
SecureHeaders.new # Adds a Security header to responses.
113+
]
114+
115+
# Routes under the root path ("/").
116+
scope do
117+
pipe_through :web # Applies the SecureHeaders middleware.
118+
pipe_through :api # Applies the PoweredByHeader middleware.
119+
120+
# Maps Server-Sent Event streaming endpoints to Wallet's stream method.
121+
sse "/wallet", Wallet, as: :stream
122+
end
123+
end
124+
end
125+
126+
# Instantiates and starts the Grip application.
127+
app = Application.new
128+
app.run
129+
```

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ nav:
5050
- Advanced routing: "advanced_routing.md"
5151
- Scope: "scope.md"
5252
- Forward: "forward.md"
53+
- Server-Sent Events routing: "server_sent_events_routing.md"
5354
- WebSocket routing: "web_socket_routing.md"
5455
- Available verbs: "verbs.md"
5556
- Runtime flags: "runtime_flags.md"

0 commit comments

Comments
 (0)