Faraday implements a Rack-like structure to allow individuals to define middleware to address specific concerns for their applications. This is where the true power of Faraday lies. By only implementing what you need, you avoid having to pull in code that will never be used or is inappropriate for your use-case.
This is just one more example of pre-existing middleware that is available. It is also very well documented and tested. Even if we didn't want to use this project directly, it would likely be a strong model for developing our own middleware.
One more external dependency.
While it is relatively easy to write custom middleware, we found certain cases where the middleware does something to the request and depends on the response to do something and responds to it. This came up when working on OAuth caching.
def call(env)
attempts = @retries + 1
request_body = env[:body]
reuse = true
begin
env[:body] = request_body
env[:request_headers][AUTH_HEADER] = auth_header(reuse)
response = @app.call(env)
reuse = false if expired_header?(response)
attempts -= 1
end until attempts == 0 || !expired_header?(response)
response
endIn this approach, we would keep http_services around and update it to consume Faraday, rather than a specific adapter. Further, we could use it to house common middleware that will be used by all applications and clients. There is also the added benefit of having a common connection housed here. This would still allow individual projects to create custom middleware for their own unique use-cases.
This approach is similar to the first but focuses on each client building the Faraday connection on its own. This is good because it gives each client fine control over what the connection and call stack looks like. However, it results in a lot of repeated code between clients, due to largely similar functionality.
def initialize(options)
@connection = Faraday.new options[:base_uri] do |faraday|
faraday.headers = HttpServices::HEADERS.merge(HttpServices.user_agent_header(self.to_s))
faraday.options.timeout = options[:read_timeout] || 6
faraday.options.open_timeout = options[:open_timeout]
faraday.use :abacus_timing, client_name: self.to_s
faraday.request :correlation_header
faraday.request :oauth_cache, options
faraday.request :retry, max: (options[:retries] || 2), interval: 0.05
faraday.response :faraday_logging, client_name: self.to_s
faraday.adapter Faraday.default_adapter
end
end