Mercurial > hg > nginx-tests
comparison http_resolver.t @ 834:37747a4ff78e
Tests: simple http resolver tests over TCP.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Thu, 28 Jan 2016 20:08:54 +0300 |
parents | 9caacdb56b53 |
children | a9c4cebcfe69 |
comparison
equal
deleted
inserted
replaced
833:62315953d703 | 834:37747a4ff78e |
---|---|
9 | 9 |
10 use warnings; | 10 use warnings; |
11 use strict; | 11 use strict; |
12 | 12 |
13 use Test::More; | 13 use Test::More; |
14 | |
15 use IO::Select; | |
14 | 16 |
15 BEGIN { use FindBin; chdir($FindBin::Bin); } | 17 BEGIN { use FindBin; chdir($FindBin::Bin); } |
16 | 18 |
17 use lib 'lib'; | 19 use lib 'lib'; |
18 use Test::Nginx qw/ :DEFAULT http_end /; | 20 use Test::Nginx qw/ :DEFAULT http_end /; |
78 location /bad { | 80 location /bad { |
79 resolver 127.0.0.1:8089; | 81 resolver 127.0.0.1:8089; |
80 resolver_timeout 1s; | 82 resolver_timeout 1s; |
81 proxy_pass http://$host:8080/backend; | 83 proxy_pass http://$host:8080/backend; |
82 } | 84 } |
85 location /tcp { | |
86 resolver 127.0.0.1:8083 127.0.0.1:8084; | |
87 resolver_timeout 1s; | |
88 proxy_pass http://$host:8080/backend; | |
89 proxy_connect_timeout 1s; | |
90 add_header X-IP $upstream_addr; | |
91 error_page 504 502 /50x; | |
92 | |
93 location /tcp2 { | |
94 resolver_timeout 8s; | |
95 proxy_pass http://$host:8080/backend; | |
96 } | |
97 } | |
83 | 98 |
84 location /backend { | 99 location /backend { |
85 return 200; | 100 return 200; |
86 } | 101 } |
87 location /50x { | 102 location /50x { |
92 | 107 |
93 EOF | 108 EOF |
94 | 109 |
95 $t->run_daemon(\&dns_daemon, 8081, $t); | 110 $t->run_daemon(\&dns_daemon, 8081, $t); |
96 $t->run_daemon(\&dns_daemon, 8082, $t); | 111 $t->run_daemon(\&dns_daemon, 8082, $t); |
112 $t->run_daemon(\&dns_daemon, 8083, $t, tcp => 1); | |
97 $t->run_daemon(\&dns_daemon, 8089, $t); | 113 $t->run_daemon(\&dns_daemon, 8089, $t); |
98 | 114 |
99 $t->run()->plan(35); | 115 $t->run()->plan(38); |
100 | 116 |
101 $t->waitforfile($t->testdir . '/8081'); | 117 $t->waitforfile($t->testdir . '/8081'); |
102 $t->waitforfile($t->testdir . '/8082'); | 118 $t->waitforfile($t->testdir . '/8082'); |
119 $t->waitforfile($t->testdir . '/8083'); | |
103 $t->waitforfile($t->testdir . '/8089'); | 120 $t->waitforfile($t->testdir . '/8089'); |
104 | 121 |
105 ############################################################################### | 122 ############################################################################### |
106 | 123 |
107 # schedule resend test, which takes about 5 seconds to complete | 124 # schedule resend test, which takes about 5 seconds to complete |
255 select undef, undef, undef, 1.1; | 272 select undef, undef, undef, 1.1; |
256 | 273 |
257 close $s; | 274 close $s; |
258 | 275 |
259 like(http_end($s2), qr/502 Bad/, 'timeout after aborted request'); | 276 like(http_end($s2), qr/502 Bad/, 'timeout after aborted request'); |
277 | |
278 # resend DNS query over TCP once UDP response came truncated | |
279 | |
280 TODO: { | |
281 local $TODO = 'not yet' unless $t->has_version('1.9.11'); | |
282 | |
283 unlike(http_host_header('tcp.example.net', '/tcp'), qr/127.0.0.201/, 'tc'); | |
284 like(http_host_header('tcp.example.net', '/tcp'), qr/X-IP: 127.0.0.1/, 'tcp'); | |
285 like(http_host_header('tcp2.example.net', '/tcp2'), qr/X-IP: 127.0.0.1/, | |
286 'tcp with resend'); | |
287 | |
288 } | |
260 | 289 |
261 ############################################################################### | 290 ############################################################################### |
262 | 291 |
263 sub http_host_header { | 292 sub http_host_header { |
264 my ($host, $uri, %extra) = @_; | 293 my ($host, $uri, %extra) = @_; |
279 } | 308 } |
280 | 309 |
281 ############################################################################### | 310 ############################################################################### |
282 | 311 |
283 sub reply_handler { | 312 sub reply_handler { |
284 my ($recv_data, $port, $state) = @_; | 313 my ($recv_data, $port, $state, %extra) = @_; |
285 | 314 |
286 my (@name, @rdata); | 315 my (@name, @rdata); |
287 | 316 |
288 use constant NOERROR => 0; | 317 use constant NOERROR => 0; |
289 use constant FORMERR => 1; | 318 use constant FORMERR => 1; |
462 } | 491 } |
463 | 492 |
464 if ($type == A) { | 493 if ($type == A) { |
465 push @rdata, rd_addr($ttl, '127.0.0.1'); | 494 push @rdata, rd_addr($ttl, '127.0.0.1'); |
466 } | 495 } |
496 | |
497 } elsif ($name =~ /tcp2?.example.net/) { | |
498 $hdr |= 0x0300 unless $extra{tcp}; | |
499 push @rdata, rd_addr($ttl, $extra{tcp} | |
500 ? '127.0.0.1' : '127.0.0.201') if $type == A; | |
467 } | 501 } |
468 | 502 |
469 $len = @name; | 503 $len = @name; |
470 pack("n6 (C/a*)$len x n2", $id, $hdr | $rcode, 1, scalar @rdata, | 504 pack("n6 (C/a*)$len x n2", $id, $hdr | $rcode, 1, scalar @rdata, |
471 0, 0, @name, $type, $class) . join('', @rdata); | 505 0, 0, @name, $type, $class) . join('', @rdata); |
480 | 514 |
481 pack 'n3N nC4', 0xc00c, A, IN, $ttl, eval "scalar $code", eval($code); | 515 pack 'n3N nC4', 0xc00c, A, IN, $ttl, eval "scalar $code", eval($code); |
482 } | 516 } |
483 | 517 |
484 sub dns_daemon { | 518 sub dns_daemon { |
485 my ($port, $t) = @_; | 519 my ($port, $t, %extra) = @_; |
486 | 520 |
487 my ($data, $recv_data); | 521 my ($data, $recv_data); |
488 my $socket = IO::Socket::INET->new( | 522 my $socket = IO::Socket::INET->new( |
489 LocalAddr => '127.0.0.1', | 523 LocalAddr => '127.0.0.1', |
490 LocalPort => $port, | 524 LocalPort => $port, |
491 Proto => 'udp', | 525 Proto => 'udp', |
492 ) | 526 ) |
493 or die "Can't create listening socket: $!\n"; | 527 or die "Can't create listening socket: $!\n"; |
528 | |
529 my $sel = IO::Select->new($socket); | |
530 my $tcp = 0; | |
531 | |
532 if ($extra{tcp}) { | |
533 $tcp = IO::Socket::INET->new( | |
534 Proto => 'tcp', | |
535 LocalHost => "127.0.0.1:$port", | |
536 Listen => 5, | |
537 Reuse => 1 | |
538 ) | |
539 or die "Can't create listening socket: $!\n"; | |
540 | |
541 $sel->add($tcp); | |
542 } | |
543 | |
544 local $SIG{PIPE} = 'IGNORE'; | |
494 | 545 |
495 # track number of relevant queries | 546 # track number of relevant queries |
496 | 547 |
497 my %state = ( | 548 my %state = ( |
498 cnamecnt => 0, | 549 cnamecnt => 0, |
510 # signal we are ready | 561 # signal we are ready |
511 | 562 |
512 open my $fh, '>', $t->testdir() . '/' . $port; | 563 open my $fh, '>', $t->testdir() . '/' . $port; |
513 close $fh; | 564 close $fh; |
514 | 565 |
515 while (1) { | 566 while (my @ready = $sel->can_read) { |
516 $socket->recv($recv_data, 65536); | 567 foreach my $fh (@ready) { |
517 next if $port == 8089; | 568 if ($tcp == $fh) { |
518 $data = reply_handler($recv_data, $port, \%state); | 569 my $new = $fh->accept; |
519 $socket->send($data); | 570 $new->autoflush(1); |
571 $sel->add($new); | |
572 | |
573 } elsif ($socket == $fh) { | |
574 $fh->recv($recv_data, 65536); | |
575 $data = reply_handler($recv_data, $port, | |
576 \%state); | |
577 $fh->send($data); | |
578 | |
579 } else { | |
580 $fh->recv($recv_data, 65536); | |
581 unless (length $recv_data) { | |
582 $sel->remove($fh); | |
583 $fh->close; | |
584 next; | |
585 } | |
586 | |
587 again: | |
588 my $len = unpack("n", $recv_data); | |
589 $data = substr $recv_data, 2, $len; | |
590 $data = reply_handler($data, $port, \%state, | |
591 tcp => 1); | |
592 $data = pack("n", length $data) . $data; | |
593 $fh->send($data); | |
594 $recv_data = substr $recv_data, 2 + $len; | |
595 goto again if length $recv_data; | |
596 } | |
597 } | |
520 } | 598 } |
521 } | 599 } |
522 | 600 |
523 ############################################################################### | 601 ############################################################################### |