Service::Client is a generic client gem to access our services. It is the base for explicit clients for each service so that those explicit clients are easy and fast to implement and maintain.
This gem should not be used as an "end-user solution".
Each client must be instantiated with a base URL to a service.
client = Service::Client.new('http://some=service.example.com/')
A client route describes a single REST HTTP end-point at the service.
client.urls.add(:author, :post, '/authors/')
client.urls.add(:author, :get, '/authors/:id:')
client.urls.add(:review, :post, '/author/:author_id:/books/:book_id:')
client.post(client.urls.author, token, name: 'Peter Lustig')
client.get(client.urls.author(123), token)
client.post(client.urls.review(author_id: 123, book_id: 456), token, name: 'Ronald Review', comment: 'This book is the bomb!')
Each Service::Client
instance supports the get
, post
, put
and delete
methods. They all share the same method signature of:
client.method(URL, TOKEN, BODY_HASH)
The URL is a relative URL to the base url the client has been created with. TOKEN is an OAuth token to authenticat the request. The BODY_HASH is any Ruby hash. The hash becomes the body of the HTTP request after it has been dumped to JSON.
The client.urls
method makes all the created routes available as an easy to use URL builder. The URL builder takes zero arguments when the URL does not have any arguments. It can also take an array of the URL paramters in their respective order or a hash to built the URL by it's named parameters.
If the HTTP response comes with a 200 status code, the client returns a Service::Client::Response
object. That allows you to query for the JSON decoded data that came along with the body of the HTTP response. If the body was empty that data is just true
. You can also reach for the raw HTTP response:
response = client.get(client.urls.author(123), token)
puts "retrieved a book written by #{response.data['name']} with an HTTP status code of #{response.raw.status}"
For any redirecting responses the client raises a Service::Client::Redirection
which can be queried for the redirection location:
begin
client.get(client.urls.author(123), token)
rescue Client::Service::Redirection => redirection
puts "The client has been redirected to: #{redirection.location}"
end
For any other response codes the client raises a Service::Client::ServiceError
if the response body was a JSON encoded object with an error
key on the root level.
begin
client.get(client.urls.author(678), token)
rescue Client::Service::ServiceError => e
puts "A service error has occured. Error description: #{e.error}"
end
If the body was not JSON encoded at all or did not include the error
key on the root level a Service::Client::ResponseError
is raised.
begin
client.get(client.urls.author(678), token)
rescue Client::Service::Error => e
puts "An error has occured. Error code: #{e.response.status} Error body: #{e.response.body}"
end
The client exposes an interface that can be used to issue raw HTTP requests to any URL relative to the given base URL at creation time.
response = client.raw.post('/authors/123/books', JSON.dump({title: 'The guide to a higher enlightment', isbn: '1234567'}))
The raw client supports the get
, post
, put
and delete
methods. They all share the same method signature of:
client.raw.method(URL, BODY, OPTIONS)
The options are a hash. Possible arguments are:
headers
: A hash (string:string) to set the request headers.
Raw requests return a Rack::Response
object that makes it easy to access the status code, headers and body of the response.
response = client.raw.get('/author/123/books')
response.body # "[{title: 'The guide to a higher enlightment', isbn: '1234567', id: 456}, {title: 'Some book', isbn: '23464527', id: 789}]"
response.status # 200
response.header # {"Some-Header" => "Some Value", "Another-Header" => "Another Value"}