123456789_123456789_123456789_123456789_123456789_

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

Do not use. This class is for internal use only.
Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Instance Chain:
self, Deferrable
Inherits: Object
Defined in: lib/em/protocols/httpclient2.rb

Constant Summary

Deferrable - Included

Pool

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Deferrable - Included

#callback

Specify a block to be executed if and when the Deferrable object receives a status of :succeeded.

#cancel_callback

Cancels an outstanding callback to &block if any.

#cancel_errback

Cancels an outstanding errback to &block if any.

#cancel_timeout

Cancels an outstanding timeout if any.

#errback

Specify a block to be executed if and when the Deferrable object receives a status of :failed.

#fail

Sugar for set_deferred_status(:failed, ...).

#set_deferred_failure

Alias for Deferrable#fail.

#set_deferred_status

Sets the "disposition" (status) of the Deferrable object.

#set_deferred_success
#succeed

Sugar for set_deferred_status(:succeeded, ...).

#timeout

Setting a timeout on a Deferrable causes it to go into the failed state after the Timeout expires (passing no arguments to the object's errbacks).

Constructor Details

.new(conn, args) ⇒ Request

[ GitHub ]

  
# File 'lib/em/protocols/httpclient2.rb', line 68

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

Instance Attribute Details

#content (readonly)

[ GitHub ]

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

attr_reader :content

#header_lines (readonly)

[ GitHub ]

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

attr_reader :header_lines

#headers (readonly)

[ GitHub ]

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

attr_reader :headers

#internal_error (readonly)

[ GitHub ]

  
# File 'lib/em/protocols/httpclient2.rb', line 66

attr_reader :internal_error

#status (readonly)

[ GitHub ]

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

attr_reader :status

#version (readonly)

[ GitHub ]

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

attr_reader :version

Instance Method Details

#process_header (private)

[ GitHub ]

  
# File 'lib/em/protocols/httpclient2.rb', line 175

def process_header
  unless @header_lines.first =~ HttpResponseRE
    @conn.close_connection
    @internal_error = :bad_request
  end
  @version = $1.dup
  @status = $2.dup.to_i

  clen = nil
  chunks = nil
  @header_lines.each_with_index do |e,ix|
    if ix > 0
      hdr,val = e.split(ColonRE,2)
      (@headers[hdr.downcase] ||= []) << val
    end

    if clen == nil and e =~ ClenRE
      clen = $1.dup.to_i
    end
    if e =~ ChunkedRE
      chunks = true
    end
  end

  if clen
    # If the content length is zero we should not call set_text_mode,
    # because a value of zero will make it wait forever, hanging the
    # connection. Just return success instead, with empty content.
    if clen == 0 then
      @content = ""
      @conn.pop_request
      succeed(self)
    else
      @conn.set_text_mode clen
    end
  elsif chunks
    @chunking = true
  else
    # Chunked transfer, multipart, or end-of-connection.
    # For end-of-connection, we need to go the unbind
    # method and suppress its desire to fail us.
    p "NO CLEN"
    p @args[:uri]
    p @header_lines
    @internal_error = :unsupported_clen
    @conn.close_connection
  end
end

#receive_chunk_header(ln)

[ GitHub ]

  
# File 'lib/em/protocols/httpclient2.rb', line 139

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)

[ GitHub ]

  
# File 'lib/em/protocols/httpclient2.rb', line 104

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)

[ GitHub ]

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

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

#receive_header_line(ln)

[ GitHub ]

  
# File 'lib/em/protocols/httpclient2.rb', line 117

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)

[ GitHub ]

  
# File 'lib/em/protocols/httpclient2.rb', line 92

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)

[ GitHub ]

  
# File 'lib/em/protocols/httpclient2.rb', line 234

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

#receive_text(text)

[ GitHub ]

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

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

#send_request

[ GitHub ]

  
# File 'lib/em/protocols/httpclient2.rb', line 78

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