Skip to content
Permalink
Newer
Older
100644 119 lines (119 sloc) 4.03 KB
Ignoring revisions in .git-blame-ignore-revs.
1
import { isPlainObject } from "is-plain-object";
July 13, 2023 11:17
2
import nodeFetch from "node-fetch";
3
import { RequestError } from "@octokit/request-error";
4
import getBuffer from "./get-buffer-response";
July 13, 2023 11:17
5
export default function fetchWrapper(requestOptions) {
6
const log = requestOptions.request && requestOptions.request.log
7
? requestOptions.request.log
8
: console;
9
if (isPlainObject(requestOptions.body) ||
10
Array.isArray(requestOptions.body)) {
11
requestOptions.body = JSON.stringify(requestOptions.body);
July 13, 2023 11:17
13
let headers = {};
14
let status;
15
let url;
16
const fetch = (requestOptions.request && requestOptions.request.fetch) || nodeFetch;
17
return fetch(requestOptions.url, Object.assign({
18
method: requestOptions.method,
19
body: requestOptions.body,
20
headers: requestOptions.headers,
21
redirect: requestOptions.redirect,
22
},
23
// `requestOptions.request.agent` type is incompatible
24
// see https://github.com/octokit/types.ts/pull/264
25
requestOptions.request))
26
.then(async (response) => {
27
url = response.url;
28
status = response.status;
29
for (const keyAndValue of response.headers) {
30
headers[keyAndValue[0]] = keyAndValue[1];
31
}
32
if ("deprecation" in headers) {
33
const matches = headers.link && headers.link.match(/<([^>]+)>; rel="deprecation"/);
34
const deprecationLink = matches && matches.pop();
35
log.warn(`[@octokit/request] "${requestOptions.method} ${requestOptions.url}" is deprecated. It is scheduled to be removed on ${headers.sunset}${deprecationLink ? `. See ${deprecationLink}` : ""}`);
36
}
37
if (status === 204 || status === 205) {
38
return;
39
}
40
// GitHub API returns 200 for HEAD requests
41
if (requestOptions.method === "HEAD") {
42
if (status < 400) {
43
return;
44
}
45
throw new RequestError(response.statusText, status, {
46
response: {
47
url,
48
status,
49
headers,
50
data: undefined,
51
},
52
request: requestOptions,
53
});
54
}
55
if (status === 304) {
56
throw new RequestError("Not modified", status, {
57
response: {
58
url,
59
status,
60
headers,
61
data: await getResponseData(response),
62
},
63
request: requestOptions,
64
});
65
}
66
if (status >= 400) {
67
const data = await getResponseData(response);
68
const error = new RequestError(toErrorMessage(data), status, {
69
response: {
70
url,
71
status,
72
headers,
73
data,
74
},
75
request: requestOptions,
76
});
77
throw error;
78
}
79
return getResponseData(response);
80
})
81
.then((data) => {
82
return {
83
status,
84
url,
85
headers,
86
data,
87
};
88
})
89
.catch((error) => {
90
if (error instanceof RequestError)
91
throw error;
92
throw new RequestError(error.message, 500, {
93
request: requestOptions,
94
});
July 13, 2023 09:09
96
}
97
async function getResponseData(response) {
July 13, 2023 11:17
98
const contentType = response.headers.get("content-type");
99
if (/application\/json/.test(contentType)) {
100
return response.json();
101
}
102
if (!contentType || /^text\/|charset=utf-8$/.test(contentType)) {
103
return response.text();
104
}
105
return getBuffer(response);
July 13, 2023 09:09
106
}
107
function toErrorMessage(data) {
July 13, 2023 11:17
108
if (typeof data === "string")
109
return data;
110
// istanbul ignore else - just in case
111
if ("message" in data) {
112
if (Array.isArray(data.errors)) {
113
return `${data.message}: ${data.errors.map(JSON.stringify).join(", ")}`;
114
}
115
return data.message;
July 13, 2023 09:09
116
}
July 13, 2023 11:17
117
// istanbul ignore next - just in case
118
return `Unknown error: ${JSON.stringify(data)}`;