[PATCH] Tests: reworked and simplified proxy variables tests
Maxim Dounin
mdounin at mdounin.ru
Wed Jul 29 04:29:36 UTC 2026
# HG changeset patch
# User Maxim Dounin <mdounin at mdounin.ru>
# Date 1785299249 -10800
# Wed Jul 29 07:27:29 2026 +0300
# Node ID 5d1b52ccd445392a64ebb2a9f416f58e9b537945
# Parent 2cbdf8a573d9d8ee60bfc8e3258674281e6b0232
Tests: reworked and simplified proxy variables tests.
diff --git a/proxy.t b/proxy.t
--- a/proxy.t
+++ b/proxy.t
@@ -21,7 +21,7 @@ use Test::Nginx;
select STDERR; $| = 1;
select STDOUT; $| = 1;
-my $t = Test::Nginx->new()->has(qw/http proxy/)->plan(28);
+my $t = Test::Nginx->new()->has(qw/http proxy/)->plan(6);
$t->write_file_expand('nginx.conf', <<'EOF');
@@ -35,26 +35,14 @@ events {
http {
%%TEST_GLOBALS_HTTP%%
- log_format time '$upstream_connect_time:$upstream_header_time:'
- '$upstream_response_time';
-
upstream u {
server 127.0.0.1:8081;
}
- upstream u2 {
- server 127.0.0.1:8081;
- server 127.0.0.1:8081;
- }
-
server {
listen 127.0.0.1:8080;
server_name localhost;
- add_header X-Connect $upstream_connect_time;
- add_header X-Header $upstream_header_time;
- add_header X-Response $upstream_response_time;
-
location / {
proxy_pass http://127.0.0.1:8081;
proxy_read_timeout 2s;
@@ -71,25 +59,6 @@ http {
proxy_pass http://127.0.0.1:8081;
proxy_connect_timeout 2s;
}
-
- location /time/ {
- proxy_pass http://127.0.0.1:8081/;
- access_log %%TESTDIR%%/time.log time;
- }
-
- location /pnu {
- proxy_pass http://u2/bad;
- }
-
- location /vars {
- proxy_pass http://127.0.0.1:8080/stub;
-
- add_header X-Proxy-Host $proxy_host;
- add_header X-Proxy-Port $proxy_port;
- add_header X-Proxy-Forwarded $proxy_add_x_forwarded_for;
- }
-
- location /stub { }
}
}
@@ -112,77 +81,8 @@ like(http_get('/var?b=u/'), qr/SEE-THIS/
like(http_get('/timeout'), qr/200 OK/, 'proxy connect timeout');
-my $re = qr/(\d\.\d{3})/;
-my $p0 = port(8080);
-my ($ct, $ht, $rt, $ct2, $ht2, $rt2, $ct3, $ht3, $rt3);
-
-like(http_get('/vars'), qr/X-Proxy-Host:\s127\.0\.0\.1:$p0/, 'proxy_host');
-like(http_get('/vars'), qr/X-Proxy-Port:\s$p0/, 'proxy_port');
-like(http_xff('/vars', '192.0.2.1'), qr/X-Proxy-Forwarded:.*192\.0\.2\.1/,
- 'proxy_add_x_forwarded_for');
-
-($ct, $ht) = get('/time/header');
-cmp_ok($ct, '<', 1, 'connect time - slow response header');
-cmp_ok($ht, '>=', 1, 'header time - slow response header');
-
-($ct, $ht) = get('/time/body');
-cmp_ok($ct, '<', 1, 'connect time - slow response body');
-cmp_ok($ht, '<', 1, 'header time - slow response body');
-
-my $s = http_get('/time/header', start => 1);
-select undef, undef, undef, 0.4;
-close ($s);
-
-# expect no header time in 1st (bad) upstream, no (yet) response time in 2nd
-
-$re = qr/(\d\.\d{3}|-)/;
-($ct, $ct2, $ht, $ht2, $rt, $rt2) = get('/pnu', many => 1);
-
-cmp_ok($ct, '<', 1, 'connect time - next');
-cmp_ok($ct2, '<', 1, 'connect time - next 2');
-
-is($ht, '-', 'header time - next');
-cmp_ok($ht2, '<', 1, 'header time - next 2');
-
-cmp_ok($rt, '>=', 1, 'response time - next');
-is($rt2, '-', 'response time - next 2');
-
-$t->stop();
-
-($ct, $ht, $rt, $ct2, $ht2, $rt2, $ct3, $ht3, $rt3)
- = $t->read_file('time.log') =~ /^$re:$re:$re\n$re:$re:$re\n$re:$re:$re$/;
-
-cmp_ok($ct, '<', 1, 'connect time log - slow response header');
-cmp_ok($ct2, '<', 1, 'connect time log - slow response body');
-cmp_ok($ct3, '<', 1, 'connect time log - client close');
-
-cmp_ok($ht, '>=', 1, 'header time log - slow response header');
-cmp_ok($ht2, '<', 1, 'header time log - slow response body');
-is($ht3, '-', 'header time log - client close');
-
-cmp_ok($rt, '>=', 1, 'response time log - slow response header');
-cmp_ok($rt2, '>=', 1, 'response time log - slow response body');
-cmp_ok($rt3, '>', $ct3, 'response time log - client close');
-
###############################################################################
-sub get {
- my ($uri, %extra) = @_;
- my $re = $extra{many} ? qr/$re, $re?/ : $re;
- my $r = http_get($uri);
- $r =~ /X-Connect: $re/, $r =~ /X-Header: $re/, $r =~ /X-Response: $re/;
-}
-
-sub http_xff {
- my ($uri, $xff) = @_;
- return http(<<EOF);
-GET $uri HTTP/1.0
-Host: localhost
-X-Forwarded-For: $xff
-
-EOF
-}
-
sub http_daemon {
my $once = 1;
my $server = IO::Socket::INET->new(
@@ -238,43 +138,6 @@ Connection: close
EOF
- } elsif ($uri eq '/bad') {
-
- if ($once) {
- $once = 0;
- select undef, undef, undef, 1.1;
- next;
- }
-
- print $client <<EOF;
-HTTP/1.1 200 OK
-Connection: close
-
-SEE-THIS-AND-THIS
-EOF
-
- } elsif ($uri eq '/header') {
- select undef, undef, undef, 1.1;
-
- print $client <<EOF;
-HTTP/1.1 200 OK
-Connection: close
-
-SEE-THIS-AND-THIS;
-EOF
-
- } elsif ($uri eq '/body') {
-
- print $client <<EOF;
-HTTP/1.1 200 OK
-Connection: close
-
-SEE-THIS-
-EOF
-
- select undef, undef, undef, 1.1;
- print $client 'AND-THIS';
-
} else {
print $client <<"EOF";
diff --git a/proxy_variables.t b/proxy_variables.t
--- a/proxy_variables.t
+++ b/proxy_variables.t
@@ -1,7 +1,6 @@
#!/usr/bin/perl
-# (C) Sergey Kandaurov
-# (C) Nginx, Inc.
+# (C) Maxim Dounin
# Tests for http proxy module with upstream variables.
@@ -11,6 +10,7 @@ use warnings;
use strict;
use Test::More;
+use Socket qw/ CRLF /;
BEGIN { use FindBin; chdir($FindBin::Bin); }
@@ -22,7 +22,7 @@ use Test::Nginx;
select STDERR; $| = 1;
select STDOUT; $| = 1;
-my $t = Test::Nginx->new()->has(qw/http proxy/)->plan(4)
+my $t = Test::Nginx->new()->has(qw/http proxy cache rewrite/)->plan(22)
->write_file_expand('nginx.conf', <<'EOF');
%%TEST_GLOBALS%%
@@ -35,100 +35,220 @@ events {
http {
%%TEST_GLOBALS_HTTP%%
- log_format u $uri:$upstream_response_length:$upstream_bytes_received:
- $upstream_bytes_sent:$upstream_http_x_len;
+ upstream u {
+ server 127.0.0.1:8082 max_fails=0;
+ server 127.0.0.1:8081 backup;
+ }
+
+ proxy_cache_path cache keys_zone=one:1m;
server {
listen 127.0.0.1:8080;
server_name localhost;
location / {
- proxy_pass http://127.0.0.1:8081;
- access_log %%TESTDIR%%/test.log u;
+ proxy_pass http://127.0.0.1:8081/stub;
+ add_header X-Proxy-Host $proxy_host;
+ add_header X-Proxy-Port $proxy_port;
+ add_header X-Proxy-Forwarded $proxy_add_x_forwarded_for;
+ add_header X-Upstream-Addr $upstream_addr;
+ add_header X-Upstream-Status $upstream_status;
+ }
+
+ location /time {
+ proxy_pass http://127.0.0.1:8081/stub;
+ add_header X-Connect-Time $upstream_connect_time;
+ add_header X-Header-Time $upstream_header_time;
+ add_header X-Response-Time $upstream_response_time;
+ }
+
+ location /next {
+ proxy_pass http://u/stub;
+ add_header X-Connect-Time $upstream_connect_time;
+ add_header X-Header-Time $upstream_header_time;
+ add_header X-Response-Time $upstream_response_time;
+ }
+
+ location /length {
+ proxy_pass http://127.0.0.1:8081/stub_length;
+ add_trailer X-Response-Length $upstream_response_length;
+ add_trailer X-Bytes-Received $upstream_bytes_received;
+ add_trailer X-Bytes-Sent $upstream_bytes_sent;
+ }
+
+ location /header {
+ proxy_pass http://127.0.0.1:8081/stub_header;
+ add_header X-Header $upstream_http_foo;
+ }
+
+ location /trailer {
+ proxy_pass http://127.0.0.1:8081/stub_trailer;
+ proxy_http_version 1.1;
+ add_header X-Trailer $upstream_trailer_foo;
+ }
+
+ location /cookie {
+ proxy_pass http://127.0.0.1:8081/stub_cookie;
+ add_header X-Cookie $upstream_cookie_foo;
}
+
+ location /cache {
+ proxy_pass http://127.0.0.1:8081/stub;
+ proxy_cache one;
+ proxy_cache_key foo;
+ proxy_cache_valid 200 1m;
+ add_header X-Cache-Status $upstream_cache_status;
+ add_header X-Cache-Key $upstream_cache_key;
+ add_header X-Cache-Age $upstream_cache_age;
+ }
+ }
+
+ server {
+ listen 127.0.0.1:8081;
+ server_name localhost;
+
+ location / {
+ }
+
+ location /stub_length {
+ add_header X-Length $request_length;
+ limit_rate 800;
+ }
+
+ location /stub_header {
+ add_header Foo foo;
+ add_header Foo bar;
+ }
+
+ location /stub_trailer {
+ add_trailer Foo foo;
+ add_trailer Foo bar;
+ }
+
+ location /stub_cookie {
+ add_header Set-Cookie foo=foo;
+ }
+ }
+
+ server {
+ listen 127.0.0.1:8082;
+ server_name localhost;
+ return 444;
}
}
EOF
-$t->run_daemon(\&http_daemon, port(8081));
+$t->write_file('stub', '');
+$t->write_file('stub_length', '1234567890' x 100);
+$t->write_file('stub_header', '');
+$t->write_file('stub_trailer', '');
+$t->write_file('stub_cookie', '');
$t->run();
-$t->waitforsocket('127.0.0.1:' . port(8081));
-
###############################################################################
my $r;
-my ($l1) = ($r = http_get('/')) =~ /X-Len: (\d+)/;
-like($r, qr/SEE-THIS/, 'proxy request');
+# $proxy_host
+# $proxy_port
+# $proxy_add_x_forwarded_for
+
+$r = get('/');
+like($r, qr/X-Proxy-Host: 127\.0\.0\.1:/, '$proxy_host');
+like($r, qr/X-Proxy-Port: \d+/, '$proxy_port');
+like($r, qr/X-Proxy-Forwarded: 127\.0\.0\.1/, '$proxy_add_x_forwarded_for');
+
+like(get('/', 'X-Forwarded-For: 192.0.2.1'),
+ qr/X-Proxy-Forwarded: 192\.0\.2\.1, 127\.0\.0\.1/,
+ '$proxy_add_x_forwarded_for add');
+
+# $upstream_addr
+# $upstream_status
-my ($l2) = ($r = http_get('/multi')) =~ /X-Len: (\d+)/;
-like($r, qr/AND-THIS/, 'proxy request with multiple packets');
+$r = get('/');
+like($r, qr/X-Upstream-Addr: 127\.0\.0\.1:/, '$upstream_addr');
+like($r, qr/X-Upstream-Status: 200/, '$upstream_status');
+
+# $upstream_connect_time
+# $upstream_header_time
+# $upstream_response_time
+
+# Note that $upstream_response_time is only available after the upstream
+# request is finalized.
+
+$r = get('/time');
+like($r, qr/X-Connect-Time: \d\./, '$upstream_connect_time');
+like($r, qr/X-Header-Time: \d\./, '$upstream_header_time');
+like($r, qr/X-Response-Time: -/, '$upstream_response_time');
+
+# Since first request fails before getting a header, $upstream_header_time
+# will be only available for the second request, after switching the next
+# upstream server. And $upstream_response_time is only available for
+# the first request, but not available for the second one, since it is
+# not yet finalized.
-$t->stop();
+$r = get('/next');
+like($r, qr/X-Connect-Time: \d\.\d+, \d\.\d+/,
+ '$upstream_connect_time next upstream');
+like($r, qr/X-Header-Time: -, \d\.\d+/,
+ '$upstream_header_time next upstream');
+like($r, qr/X-Response-Time: \d\.\d+, -/,
+ '$upstream_response_time next upstream');
+
+# $upstream_response_length
+# $upstream_bytes_received
+# $upstream_bytes_sent
+
+# Final values are only available after the response is received, so
+# we use trailers here. Note that this requires HTTP/1.1 request.
+
+$r = get('/length');
+like($r, qr/X-Response-Length: 1000/, '$upstream_response_length');
+like($r, qr/X-Bytes-Received: \d+/, '$upstream_bytes_received');
+like($r, qr/X-Length: (\d+).*X-Bytes-Sent: \1/s, '$upstream_bytes_sent');
+
+# $upstream_http_
+# $upstream_trailer_
+
+like(get('/header'), qr/X-Header: foo, bar/, '$upstream_http_foo');
-my $f = $t->read_file('test.log');
-Test::Nginx::log_core('||', $f);
+TODO: {
+local $TODO = 'no trailers support in proxy yet';
+
+like(get('/trailer'), qr/X-Trailer: foo, bar/, '$upstream_trailer_foo');
+
+}
+
+# $upstream_cookie_
+
+like(get('/cookie'), qr/X-Cookie: foo/, '$upstream_cookie_foo');
-like($f, qr!^/:23:68:$l1:$l1!m, 'log - response length');
-like($f, qr!^/multi:32:77:$l2:$l2!m, 'log - response length - multi packets');
+# $upstream_cache_status
+# $upstream_cache_key
+# $upstream_cache_age
+
+# Note that the $upstream_cache_last_modified and $upstream_cache_etag
+# variables are internal, and therefore not tested here.
+
+$r = get('/cache');
+like($r, qr/X-Cache-Status: MISS/, '$upstream_cache_status');
+like($r, qr/X-Cache-Key: foo/, '$upstream_cache_key');
+
+$r = get('/cache');
+like($r, qr/X-Cache-Status: HIT/, '$upstream_cache_status hit');
+like($r, qr/X-Cache-Age: \d+/, '$upstream_cache_age');
###############################################################################
-sub http_daemon {
- my ($port) = @_;
- my $server = IO::Socket::INET->new(
- Proto => 'tcp',
- LocalHost => '127.0.0.1',
- LocalPort => $port,
- Listen => 5,
- Reuse => 1
- )
- or die "Can't create listening socket: $!\n";
-
- local $SIG{PIPE} = 'IGNORE';
-
- while (my $client = $server->accept()) {
- $client->autoflush(1);
-
- my $headers = '';
- my $uri = '';
-
- while (<$client>) {
- $headers .= $_;
- last if (/^\x0d?\x0a?$/);
- }
-
- $uri = $1 if $headers =~ /^\S+\s+([^ ]+)\s+HTTP/i;
- my $len = length($headers);
-
- if ($uri eq '/') {
- print $client <<"EOF";
-HTTP/1.1 200 OK
-Connection: close
-X-Len: $len
-
-EOF
- print $client "TEST-OK-IF-YOU-SEE-THIS"
- unless $headers =~ /^HEAD/i;
-
- } elsif ($uri eq '/multi') {
-
- print $client <<"EOF";
-HTTP/1.1 200 OK
-Connection: close
-X-Len: $len
-
-TEST-OK-IF-YOU-SEE-THIS
-EOF
-
- select undef, undef, undef, 0.1;
- print $client 'AND-THIS';
- }
-
- close $client;
- }
+sub get {
+ my ($url, @headers) = @_;
+ return http(
+ "GET $url HTTP/1.1" . CRLF .
+ 'Host: localhost' . CRLF .
+ 'Connection: close' . CRLF .
+ join(CRLF, @headers) . CRLF . CRLF
+ );
}
###############################################################################
More information about the nginx-devel
mailing list