1.3.5. Proximie REST services
The Proximie infrastructure provides a comprehensive set of REST APIs for accessing the Proximie services. These are described in detail on Proximie’s API Developer Hub.
The Proximie::PxRestApi namespace provides high level support for key Proximie REST APIs for use with SDK applications.
Access tokens
All requests need to provide an access token, which allows the Proximie services to know what the requestor is authorised to access. Access tokens are obtained via an authentication flow using requests with Proximie’s authentication service.
Note that access tokens have a limited life span; depending on the service or tenant being accessed, this can range from minutes to hours. Applications need to handle token expiry and refresh flows to keep an up-to-date and valid token.
For more information on obtaining and managing access tokens, see Authentication & authorisation.
Using PxRestApi::ProximieServices
An application can use a ProximieServices
object
to make API calls to the Proximie service. The Proximie APIs are numerous and the
SDK ProximieServices implements a limited useful subset of functions and types.
This set will grow as the SDK continues to develop.
Creating a ProximieServices instance
To create a new ProximieServices object, the application needs to provide:
A
ProximieContext
for the applicationA
ServiceSettings
object providing details on how to access the service - e.g. the host name and portA
RequestFields
object providing request fields to be used for each request
using ProximieServices = Proximie::PxRestApi::ProximieServices;
ProximieServices::ServiceSettings service;
service.host = "my.proximie.net";
ProximieServices::RequestFields reqFields;
reqFields.tokenProvider(auth);
ProximieServices pxapi(pxcontext, service, reqFields);
We assume pxcontext
is already created (see ProximieContext for details).
The ServiceSettings
object
simply has the host
set (this will differ depending on which Proximie
environment or tenant you are using).
Then, the request fields are set. Here, we just set a tokenProvider
,
which is an object that the application creates. It is responsible, upon request,
to provide a valid access token for a REST call. See Authentication & authorisation for more
information on token providers.
Making REST API requests
Once you have your ProximieServices object, you can use its member functions to make API requests. As mentioned previously only a subset of the full Proximie APIs are implemented, but the functions provided use full C++ types for ease of calling and obtaining results.
The API functions typically come in two forms: with callback handler or returning a future.
Example using a callback:
using Sessions = Proximie::PxRestApi::Sessions;
using SessionsResult = ProximieServices::PayloadResult<Sessions>;
pxapi.getSessions([](const SessionsResult& result) {
if (result.error) {
// Handle error
} else {
// The result contains a response with a typed payload
std::shared_ptr<Sessions> sessionsPayload = result.payload;
// ...
}
});
And using a future:
SessionsResult result = pxapi.getSessions().get(); // Note: get() will block
if (result.error) {
// Handle error
} else {
// The result contains a response with a typed payload
std::shared_ptr<Sessions> sessionsPayload = result.payload;
// ...
}
As you can see, the resulting objects are the same, but returned to the application using different approaches.
See the full SDK documentation for ProximieServices
for a list of REST API functions supported.
Error handling
As outlined above, the result value for an service call has an error
,
which is a error_code
value.
Depending on the type of error, there may be additional details in the response returned.
If the error was so severe that the actual end point could not be reached, only the error code will be present. If the error was in the request itself, the response will contain additional details of the response from the Proximie services.
auto result = pxapi.getSessions().get();
if (result.error) {
if (result.response) {
// The response is the generic data from the response
auto httpStatus = result.response->httpStatus;
auto payloadText = result.response->valueText;
//...
}
}
Where errors indicate a problem with the request itself, e.g. an invalid parameter or ID,
the returned response usually has additional information, which is included in the
response’s errorDetails
field.
// If there are error details, we can examine them
if (result.errorDetails) {
auto& error = result.errorDetails->error;
auto httpStatus = error.statusCode; // HTTP status code
auto errorCode = error.errorCode; // Service error code string
auto message = error.message; // Error message
// ...
}
Finally, you can also obtain a string representation of the error using the
errorSummary()
member function. The advantage of this function is that is checks the response and
error details to produce the most informative message it can.
auto message = result.errorSummary();
std::cerr << "Error getting session: " << message << std::endl;
Could output something like:
Error getting session: [404] client error: Session aebebe1e-d9a7-47ff-8a5f-20b4f70f10a1 was not found