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



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

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



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

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



124
125
126
# File 'lib/faraday/adapter/httpclient.rb', line 124

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

#configure_proxy(client, proxy) ⇒ Object

Configure proxy URI and any user credentials.

Parameters:

  • proxy (Hash)


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

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)


81
82
83
84
# File 'lib/faraday/adapter/httpclient.rb', line 81

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)


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

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)


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

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)


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

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)


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

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