Module: FTW::Protocol

Included in:
Agent, Request, Rack::Handler::FTW
Defined in:
lib/ftw/protocol.rb

Overview

This module provides web protocol handling as a mixin.

Instance Method Summary collapse

Instance Method Details

#read_http_message(connection) ⇒ Object

Read an HTTP message from a given connection

This method blocks until a full http message header has been consumed (request or response)

The body of the message, if any, will not be consumed, and the read position for the connection will be left at the end of the message headers.

The ‘connection’ object must respond to #read(timeout) and #pushback(string)



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/ftw/protocol.rb', line 16

def read_http_message(connection)
  parser = HTTP::Parser.new
  headers_done = false
  parser.on_headers_complete = proc { headers_done = true; :stop }

  # headers_done will be set to true when parser finishes parsing the http
  # headers for this request
  while !headers_done
    # TODO(sissel): This read could toss an exception of the server aborts
    # prior to sending the full headers. Figure out a way to make this happy.
    # Perhaps fabricating a 500 response?
    data = connection.read(16384)

    # Feed the data into the parser. Offset will be nonzero if there's 
    # extra data beyond the header.
    offset = parser << data
  end

  # If we consumed part of the body while parsing headers, put it back
  # onto the connection's read buffer so the next consumer can use it.
  if offset < data.length
    connection.pushback(data[offset .. -1])
  end

  # This will have an 'http_method' if it's a request
  if !parser.http_method.nil?
    # have http_method, so this is an HTTP Request message
    request = FTW::Request.new
    request.method = parser.http_method
    request.request_uri = parser.request_url
    request.version = "#{parser.http_major}.#{parser.http_minor}".to_f
    parser.headers.each { |field, value| request.headers.add(field, value) }
    return request
  else
    # otherwise, no http_method, so this is an HTTP Response message
    response = FTW::Response.new
    response.version = "#{parser.http_major}.#{parser.http_minor}".to_f
    response.status = parser.status_code
    parser.headers.each { |field, value| response.headers.add(field, value) }
    return response
  end
end