api-connector-lite v0.1.2
ApiConnector lite
An axios-based API connector to handle complex aspects of real-life APIs. This API connector can be used with any Javascript framework currently supported by axios.
Features
- Mutiple instances - support multiple instances for multiple APIs.
- JWT / Bearer Authentication - for any request which return
accessTokenandrefreshToken, those are internally stored. TheaccessTokenwill be included in the headers asBearertoken for all requests. TherefreshTokenwill be internally used for/v1/oauth2/refreshendpoint. - Retry on Timeout - if a request will timeout, either by the server or with
504 Gateway timeoutit will be automatically retried with increased timeout. - Idempotency Support - all
POST,PUTandPATCHrequests will automatically include an idempotency key in the header (Idempotency-Key) as a hash build from the request's URL and payload, inuuidv4format. - Cancel Repeated Requests - if an identical request is sent more than once, either future requests will be canceled until the initial one responded or the existing will be canceled and the new one will be processed.
- StepUp Support - Require users to authenticate with a stronger mechanism to access sensitive information or perform certain transactions.
Instalation
You can use either npm or yarn to add it to your project.
yarn add api-connector-lite or npm install api-connector-lite
- Supports
node, browser, andreact-native - Built with TypeScript
- Depends on axios
Quick Start
// in main or config file
import { ApiConnector } from 'api-connector-lite'
ApiConnector.getInstance('default', {
baseURL: 'https://my-platform.com/v1',
apiKey: 'the-api-key-to-use-for-this-server',
cancelOldRequests: true, // cancel all pending request for search autocomplete
})
// later, maybe in another file
import { ApiConnector } from 'api-connector-lite'
const result = await ApiConnector.getInstance().get('/products').then(response => response?.data)Documentation
Import
You can import the API connector in any of your .js or .ts file.
import { ApiConnector } from 'api-connector-lite'Initialisation
ApiConnector supports multiple axios instances by using different connection names. The name for the implicit instance is default.
Initialise ApiConnection
Initialise default instance
The implicit instance is using the reserved default name.
ApiConnector.getInstance('default', {
baseURL: 'https://my-platform.com/v1',
apiKey: 'the-api-key-to-use-for-this-environment',
autoRefreshToken: false, // turn off autoRefresh
useIdempotency: false, // turn off idempotency support
cancelOldRequests: false, // cancel new requests
stepUpAuthEnabled: true, // enable stepUpAuth
retryOnTimeout: false, // disable timeout retries
useResponseTime: true, // enable response time calculation
})You can call the .getInstance('default', {...}) multiple times to overwrite certain options.
Note: The default name is only required when initializing the implicit instance. When calling the instance the default name can be omitted.
Once the initialisation is done, the ApiConnector can be used like this a classic axios instance:
const instance = ApiConnector.getInstance()
const response = await instance.get('/products')or shorter,
const response = await ApiConnector.getInstance().get('/products')Initialise suplemental connections
Suplemental connections can be initialised by using different names. Please remember that the name default is reserved for the default instance.
ApiConnector.getInstance('legacy', {
baseURL: 'https://my-legacy-platform.com/v2',
apiKey: 'the-api-key-to-use-for-this-legacy-environment,
})You can call the .getInstance('legacy', {...}) multiple times to overwrite certain options.
Note: For all other instances except the default one, you need to specify the same name used at initialization when you want to use them.
Once the initialisation is done, the ApiConnector can be used like a classic axios instance quoting its name:
const legacyInstance = ApiConnector.getInstance('legacy')
const response = await legacyInstance.get('/products')or shorter,
const response = await ApiConnector.getInstance('legacy').get('/products')Initialisation options
The following options can be used on top of the axios options:
autoRefreshToken- flag to enable token refresh if401status code is returned with certain response code; defaulttrueretryOnTimeout- flag to enable request retry on timeout. Timeout can happen either if the server response is not received in due time or if the server responds with status code504Gateway timeout. The request will retry with a temporary timeout increase of 10 folds and stops before reaching 60sec; defaulttrueuseIdempotency- enable static idempotency key calculation based on payload forpost,putandpatchmethods; defaulttruecancelOldRequests- enable repeated request cancellation; if the current request did not completeded before a new same request was made, either the existing request or the new request will be cancelled, depending on this flag's value; defaultundefined(disabled).stepUpAuthEnabled- flag to enable StepUp Authentication (reauthentication with user/password) before the request will be processed; defautfalseuseResponseTime- flag to enable the response time calculation for both request success or error. The duration of the request can be found in theconfig.metadata.durationofresponseorerrorobject; default:false
Note: Don't forget to add axios mandatory parameter baseURL.
Usage examples
The ApiConnector instances are axios instances so they can be used as expected.
GET method
const response = await ApiConnector.getInstance()
.get('/products')
.then((result) => result?.data)
.catch(console.error)POST method
const response = await ApiConnector.getInstance()
.post('/conversations', { messages })
.then((result) => result?.data)
.catch(console.error)PUT method
const response = await ApiConnector.getInstance()
.put('/conversations', { messages })
.then((result) => result?.data)
.catch(console.error)PATCH method
const response = await ApiConnector.getInstance()
.patch('/conversations', { messages })
.then((result) => result?.data)
.catch(console.error)DELETE method
const wasDeleted = await ApiConnector.getInstance()
.delete(`/conversations/${id}`)
.then((result) => [202, 204].includes(result?.status))
.catch(console.error)Special methods
The returned axios instance was enhanced with some utility functions one can find useful.
refreshToken
Although the authentication tokens are refreshed when needed, there may be certain cases where you may want to force authentication tokens refresh. For that you can call:
ApiConnector.getInstance().refreshToken()updateHeaders
There may be cases you want to add or update certain headers while preserving the authentication tokens. Thus, reinitialising the instance is not a viable solution. For that you can call, for example:
ApiConnector.getInstance().updateHeaders({ 'x-device-id': '000-111-222-333-999' })getApiHeaders
There are cases you want to make a request outside the ApiConnector instances, such as using PDFReader to access remote pdf files. For that you need to pass the authentication token and the API key, but these are kept internally in the ApiConnector instances. To get the authetication headers you can use:
const headers = ApiConnector.getInstance().getApiHeaders()The headers will contain both X-ApiKey and Authorization headers. Keep in mind that the Authorization header changes in time so you need to repeteadly call getApiHeaders() method for the updated value.
stepUp
If the stepUpAuthEnabled option is enabled and a request responded with status code 403 Forbidden and there is a transactionId value present in the response.data, then the request can be retried by calling the stepUp method. This assumes the presence of an endpoint /v1/oauth2/stepup. This endpoint is accepting X-TransactionId in headers and either username and passcode or refreshToken and authenticationMethod: 'BIOMETRIC' as payload.
When calling stepUp method, if the username and passcode are not provided, then the refreshToken and authenticationMethod: 'BIOMETRIC' will be used instead. This will force a reauthentication before the original request will be retried.
const response = await ApiConnector.getInstance().stepUp()or
const response = await ApiConnector.getInstance().stepUp(username, passcode)Why ApiConnectorLite?
The ApiConnector (for now in a private github repo) includes an HTTP adapter from Cryptomathic which can optionally replace the current axios one, for increased, banking-grade security. This is not an opensource software, thus the private repo.
4 years ago