diff --git a/lib/cramp/websocket/extension.rb b/lib/cramp/websocket/extension.rb index a714364..4750c56 100644 --- a/lib/cramp/websocket/extension.rb +++ b/lib/cramp/websocket/extension.rb @@ -1,9 +1,16 @@ +require 'base64' +require 'digest/sha1' + module Cramp module WebsocketExtension WEBSOCKET_RECEIVE_CALLBACK = 'websocket.receive_callback'.freeze + def protocol_class + @env['HTTP_SEC_WEBSOCKET_VERSION'] ? Protocol10 : Protocol76 + end + def websocket? - @env['HTTP_CONNECTION'] == 'Upgrade' && @env['HTTP_UPGRADE'] == 'WebSocket' + @env['HTTP_CONNECTION'] == 'Upgrade' && ['WebSocket', 'websocket'].include?(@env['HTTP_UPGRADE']) end def secure_websocket? @@ -20,13 +27,27 @@ def websocket_url end class WebSocketHandler - def initialize(env, websocket_url, body) + def initialize(env, websocket_url, body = nil) @env = env @websocket_url = websocket_url @body = body end end + class Protocol10 < WebSocketHandler + MAGIC_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11".freeze + + def handshake + digest = Base64.encode64(Digest::SHA1.digest("#{@env['HTTP_SEC_WEBSOCKET_KEY']}#{MAGIC_GUID}")).chomp + + upgrade = "HTTP/1.1 101 Switching Protocols\r\n" + upgrade << "Upgrade: websocket\r\n" + upgrade << "Connection: Upgrade\r\n" + upgrade << "Sec-WebSocket-Accept: #{digest}\r\n\r\n" + upgrade + end + end + class Protocol76 < WebSocketHandler def handshake key1 = @env['HTTP_SEC_WEBSOCKET_KEY1'] diff --git a/lib/cramp/websocket/rainbows.rb b/lib/cramp/websocket/rainbows.rb index 9f3691e..dbd1ff7 100644 --- a/lib/cramp/websocket/rainbows.rb +++ b/lib/cramp/websocket/rainbows.rb @@ -24,7 +24,7 @@ def on_read(data) @state = :websocket @input.rewind - write(Protocol76.new(@env, websocket_url, @buf).handshake) + write(protocol_class.new(@env, websocket_url, @buf).handshake) app_call NULL_IO else super diff --git a/lib/cramp/websocket/thin_backend.rb b/lib/cramp/websocket/thin_backend.rb index d92d998..28e218d 100644 --- a/lib/cramp/websocket/thin_backend.rb +++ b/lib/cramp/websocket/thin_backend.rb @@ -33,7 +33,7 @@ class Thin::Request include Cramp::WebsocketExtension def websocket_upgrade_data - Protocol76.new(@env, websocket_url, body.read).handshake + protocol_class.new(@env, websocket_url, body.read).handshake end end