fetch-wrapper.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import isPlainObject from "is-plain-object";
  2. import nodeFetch from "node-fetch";
  3. import { RequestError } from "@octokit/request-error";
  4. import getBuffer from "./get-buffer-response";
  5. export default function fetchWrapper(requestOptions) {
  6. if (isPlainObject(requestOptions.body) ||
  7. Array.isArray(requestOptions.body)) {
  8. requestOptions.body = JSON.stringify(requestOptions.body);
  9. }
  10. let headers = {};
  11. let status;
  12. let url;
  13. const fetch = (requestOptions.request && requestOptions.request.fetch) || nodeFetch;
  14. return fetch(requestOptions.url, Object.assign({
  15. method: requestOptions.method,
  16. body: requestOptions.body,
  17. headers: requestOptions.headers,
  18. redirect: requestOptions.redirect,
  19. }, requestOptions.request))
  20. .then((response) => {
  21. url = response.url;
  22. status = response.status;
  23. for (const keyAndValue of response.headers) {
  24. headers[keyAndValue[0]] = keyAndValue[1];
  25. }
  26. if (status === 204 || status === 205) {
  27. return;
  28. }
  29. // GitHub API returns 200 for HEAD requests
  30. if (requestOptions.method === "HEAD") {
  31. if (status < 400) {
  32. return;
  33. }
  34. throw new RequestError(response.statusText, status, {
  35. headers,
  36. request: requestOptions,
  37. });
  38. }
  39. if (status === 304) {
  40. throw new RequestError("Not modified", status, {
  41. headers,
  42. request: requestOptions,
  43. });
  44. }
  45. if (status >= 400) {
  46. return response
  47. .text()
  48. .then((message) => {
  49. const error = new RequestError(message, status, {
  50. headers,
  51. request: requestOptions,
  52. });
  53. try {
  54. let responseBody = JSON.parse(error.message);
  55. Object.assign(error, responseBody);
  56. let errors = responseBody.errors;
  57. // Assumption `errors` would always be in Array format
  58. error.message =
  59. error.message + ": " + errors.map(JSON.stringify).join(", ");
  60. }
  61. catch (e) {
  62. // ignore, see octokit/rest.js#684
  63. }
  64. throw error;
  65. });
  66. }
  67. const contentType = response.headers.get("content-type");
  68. if (/application\/json/.test(contentType)) {
  69. return response.json();
  70. }
  71. if (!contentType || /^text\/|charset=utf-8$/.test(contentType)) {
  72. return response.text();
  73. }
  74. return getBuffer(response);
  75. })
  76. .then((data) => {
  77. return {
  78. status,
  79. url,
  80. headers,
  81. data,
  82. };
  83. })
  84. .catch((error) => {
  85. if (error instanceof RequestError) {
  86. throw error;
  87. }
  88. throw new RequestError(error.message, 500, {
  89. headers,
  90. request: requestOptions,
  91. });
  92. });
  93. }