Writing modular HTTP client code with Faraday

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.

blog comments powered by Disqus