fetch-json.js 2.0 KB

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