Class: Faraday::Adapter::HTTPClient

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

Overview

This class provides the main implementation for your adapter. There are some key responsibilities that your adapter should satisfy:

  • Initialize and store internally the client you chose (e.g. Net::HTTP)

  • Process requests and save the response (see ‘#call`)

Instance Method Summary collapse

Instance Method Details

#build_connection(env) ⇒ Object



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
35
# File 'lib/faraday/adapter/httpclient.rb', line 10

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



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
76
# File 'lib/faraday/adapter/httpclient.rb', line 37

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



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

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

#configure_proxy(client, proxy) ⇒ Object

Configure proxy URI and any user credentials.

Parameters:

  • proxy (Hash)


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

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)


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

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)


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

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)


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

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)


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

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

  # Use the default cert store by default, i.e. system ca certs
  @ssl_cert_store ||= OpenSSL::X509::Store.new.tap(&:set_default_paths)
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