I have created a wrapper for Fetch to send requests to my API. The module exports api
, and requests can be made with:
api.get({ url: '/users' })
or
api.post({ url: '/users', data: {id: 1, name: myName} })
After receiving the HTTP response from fetch
I do some additional tasks, like update a token, then extract the JSON, camelCase the JSON keys, then return the JSON.
I'm mostly interested in a review of the api
export, and handle errors in the fetch
request.
const baseURL = 'http://mydomain.com/'
const csrfTokenExtractor = (response) => {
const token = response.headers['x-csrf-token']
if (token) {
document.querySelector('meta[name=csrf-token]').setAttribute('content', token)
}
return response
}
const csrfHeader = () => {
const token = document.querySelector('meta[name=csrf-token]').getAttribute('content')
return {
'X-CSRF-Token': token,
}
}
const defaultHeader = () => {
return {
'X-App-Component': 'app',
}
}
const sessionDetector = (response) => {
if (response.status === 401) {
window.location.replace(response.data.url)
}
return response
}
const buildURLQuery = (obj) =>
Object.entries(obj)
.map((pair) => pair.map(encodeURIComponent).join('='))
.join('&')
const request = async ({ url, method, ...params }) => {
params.credentials = 'same-origin'
params.headers = Object.assign({}, params.headers || {}, defaultHeader())
params.method = method
if (method !== 'GET') {
params.headers = Object.assign({}, params.headers || {}, { 'Content-Type': 'application/json' }, csrfHeader())
}
let response
try {
response = await fetch(`${baseURL}${url}`, {
...params })
if (!response.ok) {
console.error(response)
throw response
}
} catch (error) {
sessionDetector(error)
console.error(error)
throw error
}
await csrfTokenExtractor(response)
const json = await response.json()
const formattedJson = camelcaseKeys(json, { deep: true })
return formattedJson
}
const api = {
get: ({ url, formData = {} }) => {
const options = {
method: 'GET',
mode: 'cors',
url: `${url}?${buildURLQuery(formData)}`,
}
return request(options)
},
post: ({ url, data = {} }) => {
const options = {
method: 'POST',
url,
body: JSON.stringify(data),
}
return request(options)
},
put: ({ url, data = {} }) => {
const options = {
method: 'PUT',
url,
body: JSON.stringify(data),
}
return request(options)
},
delete: ({ url }) => {
const options = {
method: 'DELETE',
url,
}
return request(options)
},
request,
}
export default api