Class: FTW::WebSocket::Rack
- Inherits:
-
Object
- Object
- FTW::WebSocket::Rack
- Includes:
- Constants
- Defined in:
- lib/ftw/websocket/rack.rb
Overview
A websocket helper for Rack
An example with Sinatra:
get "/websocket/echo" do
ws = FTW::WebSocket::Rack.new(env)
stream(:keep_open) do |out|
ws.each do |payload|
# 'payload' is the text payload of a single websocket message
# publish it back to the client
ws.publish(payload)
end
end
ws.rack_response
end
Constant Summary
Constants included from Constants
Constants::OPCODE_BINARY, Constants::OPCODE_CLOSE, Constants::OPCODE_CONTINUATION, Constants::OPCODE_PING, Constants::OPCODE_PONG, Constants::OPCODE_TEXT, Constants::WEBSOCKET_ACCEPT_UUID
Instance Method Summary collapse
-
#each ⇒ Object
Enumerate each websocket payload (message).
-
#initialize(rack_env) ⇒ Rack
constructor
Create a new websocket rack helper…
-
#publish(message) ⇒ Object
Publish a message over this websocket.
-
#rack_response ⇒ number, ...
Get the response Rack is expecting.
-
#valid? ⇒ Boolean
Is this a valid handshake?.
Constructor Details
#initialize(rack_env) ⇒ Rack
Create a new websocket rack helper… thing.
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/ftw/websocket/rack.rb', line 29 def initialize(rack_env) @env = rack_env @handshake_errors = [] # RFC6455 section 4.2.1 bullet 3 expect_equal("websocket", @env["HTTP_UPGRADE"], "The 'Upgrade' header must be set to 'websocket'") # RFC6455 section 4.2.1 bullet 4 expect_equal("Upgrade", @env["HTTP_CONNECTION"], "The 'Connection' header must be set to 'Upgrade'") # RFC6455 section 4.2.1 bullet 6 expect_equal("13", @env["HTTP_SEC_WEBSOCKET_VERSION"], "Sec-WebSocket-Version must be set to 13") # RFC6455 section 4.2.1 bullet 5 @key = @env["HTTP_SEC_WEBSOCKET_KEY"] @parser = FTW::WebSocket::Parser.new end |
Instance Method Details
#each ⇒ Object
Enumerate each websocket payload (message).
The payload of each message will be yielded to the block.
Example:
ws.each do |payload|
puts "Received: #{payload}"
end
100 101 102 103 104 105 106 107 108 |
# File 'lib/ftw/websocket/rack.rb', line 100 def each connection = @env["ftw.connection"] while true data = connection.read(16384) @parser.feed(data) do |payload| yield payload if !payload.nil? end end end |
#publish(message) ⇒ Object
Publish a message over this websocket.
113 114 115 116 |
# File 'lib/ftw/websocket/rack.rb', line 113 def publish() writer = FTW::WebSocket::Writer.singleton writer.write_text(@env["ftw.connection"], ) end |
#rack_response ⇒ number, ...
Get the response Rack is expecting.
If this was a valid websocket request, it will return a response that completes the HTTP portion of the websocket handshake.
If this was an invalid websocket request, it will return a 400 status code and descriptions of what failed in the body of the response.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/ftw/websocket/rack.rb', line 71 def rack_response if valid? # Return the status, headers, body that is expected. sec_accept = @key + WEBSOCKET_ACCEPT_UUID sec_accept_hash = Digest::SHA1.base64digest(sec_accept) headers = { "Upgrade" => "websocket", "Connection" => "Upgrade", "Sec-WebSocket-Accept" => sec_accept_hash } # See RFC6455 section 4.2.2 return 101, headers, nil else # Invalid request, tell the client why. return 400, { "Content-Type" => "text/plain" }, @handshake_errors.map { |m| "#{m}#{CRLF}" } end end |
#valid? ⇒ Boolean
Is this a valid handshake?
57 58 59 |
# File 'lib/ftw/websocket/rack.rb', line 57 def valid? return @handshake_errors.empty? end |