Skip to content

Instantly share code, notes, and snippets.

@johandalabacka
Created May 25, 2023 08:40
Show Gist options
  • Save johandalabacka/d3381f1c53e1fd6d8102a11dc5232c28 to your computer and use it in GitHub Desktop.
Save johandalabacka/d3381f1c53e1fd6d8102a11dc5232c28 to your computer and use it in GitHub Desktop.
/**
*
* @param {Response} response
* @returns {any}
*/
async function _fetchBody (response) {
const contentType = response.headers.get('content-type')
if (contentType === 'application/json') {
return await response.json()
} else if (contentType.includes('text')) {
return await response.text()
} else {
return await response.blob()
}
}
class FetchAxiosError extends Error {
constructor (message, response) {
super(message)
this.response = response
}
}
class FetchAxios {
constructor ({ baseURL = '', params, auth, headers } = {}) {
this.baseURL = baseURL
this.params = params
this.headers = headers
this.auth = auth?.username && auth?.password ? btoa(`${auth.username}:${auth.password}`) : null
}
_getUrl (url, params) {
/**
* @type {URLSearchParams?} combinedParams
*/
let combinedParams = null
if (this.params || params) {
combinedParams = URLSearchParams({ ...this.params, ...params })
}
let finalUrl = this.baseURL + url
if (combinedParams) {
finalUrl = finalUrl + '?' + combinedParams.toString()
}
return finalUrl
}
_getHeaders (headers) {
const combinedHeaders = { ...this.headers, ...headers }
if (this.auth) {
combinedHeaders.Authorization = `Basic ${this.auth}`
}
if (!combinedHeaders.Accept) {
combinedHeaders.Accept = 'application/json'
}
return combinedHeaders
}
async get (url, options = {}) {
const combinedOptions = { method: 'GET' }
const combinedUrl = this._getUrl(url, options.params)
combinedOptions.headers = this._getHeaders(options.headers)
const response = await fetch(combinedUrl, combinedOptions)
response.data = await _fetchBody(response)
if (!response.ok) {
throw new FetchAxiosError(`${response.status} - ${response.statusText}`, response)
}
return response
}
async post (url, payload, options) {
/**
* @type {Request} input
*/
const combinedOptions = { method: 'POST' }
const combinedUrl = this._getUrl(url, options.params)
combinedOptions.headers = this._getHeaders(options.headers)
const response = await fetch(combinedUrl, combinedOptions)
response.data = _fetchBody(response)
if (!response.ok) {
throw new FetchAxiosError(`${response.status} - ${response.statusText}`, response)
}
return response
}
}
module.exports = {
client: new FetchAxios(),
FetchAxios,
FetchAxiosError,
create (options) {
return new FetchAxios(options)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment