class EventMachine::Protocols::HeaderAndContentProtocol

Usage

class RequestHandler < EM::P::HeaderAndContentProtocol
  def receive_request headers, content
    p [:request, headers, content]
  end
end

EM.run{
  EM.start_server 'localhost', 80, RequestHandler
}

Constants

ContentLengthPattern

Public Class Methods

headers_2_hash(hdrs) click to toggle source
# File lib/em/protocols/header_and_content.rb, line 124
def headers_2_hash hdrs
  hash = {}
  hdrs.each {|h|
    if /\A([^\s:]+)\s*:\s*/ =~ h
      tail = $'.dup
      hash[ $1.downcase.gsub(/-/,"_").intern ] = tail
    end
  }
  hash
end
new(*args) click to toggle source
Calls superclass method EventMachine::Connection::new
# File lib/em/protocols/header_and_content.rb, line 51
def initialize *args
  super
  init_for_request
end

Public Instance Methods

headers_2_hash(hdrs) click to toggle source

Basically a convenience method. We might create a subclass that does this automatically. But it’s such a performance killer.

# File lib/em/protocols/header_and_content.rb, line 119
def headers_2_hash hdrs
  self.class.headers_2_hash hdrs
end
receive_binary_data(text) click to toggle source
# File lib/em/protocols/header_and_content.rb, line 92
def receive_binary_data text
  @hc_content = text
  dispatch_request
end
receive_line(line) click to toggle source
# File lib/em/protocols/header_and_content.rb, line 56
def receive_line line
  case @hc_mode
  when :discard_blanks
    unless line == ""
      @hc_mode = :headers
      receive_line line
    end
  when :headers
    if line == ""
      raise "unrecognized state" unless @hc_headers.length > 0
      if respond_to?(:receive_headers)
        receive_headers @hc_headers
      end
      # @hc_content_length will be nil, not 0, if there was no content-length header.
      if @hc_content_length.to_i > 0
        set_binary_mode @hc_content_length
      else
        dispatch_request
      end
    else
      @hc_headers << line
      if ContentLengthPattern =~ line
        # There are some attacks that rely on sending multiple content-length
        # headers. This is a crude protection, but needs to become tunable.
        raise "extraneous content-length header" if @hc_content_length
        @hc_content_length = $1.to_i
      end
      if @hc_headers.length == 1 and respond_to?(:receive_first_header_line)
        receive_first_header_line line
      end
    end
  else
    raise "internal error, unsupported mode"
  end
end

Private Instance Methods

dispatch_request() click to toggle source
# File lib/em/protocols/header_and_content.rb, line 97
def dispatch_request
  if respond_to?(:receive_request)
    receive_request @hc_headers, @hc_content
  end
  init_for_request
end
init_for_request() click to toggle source
# File lib/em/protocols/header_and_content.rb, line 105
def init_for_request
  @hc_mode = :discard_blanks
  @hc_headers = []
  # originally was @hc_headers ||= []; @hc_headers.clear to get a performance
  # boost, but it's counterproductive because a subclassed handler will have to
  # call dup to use the header array we pass in receive_headers.

  @hc_content_length = nil
  @hc_content = ""
end