fetch-json.js 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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 putJSON(path, options) {
  14. return fetchJSON(path, { ...options, method: 'PUT' })
  15. }
  16. export function deleteJSON(path, options) {
  17. return fetchJSON(path, { ...options, method: 'DELETE' })
  18. }
  19. function fetchJSON(
  20. path,
  21. {
  22. body = {},
  23. headers = {},
  24. method = 'GET',
  25. credentials = 'same-origin',
  26. ...otherOptions
  27. }
  28. ) {
  29. const options = {
  30. ...otherOptions,
  31. headers: {
  32. ...headers,
  33. 'Content-Type': 'application/json',
  34. 'X-Csrf-Token': window.csrfToken,
  35. Accept: 'application/json'
  36. },
  37. credentials,
  38. method
  39. }
  40. if (method !== 'GET' && method !== 'HEAD') {
  41. options.body = JSON.stringify(body)
  42. }
  43. return fetch(path, options)
  44. .then(parseResponseBody)
  45. .then(({ responseBody, response }) => {
  46. if (!response.ok) {
  47. throw new OError(response.statusText, {
  48. statusCode: response.status,
  49. responseBody,
  50. response
  51. })
  52. }
  53. return responseBody
  54. })
  55. }
  56. function parseResponseBody(response) {
  57. const contentType = response.headers.get('Content-Type')
  58. if (/application\/json/.test(contentType)) {
  59. return response.json().then(json => {
  60. return { responseBody: json, response }
  61. })
  62. } else if (
  63. /text\/plain/.test(contentType) ||
  64. /text\/html/.test(contentType)
  65. ) {
  66. return response.text().then(text => {
  67. return { responseBody: { message: text }, response }
  68. })
  69. } else {
  70. // response body ignored as content-type is either not set (e.g. 204
  71. // responses) or unsupported
  72. return Promise.resolve({ responseBody: {}, response })
  73. }
  74. }