Class: Faraday::Adapter::EMHttp

Inherits:
Faraday::Adapter show all
Defined in:
lib/faraday/adapter/em_http.rb

Overview

EventMachine adapter is useful for either asynchronous requests when in EM reactor loop or for making parallel requests in synchronous code.

Defined Under Namespace

Classes: Manager

Constant Summary

Constants inherited from Faraday::Adapter

CONTENT_LENGTH

Instance Attribute Summary

Attributes included from Parallelism

#supports_parallel

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Faraday::Adapter

#prepend_proxy_auth_string, #save_response

Methods included from Faraday::AutoloadHelper

#all_loaded_constants, #autoload_all, #load_autoloaded_constants

Methods included from MiddlewareRegistry

#lookup_middleware, #register_middleware

Methods included from Parallelism

#inherited, #supports_parallel?

Methods inherited from Middleware

dependency, inherited, #initialize, loaded?, new

Constructor Details

This class inherits a constructor from Faraday::Middleware

Class Method Details

.setup_parallel_manager(options = nil) ⇒ Object



12
13
14
# File 'lib/faraday/adapter/em_http.rb', line 12

def self.setup_parallel_manager(options = nil)
  Manager.new
end

Instance Method Details

#call(env) ⇒ Object



16
17
18
19
20
# File 'lib/faraday/adapter/em_http.rb', line 16

def call(env)
  super
  perform_request env
  @app.call env
end

#configure_compression(options, env) ⇒ Object



134
135
136
137
138
# File 'lib/faraday/adapter/em_http.rb', line 134

def configure_compression(options, env)
  if env[:method] == :get and not options[:head].key? 'accept-encoding'
    options[:head]['accept-encoding'] = 'gzip, compressed'
  end
end

#configure_proxy(options, env) ⇒ Object



119
120
121
122
123
124
125
126
# File 'lib/faraday/adapter/em_http.rb', line 119

def configure_proxy(options, env)
  if proxy = request_options(env)[:proxy]
    options[:proxy] = {
      :host => proxy[:uri].host,
      :port => proxy[:uri].port
    }
  end
end

#configure_ssl(options, env) ⇒ Object



110
111
112
113
114
115
116
117
# File 'lib/faraday/adapter/em_http.rb', line 110

def configure_ssl(options, env)
  if ssl = env[:ssl]
    # :ssl => {
    #   :private_key_file => '/tmp/server.key',
    #   :cert_chain_file => '/tmp/server.crt',
    #   :verify_peer => false
  end
end

#configure_timeout(options, env) ⇒ Object



128
129
130
131
132
# File 'lib/faraday/adapter/em_http.rb', line 128

def configure_timeout(options, env)
  timeout, open_timeout = request_options(env).values_at(:timeout, :open_timeout)
  options[:connect_timeout] = options[:inactivity_timeout] = timeout
  options[:connect_timeout] = open_timeout if open_timeout
end

#connection_config(env) ⇒ Object



83
84
85
86
87
88
89
# File 'lib/faraday/adapter/em_http.rb', line 83

def connection_config(env)
  options = {}
  configure_ssl(options, env)
  configure_proxy(options, env)
  configure_timeout(options, env)
  options
end

#error_message(client) ⇒ Object



67
68
69
# File 'lib/faraday/adapter/em_http.rb', line 67

def error_message(client)
  client.error or "request failed"
end

#parallel?(env) ⇒ Boolean

Returns:

  • (Boolean)


144
145
146
# File 'lib/faraday/adapter/em_http.rb', line 144

def parallel?(env)
  !!env[:parallel_manager]
end

#perform_request(env) ⇒ Object



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
# File 'lib/faraday/adapter/em_http.rb', line 22

def perform_request(env)
  if parallel?(env)
    manager = env[:parallel_manager]
    manager.add {
      perform_single_request(env).
        callback { env[:response].finish(env) }
    }
  else
    unless EventMachine.reactor_running?
      error = nil
      # start EM, block until request is completed
      EventMachine.run do
        perform_single_request(env).
          callback { EventMachine.stop }.
          errback { |client|
            error = error_message(client)
            EventMachine.stop
          }
      end
      raise_error(error) if error
    else
      # EM is running: instruct upstream that this is an async request
      env[:parallel_manager] = true
      perform_single_request(env).
        callback { env[:response].finish(env) }.
        errback {
          # TODO: no way to communicate the error in async mode
          raise NotImplementedError
        }
    end
  end
end

#perform_single_request(env) ⇒ Object

TODO: reuse the connection to support pipelining



56
57
58
59
60
61
62
63
64
65
# File 'lib/faraday/adapter/em_http.rb', line 56

def perform_single_request(env)
  req = EventMachine::HttpRequest.new(env[:url], connection_config(env))
  req.setup_request(env[:method], request_config(env)).callback { |client|
    save_response(env, client.response_header.status, client.response) do |resp_headers|
      client.response_header.each do |name, value|
        resp_headers[name.to_sym] = value
      end
    end
  }
end

#raise_error(msg) ⇒ Object

Raises:

  • (errklass)


71
72
73
74
75
76
77
78
79
80
81
# File 'lib/faraday/adapter/em_http.rb', line 71

def raise_error(msg)
  errklass = Faraday::Error::ClientError
  if msg == Errno::ETIMEDOUT
    errklass = Faraday::Error::TimeoutError
    msg = "request timed out"
  elsif msg == Errno::ECONNREFUSED
    errklass = Faraday::Error::ConnectionFailed
    msg = "connection refused"
  end
  raise errklass, msg
end

#read_body(env) ⇒ Object



105
106
107
108
# File 'lib/faraday/adapter/em_http.rb', line 105

def read_body(env)
  body = env[:body]
  body.respond_to?(:read) ? body.read : body
end

#request_config(env) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/faraday/adapter/em_http.rb', line 91

def request_config(env)
  options = {
    :body => read_body(env),
    :head => env[:request_headers],
    # :keepalive => true,
    # :file => 'path/to/file', # stream data off disk
  }
  configure_compression(options, env)
  # configure_proxy_auth
  # :proxy => {:authorization => [user, pass]}
  # proxy[:username] && proxy[:password]
  options
end

#request_options(env) ⇒ Object



140
141
142
# File 'lib/faraday/adapter/em_http.rb', line 140

def request_options(env)
  env[:request]
end