Class: PumaPlus::WSEvent
- Inherits:
-
Object
- Object
- PumaPlus::WSEvent
- Defined in:
- lib/puma_plus/ws_event.rb
Overview
Convenience wrapper over the WebSocket keys in a Rack env.
A WebSocket event arrives as an ordinary Rack call with REQUEST_METHOD set to WEBSOCKET, so existing routing and middleware work unchanged. This just saves the app from string-keyed env lookups.
Class Method Summary collapse
-
.upgrade(mode: :flexible, topics: [], meta: {}, transport: nil) ⇒ Object
Build the 101 response that asks Go to take over a connection.
- .websocket?(env) ⇒ Boolean
Instance Method Summary collapse
- #binary? ⇒ Boolean
- #close? ⇒ Boolean
- #close_code ⇒ Object
- #close_reason ⇒ Object
- #conn_id ⇒ Object
-
#data ⇒ Object
The message payload.
-
#datagram? ⇒ Boolean
An unreliable datagram.
-
#initialize(env) ⇒ WSEvent
constructor
A new instance of WSEvent.
-
#kind ⇒ Object
open | message | datagram | stream_open | stream_close | close.
- #message? ⇒ Boolean
-
#meta ⇒ Object
Metadata captured at upgrade time and echoed on every event, so a flexible handler knows who it is talking to without a lookup.
- #mode ⇒ Object
- #open? ⇒ Boolean
-
#queue_time ⇒ Object
Queue time for this event, in seconds.
- #sticky? ⇒ Boolean
- #stream_close? ⇒ Boolean
-
#stream_id ⇒ Object
Which stream a WebTransport message arrived on.
- #stream_open? ⇒ Boolean
-
#transport ⇒ Object
"websocket" or "webtransport".
- #webtransport? ⇒ Boolean
Constructor Details
#initialize(env) ⇒ WSEvent
Returns a new instance of WSEvent.
12 13 14 |
# File 'lib/puma_plus/ws_event.rb', line 12 def initialize(env) @env = env end |
Class Method Details
.upgrade(mode: :flexible, topics: [], meta: {}, transport: nil) ⇒ Object
68 69 70 71 72 73 74 75 76 |
# File 'lib/puma_plus/ws_event.rb', line 68 def self.upgrade(mode: :flexible, topics: [], meta: {}, transport: nil) headers = { "puma-plus-websocket" => mode.to_s } headers["puma-plus-transport"] = transport.to_s if transport headers["puma-plus-websocket-topic"] = Array(topics).map(&:to_s) unless Array(topics).empty? unless .empty? headers["puma-plus-websocket-meta"] = .map { |k, v| "#{k}=#{v}" } end [101, headers, []] end |
.websocket?(env) ⇒ Boolean
10 |
# File 'lib/puma_plus/ws_event.rb', line 10 def self.websocket?(env) = env["REQUEST_METHOD"] == "WEBSOCKET" |
Instance Method Details
#binary? ⇒ Boolean
42 |
# File 'lib/puma_plus/ws_event.rb', line 42 def binary? = @env["puma_plus.ws.opcode"] == "binary" |
#close? ⇒ Boolean
20 |
# File 'lib/puma_plus/ws_event.rb', line 20 def close? = kind == "close" |
#close_code ⇒ Object
44 |
# File 'lib/puma_plus/ws_event.rb', line 44 def close_code = @env["puma_plus.ws.close_code"]&.to_i |
#close_reason ⇒ Object
45 |
# File 'lib/puma_plus/ws_event.rb', line 45 def close_reason = @env["puma_plus.ws.close_reason"] |
#conn_id ⇒ Object
39 |
# File 'lib/puma_plus/ws_event.rb', line 39 def conn_id = @env["puma_plus.ws.conn_id"] |
#data ⇒ Object
The message payload.
48 49 50 |
# File 'lib/puma_plus/ws_event.rb', line 48 def data @data ||= (@env["rack.input"]&.read || "") end |
#datagram? ⇒ Boolean
An unreliable datagram. A distinct event kind from #message? on purpose: this payload may have been dropped, duplicated or reordered, and handling it identically to a guaranteed message is usually a bug.
25 |
# File 'lib/puma_plus/ws_event.rb', line 25 def datagram? = kind == "datagram" |
#kind ⇒ Object
open | message | datagram | stream_open | stream_close | close
17 |
# File 'lib/puma_plus/ws_event.rb', line 17 def kind = @env["puma_plus.ws.event"] |
#message? ⇒ Boolean
19 |
# File 'lib/puma_plus/ws_event.rb', line 19 def = kind == "message" |
#meta ⇒ Object
Metadata captured at upgrade time and echoed on every event, so a flexible handler knows who it is talking to without a lookup.
54 55 56 57 58 |
# File 'lib/puma_plus/ws_event.rb', line 54 def @meta ||= @env.each_with_object({}) do |(k, v), h| h[k.delete_prefix("puma_plus.ws.meta.")] = v if k.start_with?("puma_plus.ws.meta.") end end |
#mode ⇒ Object
40 |
# File 'lib/puma_plus/ws_event.rb', line 40 def mode = @env["puma_plus.ws.mode"] |
#open? ⇒ Boolean
18 |
# File 'lib/puma_plus/ws_event.rb', line 18 def open? = kind == "open" |
#queue_time ⇒ Object
Queue time for this event, in seconds. WebSocket messages are queued and measured exactly like HTTP requests, which is what lets them drive autoscaling.
63 |
# File 'lib/puma_plus/ws_event.rb', line 63 def queue_time = @env["puma.request_queue_time"] |
#sticky? ⇒ Boolean
41 |
# File 'lib/puma_plus/ws_event.rb', line 41 def sticky? = mode == "sticky" |
#stream_close? ⇒ Boolean
28 |
# File 'lib/puma_plus/ws_event.rb', line 28 def stream_close? = kind == "stream_close" |
#stream_id ⇒ Object
Which stream a WebTransport message arrived on. nil for WebSocket, whose single channel needs no name.
37 |
# File 'lib/puma_plus/ws_event.rb', line 37 def stream_id = @env["puma_plus.ws.stream_id"] |
#stream_open? ⇒ Boolean
27 |
# File 'lib/puma_plus/ws_event.rb', line 27 def stream_open? = kind == "stream_open" |
#transport ⇒ Object
"websocket" or "webtransport". Usually irrelevant -- that is the point of a shared hub -- but needed before reaching for a datagram.
32 |
# File 'lib/puma_plus/ws_event.rb', line 32 def transport = @env["puma_plus.ws.transport"] |
#webtransport? ⇒ Boolean
33 |
# File 'lib/puma_plus/ws_event.rb', line 33 def webtransport? = transport == "webtransport" |