Class: EventMachine::HttpClient

### Home Classes Methods

### In Files

- lib/em-http/client.rb

### Parent

Object

### Namespace

- CLASS EventMachine::HttpClient::CookieJar

### Methods

- ::new
- #build_request
- #close
- #connection_completed
- #continue?
- #finished?
- #headers
- #last_effective_url
- #normalize_body
- #on_body_data
- #on_decoded_body_data
- #on_error
- #on_request_complete
- #parse_response_header
- #peer
- #redirect?
- #redirects
- #reset!
- #send_request
- #stream
- #unbind

### Included Modules

- Deferrable
- EventMachine::HttpEncoding
- EventMachine::HttpStatus

### Class/Module Index

Quicksearch

- EventMachine
- EventMachine::HTTPMethods
- EventMachine::HttpClient
- EventMachine::HttpClient::CookieJar
- EventMachine::HttpConnection
- EventMachine::HttpDecoders
- EventMachine::HttpDecoders::Base
- EventMachine::HttpDecoders::DecoderError
- EventMachine::HttpDecoders::Deflate
- EventMachine::HttpDecoders::GZip
- EventMachine::HttpDecoders::GZipHeader
- EventMachine::HttpEncoding
- EventMachine::HttpRequest
- EventMachine::HttpResponseHeader
- EventMachine::HttpStatus
- EventMachine::HttpStubConnection
- EventMachine::Middleware
- EventMachine::Middleware::DigestAuth
- EventMachine::Middleware::JSONResponse
- EventMachine::Middleware::OAuth
- EventMachine::Middleware::OAuth2
- EventMachine::MultiRequest
- HttpClientOptions
- HttpConnectionOptions
- String

No matching classes.

# EventMachine::HttpClient

### Constants

CONTENT_ENCODING
CONTENT_LENGTH
CONTENT_TYPE
CRLF
ETAG
HOST
KEEP_ALIVE
LAST_MODIFIED
LOCATION
SET_COOKIE
TRANSFER_ENCODING

### Attributes

content_charset[R]
cookies[R]
error[R]
req[R]
response[RW]
response_header[R]
state[RW]

### Public Class Methods

new(conn, options) click to toggle source

    # File lib/em-http/client.rb, line 27
    def initialize(conn, options)
      @conn = conn
      @req  = options

      @stream    = nil
      @headers   = nil
      @cookies   = []
      @cookiejar = CookieJar.new

      reset!
    end

### Public Instance Methods

build_request() click to toggle source

    # File lib/em-http/client.rb, line 135
    def build_request
      head    = @req.headers ? munge_header_keys(@req.headers) : {}

      if @conn.connopts.http_proxy?
        proxy = @conn.connopts.proxy
        head['proxy-authorization'] = proxy[:authorization] if proxy[:authorization]
      end

      # Set the cookie header if provided
      if cookie = head['cookie']
        @cookies << encode_cookie(cookie) if cookie
      end
      head['cookie'] = @cookies.compact.uniq.join("; ").squeeze(";") unless @cookies.empty?

      # Set connection close unless keepalive
      if !@req.keepalive
        head['connection'] = 'close'
      end

      # Set the Host header if it hasn't been specified already
      head['host'] ||= encode_host

      # Set the User-Agent if it hasn't been specified
      if !head.key?('user-agent')
        head['user-agent'] = "EventMachine HttpClient"
      elsif head['user-agent'].nil?
        head.delete('user-agent')
      end

      # Set the auth from the URI if given
      head['Authorization'] = @req.uri.userinfo.split(/:/, 2) if @req.uri.userinfo

      head
    end

close(msg = nil) click to toggle source
Alias for: on_error
connection_completed() click to toggle source

    # File lib/em-http/client.rb, line 53
    def connection_completed
      @state = :response_header

      head, body = build_request, @req.body
      @conn.middleware.each do |m|
        head, body = m.request(self, head, body) if m.respond_to?(:request)
      end

      send_request(head, body)
    end

continue?() click to toggle source

    # File lib/em-http/client.rb, line 74
    def continue?
      @response_header.status == 100 && (@req.method == 'POST' || @req.method == 'PUT')
    end

finished?() click to toggle source

    # File lib/em-http/client.rb, line 78
    def finished?
      @state == :finished || (@state == :body && @response_header.content_length.nil?)
    end

headers(&blk) click to toggle source

    # File lib/em-http/client.rb, line 129
    def headers(&blk); @headers = blk; end

last_effective_url() click to toggle source

    # File lib/em-http/client.rb, line 49
    def last_effective_url; @req.uri; end

normalize_body(body) click to toggle source

    # File lib/em-http/client.rb, line 131
    def normalize_body(body)
      body.is_a?(Hash) ? form_encode_body(body) : body
    end

on_body_data(data) click to toggle source

    # File lib/em-http/client.rb, line 204
    def on_body_data(data)
      if @content_decoder
        begin
          @content_decoder << data
        rescue HttpDecoders::DecoderError
          on_error "Content-decoder error"
        end
      else
        on_decoded_body_data(data)
      end
    end

on_decoded_body_data(data) click to toggle source

    # File lib/em-http/client.rb, line 216
    def on_decoded_body_data(data)
      data.force_encoding @content_charset if @content_charset
      if @stream
        @stream.call(data)
      else
        @response << data
      end
    end

on_error(msg = nil) click to toggle source

    # File lib/em-http/client.rb, line 122
    def on_error(msg = nil)
      @error = msg
      fail(self)
    end

Also aliased as: close
on_request_complete() click to toggle source

    # File lib/em-http/client.rb, line 64
    def on_request_complete
      begin
        @content_decoder.finalize! if @content_decoder
      rescue HttpDecoders::DecoderError
        on_error "Content-decoder error"
      end

      unbind
    end

parse_response_header(header, version, status) click to toggle source

    # File lib/em-http/client.rb, line 225
    def parse_response_header(header, version, status)
      @response_header.raw = header
      header.each do |key, val|
        @response_header[key.upcase.gsub('-','_')] = val
      end

      @response_header.http_version = version.join('.')
      @response_header.http_status  = status
      @response_header.http_reason  = CODE[status] || 'unknown'

      # invoke headers callback after full parse
      # if one is specified by the user
      @headers.call(@response_header) if @headers

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

      # add set-cookie's to cookie list
      if @response_header.cookie && @req.pass_cookies
        [@response_header.cookie].flatten.each {|cookie| @cookiejar.set(cookie, @req.uri)}
      end

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

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

          @response_header[LOCATION] = location.to_s

        rescue
          on_error "Location header format error"
          return
        end
      end

      # Fire callbacks immediately after recieving header requests
      # if the request method is HEAD. In case of a redirect, terminate
      # current connection and reinitialize the process.
      if @req.method == "HEAD"
        @state = :finished
        return
      end

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

      if @req.decoding && 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

      # handle malformed header - Content-Type repetitions.
      content_type = [response_header[CONTENT_TYPE]].flatten.first

      if String.method_defined?(:force_encoding) && /;\s*charset=\s*(.+?)\s*(;|$)/.match(content_type)
        @content_charset = Encoding.find($1.gsub(/^\"|\"$/, '')) rescue Encoding.default_external
      end
    end

peer() click to toggle source

    # File lib/em-http/client.rb, line 51
    def peer; @conn.peer; end

redirect?() click to toggle source

    # File lib/em-http/client.rb, line 82
    def redirect?
      @response_header.redirection? && @req.follow_redirect?
    end

redirects() click to toggle source

    # File lib/em-http/client.rb, line 50
    def redirects; @req.followed; end

reset!() click to toggle source

    # File lib/em-http/client.rb, line 39
    def reset!
      @response_header = HttpResponseHeader.new
      @state = :response_header

      @response = ''
      @error = nil
      @content_decoder = nil
      @content_charset = nil
    end

send_request(head, body) click to toggle source

    # File lib/em-http/client.rb, line 170
    def send_request(head, body)
      body    = normalize_body(body)
      file    = @req.file
      query   = @req.query

      # Set the Content-Length if file is given
      head['content-length'] = File.size(file) if file

      # Set the Content-Length if body is given,
      # or we're doing an empty post or put
      if body
        head['content-length'] = body.bytesize
      elsif @req.method == 'POST' or @req.method == 'PUT'
        # wont happen if body is set and we already set content-length above
        head['content-length'] ||= 0
      end

      # Set content-type header if missing and body is a Ruby hash
      if !head['content-type'] and @req.body.is_a? Hash
        head['content-type'] = 'application/x-www-form-urlencoded'
      end

      request_header ||= encode_request(@req.method, @req.uri, query, @conn.connopts.proxy)
      request_header << encode_headers(head)
      request_header << CRLF
      @conn.send_data request_header

      if body
        @conn.send_data body
      elsif @req.file
        @conn.stream_file_data @req.file, :http_chunks => false
      end
    end

stream(&blk) click to toggle source

    # File lib/em-http/client.rb, line 128
    def stream(&blk); @stream = blk; end

unbind(reason = nil) click to toggle source

    # File lib/em-http/client.rb, line 86
    def unbind(reason = nil)
      if finished?
        if redirect?

          begin
            @conn.middleware.each do |m|
              m.response(self) if m.respond_to?(:response)
            end

            # one of the injected middlewares could have changed
            # our redirect settings, check if we still want to
            # follow the location header
            if redirect?
              @req.followed += 1

              @cookies.clear
              @cookies = @cookiejar.get(@response_header.location).map(&:to_s) if @req.pass_cookies
              @req.set_uri(@response_header.location)

              @conn.redirect(self)
            else
              succeed(self)
            end

          rescue Exception => e
            on_error(e.message)
          end
        else
          succeed(self)
        end

      else
        on_error(reason || 'connection closed by server')
      end
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.