Class: Faraday::Adapter::HTTPClient

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

Overview

HTTPClient adapter.

Constant Summary

Constants inherited from Faraday::Adapter

CONTENT_LENGTH

Instance Attribute Summary

Attributes included from Parallelism

#supports_parallel

Attributes included from DependencyLoader

#load_error

Instance Method Summary collapse

Methods inherited from Faraday::Adapter

#close, #connection, #initialize

Methods included from Faraday::AutoloadHelper

#all_loaded_constants, #autoload_all, #load_autoloaded_constants

Methods included from Parallelism

#inherited, #supports_parallel?

Methods included from DependencyLoader

#dependency, #inherited, #loaded?, #new

Methods included from MiddlewareRegistry

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

Constructor Details

This class inherits a constructor from Faraday::Adapter

Instance Method Details

#build_connection(env) ⇒ Object


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/faraday/adapter/httpclient.rb', line 9

def build_connection(env)
  @client ||= ::HTTPClient.new.tap do |cli|
    # enable compression
    cli.transparent_gzip_decompression = true
  end

  if (req = env[:request])
    if (proxy = req[:proxy])
      configure_proxy @client, proxy
    end

    if (bind = req[:bind])
      configure_socket @client, bind
    end

    configure_timeouts @client, req
  end

  if env[:url].scheme == 'https' && (ssl = env[:ssl])
    configure_ssl @client, ssl
  end

  configure_client @client

  @client
end

#call(env) ⇒ Object


36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/faraday/adapter/httpclient.rb', line 36

def call(env)
  super

  # TODO: Don't stream yet.
  # https://github.com/nahi/httpclient/pull/90
  env[:body] = env[:body].read if env[:body].respond_to? :read

  connection(env) do |http|
    resp = http.request env[:method], env[:url],
                        body: env[:body],
                        header: env[:request_headers]

    if (req = env[:request]).stream_response?
      warn "Streaming downloads for #{self.class.name} " \
        'are not yet implemented.'
      req.on_data.call(resp.body, resp.body.bytesize)
    end
    save_response env, resp.status, resp.body, resp.headers, resp.reason

    @app.call env
  end
rescue ::HTTPClient::TimeoutError, Errno::ETIMEDOUT
  raise Faraday::TimeoutError, $ERROR_INFO
rescue ::HTTPClient::BadResponseError => e
  if e.message.include?('status 407')
    raise Faraday::ConnectionFailed,
          %(407 "Proxy Authentication Required ")
  end

  raise Faraday::ClientError, $ERROR_INFO
rescue Errno::EADDRNOTAVAIL, Errno::ECONNREFUSED, IOError, SocketError
  raise Faraday::ConnectionFailed, $ERROR_INFO
rescue StandardError => e
  if defined?(::OpenSSL::SSL::SSLError) && \
     e.is_a?(::OpenSSL::SSL::SSLError)
    raise Faraday::SSLError, e
  end

  raise
end

#configure_client(client) ⇒ Object


121
122
123
# File 'lib/faraday/adapter/httpclient.rb', line 121

def configure_client(client)
  @config_block&.call(client)
end

#configure_proxy(client, proxy) ⇒ Object

Configure proxy URI and any user credentials.

Parameters:

  • proxy (Hash)

86
87
88
89
90
91
# File 'lib/faraday/adapter/httpclient.rb', line 86

def configure_proxy(client, proxy)
  client.proxy = proxy[:uri]
  return unless proxy[:user] && proxy[:password]

  client.set_proxy_auth(proxy[:user], proxy[:password])
end

#configure_socket(client, bind) ⇒ Object

Parameters:

  • bind (Hash)

78
79
80
81
# File 'lib/faraday/adapter/httpclient.rb', line 78

def configure_socket(client, bind)
  client.socket_local.host = bind[:host]
  client.socket_local.port = bind[:port]
end

#configure_ssl(client, ssl) ⇒ Object

Parameters:

  • ssl (Hash)

94
95
96
97
98
99
100
101
102
103
104
# File 'lib/faraday/adapter/httpclient.rb', line 94

def configure_ssl(client, ssl)
  ssl_config = client.ssl_config
  ssl_config.verify_mode = ssl_verify_mode(ssl)
  ssl_config.cert_store = ssl_cert_store(ssl)

  ssl_config.add_trust_ca ssl[:ca_file]        if ssl[:ca_file]
  ssl_config.add_trust_ca ssl[:ca_path]        if ssl[:ca_path]
  ssl_config.client_cert  = ssl[:client_cert]  if ssl[:client_cert]
  ssl_config.client_key   = ssl[:client_key]   if ssl[:client_key]
  ssl_config.verify_depth = ssl[:verify_depth] if ssl[:verify_depth]
end

#configure_timeouts(client, req) ⇒ Object

Parameters:

  • req (Hash)

107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/faraday/adapter/httpclient.rb', line 107

def configure_timeouts(client, req)
  if (sec = request_timeout(:open, req))
    client.connect_timeout = sec
  end

  if (sec = request_timeout(:write, req))
    client.send_timeout = sec
  end

  return unless (sec = request_timeout(:read, req))

  client.receive_timeout = sec
end

#ssl_cert_store(ssl) ⇒ OpenSSL::X509::Store

Parameters:

  • ssl (Hash)

Returns:

  • (OpenSSL::X509::Store)

127
128
129
130
131
132
133
134
135
136
137
# File 'lib/faraday/adapter/httpclient.rb', line 127

def ssl_cert_store(ssl)
  return ssl[:cert_store] if ssl[:cert_store]

  # Memoize the cert store so that the same one is passed to
  # HTTPClient each time, to avoid resyncing SSL sessions when
  # it's changed
  @ssl_cert_store ||= begin
    # Use the default cert store by default, i.e. system ca certs
    OpenSSL::X509::Store.new.tap(&:set_default_paths)
  end
end

#ssl_verify_mode(ssl) ⇒ Object

Parameters:

  • ssl (Hash)

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

def ssl_verify_mode(ssl)
  ssl[:verify_mode] || begin
    if ssl.fetch(:verify, true)
      OpenSSL::SSL::VERIFY_PEER |
        OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
    else
      OpenSSL::SSL::VERIFY_NONE
    end
  end
end