Class: EventMachine::Protocols::HttpClient2::Request

Inherits:
Object
  • Object
show all
Includes:
Deferrable
Defined in:
lib/em/protocols/httpclient2.rb

Constant Summary

HttpResponseRE =

– TODO, inefficient how we're handling this. Part of it is done so as to make sure we don't have problems in detecting chunked-encoding, content-length, etc.

/\AHTTP\/(1.[01]) ([\d]{3})/i
ClenRE =
/\AContent-length:\s*(\d+)/i
ChunkedRE =
/\ATransfer-encoding:\s*chunked/i
ColonRE =
/\:\s*/

Constants included from Deferrable

Deferrable::Pool

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Deferrable

#callback, #cancel_callback, #cancel_errback, #cancel_timeout, #errback, #fail, future, #set_deferred_status, #succeed, #timeout

Constructor Details

#initialize(conn, args) ⇒ Request



65
66
67
68
69
70
71
72
73
# File 'lib/em/protocols/httpclient2.rb', line 65

def initialize conn, args
  @conn = conn
  @args = args
  @header_lines = []
  @headers = {}
  @blanks = 0
  @chunk_trailer = nil
  @chunking = nil
end

Instance Attribute Details

#contentObject (readonly)

Returns the value of attribute content



62
63
64
# File 'lib/em/protocols/httpclient2.rb', line 62

def content
  @content
end

#header_linesObject (readonly)

Returns the value of attribute header_lines



60
61
62
# File 'lib/em/protocols/httpclient2.rb', line 60

def header_lines
  @header_lines
end

#headersObject (readonly)

Returns the value of attribute headers



61
62
63
# File 'lib/em/protocols/httpclient2.rb', line 61

def headers
  @headers
end

#internal_errorObject (readonly)

Returns the value of attribute internal_error



63
64
65
# File 'lib/em/protocols/httpclient2.rb', line 63

def internal_error
  @internal_error
end

#statusObject (readonly)

Returns the value of attribute status



59
60
61
# File 'lib/em/protocols/httpclient2.rb', line 59

def status
  @status
end

#versionObject (readonly)

Returns the value of attribute version



58
59
60
# File 'lib/em/protocols/httpclient2.rb', line 58

def version
  @version
end

Instance Method Details

#receive_chunk_header(ln) ⇒ Object

– Cf RFC 2616 pgh 3.6.1 for the format of HTTP chunks.



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/em/protocols/httpclient2.rb', line 137

def receive_chunk_header ln
  if ln.length > 0
    chunksize = ln.to_i(16)
    if chunksize > 0
      @conn.set_text_mode(ln.to_i(16))
    else
      @content = @content ? @content.join : ''
      @chunk_trailer = true
    end
  else
    # We correctly come here after each chunk gets read.
    # p "Got A BLANK chunk line"
  end

end

#receive_chunk_trailer(ln) ⇒ Object



102
103
104
105
106
107
108
109
# File 'lib/em/protocols/httpclient2.rb', line 102

def receive_chunk_trailer ln
  if ln.length == 0
    @conn.pop_request
    succeed(self)
  else
    p "Received chunk trailer line"
  end
end

#receive_chunked_text(text) ⇒ Object

– We get a single chunk. Append it to the incoming content and switch back to line mode.



157
158
159
160
# File 'lib/em/protocols/httpclient2.rb', line 157

def receive_chunked_text text
  # p "RECEIVED #{text.length} CHUNK"
  (@content ||= []) << text
end

#receive_header_line(ln) ⇒ Object

– Allow up to ten blank lines before we get a real response line. Allow no more than 100 lines in the header.



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/em/protocols/httpclient2.rb', line 115

def receive_header_line ln
  if ln.length == 0
    if @header_lines.length > 0
      process_header
    else
      @blanks += 1
      if @blanks > 10
        @conn.close_connection
      end
    end
  else
    @header_lines << ln
    if @header_lines.length > 100
      @internal_error = :bad_header
      @conn.close_connection
    end
  end
end

#receive_line(ln) ⇒ Object



90
91
92
93
94
95
96
97
98
# File 'lib/em/protocols/httpclient2.rb', line 90

def receive_line ln
  if @chunk_trailer
    receive_chunk_trailer(ln)
  elsif @chunking
    receive_chunk_header(ln)
  else
    receive_header_line(ln)
  end
end

#receive_sized_text(text) ⇒ Object

– At the present time, we only handle contents that have a length specified by the content-length header.



232
233
234
235
236
# File 'lib/em/protocols/httpclient2.rb', line 232

def receive_sized_text text
  @content = text
  @conn.pop_request
  succeed(self)
end

#receive_text(text) ⇒ Object



224
225
226
# File 'lib/em/protocols/httpclient2.rb', line 224

def receive_text text
  @chunking ? receive_chunked_text(text) : receive_sized_text(text)
end

#send_requestObject



75
76
77
78
79
80
81
82
83
84
85
# File 'lib/em/protocols/httpclient2.rb', line 75

def send_request
  az = @args[:authorization] and az = "Authorization: #{az}\r\n"

  r = [
    "#{@args[:verb]} #{@args[:uri]} HTTP/#{@args[:version] || "1.1"}\r\n",
    "Host: #{@args[:host_header] || "_"}\r\n",
    az || "",
      "\r\n"
  ]
  @conn.send_data r.join
end