lib/websocket/handshake/base.rb in websocket-1.0.1 vs lib/websocket/handshake/base.rb in websocket-1.0.2
- old
+ new
@@ -1,66 +1,102 @@
module WebSocket
module Handshake
+ # @abstract Subclass and override to implement custom handshakes
class Base
attr_reader :host, :port, :path, :query,
:error, :state, :version, :secure
+ # Initialize new WebSocket Handshake and set it's state to :new
def initialize(args = {})
@state = :new
@data = ""
@headers = {}
end
+ # @abstract Add data to handshake
def <<(data)
raise NotImplementedError
end
+ # Return textual representation of handshake request or response
+ # @return [String] text of response
+ def to_s
+ ""
+ end
+
+ # Is parsing of data finished?
+ # @return [Boolena] True if request was completely parsed or error occured. False otherwise
def finished?
@state == :finished || @state == :error
end
+ # Is parsed data valid?
+ # @return [Boolean] False if some errors occured. Reason for error could be found in error method
def valid?
finished? && @error == nil
end
+ # @abstract Should send data after parsing is finished?
def should_respond?
raise NotImplementedError
end
+ # Data left from parsing. Sometimes data that doesn't belong to handshake are added - use this method to retrieve them.
+ # @return [String] String if some data are available. Nil otherwise
def leftovers
@leftovers.split("\n", reserved_leftover_lines + 1)[reserved_leftover_lines]
end
+ # URI of request.
+ # @return [String] Full URI with protocol
+ # @example
+ # @handshake.uri #=> "ws://example.com/path?query=true"
+ def uri
+ uri = secure ? "wss://" : "ws://"
+ uri << host
+ uri << ":#{port}" if port
+ uri << path
+ uri << "?#{query}" if query
+ uri
+ end
+
private
+ # Number of lines after header that should be handled as belonging to handshake. Any data after those lines will be handled as leftovers.
+ # @return [Integer] Number of lines
def reserved_leftover_lines
0
end
+ # Changes state to error and sets error message
+ # @param [String] message Error message to set
def set_error(message)
@state = :error
@error = message
end
HEADER = /^([^:]+):\s*(.+)$/
+ # Parse data imported to handshake and sets state to finished if necessary.
+ # @return [Boolean] True if finished parsing. False if not all data received yet.
def parse_data
header, @leftovers = @data.split("\r\n\r\n", 2)
- return unless @leftovers # The whole header has not been received yet.
+ return false unless @leftovers # The whole header has not been received yet.
lines = header.split("\r\n")
first_line = lines.shift
- return unless parse_first_line(first_line)
+ return false unless parse_first_line(first_line)
lines.each do |line|
h = HEADER.match(line)
@headers[h[1].strip.downcase] = h[2].strip if h
end
@state = :finished
+ true
end
end
end
end