Hyperclient is a Hypermedia API client written in Ruby. It fully supports JSON HAL.
The examples in this README use the Splines Demo API running here. If you're upgrading from a previous version, please make sure to read UPGRADING.
Create an API client.
require 'hyperclient'
api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api')
By default, Hyperclient adds application/hal+json
as Content-Type
and Accept
headers. It will also send requests as JSON and parse JSON responses. Specify additional headers or authentication if necessary.
api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api') do |client|
client.headers['Access-Token'] = 'token'
end
Hyperclient constructs a connection using typical Faraday middleware for handling JSON requests and responses. You can specify additional Faraday middleware if necessary.
api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api') do |client|
client.connection do |conn|
conn.use Faraday::Request::OAuth
end
end
You can pass options to the Faraday connection block in the connection
block:
api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api') do |client|
client.connection(ssl: { verify: false }) do |conn|
conn.use Faraday::Request::OAuth
end
end
Or when using the default connection configuration you can use faraday_options
:
api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api') do |client|
client.faraday_options = { ssl: { verify: false } }
end
You can build a new Faraday connection block without inheriting default middleware by specifying default: false
in the connection
block.
api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api') do |client|
client.connection(default: false) do |conn|
conn.request :json
conn.response :json, content_type: /\bjson$/
conn.adapter :net_http
end
end
You can modify headers or specify authentication after a connection has been created. Hyperclient supports Basic, Token or Digest auth as well as many other Faraday extensions.
require 'faraday/digestauth'
api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api') do |client|
client.connection(default: false) do |conn|
conn.request :digest, 'username', 'password'
conn.request :json
conn.response :json, content_type: /\bjson$/
conn.adapter :net_http
end
end
You can access the Faraday connection directly after it has been created and add middleware to it. As an example, you could use the faraday-http-cache-middleware.
api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api')
api.connection.use :http_cache
Hyperclient will fetch and discover the resources from your API and automatically paginate when possible.
api.splines.each do |spline|
puts "A spline with ID #{spline.uuid}."
end
Other methods, including []
and fetch
are also available
api.splines.each do |spline|
puts "A spline with ID #{spline[:uuid]}."
puts "Maybe with reticulated: #{spline.fetch(:reticulated, '-- no reticulated')}"
end
The splines example above followed a link called "splines". While you can, you do not need to specify the HAL navigational structure, including links or embedded resources. Hyperclient will resolve these for you. If you prefer, you can explicitly navigate the link structure via _links
. In the following example the "splines" link leads to a collection of embedded splines. Invoking api.splines
is equivalent to api._links.splines._embedded.splines
.
api._links.splines
Templated links require variables to be expanded. For example, the demo API has a link called "spline" that requires a spline "uuid".
spline = api.spline(uuid: 'uuid')
puts "Spline #{spline.uuid} is #{spline.reticulated ? 'reticulated' : 'not reticulated'}."
Invoking api.spline(uuid: 'uuid').reticulated
is equivalent to api._links.spline._expand(uuid: 'uuid')._resource._attributes.reticulated
.
The client is responsible for supplying all the necessary parameters. Templated links don't do any strict parameter name checking and don't support required vs. optional parameters. Parameters not declared by the API will be dropped and will not have any effect when passed to _expand
.
Curies are a suggested means by which to link documentation of a given resource. For example, the demo API contains very long links to images that use an "images" curie.
puts spline['image:thumbnail'] # => https://grape-with-roar.herokuapp.com/api/splines/uuid/images/thumbnail.jpg
puts spline.links._curies['image'].expand('thumbnail') # => /docs/images/thumbnail
Resource attributes can also be accessed as a hash.
puts spline.to_h # => {"uuid" => "uuid", "reticulated" => true}
The above is equivalent to spline._attributes.to_h
.
Hyperclient uses Faraday under the hood to perform HTTP calls. You can call any valid HTTP method on any resource.
For example, you can examine the API raw JSON by invoking _get
and examining the _response.body
hash.
api._get
api._response.body
Other methods, including _head
or _options
are also available.
spline = api.spline(uuid: 'uuid')
spline._head
spline._options
Invoke _post
to create resources.
splines = api.splines
splines._post(uuid: 'new uuid', reticulated: false)
Invoke _put
or _patch
to update resources.
spline = api.spline(uuid: 'uuid')
spline._put(reticulated: true)
spline._patch(reticulated: true)
Invoke _delete
to destroy a resource.
spline = api.spline(uuid: 'uuid')
spline._delete
HTTP methods always return a new instance of Resource.
You can combine RSpec, Faraday::Adapter::Rack and Hyperclient to test your HAL API without having to ever examine the raw JSON response.
describe Acme::Api do
def app
Acme::App.instance
end
let(:client) do
Hyperclient.new('http://example.org/api') do |client|
client.headers['Content-Type'] = 'application/json'
client.connection(default: false) do |conn|
conn.request :json
conn.response :json
conn.use Faraday::Adapter::Rack, app
end
end
end
it 'splines returns 3 splines by default' do
expect(client.splines.count).to eq 3
end
end
For a complete example refer to this Splines Demo API test.
Using Hyperclient? Add your project to our wiki, please: https://github.com/codegram/hyperclient/wiki.
Hyperclient is work of many people. You're encouraged to submit pull requests, propose features and discuss issues. See CONTRIBUTING for details.
MIT License, see LICENSE for details.
Copyright (c) 2012-2018 Oriol Gual, Codegram Technologies and Contributors