fetch-json.js 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. // fetch wrapper to make simple JSON requests:
  2. // - send the CSRF token in the request
  3. // - set the JSON content-type in the request headers
  4. // - throw errors on non-ok response
  5. // - parse JSON response body, unless response is empty
  6. const OError = require('@overleaf/o-error')
  7. export function getJSON(path, options) {
  8. return fetchJSON(path, { ...options, method: 'GET' })
  9. }
  10. export function postJSON(path, options) {
  11. return fetchJSON(path, { ...options, method: 'POST' })
  12. }
  13. export function deleteJSON(path, options) {
  14. return fetchJSON(path, { ...options, method: 'DELETE' })
  15. }
  16. export default function fetchJSON(
  17. path,
  18. { body = {}, headers = {}, method = 'GET', ...otherOptions }
  19. ) {
  20. const options = {
  21. ...otherOptions,
  22. headers: {
  23. ...headers,
  24. 'Content-Type': 'application/json',
  25. 'X-Csrf-Token': window.csrfToken,
  26. Accept: 'application/json'
  27. },
  28. method
  29. }
  30. if (method !== 'GET' && method !== 'HEAD') {
  31. options.body = JSON.stringify(body)
  32. }
  33. return fetch(path, options)
  34. .then(parseResponseBody)
  35. .then(({ responseBody, response }) => {
  36. if (!response.ok) {
  37. throw new OError(response.statusText, {
  38. statusCode: response.status,
  39. responseBody,
  40. response
  41. })
  42. }
  43. return responseBody
  44. })
  45. }
  46. function parseResponseBody(response) {
  47. const contentType = response.headers.get('Content-Type')
  48. if (/application\/json/.test(contentType)) {
  49. return response.json().then(json => {
  50. return { responseBody: json, response }
  51. })
  52. } else if (
  53. /text\/plain/.test(contentType) ||
  54. /text\/html/.test(contentType)
  55. ) {
  56. return response.text().then(text => {
  57. return { responseBody: { message: text }, response }
  58. })
  59. } else {
  60. // response body ignored as content-type is either not set (e.g. 204
  61. // responses) or unsupported
  62. return Promise.resolve({ responseBody: {}, response })
  63. }
  64. }