swiftyper-node 1.0.9 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Error.js +77 -77
- package/lib/SwiftyperMethod.js +24 -21
- package/lib/SwiftyperResource.js +432 -352
- package/lib/makeRequest.js +105 -103
- package/lib/resources/Business.js +23 -23
- package/lib/resources/EmailUtil.js +13 -13
- package/lib/resources/Fbt.js +13 -13
- package/lib/resources/HelpCenter.js +18 -0
- package/lib/resources/HelpCenterArticle.js +23 -0
- package/lib/resources/HelpCenterCategory.js +18 -0
- package/lib/resources/HelpCenterChat.js +40 -0
- package/lib/resources/IpUtil.js +13 -13
- package/lib/resources/Phrase.js +23 -23
- package/lib/resources/Places.js +58 -58
- package/lib/resources/Translation.js +38 -38
- package/lib/resources/Translator.js +13 -13
- package/lib/resources/ViesUtil.js +13 -13
- package/lib/resources.js +17 -13
- package/lib/swiftyper.js +159 -159
- package/lib/utils.js +332 -272
- package/package.json +36 -36
package/lib/SwiftyperResource.js
CHANGED
|
@@ -1,352 +1,432 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const http = require('http');
|
|
4
|
-
const https = require('https');
|
|
5
|
-
const path = require('path');
|
|
6
|
-
|
|
7
|
-
const utils = require('./utils');
|
|
8
|
-
const {
|
|
9
|
-
SwiftyperConnectionError,
|
|
10
|
-
SwiftyperError,
|
|
11
|
-
SwiftyperAPIError,
|
|
12
|
-
} = require('./Error');
|
|
13
|
-
|
|
14
|
-
const defaultHttpAgent = new http.Agent({keepAlive: true});
|
|
15
|
-
const defaultHttpsAgent = new https.Agent({keepAlive: true});
|
|
16
|
-
let requests = 0;
|
|
17
|
-
|
|
18
|
-
SwiftyperResource.extend = utils.protoExtend;
|
|
19
|
-
|
|
20
|
-
SwiftyperResource.method = require('./SwiftyperMethod');
|
|
21
|
-
|
|
22
|
-
const MAX_RETRY_AFTER_WAIT = 60;
|
|
23
|
-
|
|
24
|
-
function SwiftyperResource(swiftyper) {
|
|
25
|
-
this._swiftyper = swiftyper;
|
|
26
|
-
|
|
27
|
-
this.basePath = utils.makeURLInterpolator(
|
|
28
|
-
this.basePath || swiftyper.getApiField('basePath')
|
|
29
|
-
);
|
|
30
|
-
this.resourcePath = this.path;
|
|
31
|
-
this.path = utils.makeURLInterpolator(this.path);
|
|
32
|
-
|
|
33
|
-
this.initialize(...arguments);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
SwiftyperResource.prototype = {
|
|
37
|
-
path: '',
|
|
38
|
-
|
|
39
|
-
basePath: null,
|
|
40
|
-
|
|
41
|
-
initialize() {},
|
|
42
|
-
|
|
43
|
-
requestDataProcessor: null,
|
|
44
|
-
|
|
45
|
-
createFullPath(commandPath, urlData) {
|
|
46
|
-
return path
|
|
47
|
-
.join(
|
|
48
|
-
this.basePath(urlData),
|
|
49
|
-
this.path(urlData),
|
|
50
|
-
typeof commandPath == 'function' ? commandPath(urlData) : commandPath
|
|
51
|
-
)
|
|
52
|
-
.replace(/\\/g, '/');
|
|
53
|
-
},
|
|
54
|
-
|
|
55
|
-
createResourcePathWithSymbols(pathWithSymbols) {
|
|
56
|
-
return `/${path
|
|
57
|
-
.join(this.resourcePath, pathWithSymbols || '')
|
|
58
|
-
.replace(/\\/g, '/')}`;
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
_timeoutHandler(timeout, req) {
|
|
62
|
-
return () => {
|
|
63
|
-
const timeoutErr = new TypeError('ETIMEDOUT');
|
|
64
|
-
timeoutErr.code = 'ETIMEDOUT';
|
|
65
|
-
|
|
66
|
-
req.destroy(timeoutErr);
|
|
67
|
-
};
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
_responseHandler(req, callback) {
|
|
71
|
-
return (res) => {
|
|
72
|
-
let response = '';
|
|
73
|
-
|
|
74
|
-
res.setEncoding('utf8');
|
|
75
|
-
res.on('data', (chunk) => {
|
|
76
|
-
response += chunk;
|
|
77
|
-
});
|
|
78
|
-
res.once('end', () => {
|
|
79
|
-
const headers = res.headers || {};
|
|
80
|
-
|
|
81
|
-
const requestEndTime = Date.now();
|
|
82
|
-
const requestDurationMs = requestEndTime - req._requestStart;
|
|
83
|
-
|
|
84
|
-
const responseEvent = utils.removeNullish({
|
|
85
|
-
method: req._requestEvent.method,
|
|
86
|
-
path: req._requestEvent.path,
|
|
87
|
-
status: res.statusCode,
|
|
88
|
-
elapsed: requestDurationMs,
|
|
89
|
-
request_start_time: req._requestStart,
|
|
90
|
-
request_end_time: requestEndTime,
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
this._swiftyper._emitter.emit('response', responseEvent);
|
|
94
|
-
|
|
95
|
-
try {
|
|
96
|
-
response = JSON.parse(response);
|
|
97
|
-
|
|
98
|
-
if (response.error) {
|
|
99
|
-
let err;
|
|
100
|
-
|
|
101
|
-
response.error.headers = headers;
|
|
102
|
-
response.error.statusCode = res.statusCode;
|
|
103
|
-
|
|
104
|
-
if (res.statusCode === 500) {
|
|
105
|
-
err = new SwiftyperAPIError(response.error);
|
|
106
|
-
} else {
|
|
107
|
-
err = SwiftyperError.generate(response.error);
|
|
108
|
-
}
|
|
109
|
-
return callback.call(this, err, null);
|
|
110
|
-
}
|
|
111
|
-
} catch (e) {
|
|
112
|
-
return callback.call(
|
|
113
|
-
this,
|
|
114
|
-
new SwiftyperAPIError({
|
|
115
|
-
message: 'Invalid JSON received from the Swiftyper API',
|
|
116
|
-
response,
|
|
117
|
-
exception: e,
|
|
118
|
-
}),
|
|
119
|
-
null
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
Object.defineProperty(response, 'lastResponse', {
|
|
124
|
-
enumerable: false,
|
|
125
|
-
writable: false,
|
|
126
|
-
value: res,
|
|
127
|
-
});
|
|
128
|
-
callback.call(this, null, response);
|
|
129
|
-
});
|
|
130
|
-
};
|
|
131
|
-
},
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
return
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
return
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
req.
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
);
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const http = require('http');
|
|
4
|
+
const https = require('https');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
const utils = require('./utils');
|
|
8
|
+
const {
|
|
9
|
+
SwiftyperConnectionError,
|
|
10
|
+
SwiftyperError,
|
|
11
|
+
SwiftyperAPIError,
|
|
12
|
+
} = require('./Error');
|
|
13
|
+
|
|
14
|
+
const defaultHttpAgent = new http.Agent({keepAlive: true});
|
|
15
|
+
const defaultHttpsAgent = new https.Agent({keepAlive: true});
|
|
16
|
+
let requests = 0;
|
|
17
|
+
|
|
18
|
+
SwiftyperResource.extend = utils.protoExtend;
|
|
19
|
+
|
|
20
|
+
SwiftyperResource.method = require('./SwiftyperMethod');
|
|
21
|
+
|
|
22
|
+
const MAX_RETRY_AFTER_WAIT = 60;
|
|
23
|
+
|
|
24
|
+
function SwiftyperResource(swiftyper) {
|
|
25
|
+
this._swiftyper = swiftyper;
|
|
26
|
+
|
|
27
|
+
this.basePath = utils.makeURLInterpolator(
|
|
28
|
+
this.basePath || swiftyper.getApiField('basePath')
|
|
29
|
+
);
|
|
30
|
+
this.resourcePath = this.path;
|
|
31
|
+
this.path = utils.makeURLInterpolator(this.path);
|
|
32
|
+
|
|
33
|
+
this.initialize(...arguments);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
SwiftyperResource.prototype = {
|
|
37
|
+
path: '',
|
|
38
|
+
|
|
39
|
+
basePath: null,
|
|
40
|
+
|
|
41
|
+
initialize() {},
|
|
42
|
+
|
|
43
|
+
requestDataProcessor: null,
|
|
44
|
+
|
|
45
|
+
createFullPath(commandPath, urlData) {
|
|
46
|
+
return path
|
|
47
|
+
.join(
|
|
48
|
+
this.basePath(urlData),
|
|
49
|
+
this.path(urlData),
|
|
50
|
+
typeof commandPath == 'function' ? commandPath(urlData) : commandPath
|
|
51
|
+
)
|
|
52
|
+
.replace(/\\/g, '/');
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
createResourcePathWithSymbols(pathWithSymbols) {
|
|
56
|
+
return `/${path
|
|
57
|
+
.join(this.resourcePath, pathWithSymbols || '')
|
|
58
|
+
.replace(/\\/g, '/')}`;
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
_timeoutHandler(timeout, req) {
|
|
62
|
+
return () => {
|
|
63
|
+
const timeoutErr = new TypeError('ETIMEDOUT');
|
|
64
|
+
timeoutErr.code = 'ETIMEDOUT';
|
|
65
|
+
|
|
66
|
+
req.destroy(timeoutErr);
|
|
67
|
+
};
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
_responseHandler(req, callback) {
|
|
71
|
+
return (res) => {
|
|
72
|
+
let response = '';
|
|
73
|
+
|
|
74
|
+
res.setEncoding('utf8');
|
|
75
|
+
res.on('data', (chunk) => {
|
|
76
|
+
response += chunk;
|
|
77
|
+
});
|
|
78
|
+
res.once('end', () => {
|
|
79
|
+
const headers = res.headers || {};
|
|
80
|
+
|
|
81
|
+
const requestEndTime = Date.now();
|
|
82
|
+
const requestDurationMs = requestEndTime - req._requestStart;
|
|
83
|
+
|
|
84
|
+
const responseEvent = utils.removeNullish({
|
|
85
|
+
method: req._requestEvent.method,
|
|
86
|
+
path: req._requestEvent.path,
|
|
87
|
+
status: res.statusCode,
|
|
88
|
+
elapsed: requestDurationMs,
|
|
89
|
+
request_start_time: req._requestStart,
|
|
90
|
+
request_end_time: requestEndTime,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
this._swiftyper._emitter.emit('response', responseEvent);
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
response = JSON.parse(response);
|
|
97
|
+
|
|
98
|
+
if (response.error) {
|
|
99
|
+
let err;
|
|
100
|
+
|
|
101
|
+
response.error.headers = headers;
|
|
102
|
+
response.error.statusCode = res.statusCode;
|
|
103
|
+
|
|
104
|
+
if (res.statusCode === 500) {
|
|
105
|
+
err = new SwiftyperAPIError(response.error);
|
|
106
|
+
} else {
|
|
107
|
+
err = SwiftyperError.generate(response.error);
|
|
108
|
+
}
|
|
109
|
+
return callback.call(this, err, null);
|
|
110
|
+
}
|
|
111
|
+
} catch (e) {
|
|
112
|
+
return callback.call(
|
|
113
|
+
this,
|
|
114
|
+
new SwiftyperAPIError({
|
|
115
|
+
message: 'Invalid JSON received from the Swiftyper API',
|
|
116
|
+
response,
|
|
117
|
+
exception: e,
|
|
118
|
+
}),
|
|
119
|
+
null
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
Object.defineProperty(response, 'lastResponse', {
|
|
124
|
+
enumerable: false,
|
|
125
|
+
writable: false,
|
|
126
|
+
value: res,
|
|
127
|
+
});
|
|
128
|
+
callback.call(this, null, response);
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
_streamResponseHandler(req, callback) {
|
|
134
|
+
return (res) => {
|
|
135
|
+
const headers = res.headers || {};
|
|
136
|
+
const contentType = (headers['content-type'] || '').toLowerCase();
|
|
137
|
+
|
|
138
|
+
const requestEndTime = Date.now();
|
|
139
|
+
const requestDurationMs = requestEndTime - req._requestStart;
|
|
140
|
+
|
|
141
|
+
const responseEvent = utils.removeNullish({
|
|
142
|
+
method: req._requestEvent.method,
|
|
143
|
+
path: req._requestEvent.path,
|
|
144
|
+
status: res.statusCode,
|
|
145
|
+
elapsed: requestDurationMs,
|
|
146
|
+
request_start_time: req._requestStart,
|
|
147
|
+
request_end_time: requestEndTime,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
this._swiftyper._emitter.emit('response', responseEvent);
|
|
151
|
+
|
|
152
|
+
if (contentType.includes('text/event-stream')) {
|
|
153
|
+
return callback.call(this, null, res);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
let response = '';
|
|
157
|
+
|
|
158
|
+
res.setEncoding('utf8');
|
|
159
|
+
res.on('data', (chunk) => {
|
|
160
|
+
response += chunk;
|
|
161
|
+
});
|
|
162
|
+
res.once('end', () => {
|
|
163
|
+
try {
|
|
164
|
+
response = JSON.parse(response);
|
|
165
|
+
} catch (e) {
|
|
166
|
+
return callback.call(
|
|
167
|
+
this,
|
|
168
|
+
new SwiftyperAPIError({
|
|
169
|
+
message: 'Invalid JSON received from the Swiftyper API',
|
|
170
|
+
response,
|
|
171
|
+
exception: e,
|
|
172
|
+
}),
|
|
173
|
+
null
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (response.error) {
|
|
178
|
+
response.error.headers = headers;
|
|
179
|
+
response.error.statusCode = res.statusCode;
|
|
180
|
+
|
|
181
|
+
if (res.statusCode === 500) {
|
|
182
|
+
err = new SwiftyperAPIError(response.error);
|
|
183
|
+
} else {
|
|
184
|
+
err = SwiftyperError.generate(response.error);
|
|
185
|
+
}
|
|
186
|
+
return callback.call(this, err, null);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return callback.call(
|
|
190
|
+
this,
|
|
191
|
+
new SwiftyperAPIError({
|
|
192
|
+
message: 'Expected a streaming response from the Swiftyper API',
|
|
193
|
+
response,
|
|
194
|
+
}),
|
|
195
|
+
null
|
|
196
|
+
);
|
|
197
|
+
});
|
|
198
|
+
};
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
_generateConnectionErrorMessage(requestRetries) {
|
|
202
|
+
return `An error occurred with our connection to Swiftyper.${
|
|
203
|
+
requestRetries > 0 ? ` Request was retried ${requestRetries} times.` : ''
|
|
204
|
+
}`;
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
_shouldRetry(res, numRetries, maxRetries) {
|
|
208
|
+
if (numRetries >= maxRetries) {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (!res) {
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (res.headers && res.headers['swiftyper-should-retry'] === 'false') {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (res.headers && res.headers['swiftyper-should-retry'] === 'true') {
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (res.statusCode === 409) {
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (res.statusCode >= 500) {
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return false;
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
_getSleepTimeInMS(numRetries, retryAfter = null) {
|
|
236
|
+
const initialNetworkRetryDelay =
|
|
237
|
+
this._swiftyper.getInitialNetworkRetryDelay();
|
|
238
|
+
const maxNetworkRetryDelay = this._swiftyper.getMaxNetworkRetryDelay();
|
|
239
|
+
|
|
240
|
+
let sleepSeconds = Math.min(
|
|
241
|
+
initialNetworkRetryDelay * Math.pow(numRetries - 1, 2),
|
|
242
|
+
maxNetworkRetryDelay
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
sleepSeconds *= 0.5 * (1 + Math.random());
|
|
246
|
+
|
|
247
|
+
sleepSeconds = Math.max(initialNetworkRetryDelay, sleepSeconds);
|
|
248
|
+
|
|
249
|
+
if (Number.isInteger(retryAfter) && retryAfter <= MAX_RETRY_AFTER_WAIT) {
|
|
250
|
+
sleepSeconds = Math.max(sleepSeconds, retryAfter);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return sleepSeconds * 1000;
|
|
254
|
+
},
|
|
255
|
+
|
|
256
|
+
_getMaxNetworkRetries(settings = {}) {
|
|
257
|
+
return settings.maxNetworkRetries &&
|
|
258
|
+
Number.isInteger(settings.maxNetworkRetries)
|
|
259
|
+
? settings.maxNetworkRetries
|
|
260
|
+
: this._swiftyper.getMaxNetworkRetries();
|
|
261
|
+
},
|
|
262
|
+
|
|
263
|
+
_makeHeaders(contentLength, method, userSuppliedHeaders) {
|
|
264
|
+
const defaultHeaders = {
|
|
265
|
+
Accept: 'application/json',
|
|
266
|
+
'Content-Type':
|
|
267
|
+
method === 'GET'
|
|
268
|
+
? 'application/json'
|
|
269
|
+
: 'application/x-www-form-urlencoded',
|
|
270
|
+
'Content-Length': contentLength,
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
return Object.assign(
|
|
274
|
+
utils.removeNullish(defaultHeaders),
|
|
275
|
+
utils.normalizeHeaders(userSuppliedHeaders)
|
|
276
|
+
);
|
|
277
|
+
},
|
|
278
|
+
|
|
279
|
+
_request(method, host, path, data, auth, options = {}, callback) {
|
|
280
|
+
let requestData;
|
|
281
|
+
|
|
282
|
+
data.__req = requests++;
|
|
283
|
+
data.api_key = auth ? auth : this._swiftyper.getApiField('auth');
|
|
284
|
+
|
|
285
|
+
const retryRequest = (requestFn, headers, requestRetries, retryAfter) => {
|
|
286
|
+
return setTimeout(
|
|
287
|
+
requestFn,
|
|
288
|
+
this._getSleepTimeInMS(requestRetries, retryAfter),
|
|
289
|
+
headers,
|
|
290
|
+
requestRetries + 1
|
|
291
|
+
);
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
const makeRequest = (headers, numRetries) => {
|
|
295
|
+
const protocol = this._swiftyper.getApiField('protocol');
|
|
296
|
+
const timeout =
|
|
297
|
+
options.settings &&
|
|
298
|
+
Number.isInteger(options.settings.timeout) &&
|
|
299
|
+
options.settings.timeout >= 0
|
|
300
|
+
? options.settings.timeout
|
|
301
|
+
: this._swiftyper.getApiField('timeout');
|
|
302
|
+
const isInsecureConnection = protocol === 'http';
|
|
303
|
+
const agent = isInsecureConnection ? defaultHttpAgent : defaultHttpsAgent;
|
|
304
|
+
|
|
305
|
+
const req = (isInsecureConnection ? http : https).request({
|
|
306
|
+
host: host || this._swiftyper.getApiField('host'),
|
|
307
|
+
port: this._swiftyper.getApiField('port'),
|
|
308
|
+
protocol: protocol + ':',
|
|
309
|
+
path,
|
|
310
|
+
method,
|
|
311
|
+
agent,
|
|
312
|
+
headers,
|
|
313
|
+
ciphers: 'DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2:!MD5',
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
this._swiftyper._lastRequest = req;
|
|
317
|
+
|
|
318
|
+
const requestStartTime = Date.now();
|
|
319
|
+
|
|
320
|
+
const requestEvent = utils.removeNullish({
|
|
321
|
+
method,
|
|
322
|
+
path,
|
|
323
|
+
request_start_time: requestStartTime,
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
const requestRetries = numRetries || 0;
|
|
327
|
+
|
|
328
|
+
const maxRetries = this._getMaxNetworkRetries(options.settings);
|
|
329
|
+
|
|
330
|
+
req._requestEvent = requestEvent;
|
|
331
|
+
|
|
332
|
+
req._requestStart = requestStartTime;
|
|
333
|
+
|
|
334
|
+
this._swiftyper._emitter.emit('request', requestEvent);
|
|
335
|
+
|
|
336
|
+
req.setTimeout(timeout, this._timeoutHandler(timeout, req));
|
|
337
|
+
|
|
338
|
+
req.once('response', (res) => {
|
|
339
|
+
if (this._shouldRetry(res, requestRetries, maxRetries)) {
|
|
340
|
+
return retryRequest(
|
|
341
|
+
makeRequest,
|
|
342
|
+
headers,
|
|
343
|
+
requestRetries,
|
|
344
|
+
((res || {}).headers || {})['retry-after']
|
|
345
|
+
);
|
|
346
|
+
} else if (options.rawStream) {
|
|
347
|
+
return this._streamResponseHandler(req, callback)(res);
|
|
348
|
+
} else {
|
|
349
|
+
return this._responseHandler(req, callback)(res);
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
req.on('error', (error) => {
|
|
354
|
+
if (this._shouldRetry(null, requestRetries, maxRetries)) {
|
|
355
|
+
return retryRequest(makeRequest, headers, requestRetries, null);
|
|
356
|
+
} else {
|
|
357
|
+
if (error.code === 'ETIMEDOUT') {
|
|
358
|
+
return callback.call(
|
|
359
|
+
this,
|
|
360
|
+
new SwiftyperConnectionError({
|
|
361
|
+
message: `Request aborted due to timeout being reached (${timeout}ms)`,
|
|
362
|
+
detail: error,
|
|
363
|
+
})
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
return callback.call(
|
|
367
|
+
this,
|
|
368
|
+
new SwiftyperConnectionError({
|
|
369
|
+
message: this._generateConnectionErrorMessage(requestRetries),
|
|
370
|
+
detail: error,
|
|
371
|
+
}),
|
|
372
|
+
null
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
req.write(requestData);
|
|
378
|
+
req.end();
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
const transformRequestData = (data) => {
|
|
382
|
+
if (typeof data === 'boolean') {
|
|
383
|
+
return data.toString();
|
|
384
|
+
} else if (Array.isArray(data)) {
|
|
385
|
+
return data.map(transformRequestData);
|
|
386
|
+
} else if (typeof data === 'object' && data !== null) {
|
|
387
|
+
return Object.fromEntries(
|
|
388
|
+
Object.entries(data).map(([key, value]) => [
|
|
389
|
+
key,
|
|
390
|
+
transformRequestData(value),
|
|
391
|
+
])
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return data;
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
const prepareAndMakeRequest = (error, data) => {
|
|
399
|
+
if (error) {
|
|
400
|
+
return callback(error);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if (method === 'GET') {
|
|
404
|
+
requestData = JSON.stringify(transformRequestData(data));
|
|
405
|
+
} else {
|
|
406
|
+
requestData = utils.stringifyRequestData(data || {});
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const headers = this._makeHeaders(
|
|
410
|
+
Buffer.byteLength(requestData, 'utf-8'),
|
|
411
|
+
method,
|
|
412
|
+
options.headers,
|
|
413
|
+
options.settings
|
|
414
|
+
);
|
|
415
|
+
|
|
416
|
+
makeRequest(headers);
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
if (this.requestDataProcessor) {
|
|
420
|
+
this.requestDataProcessor(
|
|
421
|
+
method,
|
|
422
|
+
data,
|
|
423
|
+
options.headers,
|
|
424
|
+
prepareAndMakeRequest
|
|
425
|
+
);
|
|
426
|
+
} else {
|
|
427
|
+
prepareAndMakeRequest(null, data);
|
|
428
|
+
}
|
|
429
|
+
},
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
module.exports = SwiftyperResource;
|