-
Notifications
You must be signed in to change notification settings - Fork 61
/
Copy pathfetch-wrapper.ts
126 lines (104 loc) · 3 KB
/
fetch-wrapper.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import isPlainObject from "is-plain-object";
import nodeFetch from "node-fetch";
import { RequestError } from "@octokit/request-error";
import { EndpointInterface } from "@octokit/types";
import getBuffer from "./get-buffer-response";
export default function fetchWrapper(
requestOptions: ReturnType<EndpointInterface> & { redirect?: string }
) {
if (
isPlainObject(requestOptions.body) ||
Array.isArray(requestOptions.body)
) {
requestOptions.body = JSON.stringify(requestOptions.body);
}
let headers: { [header: string]: string } = {};
let status: number;
let url: string;
const fetch: typeof nodeFetch =
(requestOptions.request && requestOptions.request.fetch) || nodeFetch;
return fetch(
requestOptions.url,
Object.assign(
{
method: requestOptions.method,
body: requestOptions.body,
headers: requestOptions.headers,
redirect: requestOptions.redirect
},
requestOptions.request
)
)
.then(response => {
url = response.url;
status = response.status;
for (const keyAndValue of response.headers) {
headers[keyAndValue[0]] = keyAndValue[1];
}
if (status === 204 || status === 205) {
return;
}
// GitHub API returns 200 for HEAD requests
if (requestOptions.method === "HEAD") {
if (status < 400) {
return;
}
throw new RequestError(response.statusText, status, {
headers,
request: requestOptions
});
}
if (status === 304) {
throw new RequestError("Not modified", status, {
headers,
request: requestOptions
});
}
if (status >= 400) {
return response
.text()
.then(message => {
const error = new RequestError(message, status, {
headers,
request: requestOptions
});
try {
let responseBody = JSON.parse(error.message);
Object.assign(error, responseBody);
let errors = responseBody.errors;
// Assumption `errors` would always be in Array format
error.message =
error.message + ": " + errors.map(JSON.stringify).join(", ");
} catch (e) {
// ignore, see octokit/rest.js#684
}
throw error;
});
}
const contentType = response.headers.get("content-type");
if (/application\/json/.test(contentType!)) {
return response.json();
}
if (!contentType || /^text\/|charset=utf-8$/.test(contentType)) {
return response.text();
}
return getBuffer(response);
})
.then(data => {
return {
status,
url,
headers,
data
};
})
.catch(error => {
if (error instanceof RequestError) {
throw error;
}
throw new RequestError(error.message, 500, {
headers,
request: requestOptions
});
});
}