whoosh 1.4.0 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/whoosh/streaming/websocket.rb +74 -11
- data/lib/whoosh/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5baff744454d485e7f9788aca18285ece0c8901a5abea6f9c2f3fd4a22a7de75
|
|
4
|
+
data.tar.gz: 6c2062d73b6bec5e60c0adfd897e7e8aec5d10fa366439471592fc196bfe5bbd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7ef32b36e7405fe117eefc60908baf71a9553d328ccd2fd7823c715b7e37d4f01aeedc29a7cb1709e865410d407a32bc511f49353b90339702a06bb7f9a31425
|
|
7
|
+
data.tar.gz: 75188ded90b9205cb7c779d18252ef842989ec84d76ad78e1167d4ca267e544918b39c5d2a3596abe0b2d6001620e98e4272a75bdd62491b4130127bba78487c
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "json"
|
|
4
|
-
require "faye/websocket"
|
|
5
4
|
|
|
6
5
|
module Whoosh
|
|
7
6
|
module Streaming
|
|
@@ -19,7 +18,8 @@ module Whoosh
|
|
|
19
18
|
|
|
20
19
|
# Check if the request is a WebSocket upgrade
|
|
21
20
|
def self.websocket?(env)
|
|
22
|
-
|
|
21
|
+
upgrade = env["HTTP_UPGRADE"]
|
|
22
|
+
upgrade && upgrade.downcase == "websocket"
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
# Register callbacks
|
|
@@ -46,18 +46,47 @@ module Whoosh
|
|
|
46
46
|
return if @closed
|
|
47
47
|
@closed = true
|
|
48
48
|
@ws&.close(code || 1000, reason || "")
|
|
49
|
+
rescue
|
|
50
|
+
# Already closed
|
|
49
51
|
end
|
|
50
52
|
|
|
51
53
|
def closed?
|
|
52
54
|
@closed
|
|
53
55
|
end
|
|
54
56
|
|
|
55
|
-
# Returns a Rack response —
|
|
57
|
+
# Returns a Rack response — auto-detects Faye (Puma) or Async (Falcon)
|
|
56
58
|
def rack_response
|
|
57
59
|
unless self.class.websocket?(@env)
|
|
58
60
|
return [400, { "content-type" => "text/plain" }, ["Not a WebSocket request"]]
|
|
59
61
|
end
|
|
60
62
|
|
|
63
|
+
if async_websocket_available? && falcon_env?
|
|
64
|
+
rack_response_async
|
|
65
|
+
else
|
|
66
|
+
rack_response_faye
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# For testing without real socket
|
|
71
|
+
def trigger_message(msg)
|
|
72
|
+
@on_message&.call(msg)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def trigger_close(code = 1000, reason = "")
|
|
76
|
+
@on_close&.call(code, reason)
|
|
77
|
+
@closed = true
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def trigger_open
|
|
81
|
+
@on_open&.call
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
# Faye WebSocket — works with Puma (threads + EventMachine)
|
|
87
|
+
def rack_response_faye
|
|
88
|
+
require "faye/websocket"
|
|
89
|
+
|
|
61
90
|
@ws = Faye::WebSocket.new(@env)
|
|
62
91
|
|
|
63
92
|
@ws.on :open do |_event|
|
|
@@ -77,18 +106,52 @@ module Whoosh
|
|
|
77
106
|
@ws.rack_response
|
|
78
107
|
end
|
|
79
108
|
|
|
80
|
-
#
|
|
81
|
-
def
|
|
82
|
-
|
|
109
|
+
# Async WebSocket — works with Falcon (fibers + async)
|
|
110
|
+
def rack_response_async
|
|
111
|
+
require "async/websocket/adapters/rack"
|
|
112
|
+
|
|
113
|
+
Async::WebSocket::Adapters::Rack.open(@env, protocols: ["ws"]) do |connection|
|
|
114
|
+
@ws = AsyncWSWrapper.new(connection)
|
|
115
|
+
@on_open&.call
|
|
116
|
+
|
|
117
|
+
while (message = connection.read)
|
|
118
|
+
@on_message&.call(message.to_str)
|
|
119
|
+
end
|
|
120
|
+
rescue EOFError, Protocol::WebSocket::ClosedError
|
|
121
|
+
# Client disconnected
|
|
122
|
+
ensure
|
|
123
|
+
@closed = true
|
|
124
|
+
@on_close&.call(1000, "")
|
|
125
|
+
@ws = nil
|
|
126
|
+
end
|
|
83
127
|
end
|
|
84
128
|
|
|
85
|
-
def
|
|
86
|
-
|
|
87
|
-
@
|
|
129
|
+
def falcon_env?
|
|
130
|
+
# Falcon sets async.* keys in the env
|
|
131
|
+
@env.key?("async.reactor") || @env.key?("protocol.http.request")
|
|
88
132
|
end
|
|
89
133
|
|
|
90
|
-
def
|
|
91
|
-
|
|
134
|
+
def async_websocket_available?
|
|
135
|
+
require "async/websocket/adapters/rack"
|
|
136
|
+
true
|
|
137
|
+
rescue LoadError
|
|
138
|
+
false
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Wrapper to give async-websocket the same #send interface
|
|
142
|
+
class AsyncWSWrapper
|
|
143
|
+
def initialize(connection)
|
|
144
|
+
@connection = connection
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def send(data)
|
|
148
|
+
@connection.write(Protocol::WebSocket::TextMessage.generate(data))
|
|
149
|
+
@connection.flush
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def close(code = 1000, reason = "")
|
|
153
|
+
@connection.close
|
|
154
|
+
end
|
|
92
155
|
end
|
|
93
156
|
end
|
|
94
157
|
end
|
data/lib/whoosh/version.rb
CHANGED