overleaf/services/web/frontend/js/infrastructure/fetch-json.js

84 lines
2 KiB
JavaScript
Raw Normal View History

// fetch wrapper to make simple JSON requests:
// - send the CSRF token in the request
// - set the JSON content-type in the request headers
// - throw errors on non-ok response
// - parse JSON response body, unless response is empty
const OError = require('@overleaf/o-error')
export function getJSON(path, options) {
return fetchJSON(path, { ...options, method: 'GET' })
}
export function postJSON(path, options) {
return fetchJSON(path, { ...options, method: 'POST' })
}
export function putJSON(path, options) {
return fetchJSON(path, { ...options, method: 'PUT' })
}
export function deleteJSON(path, options) {
return fetchJSON(path, { ...options, method: 'DELETE' })
}
function fetchJSON(
path,
{
body = {},
headers = {},
method = 'GET',
credentials = 'same-origin',
...otherOptions
}
) {
const options = {
...otherOptions,
headers: {
...headers,
'Content-Type': 'application/json',
'X-Csrf-Token': window.csrfToken,
Accept: 'application/json'
},
credentials,
method
}
if (method !== 'GET' && method !== 'HEAD') {
options.body = JSON.stringify(body)
}
return fetch(path, options)
.then(parseResponseBody)
.then(({ data, response }) => {
if (!response.ok) {
throw new OError(response.statusText, {
statusCode: response.status,
data,
response
})
}
return data
})
}
function parseResponseBody(response) {
const contentType = response.headers.get('Content-Type')
if (/application\/json/.test(contentType)) {
return response.json().then(data => {
return { data, response }
})
} else if (
/text\/plain/.test(contentType) ||
/text\/html/.test(contentType)
) {
return response.text().then(text => {
return { data: { message: text }, response }
})
} else {
// response body ignored as content-type is either not set (e.g. 204
// responses) or unsupported
return Promise.resolve({ data: {}, response })
}
}