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

MaxBinaryLength, MaxLineLength

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

#close_connection, #close_connection_after_writing, #comm_inactivity_timeout, #comm_inactivity_timeout=, #connection_completed, #detach, #error?, #get_idle_time, #get_peer_cert, #get_peername, #get_pid, #get_proxied_bytes, #get_sock_opt, #get_sockname, #get_status, #notify_readable=, #notify_readable?, #notify_writable=, #notify_writable?, #pause, #paused?, #pending_connect_timeout=, #post_init, #proxy_completed, #proxy_incoming_to, #proxy_target_unbound, #receive_data, #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

- (HeaderAndContentProtocol) initialize(*args)

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

+ (Object) headers_2_hash(hdrs)



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

- (Object) headers_2_hash(hdrs)

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

- (Object) receive_binary_data(text)



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

- (Object) receive_line(line)



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