-
Notifications
You must be signed in to change notification settings - Fork 723
/
makeRequest.ts
138 lines (120 loc) · 3.78 KB
/
makeRequest.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
127
128
129
130
131
132
133
134
135
136
137
138
const utils = require('./utils');
type MethodSpec = {
method: string;
urlParams: Array<string>;
path?: string;
fullPath?: string;
encode: (data: Record<string, unknown>) => Record<string, unknown>;
validator: (
data: Record<string, unknown>,
headers: Record<string, string>
) => void;
headers: Record<string, string>;
streaming?: boolean;
host?: string;
};
function getRequestOpts(self, requestArgs, spec: MethodSpec, overrideData) {
// Extract spec values with defaults.
const requestMethod = (spec.method || 'GET').toUpperCase();
const urlParams = spec.urlParams || [];
const encode = spec.encode || ((data) => data);
const isUsingFullPath = !!spec.fullPath;
const commandPath = utils.makeURLInterpolator(
isUsingFullPath ? spec.fullPath : spec.path || ''
);
// When using fullPath, we ignore the resource path as it should already be
// fully qualified.
const path = isUsingFullPath
? spec.fullPath
: self.createResourcePathWithSymbols(spec.path);
// Don't mutate args externally.
const args = [].slice.call(requestArgs);
// Generate and validate url params.
const urlData = urlParams.reduce<Record<string, unknown>>(
(urlData, param) => {
const arg = args.shift();
if (typeof arg !== 'string') {
throw new Error(
`Stripe: Argument "${param}" must be a string, but got: ${arg} (on API request to \`${requestMethod} ${path}\`)`
);
}
urlData[param] = arg;
return urlData;
},
{}
);
// Pull request data and options (headers, auth) from args.
const dataFromArgs = utils.getDataFromArgs(args);
const data = encode(Object.assign({}, dataFromArgs, overrideData));
const options = utils.getOptionsFromArgs(args);
const host = options.host || spec.host;
const streaming = !!spec.streaming;
// Validate that there are no more args.
if (args.filter((x) => x != null).length) {
throw new Error(
`Stripe: Unknown arguments (${args}). Did you mean to pass an options object? See https://github.com/stripe/stripe-node/wiki/Passing-Options. (on API request to ${requestMethod} \`${path}\`)`
);
}
// When using full path, we can just invoke the URL interpolator directly
// as we don't need to use the resource to create a full path.
const requestPath = isUsingFullPath
? commandPath(urlData)
: self.createFullPath(commandPath, urlData);
const headers = Object.assign(options.headers, spec.headers);
if (spec.validator) {
spec.validator(data, {headers});
}
const dataInQuery = spec.method === 'GET' || spec.method === 'DELETE';
const bodyData = dataInQuery ? {} : data;
const queryData = dataInQuery ? data : {};
return {
requestMethod,
requestPath,
bodyData,
queryData,
auth: options.auth,
headers,
host,
streaming,
settings: options.settings,
};
}
function makeRequest(self, requestArgs, spec, overrideData) {
return new Promise((resolve, reject) => {
let opts;
try {
opts = getRequestOpts(self, requestArgs, spec, overrideData);
} catch (err) {
reject(err);
return;
}
function requestCallback(err: any, response) {
if (err) {
reject(err);
} else {
resolve(
spec.transformResponseData
? spec.transformResponseData(response)
: response
);
}
}
const emptyQuery = Object.keys(opts.queryData).length === 0;
const path = [
opts.requestPath,
emptyQuery ? '' : '?',
utils.stringifyRequestData(opts.queryData),
].join('');
const {headers, settings} = opts;
self._request(
opts.requestMethod,
opts.host,
path,
opts.bodyData,
opts.auth,
{headers, settings, streaming: opts.streaming},
requestCallback
);
});
}
export = makeRequest;