[Awesome Ruby Gem] Use faraday gem to provide a common interface over many adapters when processing the HTTP request/response

faraday

Faraday is an HTTP client library that provides a common interface over many adapters (such as Net::HTTP) and embraces the concept of Rack middleware when processing the request/response cycle.

Installation

You can install it as a gem:

1
2
3
$ gem install faraday

$ gem install faraday_middleware

or add it into a Gemfile (Bundler):

1
2
3
4
5
6
7
# Gemfile

# lostisland/faraday: Simple, but flexible HTTP client library, with support for multiple backends.
# https://github.com/lostisland/faraday
gem 'faraday', '1.5.1'

gem 'faraday_middleware', '1.1.0'

Usages

Make a simple GET request by requiring the Faraday gem and using Faraday.get:

1
2
3
require 'faraday'

response = Faraday.get 'http://httpbingo.org'

This returns a Faraday::Response object with the response status, headers, and body.

1
2
3
4
5
6
7
8
response.status
# => 200

response.headers
# => {"server"=>"Fly/c375678 (2021-04-23)", "content-type"=> ...

response.body
# => "<!DOCTYPE html><html> ...

GET

Faraday supports the following HTTP verbs that typically don’t include a request body:

1
2
3
4
get(url, params = nil, headers = nil)
head(url, params = nil, headers = nil)
delete(url, params = nil, headers = nil)
trace(url, params = nil, headers = nil)

You can specify URI query parameters and HTTP headers when making a request.

1
2
3
url = 'http://httpbingo.org/get'
response = Faraday.get(url, {boom: 'zap'}, {'User-Agent' => 'myapp'})
# => GET http://httpbingo.org/get?boom=zap

POST

Faraday also supports HTTP verbs with bodies. Instead of query parameters, these accept a request body:

1
2
3
4
post(url, body = nil, headers = nil)
put(url, body = nil, headers = nil)
patch(url, body = nil, headers = nil)
url = 'http://httpbingo.org/post'
1
2
3
4
5
6
# POST 'application/x-www-form-urlencoded' content
response = Faraday.post(url, "boom=zap")

# POST JSON content
response = Faraday.post(url, '{"boom": "zap"}',
"Content-Type" => "application/json")

Posting Forms

Faraday will automatically convert key/value hashes into proper form bodies.

1
2
3
4
# POST 'application/x-www-form-urlencoded' content
url = 'http://httpbingo.org/post'
response = Faraday.post(url, boom: 'zap')
# => POST 'boom=zap' to http://httpbingo.org/post

Detailed HTTP Requests

Faraday supports a longer style for making requests. This is handy if you need to change many of the defaults, or if the details of the HTTP request change according to method arguments. Each of the HTTP verb helpers can yield a Faraday::Request that can be modified before being sent.

This example shows a hypothetical search endpoint that accepts a JSON request body as the actual search query.

1
2
3
4
5
6
response = Faraday.post('http://httpbingo.org/post') do |req|
req.params['limit'] = 100
req.headers['Content-Type'] = 'application/json'
req.body = {query: 'chunky bacon'}.to_json
end
# => POST http://httpbingo.org/post?limit=100

Customizing Faraday::Connection

You may want to create a Faraday::Connection to setup a common config for multiple requests. The connection object can be configured with things like:

  • default request headers & query parameters

  • network settings like proxy or timeout

  • common URL base path

  • Faraday adapter & middleware (see below)

Create a Faraday::Connection by calling Faraday.new. The HTTP verbs described above (get, post, …) are Faraday::Connection methods:

1
2
3
4
5
6
7
8
9
10
11
conn = Faraday.new(
url: 'http://httpbingo.org',
params: {param: '1'},
headers: {'Content-Type' => 'application/json'}
)

response = conn.post('/post') do |req|
req.params['limit'] = 100
req.body = {query: 'chunky bacon'}.to_json
end
# => POST http://httpbingo.org/post?param=1&limit=100

Adapters

Adapters are responsible for actually executing HTTP requests. The default adapter uses Ruby’s Net::HTTP, but there are many different adapters available. You might want to use Faraday with the Typhoeus adapter, for example. Learn more about Adapters - https://lostisland.github.io/faraday/adapters/.

Built-in adapters

Faraday includes these adapters (but not the HTTP client libraries):

  • Net::HTTP (this is the default adapter)

  • Net::HTTP::Persistent

  • Excon

  • Patron

  • EM-Synchrony

  • EM-Http

  • HTTPClient

While most adapters use a common Ruby HTTP client library, adapters can also have completely custom implementations.

  • Test Adapter

  • Rack Adapter (link TBD)

External adapters

Adapters are slowly being moved into their own gems, or bundled with HTTP clients. Please refer to their documentation for usage examples.

  • Typhoeus

  • HTTP.rb

  • httpx

Middleware

Under the hood, Faraday uses a Rack-inspired middleware stack for making requests. Much of Faraday’s power is unlocked with custom middleware. Some middleware is included with Faraday, and others are in external gems. Learn more about Middleware - https://lostisland.github.io/faraday/middleware.

Here are some of the features that middleware can provide:

  • authentication

  • caching responses on disk or in memory

  • cookies

  • following redirects

  • JSON encoding/decoding

  • logging

  • retrying

To use these great features, create a Faraday::Connection with Faraday.new and add the correct middleware in a block. For example:

1
2
3
4
5
6
7
8
9
require 'faraday_middleware'

conn = Faraday.new do |f|
f.request :json # encode req bodies as JSON
f.request :retry # retry transient failures
f.response :follow_redirects # follow redirects
f.response :json # decode response bodies as JSON
end
response = conn.get("http://httpbingo.org/get")

Default Connection, Default Middleware

Remember how we said that Faraday will automatically encode key/value hash bodies into form bodies? Internally, the top level shortcut methods Faraday.get, post, etc. use a simple default Faraday::Connection. The only middleware used for the default connection is :url_encoded, which encodes those form hashes.

Note that if you create your own connection with middleware, it won’t encode form bodies unless you too include the :url_encoded middleware!

References

[1] lostisland/faraday: Simple, but flexible HTTP client library, with support for multiple backends. - https://github.com/lostisland/faraday

[2] Homepage | Faraday - https://lostisland.github.io/faraday/

[3] lostisland/faraday - Gitter - https://gitter.im/lostisland/faraday

[4] faraday | RubyGems.org | your community gem host - https://rubygems.org/gems/faraday/

[5] lostisland/faraday_middleware: Various Faraday middlewares for Faraday-based API wrappers - https://github.com/lostisland/faraday_middleware