Aitch
A simple HTTP client.
Features:
- Supports Gzip|Deflate response
- Automatically parses JSON, HTML and XML responses
- Automatically follows redirect
Installation
Add this line to your application's Gemfile:
gem "aitch"
And then execute:
$ bundle
Or install it yourself as:
$ gem install aitch
Usage
Configuration
These are the default settings:
Aitch.configure do |config|
# Set request timeout.
config.timeout = 5
# Set default headers.
config.default_headers = {}
# Set follow redirect.
config.follow_redirect = true
# Set redirection limit.
config.redirect_limit = 5
# Set the user agent.
config.user_agent = "Aitch/0.0.1 (http://rubygems.org/gems/aitch)"
# Set the logger.
config.logger = nil
# Set the base url.
config.base_url = nil
end
Requests
Performing requests:
response = Aitch.get("http://example.org", params, headers, )
Aitch.post("http://example.org", params, headers, )
Aitch.put("http://example.org", params, headers, )
Aitch.patch("http://example.org", params, headers, )
Aitch.delete("http://example.org", params, headers, )
Aitch.("http://example.org", params, headers, )
Aitch.trace("http://example.org", params, headers, )
Aitch.head("http://example.org", params, headers, )
You can also use a DSL.
response = Aitch.get do
url "http://simplesideias.com.br"
headers Authorization: "Token token=abc"
follow_redirect: false
params a: 1, b: 2
end
Finally, you can use keyword arguments:
Aitch.get(
url: "http://example.org",
params: {a: 1, b: 2},
headers: {Authorization: "Token token=abc"},
options: {follow_redirect: false}
)
Response
The response object:
response.html?
response.xml?
response.json?
response.content_type
response.headers
response.location
response.success? # status >= 200 && status <= 399
response.redirect? # status 3xx
response.error? # status 4xx or 5xx
response.error # response error
response.body # returned body
response.data # Parsed response body
Parsing JSON, XML and HTML with Nokogiri
If your response is a JSON, XML or a HTML content type, we'll automatically convert the response into the appropriate object.
response = Aitch.get("http://simplesideias.com.br")
response.data.class
#=> Nokogiri::HTML::Document
response.data.css("h1").size
#=> 69
response = Aitch.get("http://simplesideias.com.br/feed")
response.data.class
#=> Nokogiri::XML::Document
response.data.css("item").size
#=> 10
response = Aitch.get("https://api.github.com/users/fnando")
response.data.class
#=> Hash
response.data["login"]
#=> fnando
Following redirects
The configuration:
Aitch.configure do |config|
config.follow_redirect = true
config.redirect_limit = 10
end
The request:
Aitch.get("http://example.org")
If the redirect limit is exceeded, then the Aitch::TooManyRedirectsError
exception is raised.
Basic auth
Setting basic auth credentials:
response = Aitch.get do
url "http://restrict.example.org/"
user: "john", password: "test"
end
Setting custom headers
Aitch.get do
url "http://example.org"
headers "User-Agent" => "MyBot/1.0.0"
end
The header value can be a callable object.
Aitch.configure do |config|
config.default_headers = {
"Authorization" => -> { "Token token=#{ENV.fetch("API_TOKEN")}" }
}
end
Creating namespaced requests
Sometimes you don't want to use the global settings (maybe you're building a lib). In this case, you can instantiate the namespace.
Request = Aitch::Namespace.new
Request.configure do |config|
config.user_agent = "MyLib/1.0.0"
end
Request.get("http://example.org")
Validating responses
When you know the kind of response you're expecting, you can validate it by
specifying the expect
option.
Aitch.get do
url "http://example.org"
expect: 200
end
If this request receives anything other than 200
, it will raise a
Aitch::StatusCodeError
exception.
Expect(200 OK) <=> Actual(404 Not Found)
You can also provide a list of accepted statuses, like expect: [200, 201]
.
Response Parsers
You can register new response parsers by using
Aitch::ResponseParser.register(name, parser)
, where parser must implement the
methods match?(content_type)
and load(response_body)
. This is how you could
load CSV values.
require "csv"
module CSVParser
def self.type
:csv
end
def self.match?(content_type)
content_type.to_s =~ /csv/
end
def self.load(source)
CSV.parse(source.to_s)
end
end
Aitch::ResponseParser.prepend(:csv, CSVParser)
The default behavior is returning the response body. You can replace it as the following:
module DefaultParser
def self.type
:default
end
def self.match?(content_type)
true
end
def self.load(source)
source.to_s
end
end
# You should use append here, to ensure
# that is that last parser on the list.
Aitch::ResponseParser.append(:default, DefaultParser)
Aitch comes with response parsers for HTML, XML and JSON.
By default, the JSON parser will be JSON
. To set it to something else, use
Aitch::ResponseParser::JSONParser.engine
.
require "oj"
Aitch::ResponseParser::JSONParser.engine = Oj
Setting the base url
When you're creating a wrapper for an API, usually the hostname is the same for
the whole API. In this case, you can avoid having to pass it around all the time
by setting Aitch::Configuration#base_url
. This option is meant to be used when
you instantiate a new namespace.
Client = Aitch::Namespace.new
Client.configure do |config|
config.base_url = "https://api.example.com"
end
Client.get("/users")
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request