comparison http_resolver.t @ 362:8ca9c75c97d2

Tests: more resolver tests. - Uncompressed answer section. - TTL handling in CNAME + A combined answer. - Case-insensitive lookups. - PTR type checking in RR for address to name resolving.
author Sergey Kandaurov <pluknet@nginx.com>
date Mon, 16 Dec 2013 18:59:16 +0400
parents cdab739eb6ea
children ec3284ebe53b
comparison
equal deleted inserted replaced
361:aac06d3bdc05 362:8ca9c75c97d2
56 } 56 }
57 location /valid { 57 location /valid {
58 resolver 127.0.0.1:8081 valid=3s; 58 resolver 127.0.0.1:8081 valid=3s;
59 proxy_pass http://$host:8080/backend; 59 proxy_pass http://$host:8080/backend;
60 } 60 }
61 location /case {
62 resolver 127.0.0.1:8081;
63 proxy_pass http://$http_x_name:8080/backend;
64 }
61 location /invalid { 65 location /invalid {
62 proxy_pass http://$host:8080/backend; 66 proxy_pass http://$host:8080/backend;
63 } 67 }
64 68
65 location /backend { 69 location /backend {
74 EOF 78 EOF
75 79
76 $t->run_daemon(\&dns_daemon, 8081, $t); 80 $t->run_daemon(\&dns_daemon, 8081, $t);
77 $t->run_daemon(\&dns_daemon, 8082, $t); 81 $t->run_daemon(\&dns_daemon, 8082, $t);
78 82
79 $t->run()->plan(27); 83 $t->run()->plan(31);
80 84
81 $t->waitforfile($t->testdir . '/8081'); 85 $t->waitforfile($t->testdir . '/8081');
82 $t->waitforfile($t->testdir . '/8082'); 86 $t->waitforfile($t->testdir . '/8082');
83 87
84 ############################################################################### 88 ###############################################################################
85 89
86 like(http_host_header('a.example.net', '/'), qr/200 OK/, 'A'); 90 like(http_host_header('a.example.net', '/'), qr/200 OK/, 'A');
91
92 # ensure that resolver serves queries from cache in a case-insensitive manner
93 # we check this by marking 2nd and subsequent queries on backend with SERVFAIL
94
95 TODO: {
96 local $TODO = 'not yet' unless $t->has_version('1.5.8');
97
98 http_x_name_header('case.example.net', '/case');
99 like(http_x_name_header('CASE.example.net', '/case'), qr/200 OK/,
100 'A case-insensitive');
101
102 }
103
104 like(http_host_header('awide.example.net', '/'), qr/200 OK/, 'A uncompressed');
87 like(http_host_header('short.example.net', '/'), qr/502 Bad/, 105 like(http_host_header('short.example.net', '/'), qr/502 Bad/,
88 'A short dns response'); 106 'A short dns response');
89 107
90 like(http_host_header('nx.example.net', '/'), qr/502 Bad/, 'NXDOMAIN'); 108 like(http_host_header('nx.example.net', '/'), qr/502 Bad/, 'NXDOMAIN');
91 like(http_host_header('cname.example.net', '/'), qr/200 OK/, 'CNAME'); 109 like(http_host_header('cname.example.net', '/'), qr/200 OK/, 'CNAME');
183 201
184 # expired "valid" value causes nginx to make actual query 202 # expired "valid" value causes nginx to make actual query
185 203
186 like(http_host_header('ttl.example.net', '/valid'), qr/502 Bad/, 204 like(http_host_header('ttl.example.net', '/valid'), qr/502 Bad/,
187 'valid expired'); 205 'valid expired');
206
207 TODO: {
208 local $TODO = 'not yet';
209
210 # Ensure that resolver respects expired A in CNAME + A combined response.
211 # When ttl in A is expired, only the canonical name should be queried.
212 # Catch this by returning SERVFAIL on the 2nd and subsequent queries for
213 # original name.
214
215 http_host_header('cname_a_ttl.example.net', '/');
216
217 # Ensure that resolver respects expired CNAME in CNAME + A combined response.
218 # When ttl in CNAME is expired, the answer should not be served from cache.
219 # Catch this by returning SERVFAIL on the 2nd and subsequent queries.
220
221 http_host_header('cname_a_ttl2.example.net', '/');
222
223 sleep 2;
224
225 like(http_host_header('cname_a_ttl.example.net', '/'), qr/200 OK/,
226 'CNAME + A with expired A ttl');
227 like(http_host_header('cname_a_ttl2.example.net', '/'), qr/502 Bad/,
228 'CNAME + A with expired CNAME ttl');
229
230 }
188 231
189 like(http_host_header('example.net', '/invalid'), qr/502 Bad/, 'no resolver'); 232 like(http_host_header('example.net', '/invalid'), qr/502 Bad/, 'no resolver');
190 233
191 ############################################################################### 234 ###############################################################################
192 235
193 sub http_host_header { 236 sub http_host_header {
194 my ($host, $uri) = @_; 237 my ($host, $uri) = @_;
195 return http(<<EOF); 238 return http(<<EOF);
196 GET $uri HTTP/1.0 239 GET $uri HTTP/1.0
197 Host: $host 240 Host: $host
241
242 EOF
243 }
244
245 sub http_x_name_header {
246 my ($host, $uri) = @_;
247 return http(<<EOF);
248 GET $uri HTTP/1.0
249 X-Name: $host
198 250
199 EOF 251 EOF
200 } 252 }
201 253
202 ############################################################################### 254 ###############################################################################
238 if (($name eq 'a.example.net') || ($name eq 'alias.example.net')) { 290 if (($name eq 'a.example.net') || ($name eq 'alias.example.net')) {
239 if ($type == A || $type == CNAME) { 291 if ($type == A || $type == CNAME) {
240 push @rdata, rd_addr($ttl, '127.0.0.1'); 292 push @rdata, rd_addr($ttl, '127.0.0.1');
241 } 293 }
242 294
295 } elsif ($name eq 'case.example.net' && $type == A) {
296 if (++$state->{casecnt} > 1) {
297 $rcode = SERVFAIL;
298 }
299
300 push @rdata, rd_addr($ttl, '127.0.0.1');
301
302 } elsif ($name eq 'awide.example.net' && $type == A) {
303 push @rdata, pack '(w/a*)3x n2N nC4',
304 ('awide', 'example', 'net'), A, IN, $ttl,
305 4, (127, 0, 0, 1);
306
243 } elsif (($name eq 'many.example.net') && $type == A) { 307 } elsif (($name eq 'many.example.net') && $type == A) {
244 $state->{manycnt}++; 308 $state->{manycnt}++;
245 if ($state->{manycnt} > 1) { 309 if ($state->{manycnt} > 1) {
246 $rcode = SERVFAIL; 310 $rcode = SERVFAIL;
247 } 311 }
286 350
287 if ($type == A) { 351 if ($type == A) {
288 push @rdata, pack('n3N nC4', 0xc031, A, IN, $ttl, 352 push @rdata, pack('n3N nC4', 0xc031, A, IN, $ttl,
289 4, split(/\./, '127.0.0.1')); 353 4, split(/\./, '127.0.0.1'));
290 } 354 }
355
356 } elsif ($name eq 'cname_a_ttl.example.net') {
357 push @rdata, pack("n3N nCa17n", 0xc00c, CNAME, IN, $ttl,
358 20, 17, 'cname_a_ttl_alias', 0xc018);
359
360 if ($type == A) {
361 if (++$state->{cttlcnt} >= 2) {
362 $rcode = SERVFAIL;
363 }
364 push @rdata, pack('n3N nC4', 0xc035, A, IN, 1,
365 4, split(/\./, '127.0.0.1'));
366 }
367
368 } elsif ($name eq 'cname_a_ttl2.example.net' && $type == A) {
369 push @rdata, pack("n3N nCa18n", 0xc00c, CNAME, IN, 1,
370 21, 18, 'cname_a_ttl2_alias', 0xc019);
371 if (++$state->{cttl2cnt} >= 2) {
372 $rcode = SERVFAIL;
373 }
374 push @rdata, pack('n3N nC4', 0xc036, A, IN, $ttl,
375 4, split(/\./, '127.0.0.1'));
376
377 } elsif ($name eq 'cname_a_ttl_alias.example.net' && $type == A) {
378 push @rdata, rd_addr($ttl, '127.0.0.1');
291 379
292 } elsif ($name eq 'cname2.example.net') { 380 } elsif ($name eq 'cname2.example.net') {
293 # points to non-existing A 381 # points to non-existing A
294 382
295 push @rdata, pack("n3N nCa2n", 0xc00c, CNAME, IN, $ttl, 383 push @rdata, pack("n3N nCa2n", 0xc00c, CNAME, IN, $ttl,
371 my %state = ( 459 my %state = (
372 cnamecnt => 0, 460 cnamecnt => 0,
373 twocnt => 0, 461 twocnt => 0,
374 ttlcnt => 0, 462 ttlcnt => 0,
375 ttl0cnt => 0, 463 ttl0cnt => 0,
464 cttlcnt => 0,
465 cttl2cnt => 0,
376 manycnt => 0, 466 manycnt => 0,
467 casecnt => 0,
377 ); 468 );
378 469
379 # signal we are ready 470 # signal we are ready
380 471
381 open my $fh, '>', $t->testdir() . '/' . $port; 472 open my $fh, '>', $t->testdir() . '/' . $port;