Files

EventMachine

#-- Copyright (C)2008 Ilya Grigorik

Includes portion originally Copyright (C)2007 Tony Arcieri Includes portion originally Copyright (C)2005 Zed Shaw You can redistribute this under the terms of the Ruby license See file LICENSE for details #--

Public Instance Methods

parse_chunk_header() click to toggle source
# File lib/em-http/client.rb, line 559
def parse_chunk_header
  return false unless parse_header(@chunk_header)

  @bytes_remaining = @chunk_header.chunk_size
  @chunk_header = HttpChunkHeader.new

  @state = @bytes_remaining > 0 ? :chunk_body : :response_footer
  true
end
parse_header(header) click to toggle source
# File lib/em-http/client.rb, line 459
def parse_header(header)
  return false if @data.empty?

  begin
    @parser_nbytes = @parser.execute(header, @data.to_str, @parser_nbytes)
  rescue EventMachine::HttpClientParserError
    @state = :invalid
    on_error "invalid HTTP format, parsing fails"
  end

  return false unless @parser.finished?

  # Clear parsed data from the buffer
  @data.read(@parser_nbytes)
  @parser.reset
  @parser_nbytes = 0

  true
end
parse_response_header() click to toggle source
# File lib/em-http/client.rb, line 479
def parse_response_header
  return false unless parse_header(@response_header)

  unless @response_header.http_status and @response_header.http_reason
    @state = :invalid
    on_error "no HTTP response"
    return false
  end

  if @state == :connect_proxy
    # when a successfull tunnel is established, the proxy responds with a
    # 200 response code. from here, the tunnel is transparent.
    if @response_header.http_status.to_i == 200
      @response_header = HttpResponseHeader.new
      connection_completed
      return true
    else
      @state = :invalid
      on_error "proxy not accessible"
      return false
    end
  end

  # correct location header - some servers will incorrectly give a relative URI
  if @response_header.location
    begin
      location = Addressable::URI.parse(@response_header.location)

      if location.relative?
        location = @uri.join(location)
        @response_header[LOCATION] = location.to_s
      else
        # if redirect is to an absolute url, check for correct URI structure
        raise if location.host.nil?
      end

      # store last url on any sign of redirect
      @last_effective_url = location

    rescue
      on_error "Location header format error"
      return false
    end
  end

  # shortcircuit on HEAD requests
  if @method == "HEAD"
    @state = :finished
    unbind
  end

  if websocket?
    if @response_header.status == 101
      @state = :websocket
      succeed
    else
      fail "websocket handshake failed"
    end

  elsif @response_header.chunked_encoding?
    @state = :chunk_header
  elsif @response_header.content_length
    @state = :body
    @bytes_remaining = @response_header.content_length
  else
    @state = :body
    @bytes_remaining = nil
  end

  if decoder_class = HttpDecoders.decoder_for_encoding(response_header[CONTENT_ENCODING])
    begin
      @content_decoder = decoder_class.new do |s| on_decoded_body_data(s) end
    rescue HttpDecoders::DecoderError
      on_error "Content-decoder error"
    end
  end

  true
end
process_body() click to toggle source
# File lib/em-http/client.rb, line 615
def process_body
  if @bytes_remaining.nil?
    on_body_data @data.read
    return false
  end

  if @bytes_remaining.zero?
    @state = :finished
    on_request_complete
    return false
  end

  if @data.size < @bytes_remaining
    @bytes_remaining -= @data.size
    on_body_data @data.read
    return false
  end

  on_body_data @data.read(@bytes_remaining)
  @bytes_remaining = 0

  # If Keep-Alive is enabled, the server may be pushing more data to us
  # after the first request is complete. Hence, finish first request, and
  # reset state.
  if @response_header.keep_alive?
    @data.clear # hard reset, TODO: add support for keep-alive connections!
    @state = :finished
    on_request_complete

  else
    if @data.empty?
      @state = :finished
      on_request_complete
    else
      @state = :invalid
      on_error "garbage at end of body"
    end
  end

  false
end
process_chunk_body() click to toggle source
# File lib/em-http/client.rb, line 569
def process_chunk_body
  if @data.size < @bytes_remaining
    @bytes_remaining -= @data.size
    on_body_data @data.read
    return false
  end

  on_body_data @data.read(@bytes_remaining)
  @bytes_remaining = 0

  @state = :chunk_footer
  true
end
process_websocket() click to toggle source
# File lib/em-http/client.rb, line 657
def process_websocket
  return false if @data.empty?

  # slice the message out of the buffer and pass in
  # for processing, and buffer data otherwise
  buffer = @data.read
  while msg = buffer.slice!(/\0000([^\3377]*)\3377/)
    msg.gsub!(/\A\x00|\xff\z/, '')
    @stream.call(msg)
  end

  # store remainder if message boundary has not yet
  # been received
  @data << buffer if not buffer.empty?

  false
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.