1 # -*- encoding: binary -*-
4 # This module is intended to be used in subclasses of Rack::Request
5 # This is normally used inside Sunshowers::Request, but may be included
6 # in Rack::Request-derived subclasses such as Sinatra::Request.
9 # Raised when processing of the current request is halted by the server.
10 # Rainbows! will not log errors or backtraces for EOFError-derived
11 # exceptions. You may rescue Sunshowers::WebSocket::Quit in other
12 # middlewares for logging (and re-raise it afterwards).
13 class Quit < EOFError; end
15 # the pywebsocket/src/example/echo_client.py has a hard-coded dependency
16 # on the first 3 lines of the following response.
17 # Order and case both matter for the first 3 lines
19 "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" \
20 "Upgrade: WebSocket\r\n" \
21 "Connection: Upgrade\r\n" \
22 "WebSocket-Origin: %s\r\n" \
23 "WebSocket-Location: %s\r\n" \
26 # returns true if WebSockets may be used, false otherwise
28 # yes, case sensitive header values
29 @env["HTTP_CONNECTION"] =~ /\AUpgrade\z/ &&
30 @env["HTTP_UPGRADE"] =~ /\AWebSocket\z/ &&
35 # returns the contents of the Origin: header
38 end unless method_defined?(:origin)
40 # performs the Web Sockets handshake, only call this once
41 # per application dispatch (unless you want to test error
42 # handling behavior in your clients).
44 ws? or raise HandShakeError, "not a Web Sockets request"
45 # get the bare IO-ish object that does not encode, this can be
46 # a Rainbows::Fiber::IO object
48 wsp = wsp ? "WebSocket-Protocol: #{wsp}\r\n" : ""
49 ws_io.to_io.write(sprintf(HANDSHAKE_HEAD, origin, ws_location, wsp))
52 # returns the underlying protocol used
54 protocol = @env["HTTP_WEBSOCKET_PROTOCOL"] or return
55 protocol =~ /\A[\x20-\x7e]+\z/ or
56 raise HandshakeError, "Invalid WebSocket-Protocol: #{protocol}"
60 # returns the ws://... or ws:/// URL
64 if (s == "wss" && port != 443) || (s == "ws" && port != 80)
70 # returns a Sunshowers::IO object
72 @ws_io ||= IO.new(@env["hack.io"])
75 # returns "ws" (unencrypted) or "wss" (SSL)
77 scheme == "https" ? "wss" : "ws"
80 # Terminates the Web Sockets request/response cycle and
81 # Rack application dispatch.
83 raise Quit, "done processing WebSocket request"