Skip to content

Commit

Permalink
Fix WebSocket negotiation (#4386)
Browse files Browse the repository at this point in the history
* Fix WebSocket HTTP negotiation (#4340)
* Add WebSocket HTTP and HTTPS negotiation specs
  • Loading branch information
RX14 authored and bcardiff committed May 18, 2017
1 parent deef66c commit 96169cc
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 0 deletions.
78 changes: 78 additions & 0 deletions spec/std/http/web_socket_spec.cr
Expand Up @@ -293,6 +293,84 @@ describe HTTP::WebSocket do
end
end

it "negotiates over HTTP correctly" do
port_chan = Channel(Int32).new

spawn do
http_ref = nil
ws_handler = HTTP::WebSocketHandler.new do |ws, ctx|
ctx.request.path.should eq("/")

ws.on_message do |str|
ws.send("pong #{str}")
end

ws.on_close do
http_ref.not_nil!.close
end
end

http_server = http_ref = HTTP::Server.new(0, [ws_handler])
http_server.bind
port_chan.send(http_server.port)
http_server.listen
end

listen_port = port_chan.receive

ws2 = HTTP::WebSocket.new("ws://127.0.0.1:#{listen_port}")

random = SecureRandom.hex
ws2.on_message do |str|
str.should eq("pong #{random}")
ws2.close
end
ws2.send(random)

ws2.run
end

it "negotiates over HTTPS correctly" do
port_chan = Channel(Int32).new

spawn do
http_ref = nil
ws_handler = HTTP::WebSocketHandler.new do |ws, ctx|
ctx.request.path.should eq("/")

ws.on_message do |str|
ws.send("pong #{str}")
end

ws.on_close do
http_ref.not_nil!.close
end
end

http_server = http_ref = HTTP::Server.new(0, [ws_handler])
tls = http_server.tls = OpenSSL::SSL::Context::Server.new
tls.certificate_chain = File.join(__DIR__, "../openssl/ssl/openssl.crt")
tls.private_key = File.join(__DIR__, "../openssl/ssl/openssl.key")
http_server.bind
port_chan.send(http_server.port)
http_server.listen
end

listen_port = port_chan.receive

client_context = OpenSSL::SSL::Context::Client.insecure
ws2 = HTTP::WebSocket.new("127.0.0.1", port: listen_port, path: "/", tls: client_context)

random = SecureRandom.hex
ws2.on_message do |str|
str.should eq("pong #{random}")
ws2.close
end
ws2.send(random)

ws2.run
end

typeof(HTTP::WebSocket.new(URI.parse("ws://localhost")))
typeof(HTTP::WebSocket.new("localhost", "/"))
typeof(HTTP::WebSocket.new("ws://localhost"))
Expand Down
1 change: 1 addition & 0 deletions src/http/web_socket/protocol.cr
Expand Up @@ -269,6 +269,7 @@ class HTTP::WebSocket::Protocol
path = "/" if path.empty?
handshake = HTTP::Request.new("GET", path, headers)
handshake.to_io(socket)
socket.flush
handshake_response = HTTP::Client::Response.from_io(socket)
unless handshake_response.status_code == 101
raise Socket::Error.new("Handshake got denied. Status code was #{handshake_response.status_code}")
Expand Down

0 comments on commit 96169cc

Please sign in to comment.