Class: EventMachine::Protocols::HeaderAndContentProtocol

Inherits:
Connection
  • Object
show all
Includes:
LineText2
Defined in:
lib/em/protocols/header_and_content.rb

Overview

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
}

– Originally, this subclassed LineAndTextProtocol, which in turn relies on BufferedTokenizer, which doesn't gracefully handle the transitions between lines and binary text. Changed 13Sep08 by FCianfrocca.

Constant Summary

ContentLengthPattern =
/Content-length:\s*(\d+)/i

Constants included from LineText2

LineText2::MaxBinaryLength

Instance Attribute Summary

Attributes inherited from Connection

#signature

Class Method Summary collapse

Instance Method Summary collapse

Methods included from LineText2

#receive_data, #receive_end_of_binary_data, #set_binary_mode, #set_delimiter, #set_line_mode, #set_text_mode, #unbind

Methods inherited from Connection

#associate_callback_target, #close_connection, #close_connection_after_writing, #comm_inactivity_timeout, #comm_inactivity_timeout=, #connection_completed, #detach, #error?, #get_cipher_bits, #get_cipher_name, #get_cipher_protocol, #get_idle_time, #get_outbound_data_size, #get_peer_cert, #get_peername, #get_pid, #get_proxied_bytes, #get_sni_hostname, #get_sock_opt, #get_sockname, #get_status, new, #notify_readable=, #notify_readable?, #notify_writable=, #notify_writable?, #pause, #paused?, #pending_connect_timeout, #pending_connect_timeout=, #post_init, #proxy_completed, #proxy_incoming_to, #proxy_target_unbound, #receive_data, #reconnect, #resume, #send_data, #send_datagram, #send_file_data, #set_sock_opt, #ssl_handshake_completed, #ssl_verify_peer, #start_tls, #stop_proxying, #stream_file_data, #unbind

Constructor Details

#initialize(*args) ⇒ HeaderAndContentProtocol

Returns a new instance of HeaderAndContentProtocol



51
52
53
54
# File 'lib/em/protocols/header_and_content.rb', line 51

def initialize *args
  super
  init_for_request
end

Class Method Details

.headers_2_hash(hdrs) ⇒ Object



124
125
126
127
128
129
130
131
132
133
# 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

Instance Method Details

#headers_2_hash(hdrs) ⇒ Object

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



119
120
121
# 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) ⇒ Object



92
93
94
95
# File 'lib/em/protocols/header_and_content.rb', line 92

def receive_binary_data text
  @hc_content = text
  dispatch_request
end

#receive_line(line) ⇒ Object



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
# 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