When working with API clients there are several distinct areas of concern. Each of these happen in sequence and are used with the goal of receiving a Domain Model at the end.
- Routing
- Configuration
- Logging
- Connection Handling
- Error Handling
- Request Building
- Request Handling
- Response Handling
- Domain Modeling
This answers the question: what can I do with this API?
When embedded links or hypermedia are not available, routing should be confined to a single responsibility and include:
- Fully qualified URIs
- Specified URI Template
By using HTTP
and available methods we can see more details as to how we can interact with a specific link. For instance, we may have a route like: /products
. This tells us the route, but doesn't tell us how to interact with it. By making a call to OPTIONS /products
, we can learn that the Allow
header specifies GET,POST,OPTIONS,HEAD
. This means we can then issue a GET
request to retrieve all products, or we can issue a POST
request to create a new product.
By providing extended meta information in the OPTIONS
request, we can also describe the requests in greater detail. We can answer questions like:
- What are my available filters on a
GET
request? (their names, data types, formats, etc) - What are the
Content-Type
s available to me? Can IGET
this asJSON
andCSV
? - What are the parameters required when
POST
ing to a new record? (their names, data types, formats, validation rules, etc)
The biggest advantage to a centralized routing library: You are not manually building URIs throughout your application code. You can see this in many applications, where the routes are scattered about the JavaScript or server side code with mixed templating and interpolation strategies. Keep it simple.
This answers the question: how should I communicate with the API?
The configuration object sets up the different variables you will use throughout your interactions. It can be used to:
- Set Defaults
- Allow User Provided values
A set of configuration options may include
- API Host
- API Version
- Proxy Information
- Basic Auth Information
- OAuth Bearer Token Information
- Default HTTP Headers
- User Agent
- Media Type
- Content Type
- Pagination Handling
This answers the question: what is happening behind the scenes?
Logging can be used in several areas:
- Raw request logging. These are the raw HTTP requests.
- Cache logging. When utilizing HTTP Caching, this provides information into your hits and misses.
- Application logging. This provides feedback in the client itself. This is useful to provide feedback and information such as:
- Deprecation warnings
- Debugging information when calling certain methods
This answers the question: can we communicate with the API server?
This involves things like:
- Establishing a connection (is the server responding at all?)
- Specifying a timeout for retries
- Ensuring the response code is not in the
500
range
This answers the question: something is wrong, but what is it and can I fix it?
Whether we are dealing with connection errors or request errors, there should be a consistent way to handle when something goes wrong.
- When there are connection errors, this is an
Exception
. We can't do anything else with the API until we can connect. - When there are request errors, it could be either an
Exception
or silent failure.
This phase allows you to prepare your request that you want to make. This includes things like:
- HTTP Headers
- HTTP Query String Params
- HTTP Body Params
This phase should provide a DSL to build requests in a consistent manner. The specific client could then have very specific implementations of the details (IE: Using Query String params like Google API)
This answers the question: Can you provide me the resource with this representation?
This takes the Request Builder from the last phase, combines in with the Connection Handling, and issues a request to the server.
One a request has been issued, there is a response that includes things like:
- HTTP Response body (according to content negotiation - CSV, JSON, etc)
- HTTP Status Code
- HTTP Headers
- Full Raw Response
The response Status Code itself allows us to immediately handle the request accordingly:
- If it's a non-successful code, handle as an error
- If it's successful, we can continue.
The response Header itself carries some important client information as well, such as:
- Scope listing
- Content Negotiation
Allow
information- Caching information
- OAuth Information
Link
information
The goal here is to ensure we get a 200
range response. Not all responses will include a body. We also need to figure out if we want to follow redirects and for how many hops (avoid infinite redirect loops).
We've configured, connected, built our request, issued the request to the server, and received a response. Now it's time to take that response and turn it into the Core Domain Model.
In most cases this is translating the JSON
response into meaningful objects. The body itself may include other pieces of helpful information:
- Metadata
- Pagination Information
- Links
- Data/Results - the body itself
Each of these models will translate accordingly and can be used to then issue subsequent requests.
- PAW: Mac Client, allows you to build requests and see responses.
- Build the request itself with headers and params
- View the request as a URL and as cURL and other tools.
- View the response as raw output, or separated by headers and body
- Allows you to extract environment variables for use in requests (configuration)
- Github Octokit