Skip to content

Commit 0faee70

Browse files
committed
Fix Server implementation and add more tests.
1 parent 8546d08 commit 0faee70

File tree

4 files changed

+115
-104
lines changed

4 files changed

+115
-104
lines changed

lib/async/websocket/server.rb

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,37 +13,15 @@ module WebSocket
1313
class Server < ::Protocol::HTTP::Middleware
1414
include ::Protocol::WebSocket::Headers
1515

16-
def initialize(delegate, protocols: [], handler: Connection)
16+
def initialize(delegate, **options, &block)
1717
super(delegate)
1818

19-
@protocols = protocols
20-
@handler = handler
21-
end
22-
23-
def select_protocol(request)
24-
if requested_protocol = request.headers[SEC_WEBSOCKET_PROTOCOL]
25-
return (requested_protocol & @protocols).first
26-
end
27-
end
28-
29-
def response(request)
19+
@options = options
20+
@block = block
3021
end
3122

3223
def call(request)
33-
if request.protocol == PROTOCOL
34-
# Select websocket sub-protocol:
35-
protocol = select_protocol(request)
36-
37-
# request.headers = nil
38-
39-
Response.for(request, headers, protocol: protocol, **options) do |stream|
40-
framer = Protocol::WebSocket::Framer.new(stream)
41-
42-
yield handler.call(framer, protocol)
43-
end
44-
else
45-
super
46-
end
24+
Async::WebSocket::Adapters::HTTP.open(request, **@options, &@block) or super
4725
end
4826
end
4927
end

test/async/websocket/adapters/rack.rb

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,42 +9,49 @@
99
require 'rack_application'
1010

1111
describe Async::WebSocket::Adapters::Rack do
12-
include RackApplication
13-
14-
it "can make non-websocket connection to server" do
15-
response = client.get("/")
16-
17-
expect(response).to be(:success?)
18-
expect(response.read).to be == "Hello World"
19-
20-
client.close
21-
end
22-
23-
let(:message) do
24-
Protocol::WebSocket::JSONMessage.generate({text: "Hello World"})
12+
it "can determine whether a rack env is a websocket request" do
13+
expect(Async::WebSocket::Adapters::Rack.websocket?(Rack::MockRequest.env_for("/"))).to be == false
14+
expect(Async::WebSocket::Adapters::Rack.websocket?(Rack::MockRequest.env_for("/", 'HTTP_CONNECTION' => 'upgrade', 'HTTP_UPGRADE' => 'websocket'))).to be == true
2515
end
2616

27-
it "can make websocket connection to server" do
28-
Async::WebSocket::Client.connect(client_endpoint) do |connection|
29-
connection.write(message)
17+
with 'rack application' do
18+
include RackApplication
19+
20+
it "can make non-websocket connection to server" do
21+
response = client.get("/")
3022

31-
expect(connection.read).to be == message
23+
expect(response).to be(:success?)
24+
expect(response.read).to be == "Hello World"
3225

33-
connection.close
26+
client.close
3427
end
35-
end
36-
37-
it "should use mask over insecure connection" do
38-
expect(endpoint).not.to be(:secure?)
3928

40-
Async::WebSocket::Client.connect(client_endpoint) do |connection|
41-
expect(connection.mask).not.to be_nil
29+
let(:message) do
30+
Protocol::WebSocket::JSONMessage.generate({text: "Hello World"})
4231
end
43-
end
44-
45-
it "should negotiate protocol" do
46-
Async::WebSocket::Client.connect(client_endpoint, protocols: ['ws']) do |connection|
47-
expect(connection.protocol).to be == 'ws'
32+
33+
it "can make websocket connection to server" do
34+
Async::WebSocket::Client.connect(client_endpoint) do |connection|
35+
connection.write(message)
36+
37+
expect(connection.read).to be == message
38+
39+
connection.close
40+
end
41+
end
42+
43+
it "should use mask over insecure connection" do
44+
expect(endpoint).not.to be(:secure?)
45+
46+
Async::WebSocket::Client.connect(client_endpoint) do |connection|
47+
expect(connection.mask).not.to be_nil
48+
end
49+
end
50+
51+
it "should negotiate protocol" do
52+
Async::WebSocket::Client.connect(client_endpoint, protocols: ['ws']) do |connection|
53+
expect(connection.protocol).to be == 'ws'
54+
end
4855
end
4956
end
5057
end

test/async/websocket/client.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11

22

33
ClientExamples = Sus::Shared("a websocket client") do
4-
include Sus::Fixtures::Async::HTTP::ServerContext
5-
64
let(:app) do
75
Protocol::HTTP::Middleware.for do |request|
86
Async::WebSocket::Adapters::HTTP.open(request) do |connection|
@@ -15,8 +13,6 @@
1513
end
1614
end
1715

18-
let(:timeout) {nil}
19-
2016
it "can connect to a websocket server and close underlying client" do
2117
Async do |task|
2218
connection = Async::WebSocket::Client.connect(client_endpoint)
@@ -31,11 +27,15 @@
3127
end
3228

3329
describe Async::WebSocket::Client do
34-
with "http/1", protocol: Async::HTTP::Protocol::HTTP1 do
30+
include Sus::Fixtures::Async::HTTP::ServerContext
31+
32+
with 'http/1' do
33+
let(:protocol) {Async::HTTP::Protocol::HTTP1}
3534
it_behaves_like ClientExamples
3635
end
37-
38-
with "http/2", protocol: Async::HTTP::Protocol::HTTP2 do
36+
37+
with 'http/2' do
38+
let(:protocol) {Async::HTTP::Protocol::HTTP2}
3939
it_behaves_like ClientExamples
4040
end
4141
end

test/async/websocket/server.rb

Lines changed: 68 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# Copyright, 2022, by Samuel Williams.
55

66
require 'protocol/websocket/json_message'
7+
require 'protocol/http/middleware/builder'
78

89
require 'async/websocket/client'
910
require 'async/websocket/server'
@@ -12,54 +13,77 @@
1213
require 'sus/fixtures/async/http/server_context'
1314

1415
ServerExamples = Sus::Shared('a websocket server') do
15-
include Sus::Fixtures::Async::HTTP::ServerContext
16-
17-
let(:message) {"Hello World"}
18-
19-
let(:app) do
20-
Protocol::HTTP::Middleware.for do |request|
21-
Async::WebSocket::Adapters::HTTP.open(request) do |connection|
22-
connection.send_text(message)
23-
connection.close
24-
end or Protocol::HTTP::Response[404, {}, []]
25-
end
26-
end
27-
2816
let(:websocket_client) {Async::WebSocket::Client.open(client_endpoint)}
2917

30-
it "can establish connection" do
31-
connection = websocket_client.connect(endpoint.authority, "/server")
32-
33-
begin
34-
expect(connection.read).to be == message
35-
expect(connection.read).to be_nil
36-
expect(connection).to be(:closed?)
37-
ensure
38-
connection.close
39-
end
40-
end
41-
42-
with "headers" do
43-
let(:headers) {{"foo" => "bar"}}
18+
with 'generic application' do
19+
let(:message) {"Hello World"}
4420

4521
let(:app) do
4622
Protocol::HTTP::Middleware.for do |request|
4723
Async::WebSocket::Adapters::HTTP.open(request) do |connection|
48-
message = Protocol::WebSocket::JSONMessage.generate(request.headers.fields)
49-
message.send(connection)
50-
24+
connection.send_text(message)
5125
connection.close
5226
end or Protocol::HTTP::Response[404, {}, []]
5327
end
5428
end
5529

56-
it "can send headers" do
57-
connection = websocket_client.connect(endpoint.authority, "/headers", headers: headers)
30+
it "can establish connection" do
31+
connection = websocket_client.connect(endpoint.authority, "/server")
5832

5933
begin
60-
json_message = Protocol::WebSocket::JSONMessage.wrap(connection.read)
34+
expect(connection.read).to be == message
35+
expect(connection.read).to be_nil
36+
expect(connection).to be(:closed?)
37+
ensure
38+
connection.close
39+
end
40+
end
41+
42+
with "headers" do
43+
let(:headers) {{"foo" => "bar"}}
44+
45+
let(:app) do
46+
Protocol::HTTP::Middleware.for do |request|
47+
Async::WebSocket::Adapters::HTTP.open(request) do |connection|
48+
message = Protocol::WebSocket::JSONMessage.generate(request.headers.fields)
49+
message.send(connection)
50+
51+
connection.close
52+
end or Protocol::HTTP::Response[404, {}, []]
53+
end
54+
end
55+
56+
it "can send headers" do
57+
connection = websocket_client.connect(endpoint.authority, "/headers", headers: headers)
6158

62-
expect(json_message.to_h).to have_keys(*headers.keys)
59+
begin
60+
json_message = Protocol::WebSocket::JSONMessage.wrap(connection.read)
61+
62+
expect(json_message.to_h).to have_keys(*headers.keys)
63+
expect(connection.read).to be_nil
64+
expect(connection).to be(:closed?)
65+
ensure
66+
connection.close
67+
end
68+
end
69+
end
70+
end
71+
72+
with 'server middleware' do
73+
let(:app) do
74+
Protocol::HTTP::Middleware.build do
75+
use Async::WebSocket::Server do |connection|
76+
connection.send_text("Hello World")
77+
connection.close
78+
end
79+
end
80+
end
81+
82+
it "can establish connection" do
83+
connection = websocket_client.connect(endpoint.authority, "/server")
84+
85+
begin
86+
expect(connection.read).to be == "Hello World"
6387
expect(connection.read).to be_nil
6488
expect(connection).to be(:closed?)
6589
ensure
@@ -69,14 +93,16 @@
6993
end
7094
end
7195

72-
describe Async::HTTP::Protocol::HTTP1 do
73-
let(:protocol) {subject}
96+
describe Async::WebSocket::Server do
97+
include Sus::Fixtures::Async::HTTP::ServerContext
7498

75-
it_behaves_like ServerExamples
76-
end
77-
78-
describe Async::HTTP::Protocol::HTTP2 do
79-
let(:protocol) {subject}
99+
with 'http/1' do
100+
let(:protocol) {Async::HTTP::Protocol::HTTP1}
101+
it_behaves_like ServerExamples
102+
end
80103

81-
it_behaves_like ServerExamples
104+
with 'http/2' do
105+
let(:protocol) {Async::HTTP::Protocol::HTTP2}
106+
it_behaves_like ServerExamples
107+
end
82108
end

0 commit comments

Comments
 (0)