dns2 1.5.0 → 2.0.2
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/.eslintrc +16 -0
- package/.github/FUNDING.yml +12 -0
- package/.github/workflows/lint.js.yml +17 -0
- package/.github/workflows/node.js.yml +1 -2
- package/README.md +46 -15
- package/client/doh.js +24 -16
- package/client/google.js +4 -4
- package/client/tcp.js +10 -10
- package/client/udp.js +6 -6
- package/example/client/doh.js +5 -5
- package/example/client/google.js +1 -2
- package/example/client/tcp-custom-dns.js +4 -4
- package/example/client/tcp.js +4 -4
- package/example/client/udp-custom-dns.js +4 -4
- package/example/client/udp-default.js +2 -2
- package/example/client/udp-subnet.js +2 -2
- package/example/client/udp.js +3 -3
- package/example/server/dns.js +46 -0
- package/example/server/doh.js +18 -16
- package/example/server/tcp.js +6 -6
- package/example/server/udp.js +4 -4
- package/index.js +22 -14
- package/lib/reader.js +20 -22
- package/lib/writer.js +11 -11
- package/package.json +11 -3
- package/packet.js +217 -202
- package/server/dns.js +94 -0
- package/server/doh.js +130 -127
- package/server/index.js +10 -3
- package/server/tcp.js +14 -6
- package/server/udp.js +10 -4
- package/test/index.js +255 -104
- package/test/test.js +24 -17
- package/.travis.yml +0 -4
package/test/index.js
CHANGED
|
@@ -1,49 +1,53 @@
|
|
|
1
1
|
const assert = require('assert');
|
|
2
2
|
const test = require('./test');
|
|
3
|
-
const Packet = require('
|
|
3
|
+
const { Packet, createDOHServer, createServer, TCPClient, DOHClient, UDPClient } = require('..');
|
|
4
|
+
const http = require('http');
|
|
5
|
+
const tcp = require('net');
|
|
6
|
+
const udp = require('dgram');
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
/* TODO: below is unused, either delete or use
|
|
9
|
+
const request = Buffer.from([
|
|
6
10
|
0x29, 0x64, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
|
|
7
11
|
0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x6f, 0x6f,
|
|
8
12
|
0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00,
|
|
9
|
-
0x00, 0x01, 0x00,
|
|
13
|
+
0x00, 0x01, 0x00, 0x01]);
|
|
14
|
+
*/
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
const response = Buffer.from([
|
|
12
17
|
0x29, 0x64, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
|
|
13
18
|
0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77,
|
|
14
19
|
0x01, 0x7a, 0x02, 0x63, 0x6e, 0x00, 0x00, 0x01,
|
|
15
20
|
0x00, 0x01, 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01,
|
|
16
21
|
0x00, 0x00, 0x01, 0x90, 0x00, 0x04, 0x36, 0xde,
|
|
17
|
-
0x3c, 0xfc]);
|
|
22
|
+
0x3c, 0xfc ]);
|
|
18
23
|
|
|
19
|
-
test('Name#encode', function
|
|
20
|
-
|
|
21
|
-
|
|
24
|
+
test('Name#encode', function() {
|
|
25
|
+
const name = Packet.Name.encode('www.google.com');
|
|
26
|
+
const pattern = [ 3, 'w', 'w', 'w', 5, 'g', 'o', 'o', 'g', 'l', 'e', 3, 'c', 'o', 'm', '0' ];
|
|
22
27
|
assert.equal(name.length, pattern.length);
|
|
23
28
|
});
|
|
24
29
|
|
|
25
|
-
test('Name#decode', function
|
|
26
|
-
|
|
27
|
-
|
|
30
|
+
test('Name#decode', function() {
|
|
31
|
+
const reader = new Packet.Reader(response, 8 * 12);
|
|
32
|
+
let name = Packet.Name.decode(reader);
|
|
28
33
|
assert.equal(name, 'www.z.cn');
|
|
29
34
|
|
|
30
35
|
reader.offset = 8 * 26;
|
|
31
|
-
|
|
36
|
+
name = Packet.Name.decode(reader);
|
|
32
37
|
assert.equal(reader.offset, 8 * 28);
|
|
33
38
|
assert.equal(name, 'www.z.cn');
|
|
34
|
-
|
|
35
39
|
});
|
|
36
40
|
|
|
37
|
-
test('Header#encode', function
|
|
38
|
-
|
|
41
|
+
test('Header#encode', function() {
|
|
42
|
+
const header = new Packet.Header({ id: 0x2964, qr: 1 });
|
|
39
43
|
header.qdcount = 1;
|
|
40
44
|
header.ancount = 2;
|
|
41
45
|
assert.deepEqual(header.toBuffer(), Buffer.from([
|
|
42
|
-
0x29, 0x64, 0x80, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00]));
|
|
46
|
+
0x29, 0x64, 0x80, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 ]));
|
|
43
47
|
});
|
|
44
48
|
|
|
45
|
-
test('Header#parse', function
|
|
46
|
-
|
|
49
|
+
test('Header#parse', function() {
|
|
50
|
+
const header = Packet.Header.parse(response);
|
|
47
51
|
assert.equal(header.id, 0x2964);
|
|
48
52
|
assert.equal(header.qr, 1);
|
|
49
53
|
assert.equal(header.opcode, 0);
|
|
@@ -58,33 +62,31 @@ test('Header#parse', function () {
|
|
|
58
62
|
assert.equal(header.arcount, 0);
|
|
59
63
|
});
|
|
60
64
|
|
|
61
|
-
test('Question#encode', function
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
class: Packet.CLASS.IN
|
|
65
|
+
test('Question#encode', function() {
|
|
66
|
+
const question = new Packet.Question({
|
|
67
|
+
name : 'google.com',
|
|
68
|
+
type : Packet.TYPE.A,
|
|
69
|
+
class : Packet.CLASS.IN,
|
|
67
70
|
});
|
|
68
71
|
//
|
|
69
72
|
assert.deepEqual(question.toBuffer(), Buffer.from([
|
|
70
73
|
0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
|
|
71
|
-
0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01
|
|
74
|
+
0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
|
|
72
75
|
]));
|
|
73
76
|
});
|
|
74
77
|
|
|
75
|
-
test('Question#decode', function
|
|
76
|
-
|
|
77
|
-
var question = new Packet.Question('google.com',
|
|
78
|
+
test('Question#decode', function() {
|
|
79
|
+
const question = new Packet.Question('google.com',
|
|
78
80
|
Packet.TYPE.A, Packet.CLASS.IN);
|
|
79
81
|
assert.deepEqual(question.toBuffer(), Buffer.from([
|
|
80
82
|
0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
|
|
81
|
-
0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01
|
|
83
|
+
0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
|
|
82
84
|
]));
|
|
83
85
|
});
|
|
84
86
|
|
|
85
87
|
//
|
|
86
|
-
test('Packet#parse', function
|
|
87
|
-
|
|
88
|
+
test('Packet#parse', function() {
|
|
89
|
+
const packet = Packet.parse(response);
|
|
88
90
|
assert.equal(packet.questions[0].name, 'www.z.cn');
|
|
89
91
|
assert.equal(packet.questions[0].type, Packet.TYPE.A);
|
|
90
92
|
assert.equal(packet.questions[0].class, Packet.CLASS.IN);
|
|
@@ -93,122 +95,119 @@ test('Packet#parse', function () {
|
|
|
93
95
|
assert.equal(packet.answers[0].address, '54.222.60.252');
|
|
94
96
|
});
|
|
95
97
|
|
|
96
|
-
test('Packet#encode', function
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
var response = new Packet();
|
|
98
|
+
test('Packet#encode', function() {
|
|
99
|
+
const response = new Packet();
|
|
100
100
|
//
|
|
101
101
|
response.header.qr = 1;
|
|
102
102
|
response.answers.push({
|
|
103
|
-
name: 'lsong.org',
|
|
104
|
-
type: Packet.TYPE.A,
|
|
105
|
-
class: Packet.CLASS.IN,
|
|
106
|
-
ttl: 300,
|
|
107
|
-
address: '127.0.0.1'
|
|
103
|
+
name : 'lsong.org',
|
|
104
|
+
type : Packet.TYPE.A,
|
|
105
|
+
class : Packet.CLASS.IN,
|
|
106
|
+
ttl : 300,
|
|
107
|
+
address : '127.0.0.1',
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
response.answers.push({
|
|
111
|
-
name: 'lsong.org',
|
|
112
|
-
type: Packet.TYPE.AAAA,
|
|
113
|
-
class: Packet.CLASS.IN,
|
|
114
|
-
ttl: 300,
|
|
115
|
-
address: '2001:db8::::ff00:42:8329'
|
|
111
|
+
name : 'lsong.org',
|
|
112
|
+
type : Packet.TYPE.AAAA,
|
|
113
|
+
class : Packet.CLASS.IN,
|
|
114
|
+
ttl : 300,
|
|
115
|
+
address : '2001:db8::::ff00:42:8329',
|
|
116
116
|
});
|
|
117
117
|
|
|
118
118
|
response.answers.push({
|
|
119
|
-
name: 'lsong.org',
|
|
120
|
-
type: Packet.TYPE.CNAME,
|
|
121
|
-
class: Packet.CLASS.IN,
|
|
122
|
-
ttl: 300,
|
|
123
|
-
domain: 'sfo1.lsong.org'
|
|
119
|
+
name : 'lsong.org',
|
|
120
|
+
type : Packet.TYPE.CNAME,
|
|
121
|
+
class : Packet.CLASS.IN,
|
|
122
|
+
ttl : 300,
|
|
123
|
+
domain : 'sfo1.lsong.org',
|
|
124
124
|
});
|
|
125
125
|
|
|
126
126
|
response.answers.push({
|
|
127
|
-
name: 'lsong.org',
|
|
128
|
-
type: Packet.TYPE.PTR,
|
|
129
|
-
class: Packet.CLASS.IN,
|
|
130
|
-
ttl: 300,
|
|
131
|
-
domain: 'sfo1.lsong.org'
|
|
127
|
+
name : 'lsong.org',
|
|
128
|
+
type : Packet.TYPE.PTR,
|
|
129
|
+
class : Packet.CLASS.IN,
|
|
130
|
+
ttl : 300,
|
|
131
|
+
domain : 'sfo1.lsong.org',
|
|
132
132
|
});
|
|
133
133
|
|
|
134
134
|
response.authorities.push({
|
|
135
|
-
name: 'lsong.org',
|
|
136
|
-
type: Packet.TYPE.MX,
|
|
137
|
-
class: Packet.CLASS.IN,
|
|
138
|
-
ttl: 300,
|
|
139
|
-
exchange: 'mail.lsong.org',
|
|
140
|
-
priority: 5
|
|
135
|
+
name : 'lsong.org',
|
|
136
|
+
type : Packet.TYPE.MX,
|
|
137
|
+
class : Packet.CLASS.IN,
|
|
138
|
+
ttl : 300,
|
|
139
|
+
exchange : 'mail.lsong.org',
|
|
140
|
+
priority : 5,
|
|
141
141
|
});
|
|
142
142
|
|
|
143
143
|
response.authorities.push({
|
|
144
|
-
name: 'lsong.org',
|
|
145
|
-
type: Packet.TYPE.NS,
|
|
146
|
-
class: Packet.CLASS.IN,
|
|
147
|
-
ttl: 300,
|
|
148
|
-
ns: 'ns1.lsong.org',
|
|
144
|
+
name : 'lsong.org',
|
|
145
|
+
type : Packet.TYPE.NS,
|
|
146
|
+
class : Packet.CLASS.IN,
|
|
147
|
+
ttl : 300,
|
|
148
|
+
ns : 'ns1.lsong.org',
|
|
149
149
|
});
|
|
150
150
|
|
|
151
151
|
response.additionals.push({
|
|
152
|
-
name: 'lsong.org',
|
|
153
|
-
type: Packet.TYPE.SOA,
|
|
154
|
-
class: Packet.CLASS.IN,
|
|
155
|
-
ttl: 300,
|
|
156
|
-
primary: 'lsong.org',
|
|
157
|
-
admin: 'admin@lsong.org',
|
|
158
|
-
serial: 2016121301,
|
|
159
|
-
refresh: 300,
|
|
160
|
-
retry: 3,
|
|
161
|
-
expiration: 10,
|
|
162
|
-
minimum: 10
|
|
152
|
+
name : 'lsong.org',
|
|
153
|
+
type : Packet.TYPE.SOA,
|
|
154
|
+
class : Packet.CLASS.IN,
|
|
155
|
+
ttl : 300,
|
|
156
|
+
primary : 'lsong.org',
|
|
157
|
+
admin : 'admin@lsong.org',
|
|
158
|
+
serial : 2016121301,
|
|
159
|
+
refresh : 300,
|
|
160
|
+
retry : 3,
|
|
161
|
+
expiration : 10,
|
|
162
|
+
minimum : 10,
|
|
163
163
|
});
|
|
164
164
|
//
|
|
165
165
|
response.additionals.push({
|
|
166
|
-
name: 'lsong.org',
|
|
167
|
-
type: Packet.TYPE.TXT,
|
|
168
|
-
class: Packet.CLASS.IN,
|
|
169
|
-
ttl: 300,
|
|
170
|
-
data: '#v=spf1 include:_spf.google.com ~all'
|
|
166
|
+
name : 'lsong.org',
|
|
167
|
+
type : Packet.TYPE.TXT,
|
|
168
|
+
class : Packet.CLASS.IN,
|
|
169
|
+
ttl : 300,
|
|
170
|
+
data : '#v=spf1 include:_spf.google.com ~all',
|
|
171
171
|
});
|
|
172
172
|
|
|
173
173
|
assert.deepEqual(Packet.parse(response.toBuffer()), response);
|
|
174
|
-
|
|
175
174
|
});
|
|
176
175
|
|
|
177
|
-
test('Packet#encode array of character strings', function
|
|
178
|
-
|
|
176
|
+
test('Packet#encode array of character strings', function() {
|
|
177
|
+
const response = new Packet();
|
|
179
178
|
//
|
|
180
|
-
|
|
179
|
+
const dkim = [ 'v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsD6Th73ZDKkFAntNZDbx',
|
|
181
180
|
'Eh8VV2DSMs3re6v9/gXoT3dGcbSsuUMpfLzP5MWp4sW5cPyZxEGSiC03ZVIcCca0GRAuX9b1M0Qy25wLmPq',
|
|
182
181
|
'8eT129mhwbeX50xTaXqq63A/oDM0QOPe1IeBMfPnR9tWXxvEzZKvVbmTlMY5bf+3QHLqmaEihnGlXh2LRVZ',
|
|
183
182
|
'be2EMlYo18YM4LU/LkZKe06rxlq38W22TL7964tr7jmOZ+huXf2iLSg4nc4UzLwb2aOdOA+w4c87h+HW/L8',
|
|
184
|
-
'0548pFguF46TKc0C0egZ+oll3Y8zySYrbkVrWFrcpnrw5qDiRVHEjxqZSubSYX+16TjNcJg9QIDAQAB'];
|
|
183
|
+
'0548pFguF46TKc0C0egZ+oll3Y8zySYrbkVrWFrcpnrw5qDiRVHEjxqZSubSYX+16TjNcJg9QIDAQAB' ];
|
|
185
184
|
|
|
186
185
|
response.header.qr = 1;
|
|
187
186
|
response.answers.push({
|
|
188
|
-
name: 'lsong.org',
|
|
189
|
-
type: Packet.TYPE.TXT,
|
|
190
|
-
class: Packet.CLASS.IN,
|
|
191
|
-
ttl: 300,
|
|
192
|
-
data: dkim
|
|
187
|
+
name : 'lsong.org',
|
|
188
|
+
type : Packet.TYPE.TXT,
|
|
189
|
+
class : Packet.CLASS.IN,
|
|
190
|
+
ttl : 300,
|
|
191
|
+
data : dkim,
|
|
193
192
|
});
|
|
194
193
|
|
|
195
|
-
assert.equal(Packet.parse(response.toBuffer()).answers[0].data, dkim.join(''))
|
|
194
|
+
assert.equal(Packet.parse(response.toBuffer()).answers[0].data, dkim.join(''));
|
|
196
195
|
});
|
|
197
196
|
|
|
198
|
-
test('EDNS.ECS#encode', function
|
|
199
|
-
|
|
200
|
-
new Packet.Resource.EDNS.ECS('10.11.12.13/24')
|
|
197
|
+
test('EDNS.ECS#encode', function() {
|
|
198
|
+
const query = new Packet.Resource.EDNS([
|
|
199
|
+
new Packet.Resource.EDNS.ECS('10.11.12.13/24'),
|
|
201
200
|
]);
|
|
202
201
|
|
|
203
|
-
|
|
202
|
+
const b = Packet.Resource.encode(query);
|
|
204
203
|
assert.deepEqual(b, Buffer.from([
|
|
205
204
|
0x00, 0x00, 0x29, 0x02, 0x00, 0x00, 0x00, 0x00,
|
|
206
205
|
0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x08, 0x00,
|
|
207
|
-
0x01, 0x18, 0x00, 0x0a, 0x0b, 0x0c, 0x0d]))
|
|
208
|
-
})
|
|
206
|
+
0x01, 0x18, 0x00, 0x0a, 0x0b, 0x0c, 0x0d ]));
|
|
207
|
+
});
|
|
209
208
|
|
|
210
|
-
test('EDNS#decode', function
|
|
211
|
-
const buffer = Buffer.from([0x00, 0x08, 0x00, 0x08, 0x00, 0x01, 0x18, 0x00, 0x0a, 0x0b, 0x0c, 0x0d]);
|
|
209
|
+
test('EDNS#decode', function() {
|
|
210
|
+
const buffer = Buffer.from([ 0x00, 0x08, 0x00, 0x08, 0x00, 0x01, 0x18, 0x00, 0x0a, 0x0b, 0x0c, 0x0d ]);
|
|
212
211
|
const reader = new Packet.Reader(buffer);
|
|
213
212
|
const record = Packet.Resource.EDNS.decode(reader, buffer.length);
|
|
214
213
|
|
|
@@ -220,7 +219,7 @@ test('EDNS#decode', function () {
|
|
|
220
219
|
assert.equal(record.rdata[0].ip, '10.11.12.13');
|
|
221
220
|
|
|
222
221
|
const query = new Packet.Resource.EDNS([
|
|
223
|
-
new Packet.Resource.EDNS.ECS('10.20.0.0/16')
|
|
222
|
+
new Packet.Resource.EDNS.ECS('10.20.0.0/16'),
|
|
224
223
|
]);
|
|
225
224
|
const encoded = Packet.Resource.encode(query);
|
|
226
225
|
const decoded = Packet.Resource.decode(encoded);
|
|
@@ -229,12 +228,12 @@ test('EDNS#decode', function () {
|
|
|
229
228
|
assert.deepEqual(decoded, query);
|
|
230
229
|
});
|
|
231
230
|
|
|
232
|
-
test('EDNS#decode multiple', function
|
|
231
|
+
test('EDNS#decode multiple', function() {
|
|
233
232
|
const query = new Packet.Resource.EDNS([
|
|
234
233
|
new Packet.Resource.EDNS.ECS('10.0.0.0/8'),
|
|
235
234
|
new Packet.Resource.EDNS.ECS('10.9.0.0/16'),
|
|
236
235
|
new Packet.Resource.EDNS.ECS('10.9.8.0/24'),
|
|
237
|
-
new Packet.Resource.EDNS.ECS('10.9.8.7/32')
|
|
236
|
+
new Packet.Resource.EDNS.ECS('10.9.8.7/32'),
|
|
238
237
|
]);
|
|
239
238
|
const encoded = Packet.Resource.encode(query);
|
|
240
239
|
const decoded = Packet.Resource.decode(encoded);
|
|
@@ -242,3 +241,155 @@ test('EDNS#decode multiple', function () {
|
|
|
242
241
|
|
|
243
242
|
assert.deepEqual(decoded, query);
|
|
244
243
|
});
|
|
244
|
+
|
|
245
|
+
test('server/doh#cors - default', async function() {
|
|
246
|
+
const server = createDOHServer();
|
|
247
|
+
const { port } = await new Promise(resolve => {
|
|
248
|
+
server.on('listening', resolve);
|
|
249
|
+
server.listen();
|
|
250
|
+
});
|
|
251
|
+
const { headers } = await get(`http://localhost:${port}`);
|
|
252
|
+
assert.equal(headers['access-control-allow-origin'], '*');
|
|
253
|
+
server.server.close();
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
test('server/doh#cors - no cors', async function() {
|
|
257
|
+
const server = createDOHServer({
|
|
258
|
+
cors: false,
|
|
259
|
+
});
|
|
260
|
+
const { port } = await new Promise(resolve => {
|
|
261
|
+
server.on('listening', resolve);
|
|
262
|
+
server.listen();
|
|
263
|
+
});
|
|
264
|
+
const { headers } = await get(`http://localhost:${port}`);
|
|
265
|
+
assert.equal(headers['access-control-allow-origin'], undefined);
|
|
266
|
+
server.server.close();
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
test('server/doh#cors - cors origin', async function() {
|
|
270
|
+
const server = createDOHServer({
|
|
271
|
+
cors: 'some.domain',
|
|
272
|
+
});
|
|
273
|
+
const { port } = await new Promise(resolve => {
|
|
274
|
+
server.on('listening', resolve);
|
|
275
|
+
server.listen();
|
|
276
|
+
});
|
|
277
|
+
const { headers } = await get(`http://localhost:${port}`);
|
|
278
|
+
assert.equal(headers['access-control-allow-origin'], 'some.domain');
|
|
279
|
+
assert.equal(headers.vary, 'Origin');
|
|
280
|
+
server.server.close();
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
test('server/doh#cors - cors function', async function() {
|
|
284
|
+
const server = createDOHServer({
|
|
285
|
+
cors(domain) {
|
|
286
|
+
if (domain === 'a.domain') {
|
|
287
|
+
return true;
|
|
288
|
+
} else if (domain === 'b.domain') {
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
throw new Error(`Unexpected domain: ${domain}`);
|
|
292
|
+
},
|
|
293
|
+
});
|
|
294
|
+
const { port } = await new Promise(resolve => {
|
|
295
|
+
server.on('listening', resolve);
|
|
296
|
+
server.listen();
|
|
297
|
+
});
|
|
298
|
+
let headers = (await get(`http://localhost:${port}`, { headers: { origin: 'a.domain' } })).headers;
|
|
299
|
+
assert.equal(headers['access-control-allow-origin'], 'a.domain');
|
|
300
|
+
assert.equal(headers.vary, 'Origin');
|
|
301
|
+
headers = (await get(`http://localhost:${port}`, { headers: { origin: 'b.domain' } })).headers;
|
|
302
|
+
assert.equal(headers['access-control-allow-origin'], 'false');
|
|
303
|
+
assert.equal(headers.vary, 'Origin');
|
|
304
|
+
server.server.close();
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
test('server/all#simple-request', async() => {
|
|
308
|
+
const server = createServer({
|
|
309
|
+
doh : true,
|
|
310
|
+
tcp : true,
|
|
311
|
+
udp : true,
|
|
312
|
+
handle(request, send, _info) {
|
|
313
|
+
const [ question ] = request.questions;
|
|
314
|
+
assert.deepEqual(request.questions, [ { name: 'test.com', type: 1, class: 1 } ]);
|
|
315
|
+
const response = Packet.createResponseFromRequest(request);
|
|
316
|
+
response.answers.push({
|
|
317
|
+
name : question.name,
|
|
318
|
+
type : Packet.TYPE.TXT,
|
|
319
|
+
class : Packet.CLASS.IN,
|
|
320
|
+
ttl : 300,
|
|
321
|
+
data : [ 'Hello World' ],
|
|
322
|
+
});
|
|
323
|
+
send(response);
|
|
324
|
+
},
|
|
325
|
+
});
|
|
326
|
+
const servers = await server.listen();
|
|
327
|
+
assert.ok(servers.udp.port > 1000);
|
|
328
|
+
assert.ok(servers.tcp.port > 1000);
|
|
329
|
+
assert.ok(servers.doh.port > 1000);
|
|
330
|
+
const doh = DOHClient({ dns: `127.0.0.1:${servers.doh.port}`, http: true });
|
|
331
|
+
const tcp = TCPClient({ dns: '127.0.0.1', port: servers.tcp.port });
|
|
332
|
+
const udp = UDPClient({ dns: '127.0.0.1', port: servers.udp.port });
|
|
333
|
+
const expected = [ { name: 'test.com', ttl: 300, type: 16, class: 1, data: 'Hello World' } ];
|
|
334
|
+
assert.deepEqual((await doh('test.com')).answers, expected);
|
|
335
|
+
assert.deepEqual((await tcp('test.com')).answers, expected);
|
|
336
|
+
assert.deepEqual((await udp('test.com')).answers, expected);
|
|
337
|
+
await server.close();
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
test('server/all#invalid-request', async() => {
|
|
341
|
+
const server = createServer({
|
|
342
|
+
doh : true,
|
|
343
|
+
tcp : true,
|
|
344
|
+
udp : true,
|
|
345
|
+
handle : () => {},
|
|
346
|
+
});
|
|
347
|
+
const servers = await server.listen();
|
|
348
|
+
assert.ok(servers.udp.port > 1000);
|
|
349
|
+
assert.ok(servers.tcp.port > 1000);
|
|
350
|
+
assert.ok(servers.doh.port > 1000);
|
|
351
|
+
|
|
352
|
+
const errors = [];
|
|
353
|
+
server.on('requestError', (e) => {
|
|
354
|
+
errors.push(e);
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
const tcpSocket = tcp.connect({ port: servers.tcp.port, host: '127.0.0.1' });
|
|
358
|
+
tcpSocket.on('connect', () => tcpSocket.end('INVALID'));
|
|
359
|
+
|
|
360
|
+
const udpSocket = udp.createSocket('udp4');
|
|
361
|
+
udpSocket.send('INVALID', servers.udp.port, '127.0.0.1', () => udpSocket.close());
|
|
362
|
+
|
|
363
|
+
const dohConn = http.get(`http://127.0.0.1:${servers.doh.port}/dns-query?dns=INVALID`, {
|
|
364
|
+
headers: { accept: 'application/dns-message' },
|
|
365
|
+
}).on('error', () => {});
|
|
366
|
+
|
|
367
|
+
await Promise.all([
|
|
368
|
+
new Promise((resolve) => tcpSocket.on('close', resolve)),
|
|
369
|
+
new Promise((resolve) => udpSocket.on('close', resolve)),
|
|
370
|
+
new Promise((resolve) => dohConn.on('close', resolve)),
|
|
371
|
+
]);
|
|
372
|
+
|
|
373
|
+
assert.equal(errors.length, 3);
|
|
374
|
+
|
|
375
|
+
await server.close();
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
function get(url, options) {
|
|
379
|
+
return new Promise((resolve, reject) => {
|
|
380
|
+
try {
|
|
381
|
+
const req = http.get(url, options, res => {
|
|
382
|
+
const result = [];
|
|
383
|
+
res.on('data', data => result.push(data));
|
|
384
|
+
res.once('error', reject);
|
|
385
|
+
res.once('end', () => resolve({
|
|
386
|
+
body : Buffer.concat(result),
|
|
387
|
+
headers : res.headers,
|
|
388
|
+
}));
|
|
389
|
+
});
|
|
390
|
+
req.on('error', reject);
|
|
391
|
+
} catch (err) {
|
|
392
|
+
reject(err);
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
}
|
package/test/test.js
CHANGED
|
@@ -1,27 +1,34 @@
|
|
|
1
1
|
const { inspect } = require('util');
|
|
2
|
+
|
|
3
|
+
let previous = Promise.resolve();
|
|
4
|
+
|
|
2
5
|
/**
|
|
3
6
|
* super tiny testing framework
|
|
4
|
-
*
|
|
7
|
+
*
|
|
5
8
|
* @author Liu song <hi@lsong.org>
|
|
6
9
|
* @github https://github.com/song940
|
|
7
10
|
*/
|
|
8
|
-
const test =
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
const test = (title, fn) => {
|
|
12
|
+
previous = previous.then(async() => {
|
|
13
|
+
try {
|
|
14
|
+
await fn();
|
|
15
|
+
console.log(color(` ✔ ${title}`, 32));
|
|
16
|
+
} catch (err) {
|
|
17
|
+
console.error(color(` ✘ ${title}`, 31));
|
|
18
|
+
console.log();
|
|
19
|
+
console.log(color(` ${err.name}: ${err.message}`, 31));
|
|
20
|
+
console.error(color(` expected: ${inspect(err.expected)}`, 32));
|
|
21
|
+
console.error(color(` actual: ${inspect(err.actual)}`, 31));
|
|
22
|
+
console.log(err.stack);
|
|
23
|
+
console.log();
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
return previous;
|
|
21
28
|
};
|
|
22
29
|
|
|
23
30
|
function color(str, c) {
|
|
24
|
-
return
|
|
25
|
-
}
|
|
31
|
+
return `\x1b[${c}m${str}\x1b[0m`;
|
|
32
|
+
}
|
|
26
33
|
|
|
27
|
-
module.exports = test;
|
|
34
|
+
module.exports = test;
|
package/.travis.yml
DELETED