Class: Faraday::Adapter::EMHttp

Inherits:
Faraday::Adapter show all
Includes:
Options
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

Modules: Options 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 included from Options

#configure_compression, #configure_proxy, #configure_socket, #configure_ssl, #configure_timeout, #connection_config, #read_body, #request_config, #request_options

Methods inherited from Faraday::Adapter

#initialize, #save_response

Methods included from Parallelism

#inherited, #supports_parallel?

Methods included from Faraday::AutoloadHelper

#all_loaded_constants, #autoload_all, #load_autoloaded_constants

Methods inherited from Middleware

dependency, inherited, #initialize, loaded?, new

Methods included from MiddlewareRegistry

#fetch_middleware, #load_middleware, #lookup_middleware, #middleware_mutex, #register_middleware

Constructor Details

This class inherits a constructor from Faraday::Adapter

Class Method Details

.setup_parallel_manager(options = nil) ⇒ Object



84
85
86
# File 'lib/faraday/adapter/em_http.rb', line 84

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

Instance Method Details

#call(env) ⇒ Object



88
89
90
91
92
# File 'lib/faraday/adapter/em_http.rb', line 88

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

#create_request(env) ⇒ Object



153
154
155
# File 'lib/faraday/adapter/em_http.rb', line 153

def create_request(env)
  EventMachine::HttpRequest.new(env[:url], connection_config(env).merge(@connection_options))
end

#error_message(client) ⇒ Object



157
158
159
# File 'lib/faraday/adapter/em_http.rb', line 157

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

#parallel?(env) ⇒ Boolean

Returns:

  • (Boolean)


175
176
177
# File 'lib/faraday/adapter/em_http.rb', line 175

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

#perform_request(env) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/faraday/adapter/em_http.rb', line 94

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
rescue EventMachine::Connectify::CONNECTError => err
  if err.message.include?("Proxy Authentication Required")
    raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
  else
    raise Error::ConnectionFailed, err
  end
rescue => err
  if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
    raise Faraday::SSLError, err
  else
    raise
  end
end

#perform_single_request(env) ⇒ Object

TODO: reuse the connection to support pipelining



140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/faraday/adapter/em_http.rb', line 140

def perform_single_request(env)
  req = create_request(env)
  req.setup_request(env[:method], request_config(env)).callback { |client|
    status = client.response_header.status
    reason = client.response_header.http_reason
    save_response(env, status, client.response, nil, reason) 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)


161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/faraday/adapter/em_http.rb', line 161

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"
  elsif msg == "connection closed by server"
    errklass = Faraday::Error::ConnectionFailed
  end
  raise errklass, msg
end