@ministryofjustice/hmpps-digital-prison-reporting-frontend
Version:
The Digital Prison Reporting Frontend contains templates and code to help display data effectively in UI applications.
113 lines (100 loc) • 3.29 kB
text/typescript
import superagent from 'superagent'
import Agent, { HttpsAgent } from 'agentkeepalive'
import logger from '../utils/logger'
import sanitiseError from '../utils/sanitisedError'
import { ApiConfig, GetRequest } from './types'
import Dict = NodeJS.Dict
export interface ResultWithHeaders<T> {
data: T
headers: Dict<string>
}
export default class RestClient {
agent: Agent
constructor(private readonly name: string, private readonly config: ApiConfig) {
this.agent = config.url.startsWith('https') ? new HttpsAgent(config.agent) : new Agent(config.agent)
}
private apiUrl() {
return this.config.url
}
private timeoutConfig() {
return this.config.agent.timeout
}
async get<T>(request: GetRequest): Promise<T> {
return this.getWithHeaders<T>(request).then((result) => result.data)
}
async getWithHeaders<T>({
path = null,
query = {},
headers = {},
responseType = '',
raw = false,
token,
}: GetRequest): Promise<ResultWithHeaders<T>> {
const loggerData = {
path: `${this.config.url}${path}`,
query,
}
logger.info(`${this.name}: ${JSON.stringify(loggerData, null, 2)}`)
try {
const result = await superagent
.get(`${this.apiUrl()}${path}`)
.agent(this.agent)
.retry(2, (err) => {
if (err) logger.info(`Retry handler found API error with ${err.code} ${err.message}`)
return undefined // retry handler only for logging retries, not to influence retry logic
})
.query(query)
.auth(token, { type: 'bearer' })
.set(headers)
.responseType(responseType)
.timeout(this.timeoutConfig())
return {
data: raw ? result : result.body,
headers: result.headers,
}
} catch (error) {
const sanitisedError = sanitiseError(error)
logger.warn({ ...sanitisedError, query }, `Error calling ${this.name}, path: '${path}', verb: 'GET'`)
throw sanitisedError
}
}
async deleteWithHeaders<T>({
path = null,
query = {},
headers = {},
responseType = '',
raw = false,
token,
}: GetRequest): Promise<ResultWithHeaders<T>> {
const loggerData = {
path: `${this.config.url}${path}`,
query,
}
logger.info(`${this.name}: ${JSON.stringify(loggerData, null, 2)}`)
try {
const result = await superagent
.delete(`${this.apiUrl()}${path}`)
.agent(this.agent)
.retry(2, (err) => {
if (err) logger.info(`Retry handler found API error with ${err.code} ${err.message}`)
return undefined // retry handler only for logging retries, not to influence retry logic
})
.query(query)
.auth(token, { type: 'bearer' })
.set(headers)
.responseType(responseType)
.timeout(this.timeoutConfig())
return {
data: raw ? result : result.body,
headers: result.headers,
}
} catch (error) {
const sanitisedError = sanitiseError(error)
logger.warn({ ...sanitisedError, query }, `Error calling ${this.name}, path: '${path}', verb: 'GET'`)
throw sanitisedError
}
}
async delete<T>(request: GetRequest): Promise<T> {
return this.deleteWithHeaders<T>(request).then((result) => result.data)
}
}