Operation defines a specific request to a remote API with some helpers to process its responses.
To specify an operation, you should define the following parts:
- options of the request sender
- http(s) path to the remote server
- http method for sending requests
- security definitions describing what credentials the request should carry
- http headers to include into the request (along with security-related ones)
- request query to be added to the request path (along with security-related)
- a content of the request and a format describing the content should be formatted
- a set of middleware that should be added to the remote connection
- a set of expected responses with corresponding handlers
An operation is specified with a unique name inside the corresponding scope.
You can add it to the root of the client, or to any subscope:
class CatsClient < Evil::Client
# Returns current information about the client
operation :info do
# ...
end
scope :cats do
# ...
# Fetches information about a specific cat
operation :fetch do
# ...
end
end
end
Operation-specific definitions should be made inside the block. They will affect only this operation:
class CatsClient < Evil::Client
# ...
scope :cats do
# ...
operation :fetch do
option :id
path { id }
http_method :get
response 200
response(400, 422) { |(status, *)| raise "#{status}: Wrong request" }
response(404) { raise "404: Not found" }
end
end
end
Besides operation-specific settings, you can add same definitions for a scope. This definitions are shared by all operations of the scope and its sub-scopes on any level of nesting. Any sub-scope or operation can reload this shared definitions, or update it with those of its own.
class CatsClient < Evil::Client
# ...
scope :cats do
path { "cats" } # relative to root scope
http_method :get
response 200
response(400, 422) { |(status, *)| raise "#{status}: Wrong request" }
response(404) { raise "404: Not found" }
operation :fetch do
option :id
path { id } # relative to upper scope
end
end
end
The user of custom client sends a request by invoking some operation by name on a corresponding scope.
client = CatsClient.new
cats = client.cats # scope for the `fetch` operaton
cats.fetch id: 44 # sends request and returns a processed response
Alternatively you can initialize the operation first, and call it later:
operation = cats.operations[:fetch].new(id: 44)
operation.call