Writing modular HTTP client code with Faraday
What is Faraday? A natural philosopher from the 1700s? An awesome Lost character? A ruby gem by technoweenie himself, Rick Olson? Since this blog is mostly development related, you may have concluded that this post is about the latter. Faraday is an HTTP client library inspired by Rack. Requests and Responses go through middleware which allow for abstraction and modular code.
Installation
gem install faraday
Be sure to also install the faraday-middleware gem by Wynn Netherland as it provides some great middleware to consume APIs.
gem install faraday-middleware
Using Faraday
To create a connection via Faraday, instantiate a new Faraday::Connection object with your desired options. The constructor of Faraday::Connection takes a block where you will define an adapter and your desired middleware.
An adapter represents the client library that Faraday will be utilizing to make your request. Faraday ships with the following:
- NetHTTP (Faraday.default_adapter)
- Patron
- Typhoeus
- Test (Allows stubbing of HTTP requests)
Example: Creating a connection
connection = Faraday::Connection.new(
:url => 'http://api.twitter.com/1/statuses/public_timeline.json',
:headers => { :accept => 'application/json',
:user_agent => 'Faraday Ruby Client'}) do |builder|
builder.adapter Faraday.default_adapter
builder.use Faraday::Response::MultiJson
builder.use Faraday::Response::Mashify
end
The above example represents a Faraday connection to the Twitter API public timeline method. This connection uses two middlewares from the faraday-middleware gem. Faraday::Response::MultiJson sets the body of the response to a parsed JSON response using the multi_json gem. Afterwards, the Faraday::Response::Mashify middleware uses the hashie gem to allow dot notation on the response body instead of brackets.
By putting request/response operations in middleware, Faraday forces your code to follow the Single Responsibility Principle. For example, Faraday::Response::MultiJson is responsible for converting the JSON response into a ruby object using the best available JSON library and that alone.
Calling methods on the connection object will allow you to perform GET, HEAD, PUT, POST or DELETE operations.
Example: Faraday response with MultiJson and Mashify
response = connection.get
first_user = response.body.first.user
puts first_user.screen_name
Creating a Middleware
A common code practice when making client HTTP requests is to verify the response was successful. To abstract the response verification, move the code to Faraday response middleware. To create one, you must inherit from Response::Middleware and implement the methods self.register_on_complete and initialize_. The interface is very similar to Rack. You can think of register_oncomplete(env) as call(env) from Rack.
Example: Twitter Error Response Middleware
module Faraday
class Response::TwitterErrors < Response::Middleware
begin
def self.register_on_complete(env)
env[:response].on_complete do |finished_env|
case finished_env[:status]
when 400
raise Twitter::RateLimitExceeded,
"#{finished_env[:body]['error'] if finished_env[:body]}"
when 401
raise Twitter::UnauthorizedError,
"#{finished_env[:body]['error'] if finished_env[:body]}"
when 500
raise Twitter::ServerError, 'api.twitter.com is currently down'
end
end
end
rescue LoadError, NameError => e
self.load_error = e
end
def initialize(app)
super
@parser = nil
end
end
end
Note
Faraday does not have gem dependencies for many of the adapters and middlewares used within it’s codebase. Ensure you have all necessary gems installed on your system.