homey-api 3.17.5 → 3.17.7
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/assets/types/homey-api.private.d.ts +8 -0
- package/lib/HomeyAPI/HomeyAPIV3/DiscoveryManager.js +63 -43
- package/lib/HomeyAPI/HomeyAPIV3/DiscoveryNodeTransport.js +589 -0
- package/lib/HomeyAPI/HomeyAPIV3/SocketSession.js +106 -12
- package/lib/HomeyAPI/HomeyAPIV3/SubscriptionRegistry.js +20 -16
- package/lib/HomeyAPI/HomeyAPIV3.js +15 -1
- package/lib/Util.js +20 -256
- package/package.json +1 -1
|
@@ -0,0 +1,589 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Util = require('../../Util');
|
|
4
|
+
|
|
5
|
+
const DNS_RECORD_TYPES = {
|
|
6
|
+
A: 0x0001,
|
|
7
|
+
AAAA: 0x001c,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const DNS_CLASS_IN = 0x0001;
|
|
11
|
+
const DNS_CLASS_QU = 0x8000;
|
|
12
|
+
|
|
13
|
+
function getNodeHttpModules() {
|
|
14
|
+
return {
|
|
15
|
+
http: require('node:http'),
|
|
16
|
+
https: require('node:https'),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function getDnsModule() {
|
|
21
|
+
return require('node:dns');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function getDgramModule() {
|
|
25
|
+
return require('node:dgram');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function getNetModule() {
|
|
29
|
+
return require('node:net');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function createAbortError(reason) {
|
|
33
|
+
const error = new Error(
|
|
34
|
+
typeof reason === 'string' && reason.length > 0 ? reason : 'The operation was aborted',
|
|
35
|
+
);
|
|
36
|
+
error.name = 'AbortError';
|
|
37
|
+
error.code = 'ABORT_ERR';
|
|
38
|
+
error.type = 'aborted';
|
|
39
|
+
return error;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getHostname(url) {
|
|
43
|
+
try {
|
|
44
|
+
return new URL(url).hostname;
|
|
45
|
+
} catch (error) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function normalizeHostname(hostname) {
|
|
51
|
+
return String(hostname || '')
|
|
52
|
+
.replace(/\.$/, '')
|
|
53
|
+
.toLowerCase();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function shouldUseResolverLookupForHostname(hostname) {
|
|
57
|
+
return normalizeHostname(hostname).endsWith('.homey.homeylocal.com');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function shouldUseMdnsLookupForHostname(hostname) {
|
|
61
|
+
return normalizeHostname(hostname).endsWith('.local');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function getMdnsQueryTypes(options) {
|
|
65
|
+
const family = Number(options?.family) || 0;
|
|
66
|
+
|
|
67
|
+
if (family === 6) {
|
|
68
|
+
return [DNS_RECORD_TYPES.AAAA];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return [DNS_RECORD_TYPES.A];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function getMdnsConfig() {
|
|
75
|
+
const host = process.env.HOMEY_DISCOVERY_MDNS_HOST || '224.0.0.251';
|
|
76
|
+
const port = Number(process.env.HOMEY_DISCOVERY_MDNS_PORT) || 5353;
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
host,
|
|
80
|
+
port,
|
|
81
|
+
joinMulticast: host === '224.0.0.251',
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function encodeDnsName(hostname) {
|
|
86
|
+
const labels = normalizeHostname(hostname).split('.');
|
|
87
|
+
const parts = [];
|
|
88
|
+
|
|
89
|
+
for (const label of labels) {
|
|
90
|
+
const encodedLabel = Buffer.from(label);
|
|
91
|
+
parts.push(Buffer.from([encodedLabel.length]));
|
|
92
|
+
parts.push(encodedLabel);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
parts.push(Buffer.from([0]));
|
|
96
|
+
|
|
97
|
+
return Buffer.concat(parts);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function buildMdnsQuestion(hostname, type) {
|
|
101
|
+
const question = Buffer.alloc(4);
|
|
102
|
+
question.writeUInt16BE(type, 0);
|
|
103
|
+
question.writeUInt16BE(DNS_CLASS_IN | DNS_CLASS_QU, 2);
|
|
104
|
+
|
|
105
|
+
return Buffer.concat([encodeDnsName(hostname), question]);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function buildMdnsQuery(hostname, options) {
|
|
109
|
+
const types = getMdnsQueryTypes(options);
|
|
110
|
+
const header = Buffer.alloc(12);
|
|
111
|
+
|
|
112
|
+
header.writeUInt16BE(0, 0);
|
|
113
|
+
header.writeUInt16BE(0, 2);
|
|
114
|
+
header.writeUInt16BE(types.length, 4);
|
|
115
|
+
|
|
116
|
+
return Buffer.concat([
|
|
117
|
+
header,
|
|
118
|
+
...types.map((type) => buildMdnsQuestion(hostname, type)),
|
|
119
|
+
]);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function readDnsName(buffer, offset, visited = new Set()) {
|
|
123
|
+
const labels = [];
|
|
124
|
+
let cursor = offset;
|
|
125
|
+
|
|
126
|
+
while (cursor < buffer.length) {
|
|
127
|
+
const length = buffer[cursor];
|
|
128
|
+
|
|
129
|
+
if (length === 0) {
|
|
130
|
+
return {
|
|
131
|
+
name: labels.join('.'),
|
|
132
|
+
offset: cursor + 1,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if ((length & 0xc0) === 0xc0) {
|
|
137
|
+
if (cursor + 1 >= buffer.length) {
|
|
138
|
+
throw new Error('Invalid DNS name pointer');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const pointer = ((length & 0x3f) << 8) | buffer[cursor + 1];
|
|
142
|
+
|
|
143
|
+
if (visited.has(pointer)) {
|
|
144
|
+
throw new Error('Invalid DNS name compression loop');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
visited.add(pointer);
|
|
148
|
+
|
|
149
|
+
const result = readDnsName(buffer, pointer, visited);
|
|
150
|
+
|
|
151
|
+
if (result.name) {
|
|
152
|
+
labels.push(result.name);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
name: labels.join('.'),
|
|
157
|
+
offset: cursor + 2,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const labelStart = cursor + 1;
|
|
162
|
+
const labelEnd = labelStart + length;
|
|
163
|
+
|
|
164
|
+
if (labelEnd > buffer.length) {
|
|
165
|
+
throw new Error('Invalid DNS label length');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
labels.push(buffer.toString('utf8', labelStart, labelEnd));
|
|
169
|
+
cursor = labelEnd;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
throw new Error('Invalid DNS name');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function decodeIPv6Address(buffer, offset) {
|
|
176
|
+
const segments = [];
|
|
177
|
+
|
|
178
|
+
for (let index = 0; index < 8; index++) {
|
|
179
|
+
segments.push(buffer.readUInt16BE(offset + index * 2).toString(16));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return segments.join(':');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function parseDnsAddresses(buffer, hostname) {
|
|
186
|
+
if (buffer.length < 12) {
|
|
187
|
+
return [];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const normalizedHostname = normalizeHostname(hostname);
|
|
191
|
+
const questionCount = buffer.readUInt16BE(4);
|
|
192
|
+
const answerCount = buffer.readUInt16BE(6);
|
|
193
|
+
const authorityCount = buffer.readUInt16BE(8);
|
|
194
|
+
const additionalCount = buffer.readUInt16BE(10);
|
|
195
|
+
const recordCount = answerCount + authorityCount + additionalCount;
|
|
196
|
+
const addresses = [];
|
|
197
|
+
let offset = 12;
|
|
198
|
+
|
|
199
|
+
for (let index = 0; index < questionCount; index++) {
|
|
200
|
+
const question = readDnsName(buffer, offset);
|
|
201
|
+
offset = question.offset + 4;
|
|
202
|
+
|
|
203
|
+
if (offset > buffer.length) {
|
|
204
|
+
return [];
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
for (let index = 0; index < recordCount; index++) {
|
|
209
|
+
const recordName = readDnsName(buffer, offset);
|
|
210
|
+
offset = recordName.offset;
|
|
211
|
+
|
|
212
|
+
if (offset + 10 > buffer.length) {
|
|
213
|
+
return [];
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const type = buffer.readUInt16BE(offset);
|
|
217
|
+
const klass = buffer.readUInt16BE(offset + 2) & 0x7fff;
|
|
218
|
+
const dataLength = buffer.readUInt16BE(offset + 8);
|
|
219
|
+
const dataOffset = offset + 10;
|
|
220
|
+
const nextOffset = dataOffset + dataLength;
|
|
221
|
+
|
|
222
|
+
if (nextOffset > buffer.length) {
|
|
223
|
+
return [];
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (klass === DNS_CLASS_IN && normalizeHostname(recordName.name) === normalizedHostname) {
|
|
227
|
+
if (type === DNS_RECORD_TYPES.A && dataLength === 4) {
|
|
228
|
+
addresses.push({
|
|
229
|
+
address: Array.from(buffer.subarray(dataOffset, nextOffset)).join('.'),
|
|
230
|
+
family: 4,
|
|
231
|
+
});
|
|
232
|
+
} else if (type === DNS_RECORD_TYPES.AAAA && dataLength === 16) {
|
|
233
|
+
addresses.push({
|
|
234
|
+
address: decodeIPv6Address(buffer, dataOffset),
|
|
235
|
+
family: 6,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
offset = nextOffset;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return addresses;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function selectLookupResult(addresses, options) {
|
|
247
|
+
const family = Number(options?.family) || 0;
|
|
248
|
+
let candidates = addresses;
|
|
249
|
+
|
|
250
|
+
if (family === 4 || family === 6) {
|
|
251
|
+
candidates = addresses.filter((address) => address.family === family);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (!candidates.length) {
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (options?.all === true) {
|
|
259
|
+
return {
|
|
260
|
+
address: candidates.map((candidate) => ({
|
|
261
|
+
address: candidate.address,
|
|
262
|
+
family: candidate.family,
|
|
263
|
+
})),
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return candidates[0];
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function createResolverLookup(signal) {
|
|
271
|
+
const dns = getDnsModule();
|
|
272
|
+
const net = getNetModule();
|
|
273
|
+
|
|
274
|
+
return (hostname, options, callback) => {
|
|
275
|
+
let settled = false;
|
|
276
|
+
let handleAbort = null;
|
|
277
|
+
const resolver = new dns.Resolver();
|
|
278
|
+
|
|
279
|
+
const finish = (error, address, family) => {
|
|
280
|
+
if (settled) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
settled = true;
|
|
285
|
+
|
|
286
|
+
if (signal && handleAbort) {
|
|
287
|
+
signal.removeEventListener('abort', handleAbort);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
callback(error, address, family);
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
const ipFamily = net.isIP(hostname);
|
|
294
|
+
|
|
295
|
+
if (ipFamily) {
|
|
296
|
+
finish(null, hostname, ipFamily);
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (signal) {
|
|
301
|
+
if (signal.aborted) {
|
|
302
|
+
finish(createAbortError(signal.reason));
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
handleAbort = () => {
|
|
307
|
+
resolver.cancel();
|
|
308
|
+
finish(createAbortError(signal.reason));
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
signal.addEventListener('abort', handleAbort, { once: true });
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const family = Number(options?.family) || 0;
|
|
315
|
+
|
|
316
|
+
if (family === 6) {
|
|
317
|
+
resolver.resolve6(hostname, (error, addresses) => {
|
|
318
|
+
if (error) {
|
|
319
|
+
finish(error);
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (!Array.isArray(addresses) || addresses.length === 0) {
|
|
324
|
+
finish(new Error(`No DNS results for ${hostname}`));
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (options?.all === true) {
|
|
329
|
+
finish(
|
|
330
|
+
null,
|
|
331
|
+
addresses.map((address) => ({
|
|
332
|
+
address,
|
|
333
|
+
family: 6,
|
|
334
|
+
})),
|
|
335
|
+
);
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
finish(null, addresses[0], 6);
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
resolver.resolve4(hostname, (resolve4Error, addresses) => {
|
|
346
|
+
if (settled) {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (!resolve4Error && Array.isArray(addresses) && addresses.length > 0) {
|
|
351
|
+
if (options?.all === true) {
|
|
352
|
+
finish(
|
|
353
|
+
null,
|
|
354
|
+
addresses.map((address) => ({
|
|
355
|
+
address,
|
|
356
|
+
family: 4,
|
|
357
|
+
})),
|
|
358
|
+
);
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
finish(null, addresses[0], 4);
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
resolver.resolve6(hostname, (resolve6Error, resolve6Addresses) => {
|
|
367
|
+
if (resolve6Error) {
|
|
368
|
+
finish(resolve4Error || resolve6Error);
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (!Array.isArray(resolve6Addresses) || resolve6Addresses.length === 0) {
|
|
373
|
+
finish(resolve4Error || new Error(`No DNS results for ${hostname}`));
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
if (options?.all === true) {
|
|
378
|
+
finish(
|
|
379
|
+
null,
|
|
380
|
+
resolve6Addresses.map((address) => ({
|
|
381
|
+
address,
|
|
382
|
+
family: 6,
|
|
383
|
+
})),
|
|
384
|
+
);
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
finish(null, resolve6Addresses[0], 6);
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function createMdnsLookup(signal) {
|
|
395
|
+
const dgram = getDgramModule();
|
|
396
|
+
const net = getNetModule();
|
|
397
|
+
|
|
398
|
+
return (hostname, options, callback) => {
|
|
399
|
+
let settled = false;
|
|
400
|
+
let handleAbort = null;
|
|
401
|
+
let sendTimers = [];
|
|
402
|
+
const mdnsConfig = getMdnsConfig();
|
|
403
|
+
const socket = mdnsConfig.joinMulticast
|
|
404
|
+
? dgram.createSocket({ type: 'udp4', reuseAddr: true })
|
|
405
|
+
: dgram.createSocket('udp4');
|
|
406
|
+
const query = buildMdnsQuery(hostname, options);
|
|
407
|
+
|
|
408
|
+
const cleanup = () => {
|
|
409
|
+
sendTimers.forEach(clearTimeout);
|
|
410
|
+
sendTimers = [];
|
|
411
|
+
|
|
412
|
+
if (signal && handleAbort) {
|
|
413
|
+
signal.removeEventListener('abort', handleAbort);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
socket.removeAllListeners('error');
|
|
417
|
+
socket.removeAllListeners('message');
|
|
418
|
+
|
|
419
|
+
try {
|
|
420
|
+
socket.close();
|
|
421
|
+
} catch (error) {
|
|
422
|
+
void error;
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
const finish = (error, address, family) => {
|
|
427
|
+
if (settled) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
settled = true;
|
|
432
|
+
cleanup();
|
|
433
|
+
callback(error, address, family);
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
const ipFamily = net.isIP(hostname);
|
|
437
|
+
|
|
438
|
+
if (ipFamily) {
|
|
439
|
+
finish(null, hostname, ipFamily);
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
if (signal) {
|
|
444
|
+
if (signal.aborted) {
|
|
445
|
+
finish(createAbortError(signal.reason));
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
handleAbort = () => {
|
|
450
|
+
finish(createAbortError(signal.reason));
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
signal.addEventListener('abort', handleAbort, { once: true });
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
socket.on('error', (error) => {
|
|
457
|
+
finish(error);
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
socket.on('message', (message) => {
|
|
461
|
+
let addresses = [];
|
|
462
|
+
|
|
463
|
+
try {
|
|
464
|
+
addresses = parseDnsAddresses(message, hostname);
|
|
465
|
+
} catch (error) {
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
const result = selectLookupResult(addresses, options);
|
|
470
|
+
|
|
471
|
+
if (!result) {
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
if (options?.all === true) {
|
|
476
|
+
finish(null, result.address);
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
finish(null, result.address, result.family);
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
socket.bind(mdnsConfig.joinMulticast ? mdnsConfig.port : 0, () => {
|
|
484
|
+
if (settled) {
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
if (mdnsConfig.joinMulticast) {
|
|
489
|
+
try {
|
|
490
|
+
socket.addMembership(mdnsConfig.host);
|
|
491
|
+
} catch (error) {
|
|
492
|
+
void error;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
const sendQuery = () => {
|
|
497
|
+
if (settled) {
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
socket.send(query, mdnsConfig.port, mdnsConfig.host, (error) => {
|
|
502
|
+
if (error) {
|
|
503
|
+
finish(error);
|
|
504
|
+
}
|
|
505
|
+
});
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
sendQuery();
|
|
509
|
+
sendTimers = [250, 1000].map((delay) => setTimeout(sendQuery, delay));
|
|
510
|
+
});
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function getLookup(url, signal) {
|
|
515
|
+
const hostname = getHostname(url);
|
|
516
|
+
|
|
517
|
+
if (typeof hostname !== 'string') {
|
|
518
|
+
return undefined;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (shouldUseResolverLookupForHostname(hostname)) {
|
|
522
|
+
return createResolverLookup(signal);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
if (shouldUseMdnsLookupForHostname(hostname)) {
|
|
526
|
+
return createMdnsLookup(signal);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
return undefined;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
function getAgent(url, signal) {
|
|
533
|
+
const { http, https } = getNodeHttpModules();
|
|
534
|
+
const lookup = getLookup(url, signal);
|
|
535
|
+
|
|
536
|
+
if (!lookup) {
|
|
537
|
+
return undefined;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
if (typeof url !== 'string') {
|
|
541
|
+
return undefined;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
if (url.startsWith('https://')) {
|
|
545
|
+
return new https.Agent({
|
|
546
|
+
keepAlive: false,
|
|
547
|
+
lookup,
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
if (url.startsWith('http://')) {
|
|
552
|
+
return new http.Agent({
|
|
553
|
+
keepAlive: false,
|
|
554
|
+
lookup,
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
return undefined;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
class DiscoveryNodeTransport {
|
|
562
|
+
static shouldUseForUrl(url) {
|
|
563
|
+
const hostname = getHostname(url);
|
|
564
|
+
|
|
565
|
+
return (
|
|
566
|
+
typeof hostname === 'string' &&
|
|
567
|
+
(
|
|
568
|
+
shouldUseResolverLookupForHostname(hostname) ||
|
|
569
|
+
shouldUseMdnsLookupForHostname(hostname)
|
|
570
|
+
)
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
static async fetch(url, options, timeoutDuration, timeoutMessage) {
|
|
575
|
+
return Util.fetch(
|
|
576
|
+
url,
|
|
577
|
+
options,
|
|
578
|
+
timeoutDuration,
|
|
579
|
+
timeoutMessage,
|
|
580
|
+
(resolvedOptions) => {
|
|
581
|
+
if (typeof resolvedOptions.agent === 'undefined') {
|
|
582
|
+
resolvedOptions.agent = getAgent(url, resolvedOptions.signal);
|
|
583
|
+
}
|
|
584
|
+
},
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
module.exports = DiscoveryNodeTransport;
|