Class: Async::WebSocket::Server::Rack

Inherits:
Object
  • Object
show all
Defined in:
lib/async/websocket/server/rack.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(env, supported_protocols: [], **options) ⇒ Rack

Returns a new instance of Rack.



43
44
45
46
47
48
49
50
51
# File 'lib/async/websocket/server/rack.rb', line 43

def initialize(env, supported_protocols: [], **options)
	scheme = env['rack.url_scheme'] == 'https' ? 'wss' : 'ws'
	@url = "#{scheme}://#{env['HTTP_HOST']}#{env['REQUEST_URI']}"
	
	@key = env['HTTP_SEC_WEBSOCKET_KEY']
	@version = Integer(env['HTTP_SEC_WEBSOCKET_VERSION'])
	
	@protocol = negotiate_protocol(env, supported_protocols)
end

Instance Attribute Details

#protocolObject (readonly)

Returns the value of attribute protocol.



59
60
61
# File 'lib/async/websocket/server/rack.rb', line 59

def protocol
  @protocol
end

Class Method Details

.open(env, **options, &block) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
# File 'lib/async/websocket/server/rack.rb', line 31

def self.open(env, **options, &block)
	return nil unless env['rack.hijack?']
	
	connection = self.new(env, **options)
	
	if connection.supported?
		return connection.response(&block)
	else
		return nil
	end
end

Instance Method Details

#make_connection(stream) ⇒ Object



65
66
67
68
69
# File 'lib/async/websocket/server/rack.rb', line 65

def make_connection(stream)
	framer = Protocol::WebSocket::Framer.new(stream)
	
	Connection.new(framer, @protocol)
end

#negotiate_protocol(env, supported_protocols) ⇒ Object



53
54
55
56
57
# File 'lib/async/websocket/server/rack.rb', line 53

def negotiate_protocol(env, supported_protocols)
	if supported_protocols and client_protocols = env['HTTP_SEC_WEBSOCKET_PROTOCOL']
		return (supported_protocols & client_protocols.split(/\s*,\s/)).first
	end
end

#response(&block) ⇒ Object



85
86
87
88
89
90
91
92
# File 'lib/async/websocket/server/rack.rb', line 85

def response(&block)
	headers = [
		['rack.hijack', ->(stream){block.call(make_connection(stream))}]
	]
	
	# https://stackoverflow.com/questions/13545453/http-response-code-when-requested-websocket-subprotocol-isnt-supported-recogniz
	return [101, response_headers + headers, nil]
end

#response_headersObject



71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/async/websocket/server/rack.rb', line 71

def response_headers
	headers = [
		['connection', 'upgrade'],
		['upgrade', 'websocket'],
		['sec-websocket-accept', ::Protocol::WebSocket.accept_digest(@key)],
	]
	
	if @protocol
		headers << ['sec-websocket-protocol', @protocol]
	end
	
	return headers
end

#supported?Boolean

Returns:

  • (Boolean)


61
62
63
# File 'lib/async/websocket/server/rack.rb', line 61

def supported?
	@key and @version == 13
end