Class: EventMachine::WebSocket::HandlerFactory
- Inherits:
-
Object
- Object
- EventMachine::WebSocket::HandlerFactory
- Defined in:
- lib/em-websocket/handler_factory.rb
Constant Summary collapse
- PATH =
/^(\w+) (\/[^\s]*) HTTP\/1\.1$/
- HEADER =
/^([^:]+):\s*(.+)$/
Class Method Summary collapse
- .build(connection, data, secure = false, debug = false) ⇒ Object
- .build_with_request(connection, request, remains, secure = false, debug = false) ⇒ Object
Class Method Details
.build(connection, data, secure = false, debug = false) ⇒ Object
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/em-websocket/handler_factory.rb', line 7 def self.build(connection, data, secure = false, debug = false) (header, remains) = data.split("\r\n\r\n", 2) unless remains # The whole header has not been received yet. return nil end request = {} lines = header.split("\r\n") # extract request path first_line = lines.shift.match(PATH) raise HandshakeError, "Invalid HTTP header" unless first_line request['method'] = first_line[1].strip request['path'] = first_line[2].strip unless request["method"] == "GET" raise HandshakeError, "Must be GET request" end # extract query string values request['query'] = Addressable::URI.parse(request['path']).query_values ||= {} # extract remaining headers lines.each do |line| h = HEADER.match(line) request[h[1].strip.downcase] = h[2].strip if h end build_with_request(connection, request, remains, secure, debug) end |
.build_with_request(connection, request, remains, secure = false, debug = false) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/em-websocket/handler_factory.rb', line 39 def self.build_with_request(connection, request, remains, secure = false, debug = false) # Determine version heuristically version = if request['sec-websocket-version'] # Used from drafts 04 onwards request['sec-websocket-version'].to_i elsif request['sec-websocket-draft'] # Used in drafts 01 - 03 request['sec-websocket-draft'].to_i elsif request['sec-websocket-key1'] 76 else 75 end # Additional handling of bytes after the header if required case version when 75 if !remains.empty? raise HandshakeError, "Extra bytes after header" end when 76, 1..3 if remains.length < 8 # The whole third-key has not been received yet. return nil elsif remains.length > 8 raise HandshakeError, "Extra bytes after third key" end request['third-key'] = remains end # Validate that Connection and Upgrade headers unless request['connection'] && request['connection'] =~ /Upgrade/ && request['upgrade'] && request['upgrade'].downcase == 'websocket' raise HandshakeError, "Connection and Upgrade headers required" end # transform headers protocol = (secure ? "wss" : "ws") request['host'] = Addressable::URI.parse("#{protocol}://"+request['host']) case version when 75 Handler75.new(connection, request, debug) when 76 Handler76.new(connection, request, debug) when 1..3 # We'll use handler03 - I believe they're all compatible Handler03.new(connection, request, debug) when 5 Handler05.new(connection, request, debug) when 6 Handler06.new(connection, request, debug) when 7 Handler07.new(connection, request, debug) when 8 Handler08.new(connection, request, debug) else # According to spec should abort the connection raise WebSocketError, "Protocol version #{version} not supported" end end |