├── sub_filter_merge.t ├── LICENSE ├── merge_slashes.t ├── random_index.t ├── README ├── worker_shutdown_timeout.t ├── stream_access_log_none.t ├── ssi_waited.t ├── mail_smtp_greeting_delay.t ├── stream_set.t ├── stream_udp_wildcard.t ├── map_complex.t ├── worker_shutdown_timeout_stream.t ├── addition_buffered.t ├── perl_ssi.t ├── stream_access_log_escape.t ├── http_method.t ├── limit_req_delay.t ├── http_keepalive_shutdown.t ├── proxy_bind_transparent.t ├── gzip_flush.t ├── map_volatile.t ├── perl_sleep.t ├── proxy_cache_min_free.t ├── stream_proxy_bind.t ├── proxy_bind_transparent_capability.t ├── stream_split_clients.t ├── upstream_zone.t ├── gunzip_perl.t ├── debug_connection.t ├── proxy_protocol_ipv6.t ├── debug_connection_unix.t ├── post_action.t ├── proxy_set_body.t ├── stream_map.t ├── stream_udp_stream.t ├── geo_volatile.t ├── stream_geo_binary.t ├── http_request_port.t ├── split_clients.t ├── ssl_curve.t ├── h2_proxy_protocol.t ├── proxy_ssi_body.t ├── auth_delay.t ├── http_location_auto.t ├── stream_upstream_zone.t ├── userid_flags.t ├── stream_proxy_complex.t ├── subrequest_output_buffer_size.t ├── realip_remote_addr.t ├── proxy_request_buffering_keepalive.t ├── geo_binary.t ├── http_listen_wildcard.t ├── worker_shutdown_timeout_h2.t ├── mp4_ssi.t ├── mirror.t ├── proxy_method.t ├── scgi_gzip.t ├── binary_upgrade.t ├── proxy_max_temp_file_size.t ├── proxy_limit_rate2.t ├── sub_filter_ssi.t ├── range_clearing.t ├── h2_proxy_request_buffering_redirect.t ├── stream_geo_unix.t ├── perl_gzip.t ├── dav_chunked.t ├── realip_hostname.t ├── memcached_fake_extra.t ├── msie_refresh.t ├── worker_shutdown_timeout_mail.t ├── empty_gif.t ├── quic_key_update.t ├── h3_reusable.t ├── rewrite_set.t ├── sub_filter_multi2.t ├── fastcgi_variables.t ├── stream_proxy_ssl_name_complex.t ├── stream_limit_conn_complex.t ├── realip_remote_port.t ├── proxy_cache_path.t ├── gunzip_ssi.t ├── proxy_cache_error.t ├── fastcgi_split.t ├── h2_proxy_ssl.t ├── gzip.t ├── limit_conn_dry_run.t ├── limit_req_dry_run.t ├── sub_filter_slice.t ├── stream_proxy_ssl_conf_command.t ├── memcached.t ├── h2_auth_request.t ├── limit_conn_complex.t ├── proxy_cache_bypass.t ├── http_listen.t ├── proxy_cache_variables.t ├── gunzip_memcached.t ├── http_include.t ├── sub_filter_buffering.t ├── http_resolver_cleanup.t ├── proxy_cache_convert_head.t ├── range_flv.t ├── proxy_cache_chunked.t └── debug_connection_syslog.t /sub_filter_merge.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Test for sub_filter inheritance from http context. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http sub/); 26 | 27 | $t->plan(1)->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | sub_filter foo bar; 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | server_name localhost; 44 | 45 | location / { } 46 | } 47 | } 48 | 49 | EOF 50 | 51 | $t->write_file('foo.html', 'foo'); 52 | $t->run(); 53 | 54 | ############################################################################### 55 | 56 | like(http_get('/foo.html'), qr/bar/, 'sub_filter inheritance'); 57 | 58 | ############################################################################### 59 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008-2011 Maxim Dounin 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * 1. Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * 2. Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 | * SUCH DAMAGE. 24 | */ 25 | -------------------------------------------------------------------------------- /merge_slashes.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for URI normalization, merge_slashes off. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http rewrite/)->plan(2) 26 | ->write_file_expand('nginx.conf', <<'EOF')->run(); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | http { 36 | %%TEST_GLOBALS_HTTP%% 37 | 38 | server { 39 | listen 127.0.0.1:8080; 40 | server_name localhost; 41 | 42 | merge_slashes off; 43 | 44 | location / { 45 | add_header X-URI "x $uri x"; 46 | return 204; 47 | } 48 | } 49 | } 50 | 51 | EOF 52 | 53 | ############################################################################### 54 | 55 | like(http_get('/foo//../bar'), qr!x /foo/bar x!, 'merge slashes'); 56 | like(http_get('/foo///../bar'), qr!x /foo//bar x!, 'merge slashes 2'); 57 | 58 | ############################################################################### 59 | -------------------------------------------------------------------------------- /random_index.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | # Tests for random index module. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx; 18 | 19 | ############################################################################### 20 | 21 | select STDERR; $| = 1; 22 | select STDOUT; $| = 1; 23 | 24 | my $t = Test::Nginx->new()->has(qw/http random_index symlink/)->plan(1) 25 | ->write_file_expand('nginx.conf', <<'EOF'); 26 | 27 | %%TEST_GLOBALS%% 28 | 29 | daemon off; 30 | 31 | events { 32 | } 33 | 34 | http { 35 | %%TEST_GLOBALS_HTTP%% 36 | 37 | server { 38 | listen 127.0.0.1:8080; 39 | server_name localhost; 40 | 41 | location / { 42 | random_index on; 43 | } 44 | } 45 | } 46 | 47 | EOF 48 | 49 | my $d = $t->testdir(); 50 | 51 | mkdir("$d/x"); 52 | mkdir("$d/x/test-dir"); 53 | symlink("$d/x/test-dir", "$d/x/test-dir-link"); 54 | 55 | $t->write_file('test-file', 'RIGHT'); 56 | symlink("$d/test-file", "$d/x/test-file-link"); 57 | 58 | $t->run(); 59 | 60 | ############################################################################### 61 | 62 | like(http_get('/x/'), qr/RIGHT/s, 'file'); 63 | 64 | ############################################################################### 65 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Test suite for nginx. 2 | 3 | Use prove to run tests as one usually do for perl tests. Individual tests 4 | may be run as well. 5 | 6 | Note: tests run nginx (and backend daemons if needed) listening on localhost 7 | and may use various ports in 8000 .. 8999 range. 8 | 9 | Usage: 10 | 11 | $ TEST_NGINX_BINARY=/path/to/nginx prove . 12 | 13 | By default tests expect nginx binary to be at ../nginx/objs/nginx. 14 | 15 | Environment variables: 16 | 17 | TEST_NGINX_BINARY 18 | 19 | Sets path to nginx binary to be tested, defaults to "../nginx/objs/nginx". 20 | 21 | TEST_NGINX_MODULES 22 | 23 | Sets path to modules directory, defaults to dirname of TEST_NGINX_BINARY. 24 | 25 | TEST_NGINX_VERBOSE 26 | 27 | Be a bit more verbose (in particular, print requests sent and responses 28 | got from nginx). Note that this requires prove -v (or HARNESS_VERBOSE). 29 | 30 | TEST_NGINX_LEAVE 31 | 32 | If set, temporary directory with configs and logs won't be deleted on test 33 | completion. Useful for debugging. 34 | 35 | TEST_NGINX_CATLOG 36 | 37 | Cat error log to stdout after test completion. Useful for debugging. 38 | 39 | TEST_NGINX_UNSAFE 40 | 41 | Run unsafe tests. 42 | 43 | TEST_NGINX_GLOBALS 44 | 45 | Sets additional directives in main context. 46 | 47 | TEST_NGINX_GLOBALS_HTTP 48 | 49 | Sets additional directives in http context. 50 | 51 | TEST_NGINX_GLOBALS_STREAM 52 | 53 | Sets additional directives in stream context. 54 | 55 | Happy testing! 56 | -------------------------------------------------------------------------------- /worker_shutdown_timeout.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for worker_shutdown_timeout directive. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | use IO::Select; 16 | 17 | BEGIN { use FindBin; chdir($FindBin::Bin); } 18 | 19 | use lib 'lib'; 20 | use Test::Nginx; 21 | 22 | ############################################################################### 23 | 24 | select STDERR; $| = 1; 25 | select STDOUT; $| = 1; 26 | 27 | my $t = Test::Nginx->new()->has(qw/http/) 28 | ->write_file_expand('nginx.conf', <<'EOF'); 29 | 30 | %%TEST_GLOBALS%% 31 | 32 | daemon off; 33 | worker_shutdown_timeout 10ms; 34 | 35 | events { 36 | } 37 | 38 | http { 39 | %%TEST_GLOBALS_HTTP%% 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | server_name localhost; 44 | 45 | location / { } 46 | } 47 | } 48 | 49 | EOF 50 | 51 | $t->run()->plan(1); 52 | 53 | ############################################################################### 54 | 55 | my $s = http('', start => 1); 56 | 57 | select undef, undef, undef, 0.2; 58 | 59 | $t->reload(); 60 | 61 | if (IO::Select->new($s)->can_read(5)) { 62 | Test::Nginx::log_core('||', "select: can_read"); 63 | } 64 | 65 | is(http_get('/', socket => $s) || '', '', 'worker_shutdown_timeout'); 66 | 67 | ############################################################################### 68 | -------------------------------------------------------------------------------- /stream_access_log_none.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Stream tests for access_log with escape parameter. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/stream stream_map stream_return/)->plan(1) 26 | ->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | stream { 36 | %%TEST_GLOBALS_STREAM%% 37 | 38 | map $pid $a { 39 | default '" \ "'; 40 | } 41 | map $pid $b { 42 | default "foo"; 43 | } 44 | 45 | log_format none escape=none $a$b$upstream_addr; 46 | 47 | server { 48 | listen 127.0.0.1:8080; 49 | return ok; 50 | 51 | access_log %%TESTDIR%%/none.log none; 52 | } 53 | } 54 | 55 | EOF 56 | 57 | $t->run(); 58 | 59 | ############################################################################### 60 | 61 | http_get('/'); 62 | 63 | $t->stop(); 64 | 65 | is($t->read_file('none.log'), '" \\ "foo' . "\n", 'none'); 66 | 67 | ############################################################################### 68 | -------------------------------------------------------------------------------- /ssi_waited.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | # Tests for nginx ssi module, waited subrequests. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx; 18 | 19 | ############################################################################### 20 | 21 | select STDERR; $| = 1; 22 | select STDOUT; $| = 1; 23 | 24 | my $t = Test::Nginx->new()->has(qw/http ssi/)->plan(1); 25 | 26 | $t->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | http { 36 | %%TEST_GLOBALS_HTTP%% 37 | 38 | server { 39 | listen 127.0.0.1:8080; 40 | server_name localhost; 41 | location / { 42 | ssi on; 43 | } 44 | } 45 | } 46 | 47 | EOF 48 | 49 | $t->write_file('index.html', 'x' . 50 | 'xx'); 51 | $t->write_file('first.html', 'FIRST'); 52 | $t->write_file('second.html', 53 | 'xSECOND'); 54 | $t->write_file('waited.html', 'WAITED'); 55 | 56 | $t->run(); 57 | 58 | ############################################################################### 59 | 60 | like(http_get('/'), qr/^xFIRSTxWAITEDxSECONDx$/m, 'waited non-active'); 61 | 62 | ############################################################################### 63 | -------------------------------------------------------------------------------- /mail_smtp_greeting_delay.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | ############################################################################### 6 | 7 | use warnings; 8 | use strict; 9 | 10 | use Test::More; 11 | 12 | BEGIN { use FindBin; chdir($FindBin::Bin); } 13 | 14 | use lib 'lib'; 15 | use Test::Nginx; 16 | use Test::Nginx::SMTP; 17 | 18 | ############################################################################### 19 | 20 | select STDERR; $| = 1; 21 | select STDOUT; $| = 1; 22 | 23 | local $SIG{PIPE} = 'IGNORE'; 24 | 25 | my $t = Test::Nginx->new()->has(qw/mail smtp/)->plan(2) 26 | ->write_file_expand('nginx.conf', <<'EOF')->run(); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | mail { 36 | proxy_pass_error_message on; 37 | proxy_timeout 15s; 38 | auth_http http://127.0.0.1:8080/mail/auth; 39 | xclient off; 40 | 41 | server { 42 | listen 127.0.0.1:8025; 43 | protocol smtp; 44 | smtp_greeting_delay 1s; 45 | } 46 | } 47 | 48 | EOF 49 | 50 | ############################################################################### 51 | 52 | # With smtp_greeting_delay session expected to be closed after first error 53 | # message if client sent something before greeting. 54 | 55 | my $s = Test::Nginx::SMTP->new(); 56 | $s->send('HELO example.com'); 57 | $s->check(qr/^5.. /, "command before greeting - session must be rejected"); 58 | ok($s->eof(), "session have to be closed"); 59 | 60 | ############################################################################### 61 | -------------------------------------------------------------------------------- /stream_set.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Vladimir Kokshenev 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for stream set directive. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | use Test::Nginx::Stream qw/ stream /; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | my $t = Test::Nginx->new() 27 | ->has(qw/stream stream_return stream_map stream_set/); 28 | 29 | $t->write_file_expand('nginx.conf', <<'EOF'); 30 | 31 | %%TEST_GLOBALS%% 32 | 33 | daemon off; 34 | 35 | events { 36 | } 37 | 38 | stream { 39 | %%TEST_GLOBALS_STREAM%% 40 | 41 | map 0 $map_var { 42 | default "original"; 43 | } 44 | 45 | server { 46 | listen 127.0.0.1:8082; 47 | return $map_var:$set_var; 48 | 49 | set $set_var $map_var; 50 | set $map_var "new"; 51 | } 52 | 53 | server { 54 | listen 127.0.0.1:8083; 55 | return $set_var; 56 | } 57 | } 58 | 59 | EOF 60 | 61 | $t->run()->plan(2); 62 | 63 | ############################################################################### 64 | 65 | is(stream('127.0.0.1:' . port(8082))->read(), 'new:original', 'set'); 66 | is(stream('127.0.0.1:' . port(8083))->read(), '', 'uninitialized variable'); 67 | 68 | ############################################################################### 69 | -------------------------------------------------------------------------------- /stream_udp_wildcard.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for stream proxy module with datagrams, source address selection. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | use Test::Nginx::Stream qw/ dgram /; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | plan(skip_all => '127.0.0.2 local address required') 27 | unless defined IO::Socket::INET->new( LocalAddr => '127.0.0.2' ); 28 | 29 | plan(skip_all => 'listen on wildcard address') 30 | unless $ENV{TEST_NGINX_UNSAFE}; 31 | 32 | my $t = Test::Nginx->new()->has(qw/stream stream_return udp/)->plan(1) 33 | ->write_file_expand('nginx.conf', <<'EOF'); 34 | 35 | %%TEST_GLOBALS%% 36 | 37 | daemon off; 38 | 39 | events { 40 | } 41 | 42 | stream { 43 | %%TEST_GLOBALS_STREAM%% 44 | 45 | server { 46 | listen %%PORT_8999_UDP%% udp; 47 | return $server_addr; 48 | } 49 | } 50 | 51 | EOF 52 | 53 | $t->run(); 54 | 55 | ############################################################################### 56 | 57 | my $s = dgram( 58 | LocalAddr => '127.0.0.1', 59 | PeerAddr => '127.0.0.2:' . port(8999) 60 | ); 61 | 62 | is($s->io('test'), '127.0.0.2', 'stream udp wildcard'); 63 | 64 | ############################################################################### 65 | -------------------------------------------------------------------------------- /map_complex.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for map module with complex value. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http map rewrite/); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | map $args $x { 40 | var foo:$y; 41 | var2 $y:foo; 42 | default foo:$y; 43 | } 44 | 45 | map $args $y { 46 | default bar; 47 | same baz; 48 | } 49 | 50 | server { 51 | listen 127.0.0.1:8080; 52 | server_name localhost; 53 | 54 | location / { 55 | add_header X-Foo $x; 56 | return 204; 57 | } 58 | } 59 | } 60 | 61 | EOF 62 | 63 | $t->run()->plan(3); 64 | 65 | ############################################################################### 66 | 67 | like(http_get('/?var'), qr/foo:bar/, 'map cv'); 68 | like(http_get('/?var2'), qr/bar:foo/, 'map cv 2'); 69 | like(http_get('/?same'), qr/foo:baz/, 'map cv key'); 70 | 71 | ############################################################################### 72 | -------------------------------------------------------------------------------- /worker_shutdown_timeout_stream.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for worker_shutdown_timeout directive within the stream module. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | use Test::Nginx::SMTP; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | local $SIG{PIPE} = 'IGNORE'; 27 | 28 | my $t = Test::Nginx->new()->has(qw/stream/)->plan(3) 29 | ->write_file_expand('nginx.conf', <<'EOF'); 30 | 31 | %%TEST_GLOBALS%% 32 | 33 | daemon off; 34 | worker_shutdown_timeout 10ms; 35 | 36 | events { 37 | } 38 | 39 | stream { 40 | %%TEST_GLOBALS_STREAM%% 41 | 42 | server { 43 | listen 127.0.0.1:8025; 44 | proxy_pass 127.0.0.1:8026; 45 | } 46 | } 47 | 48 | EOF 49 | 50 | $t->run_daemon(\&Test::Nginx::SMTP::smtp_test_daemon); 51 | $t->run()->waitforsocket('127.0.0.1:' . port(8026)); 52 | 53 | ############################################################################### 54 | 55 | my $s = Test::Nginx::SMTP->new(); 56 | $s->check(qr/^220 /, "greeting"); 57 | 58 | $s->send('EHLO example.com'); 59 | $s->check(qr/^250 /, "ehlo"); 60 | 61 | $t->reload(); 62 | 63 | ok($s->can_read(), 'stream connection shutdown'); 64 | 65 | undef $s; 66 | 1; 67 | 68 | ############################################################################### 69 | -------------------------------------------------------------------------------- /addition_buffered.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for addition module with buffered data from other filters. 7 | 8 | # In particular, sub filter may have a partial match buffered. 9 | 10 | ############################################################################### 11 | 12 | use warnings; 13 | use strict; 14 | 15 | use Test::More; 16 | 17 | BEGIN { use FindBin; chdir($FindBin::Bin); } 18 | 19 | use lib 'lib'; 20 | use Test::Nginx; 21 | 22 | ############################################################################### 23 | 24 | select STDERR; $| = 1; 25 | select STDOUT; $| = 1; 26 | 27 | my $t = Test::Nginx->new()->has(qw/http proxy sub addition/)->plan(1); 28 | 29 | $t->write_file_expand('nginx.conf', <<'EOF'); 30 | 31 | %%TEST_GLOBALS%% 32 | 33 | daemon off; 34 | 35 | events { 36 | } 37 | 38 | http { 39 | %%TEST_GLOBALS_HTTP%% 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | server_name localhost; 44 | 45 | location / { } 46 | location /proxy/ { 47 | sub_filter foo bar; 48 | add_after_body /after.html; 49 | proxy_pass http://127.0.0.1:8080/; 50 | } 51 | } 52 | } 53 | 54 | EOF 55 | 56 | $t->write_file('after.html', 'after'); 57 | $t->write_file('body.html', 'XXXXX'); 58 | 59 | $t->run(); 60 | 61 | ############################################################################### 62 | 63 | # if data is buffered, there should be no interleaved data in output 64 | 65 | like(http_get('/proxy/body.html'), qr/^XXXXXafter$/m, 'request'); 66 | 67 | ############################################################################### 68 | -------------------------------------------------------------------------------- /perl_ssi.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | # Tests for embedded perl module. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx; 18 | 19 | ############################################################################### 20 | 21 | select STDERR; $| = 1; 22 | select STDOUT; $| = 1; 23 | 24 | my $t = Test::Nginx->new()->has(qw/http perl ssi/)->plan(3) 25 | ->write_file_expand('nginx.conf', <<'EOF'); 26 | 27 | %%TEST_GLOBALS%% 28 | 29 | daemon off; 30 | 31 | events { 32 | } 33 | 34 | http { 35 | %%TEST_GLOBALS_HTTP%% 36 | 37 | server { 38 | listen 127.0.0.1:8080; 39 | server_name localhost; 40 | 41 | location / { 42 | ssi on; 43 | } 44 | 45 | location /dummy { 46 | perl 'sub foo { my $r = shift; $r->print(join ",", @_); }'; 47 | } 48 | } 49 | } 50 | 51 | EOF 52 | 53 | $t->write_file('t1.html', 'XX'); 54 | $t->write_file('t2.html', 'XX'); 55 | $t->write_file('noargs.html', 'XX'); 56 | 57 | $t->run(); 58 | 59 | ############################################################################### 60 | 61 | like(http_get('/t1.html'), qr/Xarg1X/, 'perl ssi response'); 62 | like(http_get('/t2.html'), qr/Xarg1,arg2X/, 'perl ssi two args'); 63 | like(http_get('/noargs.html'), qr/XX/, 'perl ssi noargs'); 64 | 65 | ############################################################################### 66 | -------------------------------------------------------------------------------- /stream_access_log_escape.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Stream tests for access_log with escape parameter. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/stream stream_map stream_return/) 26 | ->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | stream { 36 | %%TEST_GLOBALS_STREAM%% 37 | 38 | map $pid $a { 39 | default '" \ "'; 40 | } 41 | map $pid $b { 42 | default "foo"; 43 | } 44 | 45 | log_format json escape=json $a$b$upstream_addr; 46 | log_format default escape=default $a$b$upstream_addr; 47 | 48 | server { 49 | listen 127.0.0.1:8080; 50 | return ok; 51 | 52 | access_log %%TESTDIR%%/json.log json; 53 | access_log %%TESTDIR%%/test.log default; 54 | } 55 | } 56 | 57 | EOF 58 | 59 | $t->run()->plan(2); 60 | 61 | ############################################################################### 62 | 63 | http_get('/'); 64 | 65 | $t->stop(); 66 | 67 | is($t->read_file('json.log'), '\" \\\\ \"foo' . "\n", 'json'); 68 | is($t->read_file('test.log'), '\x22 \x5C \x22foo-' . "\n", 'default'); 69 | 70 | ############################################################################### 71 | -------------------------------------------------------------------------------- /http_method.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for HTTP methods. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http rewrite/)->plan(4) 26 | ->write_file_expand('nginx.conf', <<'EOF')->run(); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | http { 36 | %%TEST_GLOBALS_HTTP%% 37 | 38 | server { 39 | listen 127.0.0.1:8080; 40 | server_name localhost; 41 | 42 | location / { 43 | return 200; 44 | } 45 | } 46 | } 47 | 48 | EOF 49 | 50 | ############################################################################### 51 | 52 | like(http(<has_version('1.29.3'); 60 | 61 | like(http(<new()->has(qw/http limit_req/)->plan(4); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | limit_req_zone $binary_remote_addr zone=one:1m rate=30r/m; 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | server_name localhost; 44 | 45 | location / { 46 | limit_req zone=one delay=1 burst=2; 47 | add_header X-Time $request_time; 48 | } 49 | } 50 | } 51 | 52 | EOF 53 | 54 | $t->write_file('delay.html', 'XtestX'); 55 | $t->run(); 56 | 57 | ############################################################################### 58 | 59 | like(http_get('/delay.html'), qr/^HTTP\/1.. 200 /m, 'request'); 60 | like(http_get('/delay.html'), qr/X-Time: 0.000/, 'not yet delayed'); 61 | my $s = http_get('/delay.html', start => 1, sleep => 0.2); 62 | like(http_get('/delay.html'), qr/^HTTP\/1.. 503 /m, 'rejected'); 63 | like(http_end($s), qr/^HTTP\/1.. 200 .*X-Time: (?!0.000)/ms, 'delayed'); 64 | 65 | ############################################################################### 66 | -------------------------------------------------------------------------------- /http_keepalive_shutdown.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for http keepalive connections on worker shutdown. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx qw/ :DEFAULT http_end /; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http limit_req/)->plan(1); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | limit_req_zone $binary_remote_addr zone=one:1m rate=1r/s; 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | server_name localhost; 44 | 45 | location / { 46 | limit_req zone=one burst=5; 47 | } 48 | } 49 | } 50 | 51 | EOF 52 | 53 | $t->write_file('test.html', 'XtestX'); 54 | $t->run(); 55 | 56 | ############################################################################### 57 | 58 | # signaling on graceful shutdown to client that keepalive connection is closing 59 | 60 | my $s = http(< 1); 61 | HEAD /test.html HTTP/1.1 62 | Host: localhost 63 | 64 | HEAD /test.html HTTP/1.1 65 | Host: localhost 66 | 67 | EOF 68 | 69 | select undef, undef, undef, 0.1; 70 | 71 | $t->stop(); 72 | 73 | like(http_end($s), qr/Connection: close/, 'connection close on exit'); 74 | 75 | ############################################################################### 76 | -------------------------------------------------------------------------------- /proxy_bind_transparent.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for http proxy_bind transparent. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | plan(skip_all => 'win32') if $^O eq 'MSWin32'; 26 | plan(skip_all => 'must be root') if $> != 0; 27 | plan(skip_all => '127.0.0.2 local address required') 28 | unless defined IO::Socket::INET->new( LocalAddr => '127.0.0.2' ); 29 | 30 | my $t = Test::Nginx->new()->has(qw/http proxy/) 31 | ->write_file_expand('nginx.conf', <<'EOF'); 32 | 33 | %%TEST_GLOBALS%% 34 | 35 | daemon off; 36 | user root wheel; 37 | 38 | events { 39 | } 40 | 41 | http { 42 | %%TEST_GLOBALS_HTTP%% 43 | 44 | server { 45 | listen 127.0.0.1:8080; 46 | server_name localhost; 47 | 48 | location / { 49 | proxy_bind 127.0.0.2 transparent; 50 | proxy_pass http://127.0.0.1:8081/; 51 | } 52 | } 53 | 54 | server { 55 | listen 127.0.0.1:8081; 56 | server_name localhost; 57 | 58 | location / { 59 | add_header X-IP $remote_addr always; 60 | } 61 | } 62 | } 63 | 64 | EOF 65 | 66 | $t->run()->plan(1); 67 | 68 | ############################################################################### 69 | 70 | like(http_get('/'), qr/X-IP: 127.0.0.2/, 'transparent'); 71 | 72 | ############################################################################### 73 | -------------------------------------------------------------------------------- /gzip_flush.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | # Tests for gzip filter module. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx qw/ :DEFAULT :gzip /; 18 | 19 | ############################################################################### 20 | 21 | select STDERR; $| = 1; 22 | select STDOUT; $| = 1; 23 | 24 | my $t = Test::Nginx->new()->has(qw/http gzip perl/)->plan(2) 25 | ->write_file_expand('nginx.conf', <<'EOF'); 26 | 27 | %%TEST_GLOBALS%% 28 | 29 | daemon off; 30 | 31 | events { 32 | } 33 | 34 | http { 35 | %%TEST_GLOBALS_HTTP%% 36 | 37 | server { 38 | listen 127.0.0.1:8080; 39 | server_name localhost; 40 | 41 | gzip on; 42 | gzip_min_length 0; 43 | 44 | location / { 45 | perl 'sub { 46 | my $r = shift; 47 | $r->send_http_header("text/html"); 48 | return OK if $r->header_only; 49 | $r->print("DA"); 50 | $r->flush(); 51 | $r->flush(); 52 | $r->print("TA"); 53 | return OK; 54 | }'; 55 | } 56 | } 57 | } 58 | 59 | EOF 60 | 61 | $t->run(); 62 | 63 | ############################################################################### 64 | 65 | like(http_get('/'), qr/DATA/, 'request with flush'); 66 | 67 | # gzip filter wasn't able to handle empty flush buffers, see 68 | # http://nginx.org/pipermail/nginx/2010-November/023693.html 69 | 70 | http_gzip_like(http_gzip_request('/'), qr/DATA/, 'gzip request with flush'); 71 | 72 | ############################################################################### 73 | -------------------------------------------------------------------------------- /map_volatile.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for map module with volatile. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http map/); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | map $uri $uri_cached { 40 | /1/ /1/redirect; 41 | /1/redirect uncached; 42 | } 43 | 44 | map $uri $uri_uncached { 45 | volatile; 46 | 47 | /2/ /2/redirect; 48 | /2/redirect uncached; 49 | } 50 | 51 | server { 52 | listen 127.0.0.1:8080; 53 | server_name localhost; 54 | 55 | location /1 { 56 | index $uri_cached; 57 | } 58 | location /1/redirect { 59 | add_header X-URI $uri_cached always; 60 | } 61 | 62 | location /2 { 63 | index $uri_uncached; 64 | } 65 | location /2/redirect { 66 | add_header X-URI $uri_uncached always; 67 | } 68 | } 69 | } 70 | 71 | EOF 72 | 73 | $t->run()->plan(2); 74 | 75 | ############################################################################### 76 | 77 | like(http_get('/1/'), qr!X-URI: /1/redirect!, 'map'); 78 | like(http_get('/2/'), qr/X-URI: uncached/, 'map volatile'); 79 | 80 | ############################################################################### 81 | -------------------------------------------------------------------------------- /perl_sleep.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | # Tests for embedded perl module, $r->sleep(). 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx; 18 | 19 | ############################################################################### 20 | 21 | select STDERR; $| = 1; 22 | select STDOUT; $| = 1; 23 | 24 | my $t = Test::Nginx->new()->has(qw/http perl ssi/)->plan(2) 25 | ->write_file_expand('nginx.conf', <<'EOF'); 26 | 27 | %%TEST_GLOBALS%% 28 | 29 | daemon off; 30 | 31 | events { 32 | } 33 | 34 | http { 35 | %%TEST_GLOBALS_HTTP%% 36 | 37 | server { 38 | listen 127.0.0.1:8080; 39 | server_name localhost; 40 | 41 | location / { 42 | ssi on; 43 | sendfile_max_chunk 100; 44 | postpone_output 0; 45 | } 46 | 47 | location /sleep { 48 | perl 'sub { 49 | my $r = shift; 50 | 51 | $r->sleep(100, sub { 52 | my $r = shift; 53 | $r->send_http_header; 54 | $r->print("it works"); 55 | return OK; 56 | }); 57 | 58 | return OK; 59 | }'; 60 | } 61 | } 62 | } 63 | 64 | EOF 65 | 66 | $t->write_file('subrequest.html', ('x' x 200) . 67 | 'XX'); 68 | 69 | $t->run(); 70 | 71 | ############################################################################### 72 | 73 | like(http_get('/sleep'), qr/works/, 'perl sleep'); 74 | like(http_get('/subrequest.html'), qr/works/, 'perl sleep in subrequest'); 75 | 76 | ############################################################################### 77 | -------------------------------------------------------------------------------- /proxy_cache_min_free.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for http proxy cache, min_free parameter. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http proxy cache/) 26 | ->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | http { 36 | %%TEST_GLOBALS_HTTP%% 37 | 38 | proxy_cache_path %%TESTDIR%%/cache levels=1:2 min_free=4k 39 | keys_zone=NAME:1m; 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | server_name localhost; 44 | 45 | location / { 46 | proxy_pass http://127.0.0.1:8081; 47 | 48 | proxy_cache NAME; 49 | 50 | proxy_cache_valid any 1m; 51 | 52 | add_header X-Cache-Status $upstream_cache_status; 53 | } 54 | } 55 | 56 | server { 57 | listen 127.0.0.1:8081; 58 | server_name localhost; 59 | 60 | location / { } 61 | } 62 | } 63 | 64 | EOF 65 | 66 | $t->write_file('t.html', 'SEE-THIS'); 67 | $t->run()->plan(2); 68 | 69 | ############################################################################### 70 | 71 | like(http_get('/t.html'), qr/SEE-THIS/, 'proxy request'); 72 | 73 | $t->write_file('t.html', 'NOOP'); 74 | like(http_get('/t.html'), qr/SEE-THIS/, 'proxy request cached'); 75 | 76 | ############################################################################### 77 | -------------------------------------------------------------------------------- /stream_proxy_bind.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Andrey Zelenkov 4 | # (C) Nginx, Inc. 5 | 6 | # Test for stream proxy_bind directive. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | plan(skip_all => 'win32') if $^O eq 'MSWin32'; 26 | plan(skip_all => '127.0.0.2 local address required') 27 | unless defined IO::Socket::INET->new( LocalAddr => '127.0.0.2' ); 28 | 29 | my $t = Test::Nginx->new()->has(qw/http proxy stream/)->plan(1) 30 | ->write_file_expand('nginx.conf', <<'EOF'); 31 | 32 | %%TEST_GLOBALS%% 33 | 34 | daemon off; 35 | 36 | events { 37 | } 38 | 39 | stream { 40 | %%TEST_GLOBALS_STREAM%% 41 | 42 | server { 43 | listen 127.0.0.1:8081; 44 | proxy_bind 127.0.0.2; 45 | proxy_pass 127.0.0.1:8082; 46 | } 47 | } 48 | 49 | http { 50 | %%TEST_GLOBALS_HTTP%% 51 | 52 | server { 53 | listen 127.0.0.1:8080; 54 | server_name localhost; 55 | 56 | location / { 57 | proxy_pass http://127.0.0.1:8081; 58 | } 59 | } 60 | 61 | server { 62 | listen 127.0.0.1:8082; 63 | 64 | location / { 65 | add_header X-IP $remote_addr; 66 | } 67 | } 68 | } 69 | 70 | EOF 71 | 72 | $t->write_file('index.html', ''); 73 | $t->run(); 74 | 75 | ############################################################################### 76 | 77 | like(http_get('/'), qr/X-IP: 127.0.0.2/, 'bind'); 78 | 79 | ############################################################################### 80 | -------------------------------------------------------------------------------- /proxy_bind_transparent_capability.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for http proxy_bind transparent with Linux CAP_NET_RAW capability. 7 | # Ensure that such configuration isn't broken under a non-priveleged user. 8 | 9 | ############################################################################### 10 | 11 | use warnings; 12 | use strict; 13 | 14 | use Test::More; 15 | 16 | BEGIN { use FindBin; chdir($FindBin::Bin); } 17 | 18 | use lib 'lib'; 19 | use Test::Nginx; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | plan(skip_all => 'no linux capability') if $^O ne 'linux'; 27 | plan(skip_all => 'must be root') if $> != 0; 28 | plan(skip_all => '127.0.0.2 local address required') 29 | unless defined IO::Socket::INET->new( LocalAddr => '127.0.0.2' ); 30 | 31 | my $t = Test::Nginx->new()->has(qw/http proxy/) 32 | ->write_file_expand('nginx.conf', <<'EOF'); 33 | 34 | %%TEST_GLOBALS%% 35 | 36 | daemon off; 37 | 38 | events { 39 | } 40 | 41 | http { 42 | %%TEST_GLOBALS_HTTP%% 43 | 44 | server { 45 | listen 127.0.0.1:8080; 46 | server_name localhost; 47 | 48 | location / { 49 | proxy_bind 127.0.0.2 transparent; 50 | proxy_pass http://127.0.0.1:8081/; 51 | } 52 | } 53 | 54 | server { 55 | listen 127.0.0.1:8081; 56 | server_name localhost; 57 | 58 | location / { 59 | add_header X-IP $remote_addr always; 60 | } 61 | } 62 | } 63 | 64 | EOF 65 | 66 | $t->run()->plan(1); 67 | 68 | ############################################################################### 69 | 70 | like(http_get('/'), qr/X-IP: 127.0.0.2/, 'transparent'); 71 | 72 | ############################################################################### 73 | -------------------------------------------------------------------------------- /stream_split_clients.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for stream split_client module. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | use Test::Nginx::Stream qw/ stream /; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | my $t = Test::Nginx->new()->has(qw/stream stream_split_clients stream_return/); 27 | 28 | $t->write_file_expand('nginx.conf', <<'EOF'); 29 | 30 | %%TEST_GLOBALS%% 31 | 32 | daemon off; 33 | 34 | events { 35 | } 36 | 37 | stream { 38 | %%TEST_GLOBALS_STREAM%% 39 | 40 | split_clients $connection $variant { 41 | 51.2% "first"; 42 | 10% "second"; 43 | * "third"; 44 | } 45 | 46 | server { 47 | listen 127.0.0.1:8080; 48 | return $variant; 49 | } 50 | } 51 | 52 | EOF 53 | 54 | $t->run(); 55 | $t->plan(1); 56 | 57 | ############################################################################### 58 | 59 | # NB: split_clients distribution is a subject to implementation details 60 | 61 | like(many('/', 20), qr/first: 12, second: 2, third: 6/, 'split'); 62 | 63 | ############################################################################### 64 | 65 | sub many { 66 | my ($uri, $count) = @_; 67 | my %dist; 68 | 69 | for (1 .. $count) { 70 | if (my $data = stream('127.0.0.1:' . port(8080))->read()) { 71 | $dist{$data} = 0 unless defined $data; 72 | $dist{$data}++; 73 | } 74 | } 75 | 76 | return join ', ', map { $_ . ": " . $dist{$_} } sort keys %dist; 77 | } 78 | 79 | ############################################################################### 80 | -------------------------------------------------------------------------------- /upstream_zone.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for upstream zone. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http proxy upstream_zone/)->plan(2) 26 | ->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | http { 36 | %%TEST_GLOBALS_HTTP%% 37 | 38 | upstream u { 39 | zone u 1m; 40 | server 127.0.0.1:8081; 41 | } 42 | 43 | upstream u2 { 44 | zone u; 45 | server 127.0.0.1:8081 down; 46 | server 127.0.0.1:8081 backup down; 47 | } 48 | 49 | server { 50 | listen 127.0.0.1:8081; 51 | server_name localhost; 52 | 53 | location / {} 54 | } 55 | 56 | server { 57 | listen 127.0.0.1:8080; 58 | server_name localhost; 59 | 60 | add_header X-Name $upstream_addr always; 61 | 62 | location / { 63 | proxy_pass http://u/; 64 | } 65 | 66 | location /down { 67 | proxy_pass http://u2/; 68 | } 69 | } 70 | } 71 | 72 | EOF 73 | 74 | $t->write_file('index.html', ''); 75 | $t->run(); 76 | 77 | ############################################################################### 78 | 79 | my $p = port(8081); 80 | 81 | like(http_get('/'), qr/X-Name: 127.0.0.1:$p/, 'upstream name'); 82 | like(http_get('/down'), qr/X-Name: u2/, 'no live upstreams'); 83 | 84 | ############################################################################### 85 | -------------------------------------------------------------------------------- /gunzip_perl.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | # Tests for gunzip filter module with perl module. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx qw/ :DEFAULT :gzip /; 18 | 19 | ############################################################################### 20 | 21 | select STDERR; $| = 1; 22 | select STDOUT; $| = 1; 23 | 24 | eval { require IO::Compress::Gzip; }; 25 | plan(skip_all => "IO::Compress::Gzip not found") if $@; 26 | 27 | my $t = Test::Nginx->new()->has(qw/http gunzip perl/)->plan(2) 28 | ->write_file_expand('nginx.conf', <<'EOF'); 29 | 30 | %%TEST_GLOBALS%% 31 | 32 | daemon off; 33 | 34 | events { 35 | } 36 | 37 | http { 38 | %%TEST_GLOBALS_HTTP%% 39 | 40 | server { 41 | listen 127.0.0.1:8080; 42 | server_name localhost; 43 | 44 | gunzip on; 45 | 46 | location / { 47 | perl 'sub { 48 | my $r = shift; 49 | $r->header_out("Content-Encoding", "gzip"); 50 | $r->send_http_header("text/plain"); 51 | return OK if $r->header_only; 52 | use IO::Compress::Gzip; 53 | my $in = "TEST"; 54 | my $out; 55 | IO::Compress::Gzip::gzip(\\$in => \\$out); 56 | $r->print($out); 57 | return OK; 58 | }'; 59 | } 60 | } 61 | } 62 | 63 | EOF 64 | 65 | $t->run(); 66 | 67 | ############################################################################### 68 | 69 | http_gzip_like(http_gzip_request('/'), qr/TEST/, 'perl response gzipped'); 70 | like(http_get('/'), qr/TEST/, 'perl response gunzipped'); 71 | 72 | ############################################################################### 73 | -------------------------------------------------------------------------------- /debug_connection.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Nginx, Inc. 4 | 5 | # Tests for debug_connection. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx; 18 | 19 | ############################################################################### 20 | 21 | select STDERR; $| = 1; 22 | select STDOUT; $| = 1; 23 | 24 | my $t = Test::Nginx->new()->has(qw/http --with-debug proxy/); 25 | 26 | $t->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | debug_connection ::1; 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | error_log %%TESTDIR%%/debug1.log alert; 40 | error_log %%TESTDIR%%/debug2.log alert; 41 | 42 | server { 43 | listen 127.0.0.1:8080; 44 | listen [::1]:%%PORT_8080%%; 45 | server_name localhost; 46 | 47 | location /debug { 48 | proxy_pass http://[::1]:%%PORT_8080%%/; 49 | } 50 | } 51 | } 52 | 53 | EOF 54 | 55 | $t->try_run('no inet6 support')->plan(5); 56 | 57 | ############################################################################### 58 | 59 | http_get('/'); 60 | 61 | select undef, undef, undef, 0.1; 62 | is($t->read_file('debug1.log'), '', 'no debug_connection file 1'); 63 | is($t->read_file('debug2.log'), '', 'no debug_connection file 2'); 64 | 65 | http_get('/debug'); 66 | 67 | select undef, undef, undef, 0.1; 68 | like($t->read_file('debug1.log'), qr/\[debug\]/, 'debug_connection file 1'); 69 | like($t->read_file('debug2.log'), qr/\[debug\]/, 'debug_connection file 2'); 70 | is($t->read_file('debug1.log'), $t->read_file('debug2.log'), 71 | 'debug_connection file1 file2 match'); 72 | 73 | ############################################################################### 74 | -------------------------------------------------------------------------------- /proxy_protocol_ipv6.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for haproxy protocol on IPv6 listening socket. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http realip stream/); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | server { 40 | listen [::1]:%%PORT_8080%% proxy_protocol; 41 | server_name localhost; 42 | 43 | add_header X-IP $remote_addr; 44 | add_header X-PP $proxy_protocol_addr; 45 | real_ip_header proxy_protocol; 46 | 47 | location / { } 48 | location /pp { 49 | set_real_ip_from ::1/128; 50 | error_page 404 =200 /t; 51 | } 52 | } 53 | } 54 | 55 | stream { 56 | %%TEST_GLOBALS_STREAM%% 57 | 58 | server { 59 | listen 127.0.0.1:8080; 60 | proxy_pass [::1]:%%PORT_8080%%; 61 | 62 | proxy_protocol on; 63 | } 64 | } 65 | 66 | EOF 67 | 68 | $t->write_file('t', 'SEE-THIS'); 69 | $t->try_run('no inet6 support')->plan(3); 70 | 71 | ############################################################################### 72 | 73 | my $r = http_get('/t'); 74 | like($r, qr/X-IP: ::1/, 'realip'); 75 | like($r, qr/X-PP: 127.0.0.1/, 'proxy protocol'); 76 | 77 | $r = http_get('/pp'); 78 | like($r, qr/X-IP: 127.0.0.1/, 'proxy protocol realip'); 79 | 80 | ############################################################################### 81 | -------------------------------------------------------------------------------- /debug_connection_unix.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Nginx, Inc. 4 | 5 | # Tests for debug_connection with unix socket. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx; 18 | 19 | ############################################################################### 20 | 21 | select STDERR; $| = 1; 22 | select STDOUT; $| = 1; 23 | 24 | my $t = Test::Nginx->new()->has(qw/http --with-debug unix proxy/); 25 | 26 | $t->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | debug_connection unix:; 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | error_log %%TESTDIR%%/debug1.log alert; 40 | error_log %%TESTDIR%%/debug2.log alert; 41 | 42 | server { 43 | listen 127.0.0.1:8080; 44 | listen unix:%%TESTDIR%%/unix.sock; 45 | server_name localhost; 46 | 47 | location /debug { 48 | proxy_pass http://unix:%%TESTDIR%%/unix.sock:/; 49 | } 50 | } 51 | } 52 | 53 | EOF 54 | 55 | $t->run()->plan(5); 56 | 57 | ############################################################################### 58 | 59 | http_get('/'); 60 | 61 | select undef, undef, undef, 0.1; 62 | is($t->read_file('debug1.log'), '', 'no debug_connection file 1'); 63 | is($t->read_file('debug2.log'), '', 'no debug_connection file 2'); 64 | 65 | http_get('/debug'); 66 | 67 | select undef, undef, undef, 0.1; 68 | like($t->read_file('debug1.log'), qr/\[debug\]/, 'debug_connection file 1'); 69 | like($t->read_file('debug2.log'), qr/\[debug\]/, 'debug_connection file 2'); 70 | is($t->read_file('debug1.log'), $t->read_file('debug2.log'), 71 | 'debug_connection file1 file2 match'); 72 | 73 | ############################################################################### 74 | -------------------------------------------------------------------------------- /post_action.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for nginx post_action directive. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http proxy/)->plan(5); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | server { 40 | listen 127.0.0.1:8080; 41 | server_name localhost; 42 | 43 | location / { 44 | post_action /post.html; 45 | } 46 | 47 | location /post.html { 48 | # static 49 | } 50 | 51 | location /remote { 52 | post_action /post.remote; 53 | } 54 | 55 | location /post.remote { 56 | proxy_pass http://127.0.0.1:8080/post.html; 57 | } 58 | } 59 | } 60 | 61 | EOF 62 | 63 | $t->write_file('index.html', 'SEE-THIS'); 64 | $t->write_file('post.html', 'HIDDEN'); 65 | $t->write_file('remote', 'SEE-THIS'); 66 | 67 | $t->run(); 68 | 69 | ############################################################################### 70 | 71 | like(http_get('/'), qr/SEE-THIS/m, 'post action'); 72 | unlike(http_get('/'), qr/HIDDEN/m, 'no additional body'); 73 | 74 | like(http_get('/remote'), qr/SEE-THIS/m, 'post action proxy'); 75 | unlike(http_get('/remote'), qr/HIDDEN/m, 'no additional body proxy'); 76 | 77 | $t->stop(); 78 | 79 | like(`cat ${\($t->testdir())}/access.log`, qr/post/, 'post action in logs'); 80 | 81 | ############################################################################### 82 | -------------------------------------------------------------------------------- /proxy_set_body.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | # Tests for proxy_set_body. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx; 18 | 19 | ############################################################################### 20 | 21 | select STDERR; $| = 1; 22 | select STDOUT; $| = 1; 23 | 24 | my $t = Test::Nginx->new()->has(qw/http proxy rewrite/)->plan(2) 25 | ->write_file_expand('nginx.conf', <<'EOF'); 26 | 27 | %%TEST_GLOBALS%% 28 | 29 | daemon off; 30 | 31 | events { 32 | } 33 | 34 | http { 35 | %%TEST_GLOBALS_HTTP%% 36 | 37 | server { 38 | listen 127.0.0.1:8080; 39 | server_name localhost; 40 | 41 | location / { 42 | proxy_pass http://127.0.0.1:8080/body; 43 | proxy_set_body "body"; 44 | } 45 | 46 | location /p1 { 47 | proxy_pass http://127.0.0.1:8080/x1; 48 | proxy_set_body "body"; 49 | } 50 | 51 | location /p2 { 52 | proxy_pass http://127.0.0.1:8080/body; 53 | proxy_set_body "body two"; 54 | } 55 | 56 | location /x1 { 57 | add_header X-Accel-Redirect /p2; 58 | return 204; 59 | } 60 | 61 | location /body { 62 | add_header X-Body $request_body; 63 | proxy_pass http://127.0.0.1:8080/empty; 64 | } 65 | 66 | location /empty { 67 | return 204; 68 | } 69 | } 70 | } 71 | 72 | EOF 73 | 74 | $t->run(); 75 | 76 | ############################################################################### 77 | 78 | like(http_get('/'), qr/X-Body: body/, 'proxy_set_body'); 79 | like(http_get('/p1'), qr/X-Body: body two/, 'proxy_set_body twice'); 80 | 81 | ############################################################################### 82 | -------------------------------------------------------------------------------- /stream_map.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for stream map module. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | use Test::Nginx::Stream qw/ stream /; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | my $t = Test::Nginx->new()->has(qw/stream stream_return stream_map/) 27 | ->has(qw/http rewrite/); 28 | 29 | $t->write_file_expand('nginx.conf', <<'EOF'); 30 | 31 | %%TEST_GLOBALS%% 32 | 33 | daemon off; 34 | 35 | events { 36 | } 37 | 38 | stream { 39 | %%TEST_GLOBALS_STREAM%% 40 | 41 | map $server_port $x { 42 | %%PORT_8080%% literal; 43 | default default; 44 | ~(%%PORT_8082%%) $1; 45 | ~(?P%%PORT_8083%%) $ncap; 46 | } 47 | 48 | server { 49 | listen 127.0.0.1:8080; 50 | listen 127.0.0.1:8081; 51 | listen 127.0.0.1:8082; 52 | listen 127.0.0.1:8083; 53 | return $x; 54 | } 55 | 56 | server { 57 | listen 127.0.0.1:8084; 58 | return $x:${x}; 59 | } 60 | } 61 | 62 | EOF 63 | 64 | $t->run()->plan(5); 65 | 66 | ############################################################################### 67 | 68 | is(stream('127.0.0.1:' . port(8080))->read(), 'literal', 'literal'); 69 | is(stream('127.0.0.1:' . port(8081))->read(), 'default', 'default'); 70 | is(stream('127.0.0.1:' . port(8082))->read(), port(8082), 'capture'); 71 | is(stream('127.0.0.1:' . port(8083))->read(), port(8083), 'named capture'); 72 | is(stream('127.0.0.1:' . port(8084))->read(), 'default:default', 'braces'); 73 | 74 | ############################################################################### 75 | -------------------------------------------------------------------------------- /stream_udp_stream.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Nginx, Inc. 4 | 5 | # Tests for UDP stream. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx; 18 | use Test::Nginx::Stream qw/ dgram /; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/stream stream_return udp/)->plan(8) 26 | ->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | stream { 36 | %%TEST_GLOBALS_STREAM%% 37 | 38 | proxy_timeout 1s; 39 | 40 | server { 41 | listen 127.0.0.1:%%PORT_8980_UDP%% udp; 42 | proxy_pass 127.0.0.1:%%PORT_8981_UDP%%; 43 | } 44 | 45 | server { 46 | listen 127.0.0.1:%%PORT_8981_UDP%% udp; 47 | return $remote_port; 48 | } 49 | } 50 | 51 | EOF 52 | 53 | $t->run(); 54 | 55 | ############################################################################### 56 | 57 | my $s = dgram('127.0.0.1:' . port(8980)); 58 | my $data = $s->io('1', read_timeout => 0.5); 59 | isnt($data, '', 'udp_stream response 1'); 60 | 61 | my $s2 = dgram('127.0.0.1:' . port(8980)); 62 | my $data2 = $s2->io('1', read_timeout => 0.5); 63 | isnt($data2, '', 'udp_stream response 2'); 64 | 65 | isnt($data, $data2, 'udp_stream two sessions'); 66 | 67 | is($s->io('1'), $data, 'udp_stream session 1'); 68 | is($s->io('1'), $data, 'udp_stream session 2'); 69 | 70 | is($s2->io('1'), $data2, 'udp_stream another session 1'); 71 | is($s2->io('1'), $data2, 'udp_stream another session 2'); 72 | 73 | select undef, undef, undef, 1.1; 74 | 75 | isnt($s->io('1'), $data, 'udp_stream new session'); 76 | 77 | ############################################################################### 78 | -------------------------------------------------------------------------------- /geo_volatile.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for geo module with volatile. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http rewrite geo/); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | geo $arg_ip $uri_cached { 40 | 192.0.2.1 /1/redirect; 41 | 192.0.2.2 uncached; 42 | } 43 | 44 | geo $arg_ip $uri_uncached { 45 | volatile; 46 | 47 | 192.0.2.1 /2/redirect; 48 | 192.0.2.2 uncached; 49 | } 50 | 51 | server { 52 | listen 127.0.0.1:8080; 53 | server_name localhost; 54 | 55 | location /1 { 56 | index $uri_cached; 57 | } 58 | location /1/redirect { 59 | set $args ip=192.0.2.2; 60 | add_header X-URI $uri_cached always; 61 | } 62 | 63 | location /2 { 64 | index $uri_uncached; 65 | } 66 | location /2/redirect { 67 | set $args ip=192.0.2.2; 68 | add_header X-URI $uri_uncached always; 69 | } 70 | } 71 | } 72 | 73 | EOF 74 | 75 | $t->try_run('no geo volatile')->plan(2); 76 | 77 | ############################################################################### 78 | 79 | like(http_get('/1/?ip=192.0.2.1'), qr!X-URI: /1/redirect!, 'geo'); 80 | like(http_get('/2/?ip=192.0.2.1'), qr/X-URI: uncached/, 'geo volatile'); 81 | 82 | ############################################################################### 83 | -------------------------------------------------------------------------------- /stream_geo_binary.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Andrey Zelenkov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for stream geo module with binary base. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | use Test::Nginx::Stream qw/ stream /; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | plan(skip_all => 'long configuration parsing') unless $ENV{TEST_NGINX_UNSAFE}; 27 | 28 | my $t = Test::Nginx->new()->has(qw/stream stream_return stream_geo/); 29 | 30 | $t->write_file_expand('nginx.conf', <<'EOF'); 31 | 32 | %%TEST_GLOBALS%% 33 | 34 | daemon off; 35 | 36 | events { 37 | } 38 | 39 | stream { 40 | %%TEST_GLOBALS_STREAM%% 41 | 42 | geo $geo_base_create { 43 | ranges; 44 | include base.conf; 45 | } 46 | 47 | geo $geo_base_include { 48 | ranges; 49 | include base.conf; 50 | } 51 | 52 | server { 53 | listen 127.0.0.1:8080; 54 | return "geo_base_create:$geo_base_create 55 | geo_base_include:$geo_base_include"; 56 | } 57 | } 58 | 59 | EOF 60 | 61 | $t->write_file('base.conf', join('', map { 62 | "127." . $_/256/256 % 256 . "." . $_/256 % 256 . "." . $_ % 256 . 63 | "-127." . $_/256/256 % 256 . "." . $_/256 % 256 . "." .$_ % 256 . " " . 64 | ($_ == 1 ? "loopback" : "range$_") . ";" } (0 .. 100000))); 65 | 66 | $t->run()->plan(2); 67 | 68 | ############################################################################### 69 | 70 | my %data = stream('127.0.0.1:' . port(8080))->read() =~ /(\w+):(\w+)/g; 71 | is($data{geo_base_create}, 'loopback', 'geo binary base create'); 72 | is($data{geo_base_include}, 'loopback', 'geo binary base include'); 73 | 74 | ############################################################################### 75 | -------------------------------------------------------------------------------- /http_request_port.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for http $request_port variable. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http/); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | server { 40 | listen 127.0.0.1:8080; 41 | server_name localhost; 42 | 43 | location / { 44 | add_header X-Port $is_request_port$request_port; 45 | } 46 | } 47 | } 48 | 49 | EOF 50 | 51 | $t->write_file('index.html', ''); 52 | $t->try_run('no request_port')->plan(5); 53 | 54 | ############################################################################### 55 | 56 | unlike(http_get('/'), qr/X-Port/, 'no host'); 57 | unlike(http_host_header('localhost'), qr/X-Port/, 'no port'); 58 | like(http_absolute_path('localhost:8080'), qr/:8080/, 'absolute uri'); 59 | like(http_host_header('localhost:8080'), qr/:8080/, 'host header'); 60 | 61 | like(http(<new()->has(qw/http split_clients/)->plan(1); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | split_clients $connection $variant { 40 | 51.2% ".one"; 41 | 10% ".two"; 42 | * ".three"; 43 | } 44 | 45 | server { 46 | listen 127.0.0.1:8080; 47 | server_name localhost; 48 | 49 | location / { 50 | index index${variant}.html; 51 | } 52 | } 53 | } 54 | 55 | EOF 56 | 57 | $t->write_file('index.one.html', 'first'); 58 | $t->write_file('index.two.html', 'second'); 59 | $t->write_file('index.three.html', 'third'); 60 | 61 | $t->run(); 62 | 63 | ############################################################################### 64 | 65 | # NB: split_clients distribution is a subject to implementation details 66 | 67 | like(many('/', 20), qr/first: 12, second: 2, third: 6/, 'split'); 68 | 69 | ############################################################################### 70 | 71 | sub many { 72 | my ($uri, $count) = @_; 73 | my %dist; 74 | 75 | for (1 .. $count) { 76 | if (http_get($uri) =~ /(first|second|third)/) { 77 | $dist{$1} = 0 unless defined $dist{$1}; 78 | $dist{$1}++; 79 | } 80 | } 81 | 82 | return join ', ', map { $_ . ": " . $dist{$_} } sort keys %dist; 83 | } 84 | 85 | ############################################################################### 86 | -------------------------------------------------------------------------------- /ssl_curve.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for http ssl module, $ssl_curve variable. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new() 26 | ->has(qw/http http_ssl rewrite socket_ssl/) 27 | ->has_daemon('openssl'); 28 | 29 | $t->write_file_expand('nginx.conf', <<'EOF'); 30 | 31 | %%TEST_GLOBALS%% 32 | 33 | daemon off; 34 | 35 | events { 36 | } 37 | 38 | http { 39 | %%TEST_GLOBALS_HTTP%% 40 | 41 | ssl_certificate_key localhost.key; 42 | ssl_certificate localhost.crt; 43 | 44 | ssl_ecdh_curve prime256v1; 45 | 46 | server { 47 | listen 127.0.0.1:8443 ssl; 48 | server_name localhost; 49 | 50 | return 200 "$ssl_curve $ssl_curves"; 51 | } 52 | } 53 | 54 | EOF 55 | 56 | $t->write_file('openssl.conf', <testdir(); 65 | 66 | foreach my $name ('localhost') { 67 | system('openssl req -x509 -new ' 68 | . "-config $d/openssl.conf -subj /CN=$name/ " 69 | . "-out $d/$name.crt -keyout $d/$name.key " 70 | . ">>$d/openssl.out 2>&1") == 0 71 | or die "Can't create certificate for $name: $!\n"; 72 | } 73 | 74 | $t->run()->plan(1); 75 | 76 | ############################################################################### 77 | 78 | local $TODO = 'OpenSSL too old' 79 | unless $t->has_feature('openssl:3.0.0') 80 | or $t->has_module('BoringSSL'); 81 | 82 | like(http_get('/curve', SSL => 1), qr/^prime256v1 /m, 'ssl curve'); 83 | 84 | ############################################################################### 85 | -------------------------------------------------------------------------------- /h2_proxy_protocol.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for HTTP/2 protocol with proxy_protocol. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | use Socket qw/ CRLF /; 16 | 17 | BEGIN { use FindBin; chdir($FindBin::Bin); } 18 | 19 | use lib 'lib'; 20 | use Test::Nginx; 21 | use Test::Nginx::HTTP2; 22 | 23 | ############################################################################### 24 | 25 | select STDERR; $| = 1; 26 | select STDOUT; $| = 1; 27 | 28 | my $t = Test::Nginx->new()->has(qw/http http_v2 realip/)->plan(3) 29 | ->write_file_expand('nginx.conf', <<'EOF'); 30 | 31 | %%TEST_GLOBALS%% 32 | 33 | daemon off; 34 | 35 | events { 36 | } 37 | 38 | http { 39 | %%TEST_GLOBALS_HTTP%% 40 | 41 | server { 42 | listen 127.0.0.1:8080 proxy_protocol; 43 | server_name localhost; 44 | 45 | http2 on; 46 | 47 | location /pp { 48 | set_real_ip_from 127.0.0.1/32; 49 | real_ip_header proxy_protocol; 50 | alias %%TESTDIR%%/t.html; 51 | add_header X-PP $remote_addr; 52 | } 53 | } 54 | } 55 | 56 | EOF 57 | 58 | $t->write_file('t.html', 'SEE-THIS'); 59 | $t->run(); 60 | 61 | ############################################################################### 62 | 63 | my $proxy = 'PROXY TCP4 192.0.2.1 192.0.2.2 1234 5678' . CRLF; 64 | my $s = Test::Nginx::HTTP2->new(port(8080), proxy => $proxy); 65 | my $sid = $s->new_stream({ path => '/pp' }); 66 | my $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); 67 | 68 | my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; 69 | ok($frame, 'PROXY HEADERS frame'); 70 | is($frame->{headers}->{'x-pp'}, '192.0.2.1', 'PROXY remote addr'); 71 | 72 | # invalid PROXY protocol string 73 | 74 | $proxy = 'BOGUS TCP4 192.0.2.1 192.0.2.2 1234 5678' . CRLF; 75 | ok(!http($proxy), 'PROXY invalid protocol'); 76 | 77 | ############################################################################### 78 | -------------------------------------------------------------------------------- /proxy_ssi_body.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Test for proxied subrequest with request body in file. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | use Socket qw/ CRLF /; 16 | 17 | BEGIN { use FindBin; chdir($FindBin::Bin); } 18 | 19 | use lib 'lib'; 20 | use Test::Nginx; 21 | 22 | ############################################################################### 23 | 24 | select STDERR; $| = 1; 25 | select STDOUT; $| = 1; 26 | 27 | my $t = Test::Nginx->new()->has(qw/http proxy ssi/)->plan(1); 28 | 29 | $t->write_file_expand('nginx.conf', <<'EOF'); 30 | 31 | %%TEST_GLOBALS%% 32 | 33 | daemon off; 34 | 35 | events { 36 | } 37 | 38 | http { 39 | %%TEST_GLOBALS_HTTP%% 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | server_name localhost; 44 | 45 | location / { 46 | } 47 | 48 | location /proxy { 49 | proxy_pass http://127.0.0.1:8080/; 50 | client_body_in_file_only on; 51 | ssi on; 52 | } 53 | } 54 | } 55 | 56 | EOF 57 | 58 | $t->write_file('ssi.html', 'XX'); 59 | $t->write_file('test.html', 'YY'); 60 | 61 | $t->run(); 62 | 63 | ############################################################################### 64 | 65 | # Request body cache file is released once a response is got. 66 | # If later a subrequest tries to use body, it fails. 67 | 68 | like(http_get_body('/proxy/ssi.html', "1234567890"), qr/^XYYX$/m, 69 | 'body in file in proxied subrequest'); 70 | 71 | ############################################################################### 72 | 73 | sub http_get_body { 74 | my ($url, $body, %extra) = @_; 75 | 76 | my $p = "GET $url HTTP/1.0" . CRLF 77 | . "Host: localhost" . CRLF 78 | . "Content-Length: " . (length $body) . CRLF . CRLF 79 | . $body; 80 | 81 | return http($p, %extra); 82 | } 83 | 84 | ############################################################################### 85 | -------------------------------------------------------------------------------- /auth_delay.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for auth_delay directive using auth basic module. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | use MIME::Base64; 16 | 17 | BEGIN { use FindBin; chdir($FindBin::Bin); } 18 | 19 | use lib 'lib'; 20 | use Test::Nginx; 21 | 22 | ############################################################################### 23 | 24 | select STDERR; $| = 1; 25 | select STDOUT; $| = 1; 26 | 27 | my $t = Test::Nginx->new()->has(qw/http auth_basic/) 28 | ->write_file_expand('nginx.conf', <<'EOF'); 29 | 30 | %%TEST_GLOBALS%% 31 | 32 | daemon off; 33 | 34 | events { 35 | } 36 | 37 | http { 38 | %%TEST_GLOBALS_HTTP%% 39 | 40 | server { 41 | listen 127.0.0.1:8080; 42 | server_name localhost; 43 | 44 | location / { 45 | auth_delay 2s; 46 | 47 | auth_basic "closed site"; 48 | auth_basic_user_file %%TESTDIR%%/htpasswd; 49 | } 50 | } 51 | } 52 | 53 | EOF 54 | 55 | $t->write_file('index.html', ''); 56 | $t->write_file('htpasswd', 'user:' . '{PLAIN}good' . "\n"); 57 | 58 | $t->run()->plan(4); 59 | 60 | ############################################################################### 61 | 62 | my $t1 = time(); 63 | like(http_get_auth('/', 'user', 'bad'), qr/401 Unauthorize/, 'not authorized'); 64 | cmp_ok(time() - $t1, '>=', 2, 'auth delay'); 65 | 66 | $t1 = time(); 67 | like(http_get_auth('/', 'user', 'good'), qr/200 OK/, 'authorized'); 68 | cmp_ok(time() - $t1, '<', 2, 'no delay'); 69 | 70 | ############################################################################### 71 | 72 | sub http_get_auth { 73 | my ($url, $user, $password) = @_; 74 | 75 | my $auth = encode_base64($user . ':' . $password, ''); 76 | 77 | return http(<new()->has(qw/http proxy rewrite/)->plan(4) 25 | ->write_file_expand('nginx.conf', <<'EOF'); 26 | 27 | %%TEST_GLOBALS%% 28 | 29 | daemon off; 30 | 31 | events { 32 | } 33 | 34 | http { 35 | %%TEST_GLOBALS_HTTP%% 36 | 37 | server { 38 | listen 127.0.0.1:8080; 39 | server_name localhost; 40 | 41 | proxy_hide_header X-Location; 42 | add_header X-Location unset; 43 | 44 | # As of nginx 1.5.4, this results in the following 45 | # location tree: 46 | # 47 | # "/a-b" 48 | # "/a-a" "/a/" 49 | # 50 | # A request to "/a" is expected to match "/a/" with auto_redirect, 51 | # but with such a tree it tests locations "/a-b", "/a-a" and then 52 | # falls back to null location. 53 | # 54 | # Key factor is that "-" is less than "/". 55 | 56 | location /a/ { proxy_pass http://127.0.0.1:8080/a-a; } 57 | location /a-a { add_header X-Location a-a; return 204; } 58 | location /a-b { add_header X-Location a-b; return 204; } 59 | } 60 | } 61 | 62 | EOF 63 | 64 | $t->run(); 65 | 66 | ############################################################################### 67 | 68 | like(http_get('/a'), qr/301 Moved/, 'auto redirect'); 69 | like(http_get('/a/'), qr/X-Location: unset/, 'match a'); 70 | like(http_get('/a-a'), qr/X-Location: a-a/, 'match a-a'); 71 | like(http_get('/a-b'), qr/X-Location: a-b/, 'match a-b'); 72 | 73 | ############################################################################### 74 | -------------------------------------------------------------------------------- /stream_upstream_zone.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Stream tests for upstream zone. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | use Test::Nginx::Stream qw/ stream /; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | my $t = Test::Nginx->new()->has(qw/stream stream_return stream_upstream_zone/) 27 | ->plan(2)->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | stream { 37 | %%TEST_GLOBALS_STREAM%% 38 | 39 | log_format test $upstream_addr; 40 | 41 | upstream u { 42 | zone u 1m; 43 | server 127.0.0.1:8081; 44 | } 45 | 46 | upstream u2 { 47 | zone u; 48 | server 127.0.0.1:8081 down; 49 | server 127.0.0.1:8081 backup down; 50 | } 51 | 52 | server { 53 | listen 127.0.0.1:8081; 54 | return OK; 55 | } 56 | 57 | server { 58 | listen 127.0.0.1:8091; 59 | proxy_pass u; 60 | 61 | access_log %%TESTDIR%%/access1.log test; 62 | } 63 | 64 | server { 65 | listen 127.0.0.1:8092; 66 | proxy_pass u2; 67 | 68 | access_log %%TESTDIR%%/access2.log test; 69 | } 70 | } 71 | 72 | EOF 73 | 74 | $t->write_file('index.html', ''); 75 | $t->run(); 76 | 77 | ############################################################################### 78 | 79 | my $p = port(8081); 80 | 81 | stream('127.0.0.1:' . port(8091))->read(); 82 | stream("127.0.0.1:" . port(8092))->read(); 83 | 84 | $t->stop(); 85 | 86 | is($t->read_file('access1.log'), "127.0.0.1:$p\n", 'upstream name'); 87 | is($t->read_file('access2.log'), "u2\n", 'no live upstreams'); 88 | 89 | ############################################################################### 90 | -------------------------------------------------------------------------------- /userid_flags.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for the userid_flags directive. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http userid/); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | server { 40 | listen 127.0.0.1:8080; 41 | server_name localhost; 42 | 43 | userid on; 44 | userid_name test; 45 | userid_path /0123456789; 46 | userid_domain test.domain; 47 | 48 | location / { 49 | userid_flags samesite=strict; 50 | 51 | location /many { 52 | userid_flags httponly samesite=none secure; 53 | } 54 | 55 | location /off { 56 | userid_flags off; 57 | } 58 | } 59 | 60 | location /lax { 61 | userid_flags samesite=lax; 62 | } 63 | 64 | location /unset { } 65 | } 66 | } 67 | 68 | EOF 69 | 70 | $t->write_file('index.html', ''); 71 | $t->write_file('lax', ''); 72 | $t->write_file('many', ''); 73 | $t->run()->plan(5); 74 | 75 | ############################################################################### 76 | 77 | like(http_get('/'), qr/samesite=strict/i, 'strict'); 78 | like(http_get('/lax'), qr/samesite=lax/i, 'lax'); 79 | like(http_get('/many'), qr/secure; httponly; samesite=none/i, 'many'); 80 | unlike(http_get('/off'), qr/(secure|httponly|samesite)/i, 'off'); 81 | unlike(http_get('/unset'), qr/(secure|httponly|samesite)/i, 'unset'); 82 | 83 | ############################################################################### 84 | -------------------------------------------------------------------------------- /stream_proxy_complex.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for stream proxy module with complex value. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | use Test::Nginx::Stream qw/ stream /; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | my $t = Test::Nginx->new()->has(qw/stream stream_return/) 27 | ->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | stream { 37 | %%TEST_GLOBALS_STREAM%% 38 | 39 | upstream %%PORT_8081%% { 40 | server 127.0.0.1:8091; 41 | } 42 | 43 | upstream %%PORT_8082%% { 44 | server 127.0.0.1:8092; 45 | server 127.0.0.1:8093; 46 | } 47 | 48 | server { 49 | listen 127.0.0.1:8081; 50 | listen 127.0.0.1:8082; 51 | proxy_pass $server_port; 52 | } 53 | 54 | server { 55 | listen 127.0.0.1:8083; 56 | proxy_pass $server_addr:%%PORT_8093%%; 57 | } 58 | 59 | server { 60 | listen 127.0.0.1:8091; 61 | listen 127.0.0.1:8092; 62 | listen 127.0.0.1:8093; 63 | return $server_port; 64 | } 65 | } 66 | 67 | EOF 68 | 69 | $t->run()->plan(5); 70 | 71 | ############################################################################### 72 | 73 | is(stream('127.0.0.1:' . port(8081))->read(), port(8091), 'upstream'); 74 | is(stream('127.0.0.1:' . port(8081))->read(), port(8091), 'upstream again'); 75 | 76 | is(stream('127.0.0.1:' . port(8082))->read(), port(8092), 'upstream 2'); 77 | is(stream('127.0.0.1:' . port(8082))->read(), port(8093), 'upstream second'); 78 | 79 | is(stream('127.0.0.1:' . port(8083))->read(), port(8093), 'implicit'); 80 | 81 | ############################################################################### 82 | -------------------------------------------------------------------------------- /subrequest_output_buffer_size.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for subrequest_output_buffer_size directive. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http proxy ssi/)->plan(4) 26 | ->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | http { 36 | %%TEST_GLOBALS_HTTP%% 37 | 38 | server { 39 | listen 127.0.0.1:8080; 40 | server_name localhost; 41 | 42 | location / { 43 | proxy_pass http://127.0.0.1:8081; 44 | subrequest_output_buffer_size 42; 45 | } 46 | 47 | location /longok { 48 | proxy_pass http://127.0.0.1:8081/long; 49 | } 50 | 51 | location /ssi { 52 | ssi on; 53 | } 54 | } 55 | 56 | server { 57 | listen 127.0.0.1:8081; 58 | server_name localhost; 59 | 60 | location / { } 61 | } 62 | } 63 | 64 | EOF 65 | 66 | $t->write_file('ssi.html', 67 | '' . 68 | 'set: '); 69 | 70 | $t->write_file('length', 'TEST-OK-IF-YOU-SEE-THIS'); 71 | $t->write_file('long', 'x' x 400); 72 | $t->write_file('empty', ''); 73 | 74 | $t->run(); 75 | 76 | ############################################################################### 77 | 78 | my ($r, $n); 79 | 80 | like(http_get('/ssi.html?c=length'), qr/SEE-THIS/, 'request'); 81 | like(http_get('/ssi.html?c=empty'), qr/set: $/, 'empty'); 82 | unlike(http_get('/ssi.html?c=long'), qr/200 OK/, 'long'); 83 | like(http_get('/ssi.html?c=longok'), qr/x{400}/, 'long ok'); 84 | 85 | ############################################################################### 86 | -------------------------------------------------------------------------------- /realip_remote_addr.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for nginx realip module, realip_remote_addr variable. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http realip/); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | set_real_ip_from 127.0.0.1/32; 40 | set_real_ip_from 192.0.2.1/32; 41 | real_ip_header X-Forwarded-For; 42 | 43 | server { 44 | listen 127.0.0.1:8080; 45 | server_name localhost; 46 | 47 | location / { 48 | add_header X-IP $remote_addr; 49 | add_header X-Real-IP $realip_remote_addr; 50 | } 51 | } 52 | } 53 | 54 | EOF 55 | 56 | $t->write_file('index.html', ''); 57 | $t->write_file('1', ''); 58 | $t->run(); 59 | 60 | plan(skip_all => 'no 127.0.0.1 on host') 61 | if http_get('/') !~ /X-IP: 127.0.0.1/m; 62 | 63 | $t->plan(4); 64 | 65 | ############################################################################### 66 | 67 | like(http_get('/1'), qr/X-Real-IP: 127.0.0.1/m, 'request'); 68 | like(http_get('/'), qr/X-Real-IP: 127.0.0.1/m, 'request redirect'); 69 | 70 | like(http_xff('/1', '192.0.2.1'), qr/X-Real-IP: 127.0.0.1/m, 'realip'); 71 | like(http_xff('/', '192.0.2.1'), qr/X-Real-IP: 127.0.0.1/m, 'realip redirect'); 72 | 73 | ############################################################################### 74 | 75 | sub http_xff { 76 | my ($uri, $xff) = @_; 77 | return http(<new()->has(qw/http proxy upstream_keepalive/)->plan(1); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | upstream backend { 40 | server 127.0.0.1:8081; 41 | keepalive 1; 42 | } 43 | 44 | server { 45 | listen 127.0.0.1:8080; 46 | server_name localhost; 47 | 48 | proxy_http_version 1.1; 49 | proxy_set_header Connection ""; 50 | 51 | location / { 52 | proxy_pass http://backend; 53 | add_header X-Body $request_body; 54 | proxy_request_buffering off; 55 | } 56 | } 57 | 58 | server { 59 | listen 127.0.0.1:8081; 60 | server_name localhost; 61 | 62 | location / { } 63 | } 64 | } 65 | 66 | EOF 67 | 68 | $t->write_file('t1', 'SEE-THIS'); 69 | $t->run(); 70 | 71 | ############################################################################### 72 | 73 | # We emulate an early upstream server response while proxy is still 74 | # transmitting the request body. In this case, the request body is 75 | # discarded by proxy, and 2nd request will be processed by upstream 76 | # as remain request body. 77 | 78 | http(< 'long configuration parsing') unless $ENV{TEST_NGINX_UNSAFE}; 26 | 27 | my $t = Test::Nginx->new()->has(qw/http geo/); 28 | 29 | $t->write_file_expand('nginx.conf', <<'EOF'); 30 | 31 | %%TEST_GLOBALS%% 32 | 33 | daemon off; 34 | 35 | events { 36 | } 37 | 38 | http { 39 | %%TEST_GLOBALS_HTTP%% 40 | 41 | geo $geo_base_create { 42 | ranges; 43 | include base.conf; 44 | } 45 | 46 | geo $geo_base_include { 47 | ranges; 48 | include base.conf; 49 | } 50 | 51 | server { 52 | listen 127.0.0.1:8080; 53 | server_name localhost; 54 | 55 | location / { 56 | add_header X-IP $remote_addr; 57 | add_header X-GBc $geo_base_create; 58 | add_header X-GBi $geo_base_include; 59 | } 60 | } 61 | } 62 | 63 | EOF 64 | 65 | $t->write_file('1', ''); 66 | $t->write_file('base.conf', join('', map { 67 | "127." . $_/256/256 % 256 . "." . $_/256 % 256 . "." . $_ % 256 . 68 | "-127." . $_/256/256 % 256 . "." . $_/256 % 256 . "." .$_ % 256 . " " . 69 | ($_ == 1 ? "loopback" : "range$_") . ";" } (0 .. 100000))); 70 | 71 | $t->run(); 72 | 73 | plan(skip_all => 'no 127.0.0.1 on host') 74 | if http_get('/1') !~ /X-IP: 127.0.0.1/m; 75 | 76 | $t->plan(2); 77 | 78 | ############################################################################### 79 | 80 | my $r = http_get('/1'); 81 | like($r, qr/^X-GBc: loopback/m, 'geo binary base create'); 82 | like($r, qr/^X-GBi: loopback/m, 'geo binary base include'); 83 | 84 | ############################################################################### 85 | -------------------------------------------------------------------------------- /http_listen_wildcard.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for listen port ranges with a wildcard address. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http proxy rewrite/); 26 | 27 | plan(skip_all => 'listen on wildcard address') 28 | unless $ENV{TEST_NGINX_UNSAFE}; 29 | 30 | $t->write_file_expand('nginx.conf', <<'EOF'); 31 | 32 | %%TEST_GLOBALS%% 33 | 34 | daemon off; 35 | 36 | events { 37 | } 38 | 39 | http { 40 | %%TEST_GLOBALS_HTTP%% 41 | 42 | server { 43 | listen 127.0.0.1:8080; 44 | listen %%PORT_8186%%-%%PORT_8187%%; 45 | server_name localhost; 46 | 47 | location / { 48 | proxy_pass http://$arg_b/t; 49 | } 50 | 51 | location /t { 52 | return 200 $server_addr:$server_port; 53 | } 54 | } 55 | 56 | # catch out of range 57 | 58 | server { 59 | listen 127.0.0.1:8185; 60 | listen 127.0.0.1:8188; 61 | server_name localhost; 62 | } 63 | } 64 | 65 | EOF 66 | 67 | my $p5 = port(8185); my $p7 = port(8187); 68 | my $p6 = port(8186); my $p8 = port(8188); 69 | 70 | plan(skip_all => 'no requested ranges') 71 | if "$p6$p7" ne "81868187"; 72 | 73 | $t->run()->plan(4); 74 | 75 | ############################################################################### 76 | 77 | unlike(http_get("/?b=127.0.0.1:$p5"), qr/127.0.0.1:$p5/, 'out of range 1'); 78 | like(http_get("/?b=127.0.0.1:$p6"), qr/127.0.0.1:$p6/, 'wildcard range 1'); 79 | like(http_get("/?b=127.0.0.1:$p7"), qr/127.0.0.1:$p7/, 'wildcard range 2'); 80 | unlike(http_get("/?b=127.0.0.1:$p8"), qr/127.0.0.1:$p8/, 'out of range 2'); 81 | 82 | ############################################################################### 83 | -------------------------------------------------------------------------------- /worker_shutdown_timeout_h2.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for worker_shutdown_timeout and HTTP/2 with proxy. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | use Test::Nginx::HTTP2; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | my $t = Test::Nginx->new()->has(qw/http http_v2 proxy/)->plan(2); 27 | 28 | $t->write_file_expand('nginx.conf', <<'EOF'); 29 | 30 | %%TEST_GLOBALS%% 31 | 32 | daemon off; 33 | worker_shutdown_timeout 10ms; 34 | 35 | events { 36 | } 37 | 38 | http { 39 | %%TEST_GLOBALS_HTTP%% 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | server_name localhost; 44 | 45 | http2 on; 46 | 47 | location / { 48 | proxy_pass http://127.0.0.1:8081; 49 | proxy_read_timeout 5s; 50 | } 51 | } 52 | } 53 | EOF 54 | 55 | $t->run_daemon(\&http_silent_daemon); 56 | $t->run()->waitforsocket('127.0.0.1:' . port(8081)); 57 | 58 | ############################################################################### 59 | 60 | my $s = Test::Nginx::HTTP2->new(); 61 | ok($s->new_stream(), 'new stream'); 62 | 63 | $s->h2_ping('SEE-THIS'); 64 | $s->read(all => [{ type => 'PING' }]); 65 | 66 | $t->stop(); 67 | 68 | like($t->read_file('access.log'), qr/ (?!504)\d{3} /, 'shutdown timeout'); 69 | 70 | ############################################################################### 71 | 72 | sub http_silent_daemon { 73 | my $server = IO::Socket::INET->new( 74 | Proto => 'tcp', 75 | LocalAddr => '127.0.0.1:' . port(8081), 76 | Listen => 5, 77 | Reuse => 1 78 | ) 79 | or die "Can't create listening socket: $!\n"; 80 | 81 | while (my $client = $server->accept()) { 82 | $client->autoflush(1); 83 | 84 | while (<$client>) { } 85 | } 86 | } 87 | 88 | ############################################################################### 89 | -------------------------------------------------------------------------------- /mp4_ssi.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Test for mp4 module in subrequests. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http mp4 ssi/)->has_daemon('ffprobe') 26 | ->has_daemon('ffmpeg')->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | http { 36 | %%TEST_GLOBALS_HTTP%% 37 | 38 | server { 39 | listen 127.0.0.1:8080; 40 | server_name localhost; 41 | 42 | location / { 43 | ssi on; 44 | } 45 | location /ssi { 46 | mp4; 47 | } 48 | } 49 | } 50 | 51 | EOF 52 | 53 | plan(skip_all => 'no lavfi') 54 | unless grep /lavfi/, `ffmpeg -loglevel quiet -formats`; 55 | system('ffmpeg -nostdin -loglevel quiet -y ' 56 | . '-f lavfi -i testsrc=duration=10:size=320x200:rate=15 ' 57 | . '-f lavfi -i testsrc=duration=20:size=320x200:rate=15 ' 58 | . '-map 0:0 -map 1:0 -pix_fmt yuv420p -g 15 -c:v libx264 ' 59 | . "${\($t->testdir())}/ssi.mp4") == 0 60 | or die "Can't create mp4 file: $!"; 61 | 62 | $t->write_file('index.html', 'XX'); 63 | 64 | $t->run()->plan(1); 65 | 66 | ############################################################################### 67 | 68 | (my $r = get('/')) =~ s/([^\x20-\x7e])/sprintf('\\x%02x', ord($1))/gmxe; 69 | unlike($r, qr/\\x0d(\\x0a)?0\\x0d(\\x0a)?\\x0d(\\x0a)?\w/, 'only final chunk'); 70 | 71 | ############################################################################### 72 | 73 | sub get { 74 | my ($url, $extra) = @_; 75 | return http(<new()->has(qw/http mirror/)->plan(8); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | log_format test $uri; 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | server_name localhost; 44 | 45 | location / { 46 | mirror /mirror; 47 | 48 | location /off { 49 | mirror off; 50 | } 51 | } 52 | 53 | location /many { 54 | mirror /mirror/1; 55 | mirror /mirror/2; 56 | } 57 | 58 | location /mirror { 59 | log_subrequest on; 60 | access_log test$args.log test; 61 | } 62 | } 63 | } 64 | 65 | EOF 66 | 67 | $t->write_file('index.html', ''); 68 | $t->write_file('many', ''); 69 | $t->write_file('off', ''); 70 | $t->run(); 71 | 72 | ############################################################################### 73 | 74 | like(http_get('/index.html?1'), qr/200 OK/, 'request'); 75 | like(http_get('/?2'), qr/200 OK/, 'internal redirect'); 76 | like(http_get('/off?3'), qr/200 OK/, 'mirror off'); 77 | like(http_get('/many?4'), qr/200 OK/, 'mirror many'); 78 | 79 | $t->stop(); 80 | 81 | is($t->read_file('test1.log'), "/mirror\n", 'log - request'); 82 | is($t->read_file('test2.log'), "/mirror\n/mirror\n", 'log - redirect'); 83 | ok(!-e $t->testdir() . '/test3.log', 'log - mirror off'); 84 | is($t->read_file('test4.log'), "/mirror/1\n/mirror/2\n", 'log - mirror many'); 85 | 86 | ############################################################################### 87 | -------------------------------------------------------------------------------- /proxy_method.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Dmitry Lazurkin 4 | 5 | # Tests for proxy_method. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx; 18 | 19 | ############################################################################### 20 | 21 | select STDERR; $| = 1; 22 | select STDOUT; $| = 1; 23 | 24 | my $t = Test::Nginx->new()->has(qw/http proxy rewrite/)->plan(4) 25 | ->write_file_expand('nginx.conf', <<'EOF'); 26 | 27 | %%TEST_GLOBALS%% 28 | 29 | daemon off; 30 | 31 | events { 32 | } 33 | 34 | http { 35 | %%TEST_GLOBALS_HTTP%% 36 | 37 | server { 38 | listen 127.0.0.1:8080; 39 | server_name localhost; 40 | 41 | location /preserve { 42 | proxy_pass http://127.0.0.1:8080/get-method; 43 | } 44 | 45 | location /const { 46 | proxy_pass http://127.0.0.1:8080/get-method; 47 | proxy_method POST; 48 | } 49 | 50 | location /var { 51 | proxy_pass http://127.0.0.1:8080/get-method; 52 | proxy_method $arg_method; 53 | } 54 | 55 | location /parent { 56 | proxy_method POST; 57 | location /parent/child { 58 | proxy_pass http://127.0.0.1:8080/get-method; 59 | } 60 | } 61 | 62 | location /get-method { 63 | return 200 "request_method=$request_method"; 64 | } 65 | } 66 | } 67 | 68 | EOF 69 | 70 | $t->run(); 71 | 72 | ############################################################################### 73 | 74 | like(http_get('/preserve'), qr/request_method=GET/, 75 | 'proxy_method from request'); 76 | 77 | like(http_get('/const'), qr/request_method=POST/, 78 | 'proxy_method from constant'); 79 | 80 | like(http_get('/var?method=POST'), qr/request_method=POST/, 81 | 'proxy_method from variable'); 82 | 83 | like(http_get('/parent/child'), qr/request_method=POST/, 84 | 'proxy_method from parent'); 85 | 86 | ############################################################################### 87 | -------------------------------------------------------------------------------- /scgi_gzip.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | # Test for scgi backend and gzip. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx qw/ :DEFAULT :gzip /; 18 | 19 | ############################################################################### 20 | 21 | select STDERR; $| = 1; 22 | select STDOUT; $| = 1; 23 | 24 | eval { require SCGI; }; 25 | plan(skip_all => 'SCGI not installed') if $@; 26 | 27 | my $t = Test::Nginx->new()->has(qw/http scgi gzip/)->plan(1) 28 | ->write_file_expand('nginx.conf', <<'EOF'); 29 | 30 | %%TEST_GLOBALS%% 31 | 32 | daemon off; 33 | 34 | events { 35 | } 36 | 37 | http { 38 | %%TEST_GLOBALS_HTTP%% 39 | 40 | server { 41 | listen 127.0.0.1:8080; 42 | server_name localhost; 43 | 44 | location / { 45 | gzip on; 46 | scgi_pass 127.0.0.1:8081; 47 | scgi_param SCGI 1; 48 | scgi_param REQUEST_URI $request_uri; 49 | scgi_param HTTP_X_BLAH "blah"; 50 | } 51 | } 52 | } 53 | 54 | EOF 55 | 56 | $t->run_daemon(\&scgi_daemon); 57 | $t->run()->waitforsocket('127.0.0.1:' . port(8081)); 58 | 59 | ############################################################################### 60 | 61 | like(http_gzip_request('/'), qr/Content-Encoding: gzip/, 'scgi request'); 62 | 63 | ############################################################################### 64 | 65 | sub scgi_daemon { 66 | my $server = IO::Socket::INET->new( 67 | Proto => 'tcp', 68 | LocalHost => '127.0.0.1:' . port(8081), 69 | Listen => 5, 70 | Reuse => 1 71 | ) 72 | or die "Can't create listening socket: $!\n"; 73 | 74 | my $scgi = SCGI->new($server, blocking => 1); 75 | 76 | while (my $request = $scgi->accept()) { 77 | eval { $request->read_env(); }; 78 | next if $@; 79 | 80 | $request->connection()->print(< 'can leave orphaned process group') 26 | unless $ENV{TEST_NGINX_UNSAFE}; 27 | 28 | my $t = Test::Nginx->new(qr/http unix/)->plan(4) 29 | ->write_file_expand('nginx.conf', <<'EOF'); 30 | 31 | %%TEST_GLOBALS%% 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | server { 40 | listen unix:%%TESTDIR%%/unix.sock; 41 | server_name localhost; 42 | } 43 | } 44 | 45 | EOF 46 | 47 | my $d = $t->testdir(); 48 | 49 | $t->run(); 50 | 51 | ############################################################################### 52 | 53 | my $pid = $t->read_file('nginx.pid'); 54 | ok($pid, 'master pid'); 55 | 56 | kill 'USR2', $pid; 57 | 58 | for (1 .. 30) { 59 | last if -e "$d/nginx.pid" && -e "$d/nginx.pid.oldbin"; 60 | select undef, undef, undef, 0.2 61 | } 62 | 63 | isnt($t->read_file('nginx.pid'), $pid, 'master pid changed'); 64 | 65 | kill 'QUIT', $pid; 66 | 67 | for (1 .. 30) { 68 | last if ! -e "$d/nginx.pid.oldbin"; 69 | select undef, undef, undef, 0.2 70 | } 71 | 72 | ok(-e "$d/unix.sock", 'unix socket exists on old master shutdown'); 73 | 74 | # unix socket on new master termination 75 | 76 | $pid = $t->read_file('nginx.pid'); 77 | 78 | kill 'USR2', $pid; 79 | 80 | for (1 .. 30) { 81 | last if -e "$d/nginx.pid" && -e "$d/nginx.pid.oldbin"; 82 | select undef, undef, undef, 0.2 83 | } 84 | 85 | kill 'TERM', $t->read_file('nginx.pid'); 86 | 87 | for (1 .. 30) { 88 | last if ! -e "$d/nginx.pid.oldbin"; 89 | select undef, undef, undef, 0.2 90 | } 91 | 92 | ok(-e "$d/unix.sock", 'unix socket exists on new master termination'); 93 | 94 | ############################################################################### 95 | -------------------------------------------------------------------------------- /proxy_max_temp_file_size.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for http proxy module, proxy_max_temp_file_size directive. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx qw/ :DEFAULT http_content /; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http proxy/)->plan(4); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | server { 40 | listen 127.0.0.1:8080 sndbuf=32k; 41 | server_name localhost; 42 | 43 | proxy_buffer_size 4k; 44 | proxy_buffers 8 4k; 45 | 46 | location / { 47 | proxy_max_temp_file_size 4k; 48 | proxy_pass http://127.0.0.1:8081/; 49 | } 50 | 51 | location /off/ { 52 | proxy_max_temp_file_size 0; 53 | proxy_pass http://127.0.0.1:8081/; 54 | } 55 | } 56 | 57 | server { 58 | listen 127.0.0.1:8081; 59 | server_name localhost; 60 | 61 | location / { } 62 | } 63 | } 64 | 65 | EOF 66 | 67 | $t->write_file('1', 'X' x (1024 * 1024)); 68 | $t->run(); 69 | 70 | ############################################################################### 71 | 72 | # test that the response is wholly proxied when all event pipe buffers are full 73 | 74 | my $body = http_content(http_get('/1', sleep => 0.4)); 75 | like($body, qr/^X+$/m, 'no pipe bufs - body'); 76 | is(length($body), 1024 * 1024, 'no pipe bufs - body length'); 77 | 78 | # also with disabled proxy temp file 79 | 80 | $body = http_content(http_get('/off/1', sleep => 0.4)); 81 | like($body, qr/^X+$/m, 'no temp file - body'); 82 | is(length($body), 1024 * 1024, 'no temp file - body length'); 83 | 84 | ############################################################################### 85 | -------------------------------------------------------------------------------- /proxy_limit_rate2.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for the proxy_limit_rate directive, variables support. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx qw/ :DEFAULT http_content /; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http proxy/); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | server { 40 | listen 127.0.0.1:8080; 41 | server_name localhost; 42 | 43 | proxy_limit_rate $upstream_http_x_rate; 44 | proxy_buffer_size 4k; 45 | 46 | location / { 47 | proxy_pass http://127.0.0.1:8080/data; 48 | add_header X-Msec $msec; 49 | add_trailer X-Msec $msec; 50 | } 51 | 52 | location /data { 53 | add_header X-Rate $arg_e; 54 | } 55 | } 56 | } 57 | 58 | EOF 59 | 60 | $t->write_file('data', 'X' x 40000); 61 | $t->try_run('no proxy_limit_rate variables')->plan(4); 62 | 63 | ############################################################################### 64 | 65 | my ($body, $t1, $t2) = get('/?e=20000'); 66 | 67 | cmp_ok($t2 - $t1, '>=', 1, 'proxy_limit_rate'); 68 | is($body, 'X' x 40000, 'response body'); 69 | 70 | # unlimited 71 | 72 | ($body, $t1, $t2) = get('/?e=0'); 73 | 74 | is($t2 - $t1, 0, 'proxy_limit_rate unlimited'); 75 | is($body, 'X' x 40000, 'response body unlimited'); 76 | 77 | ############################################################################### 78 | 79 | sub get { 80 | my ($uri) = @_; 81 | my $r = http(<new()->has(qw/http sub ssi xslt/)->plan(2) 25 | ->write_file_expand('nginx.conf', <<'EOF'); 26 | 27 | %%TEST_GLOBALS%% 28 | 29 | daemon off; 30 | 31 | events { 32 | } 33 | 34 | http { 35 | %%TEST_GLOBALS_HTTP%% 36 | 37 | types { 38 | text/html html; 39 | text/xml xml; 40 | } 41 | 42 | server { 43 | listen 127.0.0.1:8080; 44 | server_name localhost; 45 | 46 | location / { 47 | ssi on; 48 | sub_filter notfoo bar; 49 | } 50 | 51 | location /xslt { 52 | ssi on; 53 | sub_filter_types *; 54 | sub_filter root>foo bar; 55 | xslt_stylesheet test.xslt; 56 | } 57 | } 58 | } 59 | 60 | EOF 61 | 62 | $t->write_file('index.html', ' truncated'); 63 | $t->write_file('not.html', 'response is not'); 64 | 65 | $t->write_file('xslt.html', ' truncated'); 66 | $t->write_file('xslt.xml', 'test'); 67 | $t->write_file('test.xslt', <<'EOF'); 68 | 69 | 71 | 72 | 73 | response is not 74 | 75 | 76 | EOF 77 | 78 | $t->run(); 79 | 80 | ############################################################################### 81 | 82 | like(http_get('/index.html'), qr/not truncated/, 'subrequest partial match'); 83 | like(http_get('/xslt.html'), qr/not.*truncated/ms, 'partial match and xslt'); 84 | 85 | ############################################################################### 86 | -------------------------------------------------------------------------------- /range_clearing.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Eugene Grebenschikov 4 | # (C) Sergey Kandaurov 5 | # (C) Nginx, Inc. 6 | 7 | # Tests for clearing of pre-existing Content-Range headers. 8 | 9 | ############################################################################### 10 | 11 | use warnings; 12 | use strict; 13 | 14 | use Test::More; 15 | 16 | BEGIN { use FindBin; chdir($FindBin::Bin); } 17 | 18 | use lib 'lib'; 19 | use Test::Nginx; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | my $t = Test::Nginx->new()->has(qw/http rewrite proxy cache/) 27 | ->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | proxy_cache_path %%TESTDIR%%/cache levels=1:2 keys_zone=NAME:1m; 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | server_name localhost; 44 | 45 | location / { 46 | proxy_pass http://127.0.0.1:8080/stub; 47 | proxy_cache NAME; 48 | proxy_cache_valid 200 1m; 49 | } 50 | 51 | location /stub { 52 | add_header Content-Range stub; 53 | add_header Accept-Ranges bytes; 54 | return 200 "SEE-THIS"; 55 | } 56 | } 57 | } 58 | 59 | EOF 60 | 61 | $t->run()->plan(3); 62 | 63 | ############################################################################### 64 | 65 | like(http_get_range('/', 'Range: bytes=0-4'), 66 | qr/ 206 (?!.*stub)/s, 'content range cleared - range request'); 67 | like(http_get_range('/', 'Range: bytes=0-2,4-'), 68 | qr/ 206 (?!.*stub)/s, 'content range cleared - multipart'); 69 | like(http_get_range('/', 'Range: bytes=1000-'), 70 | qr/ 416 (?!.*stub)/s, 'content range cleared - not satisfable'); 71 | 72 | ############################################################################### 73 | 74 | sub http_get_range { 75 | my ($url, $extra) = @_; 76 | return http(<new()->has(qw/http http_v2 proxy rewrite/)->plan(1); 27 | 28 | $t->write_file_expand('nginx.conf', <<'EOF'); 29 | 30 | %%TEST_GLOBALS%% 31 | 32 | daemon off; 33 | 34 | events { 35 | } 36 | 37 | http { 38 | %%TEST_GLOBALS_HTTP%% 39 | 40 | server { 41 | listen 127.0.0.1:8080; 42 | listen 127.0.0.1:8081; 43 | server_name localhost; 44 | 45 | http2 on; 46 | 47 | proxy_http_version 1.1; 48 | 49 | location / { 50 | proxy_request_buffering off; 51 | proxy_pass http://127.0.0.1:8081/bad; 52 | proxy_intercept_errors on; 53 | error_page 502 = /pass; 54 | } 55 | 56 | location /bad { 57 | return 502; 58 | } 59 | 60 | location /pass { 61 | proxy_pass http://127.0.0.1:8081/good; 62 | } 63 | 64 | location /good { 65 | limit_rate 100; 66 | return 200; 67 | } 68 | } 69 | } 70 | 71 | EOF 72 | 73 | $t->run(); 74 | 75 | ############################################################################### 76 | 77 | # unbuffered request body 78 | 79 | my $s = Test::Nginx::HTTP2->new(); 80 | my $sid = $s->new_stream({ body_more => 1 }); 81 | 82 | $s->h2_body('SEE-', { body_more => 1 }); 83 | sleep 1; 84 | $s->h2_body('THIS'); 85 | 86 | my $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); 87 | my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; 88 | is($frame->{headers}->{':status'}, 200, 'discard body rest on redirect'); 89 | 90 | ############################################################################### 91 | -------------------------------------------------------------------------------- /stream_geo_unix.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for stream geo module with unix socket. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | use Test::Nginx::Stream qw/ stream /; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | my $t = Test::Nginx->new()->has(qw/stream stream_geo stream_return unix/) 27 | ->plan(4); 28 | 29 | $t->write_file_expand('nginx.conf', <<'EOF'); 30 | 31 | %%TEST_GLOBALS%% 32 | 33 | daemon off; 34 | 35 | events { 36 | } 37 | 38 | stream { 39 | %%TEST_GLOBALS_STREAM%% 40 | 41 | geo $geo { 42 | default default; 43 | 255.255.255.255 none; 44 | } 45 | 46 | geo $remote_addr $geora { 47 | default default; 48 | 255.255.255.255 none; 49 | } 50 | 51 | geo $geor { 52 | ranges; 53 | 0.0.0.0-255.255.255.254 test; 54 | default none; 55 | } 56 | 57 | geo $remote_addr $georra { 58 | ranges; 59 | 0.0.0.0-255.255.255.254 test; 60 | default none; 61 | } 62 | 63 | server { 64 | listen unix:%%TESTDIR%%/unix.sock; 65 | return "geo:$geo geora:$geora geor:$geor georra:$georra"; 66 | } 67 | 68 | server { 69 | listen 127.0.0.1:8080; 70 | proxy_pass unix:%%TESTDIR%%/unix.sock; 71 | } 72 | } 73 | 74 | EOF 75 | 76 | $t->write_file('index.html', ''); 77 | $t->run(); 78 | 79 | ############################################################################### 80 | 81 | my %data = stream('127.0.0.1:' . port(8080))->read() =~ /(\w+):(\w+)/g; 82 | is($data{geo}, 'none', 'geo unix'); 83 | is($data{geor}, 'none', 'geo unix ranges'); 84 | is($data{geora}, 'none', 'geo unix remote addr'); 85 | is($data{georra}, 'none', 'geo unix ranges remote addr'); 86 | 87 | ############################################################################### 88 | -------------------------------------------------------------------------------- /perl_gzip.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | # Tests for embedded perl module. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx qw/ :DEFAULT :gzip /; 18 | 19 | ############################################################################### 20 | 21 | select STDERR; $| = 1; 22 | select STDOUT; $| = 1; 23 | 24 | eval { require IO::Compress::Gzip; }; 25 | plan(skip_all => "IO::Compress::Gzip not found") if $@; 26 | 27 | my $t = Test::Nginx->new()->has(qw/http perl gzip/)->plan(2) 28 | ->write_file_expand('nginx.conf', <<'EOF'); 29 | 30 | %%TEST_GLOBALS%% 31 | 32 | daemon off; 33 | 34 | events { 35 | } 36 | 37 | http { 38 | %%TEST_GLOBALS_HTTP%% 39 | 40 | server { 41 | listen 127.0.0.1:8080; 42 | server_name localhost; 43 | 44 | gzip on; 45 | gzip_types text/plain; 46 | 47 | location / { 48 | perl 'sub { 49 | my $r = shift; 50 | $r->send_http_header("text/plain"); 51 | return OK if $r->header_only; 52 | $r->print("TEST"); 53 | return OK; 54 | }'; 55 | } 56 | 57 | location /gz { 58 | perl 'sub { 59 | my $r = shift; 60 | $r->header_out("Content-Encoding", "gzip"); 61 | $r->send_http_header("text/plain"); 62 | return OK if $r->header_only; 63 | use IO::Compress::Gzip; 64 | my $in = "TEST"; 65 | my $out; 66 | IO::Compress::Gzip::gzip(\\$in => \\$out); 67 | $r->print($out); 68 | return OK; 69 | }'; 70 | } 71 | } 72 | } 73 | 74 | EOF 75 | 76 | $t->run(); 77 | 78 | ############################################################################### 79 | 80 | http_gzip_like(http_gzip_request('/'), qr/TEST/, 'perl response gzipped'); 81 | http_gzip_like(http_gzip_request('/gz'), qr/TEST/, 'not doublegzipped'); 82 | 83 | ############################################################################### 84 | -------------------------------------------------------------------------------- /dav_chunked.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | # Tests for nginx dav module with chunked request body. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | use Socket qw/ CRLF /; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http dav/)->plan(6); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | server { 40 | listen 127.0.0.1:8080; 41 | server_name localhost; 42 | 43 | client_header_buffer_size 1k; 44 | client_body_buffer_size 2k; 45 | 46 | location / { 47 | dav_methods PUT; 48 | } 49 | } 50 | } 51 | 52 | EOF 53 | 54 | $t->run(); 55 | 56 | ############################################################################### 57 | 58 | like(http_put_chunked('/file', '1234567890'), 59 | qr/201 Created.*(Content-Length|\x0d\0a0\x0d\x0a)/ms, 'put chunked'); 60 | is($t->read_file('file'), '1234567890', 'put content'); 61 | 62 | like(http_put_chunked('/file', ''), qr/204 No Content/, 'put chunked empty'); 63 | is($t->read_file('file'), '', 'put empty content'); 64 | 65 | like(http_put_chunked('/file', '1234567890', 1024), 66 | qr/204 No Content/, 'put chunked big'); 67 | is($t->read_file('file'), '1234567890' x 1024, 'put big content'); 68 | 69 | ############################################################################### 70 | 71 | sub http_put_chunked { 72 | my ($url, $body, $count) = @_; 73 | my $length = sprintf("%x", length $body); 74 | $body = $length ? $length . CRLF . $body . CRLF : ''; 75 | $body x= ($count || 1); 76 | $body .= '0' . CRLF . CRLF; 77 | return http(<new()->has(qw/http realip proxy unix/); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | server { 40 | listen 127.0.0.1:8080; 41 | listen unix:%%TESTDIR%%/unix.sock; 42 | server_name localhost; 43 | 44 | location /1 { 45 | set_real_ip_from localhost; 46 | add_header X-IP $remote_addr; 47 | } 48 | 49 | location /2 { 50 | set_real_ip_from unix:; 51 | add_header X-IP $remote_addr; 52 | } 53 | 54 | location /unix { 55 | proxy_pass http://unix:%%TESTDIR%%/unix.sock:/; 56 | proxy_set_header X-Real-IP 192.0.2.1; 57 | } 58 | 59 | location /ip { 60 | proxy_pass http://127.0.0.1:8080/; 61 | proxy_set_header X-Real-IP 192.0.2.1; 62 | } 63 | } 64 | } 65 | 66 | EOF 67 | 68 | $t->write_file('1', ''); 69 | $t->write_file('2', ''); 70 | $t->run(); 71 | 72 | plan(skip_all => 'no 127.0.0.1 on host') 73 | if http_get('/1') !~ /X-IP: 127.0.0.1/m; 74 | 75 | $t->plan(4); 76 | 77 | ############################################################################### 78 | 79 | like(http_get('/unix/2'), qr/X-IP: 192.0.2.1/, 'realip unix'); 80 | unlike(http_get('/unix/1'), qr/X-IP: 192.0.2.1/, 'realip unix - no match'); 81 | 82 | like(http_get('/ip/1'), qr/X-IP: 192.0.2.1/, 'realip hostname'); 83 | unlike(http_get('/ip/2'), qr/X-IP: 192.0.2.1/, 'realip hostname - no match'); 84 | 85 | ############################################################################### 86 | -------------------------------------------------------------------------------- /memcached_fake_extra.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | # (C) Nginx, Inc. 5 | 6 | # Test for memcached backend returning extra data after trailer. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | use Socket qw/ CRLF /; 15 | 16 | BEGIN { use FindBin; chdir($FindBin::Bin); } 17 | 18 | use lib 'lib'; 19 | use Test::Nginx; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | my $t = Test::Nginx->new()->has(qw/http rewrite memcached/)->plan(1) 27 | ->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | server { 40 | listen 127.0.0.1:8080; 41 | server_name localhost; 42 | 43 | location / { 44 | set $memcached_key $uri; 45 | memcached_pass 127.0.0.1:8081; 46 | } 47 | } 48 | } 49 | 50 | EOF 51 | 52 | $t->run_daemon(\&memcached_fake_daemon); 53 | $t->run(); 54 | 55 | $t->waitforsocket('127.0.0.1:' . port(8081)) 56 | or die "Can't start fake memcached"; 57 | 58 | ############################################################################### 59 | 60 | like(http_get('/'), qr/SEE-THIS/, 'memcached data after trailer'); 61 | 62 | ############################################################################### 63 | 64 | sub memcached_fake_daemon { 65 | my $server = IO::Socket::INET->new( 66 | Proto => 'tcp', 67 | LocalAddr => '127.0.0.1:' . port(8081), 68 | Listen => 5, 69 | Reuse => 1 70 | ) 71 | or die "Can't create listening socket: $!\n"; 72 | 73 | local $SIG{PIPE} = 'IGNORE'; 74 | 75 | while (my $client = $server->accept()) { 76 | $client->autoflush(1); 77 | 78 | while (<$client>) { 79 | last if (/\x0d\x0a$/); 80 | } 81 | 82 | print $client 'VALUE / 0 8' . CRLF; 83 | print $client 'SEE-THIS' . CRLF . 'END' . CRLF 84 | . "\0" . ("1" x 1024); 85 | 86 | select(undef, undef, undef, 0.2); 87 | 88 | print $client 'EXTRA' . CRLF; 89 | close $client; 90 | } 91 | } 92 | 93 | ############################################################################### 94 | -------------------------------------------------------------------------------- /msie_refresh.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Test for msie_refresh. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http rewrite ssi/)->plan(5) 26 | ->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | http { 36 | %%TEST_GLOBALS_HTTP%% 37 | 38 | server { 39 | listen 127.0.0.1:8080; 40 | server_name localhost; 41 | 42 | msie_refresh on; 43 | 44 | location / { 45 | return 301 text; 46 | } 47 | 48 | location /space { 49 | return 301 "space "; 50 | } 51 | 52 | location /error_page { 53 | return 301; 54 | error_page 301 text; 55 | } 56 | 57 | location /off { 58 | msie_refresh off; 59 | return 301 text; 60 | } 61 | 62 | location /ssi { 63 | ssi on; 64 | } 65 | } 66 | } 67 | 68 | EOF 69 | 70 | $t->write_file('ssi.html', 'XX'); 71 | $t->run(); 72 | 73 | ############################################################################### 74 | 75 | like(get('/'), qr/Refresh.*URL=text"/, 'msie refresh'); 76 | like(get('/space'), qr/URL=space%20"/, 'msie refresh escaped url'); 77 | like(get('/error_page'), qr/URL=text"/, 'msie refresh error page'); 78 | 79 | unlike(get('/off'), qr/Refresh/, 'msie refresh disabled'); 80 | 81 | unlike(get('/ssi.html'), qr/^0\x0d\x0a?\x0d\x0a?\w/m, 'only final chunk'); 82 | 83 | ############################################################################### 84 | 85 | sub get { 86 | my ($url, $extra) = @_; 87 | return http(<new()->has(qw/mail imap http rewrite/)->plan(4) 31 | ->write_file_expand('nginx.conf', <<'EOF'); 32 | 33 | %%TEST_GLOBALS%% 34 | 35 | daemon off; 36 | worker_shutdown_timeout 10ms; 37 | 38 | events { 39 | } 40 | 41 | mail { 42 | proxy_pass_error_message on; 43 | proxy_timeout 15s; 44 | auth_http http://127.0.0.1:8080/mail/auth; 45 | xclient off; 46 | 47 | server { 48 | listen 127.0.0.1:8025; 49 | protocol smtp; 50 | } 51 | } 52 | 53 | http { 54 | %%TEST_GLOBALS_HTTP%% 55 | 56 | server { 57 | listen 127.0.0.1:8080; 58 | server_name localhost; 59 | 60 | location = /mail/auth { 61 | add_header Auth-Status OK; 62 | add_header Auth-Server 127.0.0.1; 63 | add_header Auth-Port %%PORT_8026%%; 64 | add_header Auth-Wait 1; 65 | return 204; 66 | } 67 | } 68 | } 69 | 70 | EOF 71 | 72 | $t->run_daemon(\&Test::Nginx::SMTP::smtp_test_daemon); 73 | $t->run()->waitforsocket('127.0.0.1:' . port(8026)); 74 | 75 | ############################################################################### 76 | 77 | my $s = Test::Nginx::SMTP->new(); 78 | $s->check(qr/^220 /, "greeting"); 79 | 80 | $s->send('EHLO example.com'); 81 | $s->check(qr/^250 /, "ehlo"); 82 | 83 | $s->send('AUTH PLAIN ' . encode_base64("\0test\@example.com\0secret", '')); 84 | $s->authok('auth plain'); 85 | 86 | $t->reload(); 87 | 88 | ok($s->can_read(), 'mail connection shutdown'); 89 | 90 | undef $s; 91 | 1; 92 | 93 | ############################################################################### 94 | -------------------------------------------------------------------------------- /empty_gif.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | 5 | # Tests for empty gif module. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | use Socket qw/ CRLF /; 15 | 16 | BEGIN { use FindBin; chdir($FindBin::Bin); } 17 | 18 | use lib 'lib'; 19 | use Test::Nginx; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | my $t = Test::Nginx->new()->has(qw/http empty_gif/)->plan(4); 27 | 28 | $t->write_file_expand('nginx.conf', <<'EOF'); 29 | 30 | %%TEST_GLOBALS%% 31 | 32 | daemon off; 33 | 34 | events { 35 | } 36 | 37 | http { 38 | %%TEST_GLOBALS_HTTP%% 39 | 40 | server { 41 | listen 127.0.0.1:8080; 42 | server_name localhost; 43 | 44 | location / { 45 | empty_gif; 46 | } 47 | } 48 | } 49 | 50 | EOF 51 | 52 | $t->run(); 53 | 54 | my $gif = unhex(<<'EOF'); 55 | 0x0000: 47 49 46 38 39 61 01 00 01 00 80 01 00 00 00 00 |GIF89a.. ........| 56 | 0x0010: ff ff ff 21 f9 04 01 00 00 01 00 2c 00 00 00 00 |...!.... ...,....| 57 | 0x0020: 01 00 01 00 00 02 02 4c 01 00 3b |.......L ..;| 58 | EOF 59 | 60 | ############################################################################### 61 | 62 | is(http_get_body('/'), $gif, 'empty gif'); 63 | like(http_get('/'), qr!Content-Type: image/gif!i, 'get content type'); 64 | like(http_head('/'), qr!Content-Type: image/gif!i, 'head content type'); 65 | like(http('PUT / HTTP/1.0' . CRLF . CRLF), qr!405 Not Allowed!i, 'put'); 66 | 67 | ############################################################################### 68 | 69 | sub unhex { 70 | my ($input) = @_; 71 | my $buffer = ''; 72 | 73 | for my $l ($input =~ m/: +((?:[0-9a-f]{2,4} +)+) /gms) { 74 | for my $v ($l =~ m/[0-9a-f]{2}/g) { 75 | $buffer .= chr(hex($v)); 76 | } 77 | } 78 | 79 | return $buffer; 80 | } 81 | 82 | sub http_get_body { 83 | my ($uri) = @_; 84 | 85 | return undef if !defined $uri; 86 | 87 | my $text = http_get($uri); 88 | 89 | if ($text !~ /(.*?)\x0d\x0a?\x0d\x0a?(.*)/ms) { 90 | return undef; 91 | } 92 | 93 | return $2; 94 | } 95 | 96 | ############################################################################### 97 | -------------------------------------------------------------------------------- /quic_key_update.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for QUIC key update. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | use Test::Nginx::HTTP3; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | my $t = Test::Nginx->new()->has(qw/http http_v3 cryptx/) 27 | ->has_daemon('openssl')->plan(3); 28 | 29 | $t->write_file_expand('nginx.conf', <<'EOF'); 30 | 31 | %%TEST_GLOBALS%% 32 | 33 | daemon off; 34 | 35 | events { 36 | } 37 | 38 | http { 39 | %%TEST_GLOBALS_HTTP%% 40 | 41 | ssl_certificate_key localhost.key; 42 | ssl_certificate localhost.crt; 43 | 44 | server { 45 | listen 127.0.0.1:%%PORT_8980_UDP%% quic; 46 | server_name localhost; 47 | 48 | location / { } 49 | } 50 | } 51 | 52 | EOF 53 | 54 | $t->write_file('openssl.conf', <testdir(); 63 | 64 | foreach my $name ('localhost') { 65 | system('openssl req -x509 -new ' 66 | . "-config $d/openssl.conf -subj /CN=$name/ " 67 | . "-out $d/$name.crt -keyout $d/$name.key " 68 | . ">>$d/openssl.out 2>&1") == 0 69 | or die "Can't create certificate for $name: $!\n"; 70 | } 71 | 72 | $t->run(); 73 | 74 | ############################################################################### 75 | 76 | my $s = Test::Nginx::HTTP3->new(); 77 | ok(get($s), 'request'); 78 | 79 | # sets the Key Phase bit 80 | 81 | $s->key_update(); 82 | ok(get($s), 'key update 1'); 83 | 84 | # clears the Key Phase bit 85 | 86 | $s->key_update(); 87 | ok(get($s), 'key update 2'); 88 | 89 | ############################################################################### 90 | 91 | sub get { 92 | my ($s) = @_; 93 | my $frames = $s->read(all => [{ sid => $s->new_stream(), fin => 1 }]); 94 | grep { $_->{type} eq "HEADERS" } @$frames; 95 | } 96 | 97 | ############################################################################### 98 | -------------------------------------------------------------------------------- /h3_reusable.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for HTTP/3, reusable connections. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | use Test::Nginx::HTTP3; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | my $t = Test::Nginx->new()->has(qw/http http_v3 cryptx/) 27 | ->has_daemon('openssl')->plan(1) 28 | ->write_file_expand('nginx.conf', <<'EOF'); 29 | 30 | %%TEST_GLOBALS%% 31 | 32 | daemon off; 33 | 34 | events { 35 | worker_connections 12; 36 | } 37 | 38 | http { 39 | %%TEST_GLOBALS_HTTP%% 40 | 41 | ssl_certificate_key localhost.key; 42 | ssl_certificate localhost.crt; 43 | 44 | server { 45 | listen 127.0.0.1:%%PORT_8980_UDP%% quic; 46 | server_name localhost; 47 | 48 | location / { } 49 | } 50 | } 51 | 52 | EOF 53 | 54 | $t->write_file('openssl.conf', <testdir(); 63 | 64 | foreach my $name ('localhost') { 65 | system('openssl req -x509 -new ' 66 | . "-config $d/openssl.conf -subj /CN=$name/ " 67 | . "-out $d/$name.crt -keyout $d/$name.key " 68 | . ">>$d/openssl.out 2>&1") == 0 69 | or die "Can't create certificate for $name: $!\n"; 70 | } 71 | 72 | $t->run(); 73 | 74 | ############################################################################### 75 | 76 | my $s1 = Test::Nginx::HTTP3->new(); 77 | $s1->insert_literal(':path', '/foo'); 78 | $s1->read(all => [ { type => 'DECODER_ICI' } ]); 79 | 80 | # expect to steal reusable worker connections 81 | 82 | my $s2 = Test::Nginx::HTTP3->new(); 83 | $s2->start_chain(); 84 | my @sids = map { $s2->new_stream() } 1 .. 5; 85 | $s2->send_chain(); 86 | my $frames = $s2->read(all => [ map { { sid => $_, fin => 1 } } @sids ]); 87 | 88 | my $streams = grep { $_->{type} eq "HEADERS" } @$frames; 89 | is($streams, 5, 'streams'); 90 | 91 | ############################################################################### 92 | -------------------------------------------------------------------------------- /rewrite_set.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for rewrite set. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http rewrite ssi/)->plan(4); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | server { 40 | listen 127.0.0.1:8080; 41 | server_name localhost; 42 | 43 | ssi on; 44 | 45 | location /t1 { 46 | set $http_foo "set_foo"; 47 | return 200 'XX'; 48 | } 49 | 50 | location /t2 { 51 | return 200 'XX'; 52 | } 53 | 54 | location /t3 { 55 | return 200 'XX'; 56 | } 57 | 58 | location /t4 { 59 | set $http_connection "bar"; 60 | return 200 "X${http_connection}X\n"; 61 | } 62 | 63 | # set in other context 64 | location /other { 65 | set $http_bar "set_bar"; 66 | } 67 | } 68 | } 69 | 70 | EOF 71 | 72 | $t->run(); 73 | 74 | ############################################################################### 75 | 76 | # prefixed variables 77 | 78 | like(http_get_extra('/t1.html', 'Foo: http_foo'), qr/Xset_fooX/, 79 | 'set in this context'); 80 | like(http_get_extra('/t2.html', 'Bar: http_bar'), qr/Xhttp_barX/, 81 | 'set in other context'); 82 | 83 | like(http_get_extra('/t3.html', 'Baz: http_baz'), qr/Xhttp_bazX/, 'not set'); 84 | 85 | like(http_get('/t4.html'), qr/XbarX/, 'set get in return'); 86 | 87 | ############################################################################### 88 | 89 | sub http_get_extra { 90 | my ($uri, $extra) = @_; 91 | return http(<new()->has(qw/http rewrite sub/)->plan(7) 26 | ->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | http { 36 | %%TEST_GLOBALS_HTTP%% 37 | 38 | server { 39 | listen 127.0.0.1:8080; 40 | server_name localhost; 41 | 42 | sub_filter_types *; 43 | 44 | location /var/replacement { 45 | sub_filter_once off; 46 | sub_filter '${arg_a}' '${arg_a}+'; 47 | sub_filter '${arg_b}' '${arg_b}-'; 48 | return 200 $arg_c; 49 | } 50 | 51 | location /var/replacement2 { 52 | sub_filter_once off; 53 | sub_filter '${arg_a}A${arg_b}' +; 54 | sub_filter '${arg_c}AA${arg_d}' -; 55 | return 200 $arg_e; 56 | } 57 | } 58 | 59 | } 60 | 61 | EOF 62 | 63 | $t->run(); 64 | 65 | ############################################################################### 66 | 67 | like(http_get('/var/replacement?a=a&b=b&c=abXYaXbZ'), 68 | qr/a\+b-XYa\+Xb-Z/, 'complex'); 69 | like(http_get('/var/replacement?a=patt&b=abyz&c=pattabyzXYpattXabyzZpatt'), 70 | qr/patt\+abyz-XYpatt\+Xabyz-Zpatt\+/, 'complex 2'); 71 | like(http_get('/var/replacement?a=a&b=b&c=ABXYAXBZ'), 72 | qr/a\+b-XYa\+Xb-Z/, 'case insensivity'); 73 | like(http_get('/var/replacement?b=b&c=abXYaXbZ'), 74 | qr/ab-XYaXb-Z/, 'one search string is empty'); 75 | like(http_get('/var/replacement?c=abXYaXbZ'), 76 | qr/abXYaXbZ/, 'all search strings are empty'); 77 | like(http_get('/var/replacement2?a=aaa&b=bbb&c=yy&d=zz&e=AaaaAbbbZyyAAzzY'), 78 | qr/A\+Z-Y/, 'multiple variables'); 79 | like(http_get('/var/replacement2?b=bbb&c=yy&e=AAbbbZyyAAY'), 80 | qr/A\+Z-Y/, 'multiple variables 2'); 81 | 82 | ############################################################################### 83 | -------------------------------------------------------------------------------- /fastcgi_variables.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Andrey Zelenkov 4 | # (C) Nginx, Inc. 5 | 6 | # Test for fastcgi variables. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | use Socket qw/ CRLF /; 16 | 17 | BEGIN { use FindBin; chdir($FindBin::Bin); } 18 | 19 | use lib 'lib'; 20 | use Test::Nginx; 21 | 22 | ############################################################################### 23 | 24 | select STDERR; $| = 1; 25 | select STDOUT; $| = 1; 26 | 27 | eval { require FCGI; }; 28 | plan(skip_all => 'FCGI not installed') if $@; 29 | plan(skip_all => 'win32') if $^O eq 'MSWin32'; 30 | 31 | my $t = Test::Nginx->new()->has(qw/http fastcgi rewrite/)->plan(3) 32 | ->write_file_expand('nginx.conf', <<'EOF'); 33 | 34 | %%TEST_GLOBALS%% 35 | 36 | daemon off; 37 | 38 | events { 39 | } 40 | 41 | http { 42 | %%TEST_GLOBALS_HTTP%% 43 | 44 | server { 45 | listen 127.0.0.1:8080; 46 | server_name localhost; 47 | 48 | add_header X-Script-Name $fastcgi_script_name; 49 | add_header X-Path-Info $fastcgi_path_info; 50 | 51 | location / { 52 | fastcgi_pass 127.0.0.1:8081; 53 | fastcgi_index index.php; 54 | } 55 | 56 | location /info { 57 | fastcgi_pass 127.0.0.1:8081; 58 | fastcgi_split_path_info ^(.+\.php)(.*)$; 59 | } 60 | } 61 | } 62 | 63 | EOF 64 | 65 | $t->run_daemon(\&fastcgi_daemon); 66 | $t->run()->waitforsocket('127.0.0.1:' . port(8081)); 67 | 68 | ############################################################################### 69 | 70 | like(http_get('/'), qr/X-Script-Name: \/index\.php/ms, 'script name'); 71 | like(http_get('/info.php/path/info'), qr/X-Script-Name: \/info\.php/ms, 72 | 'info script name'); 73 | like(http_get('/info.php/path/info'), qr/X-Path-Info: \/path\/info/ms, 74 | 'info path'); 75 | 76 | ############################################################################### 77 | 78 | sub fastcgi_daemon { 79 | my $socket = FCGI::OpenSocket('127.0.0.1:' . port(8081), 5); 80 | my $request = FCGI::Request(\*STDIN, \*STDOUT, \*STDERR, \%ENV, 81 | $socket); 82 | 83 | while( $request->Accept() >= 0 ) { 84 | print CRLF . CRLF; 85 | } 86 | 87 | FCGI::CloseSocket($socket); 88 | } 89 | 90 | ############################################################################### 91 | -------------------------------------------------------------------------------- /stream_proxy_ssl_name_complex.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Stream tests for proxy to ssl backend, use of Server Name Indication 7 | # (proxy_ssl_name, proxy_ssl_server_name directives) with complex value. 8 | 9 | ############################################################################### 10 | 11 | use warnings; 12 | use strict; 13 | 14 | use Test::More; 15 | 16 | BEGIN { use FindBin; chdir($FindBin::Bin); } 17 | 18 | use lib 'lib'; 19 | use Test::Nginx; 20 | use Test::Nginx::Stream qw/ stream /; 21 | 22 | ############################################################################### 23 | 24 | select STDERR; $| = 1; 25 | select STDOUT; $| = 1; 26 | 27 | my $t = Test::Nginx->new()->has(qw/stream stream_ssl stream_return sni/) 28 | ->has_daemon('openssl'); 29 | 30 | $t->write_file_expand('nginx.conf', <<'EOF'); 31 | 32 | %%TEST_GLOBALS%% 33 | 34 | daemon off; 35 | 36 | events { 37 | } 38 | 39 | stream { 40 | %%TEST_GLOBALS_STREAM%% 41 | 42 | proxy_ssl on; 43 | proxy_ssl_session_reuse off; 44 | 45 | server { 46 | listen 127.0.0.1:8081; 47 | listen 127.0.0.1:8082; 48 | proxy_pass 127.0.0.1:8085; 49 | 50 | proxy_ssl_server_name on; 51 | proxy_ssl_name x${server_port}x; 52 | } 53 | 54 | server { 55 | ssl_certificate_key localhost.key; 56 | ssl_certificate localhost.crt; 57 | 58 | listen 127.0.0.1:8085 ssl; 59 | return $ssl_server_name; 60 | } 61 | } 62 | 63 | EOF 64 | 65 | $t->write_file('openssl.conf', <testdir(); 74 | 75 | foreach my $name ('localhost') { 76 | system('openssl req -x509 -new ' 77 | . "-config $d/openssl.conf -subj /CN=$name/ " 78 | . "-out $d/$name.crt -keyout $d/$name.key " 79 | . ">>$d/openssl.out 2>&1") == 0 80 | or die "Can't create certificate for $name: $!\n"; 81 | } 82 | 83 | $t->run()->plan(2); 84 | 85 | ############################################################################### 86 | 87 | my ($p1, $p2) = (port(8081), port(8082)); 88 | 89 | is(stream("127.0.0.1:$p1")->read(), "x${p1}x", 'name 1'); 90 | is(stream("127.0.0.1:$p2")->read(), "x${p2}x", 'name 2'); 91 | 92 | ############################################################################### 93 | -------------------------------------------------------------------------------- /stream_limit_conn_complex.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Andrey Zelenkov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for stream limit_conn module. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http stream stream_limit_conn/) 26 | ->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | stream { 36 | %%TEST_GLOBALS_STREAM%% 37 | 38 | limit_conn_zone $binary_remote_addr$server_port zone=zone:1m; 39 | 40 | server { 41 | listen 127.0.0.1:8080; 42 | proxy_pass 127.0.0.1:8084; 43 | limit_conn zone 1; 44 | } 45 | 46 | server { 47 | listen 127.0.0.1:8081; 48 | proxy_pass 127.0.0.1:8084; 49 | limit_conn zone 1; 50 | } 51 | } 52 | 53 | http { 54 | %%TEST_GLOBALS_HTTP%% 55 | 56 | server { 57 | listen 127.0.0.1:8084; 58 | server_name localhost; 59 | 60 | location / { } 61 | } 62 | } 63 | 64 | EOF 65 | 66 | $t->write_file('index.html', ''); 67 | $t->run()->plan(4); 68 | 69 | ############################################################################### 70 | 71 | like(get(port(8080)), qr/200 OK/, 'passed'); 72 | 73 | my $s = http(< 1, sleep => 0.2); 74 | GET / HTTP/1.0 75 | EOF 76 | 77 | ok($s, 'long connection'); 78 | 79 | is(get(port(8080)), undef, 'rejected same key'); 80 | like(get(port(8081)), qr/200 OK/, 'passed different key'); 81 | 82 | ############################################################################### 83 | 84 | sub get { 85 | my $port = shift; 86 | 87 | my $s = IO::Socket::INET->new( 88 | Proto => 'tcp', 89 | PeerAddr => "127.0.0.1:$port" 90 | ) 91 | or die "Can't connect to nginx: $!\n"; 92 | 93 | my $r = http_get('/', socket => $s); 94 | if (!$r) { 95 | $r = undef; 96 | } 97 | 98 | return $r; 99 | } 100 | 101 | ############################################################################### 102 | -------------------------------------------------------------------------------- /realip_remote_port.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Andrey Zelenkov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for nginx realip module, $realip_remote_port variable. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx qw/ :DEFAULT http_end /; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http realip/) 26 | ->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | http { 36 | %%TEST_GLOBALS_HTTP%% 37 | 38 | set_real_ip_from 127.0.0.1/32; 39 | real_ip_header X-Forwarded-For; 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | server_name localhost; 44 | 45 | location / { 46 | add_header X-IP $remote_addr; 47 | add_header X-Real-Port $realip_remote_port; 48 | } 49 | } 50 | } 51 | 52 | EOF 53 | 54 | $t->write_file('index.html', ''); 55 | $t->write_file('1', ''); 56 | $t->run(); 57 | 58 | plan(skip_all => 'no 127.0.0.1 on host') 59 | if http_get('/') !~ /X-IP: 127.0.0.1/m; 60 | 61 | $t->plan(4); 62 | 63 | ############################################################################### 64 | 65 | my ($sp, $data) = http_sp_get('/1'); 66 | like($data, qr/X-Real-Port: $sp/, 'request'); 67 | 68 | ($sp, $data) = http_sp_get('/'); 69 | like($data, qr/X-Real-Port: $sp/, 'request redirect'); 70 | 71 | ($sp, $data) = http_sp_xff('/1', '127.0.0.1:123'); 72 | like($data, qr/X-Real-Port: $sp/, 'realip'); 73 | 74 | ($sp, $data) = http_sp_xff('/', '127.0.0.1:123'); 75 | like($data, qr/X-Real-Port: $sp/, 'realip redirect'); 76 | 77 | ############################################################################### 78 | 79 | sub http_sp_get { 80 | my $s = http_get(shift, start => 1); 81 | return ($s->sockport(), http_end($s)); 82 | } 83 | 84 | sub http_sp_xff { 85 | my ($url, $xff) = @_; 86 | 87 | my $s = http(< 1); 88 | GET $url HTTP/1.0 89 | Host: localhost 90 | X-Forwarded-For: $xff 91 | 92 | EOF 93 | 94 | return ($s->sockport(), http_end($s)); 95 | } 96 | 97 | ############################################################################### 98 | -------------------------------------------------------------------------------- /proxy_cache_path.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for http proxy cache with use_temp_path parameter. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http proxy cache/)->plan(6) 26 | ->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | http { 36 | %%TEST_GLOBALS_HTTP%% 37 | 38 | proxy_cache_path %%TESTDIR%%/cache1 39 | keys_zone=ON:1m use_temp_path=on; 40 | proxy_cache_path %%TESTDIR%%/cache2 41 | keys_zone=OFF:1m use_temp_path=off; 42 | proxy_cache_path %%TESTDIR%%/cache4 levels=1:2 43 | keys_zone=LEVELS:1m use_temp_path=off; 44 | 45 | server { 46 | listen 127.0.0.1:8080; 47 | server_name localhost; 48 | 49 | location / { 50 | proxy_pass http://127.0.0.1:8081; 51 | 52 | proxy_cache $arg_c; 53 | 54 | proxy_cache_valid any 1m; 55 | 56 | add_header X-Cache-Status $upstream_cache_status; 57 | } 58 | } 59 | 60 | server { 61 | listen 127.0.0.1:8081; 62 | server_name localhost; 63 | 64 | location / { 65 | } 66 | } 67 | } 68 | 69 | EOF 70 | 71 | $t->write_file('t', 'SEE-THIS'); 72 | 73 | $t->run(); 74 | 75 | ############################################################################### 76 | 77 | like(http_get('/t?c=ON'), qr/MISS.*SEE-THIS/ms, 'temp path'); 78 | like(http_get('/t?c=OFF'), qr/MISS.*SEE-THIS/ms, 'temp path off'); 79 | like(http_get('/t?c=LEVELS'), qr/MISS.*SEE-THIS/ms, 'temp path levels'); 80 | 81 | $t->write_file('t', 'SEE-THAT'); 82 | 83 | like(http_get('/t?c=ON'), qr/HIT.*SEE-THIS/ms, 'temp path cached'); 84 | like(http_get('/t?c=OFF'), qr/HIT.*SEE-THIS/ms, 'temp path cached off'); 85 | like(http_get('/t?c=LEVELS'), qr/HIT.*SEE-THIS/ms, 'temp path cached levels'); 86 | 87 | ############################################################################### 88 | -------------------------------------------------------------------------------- /gunzip_ssi.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | # Tests for gunzip filter module with subrequests. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx qw/ :DEFAULT :gzip /; 18 | 19 | ############################################################################### 20 | 21 | select STDERR; $| = 1; 22 | select STDOUT; $| = 1; 23 | 24 | eval { require IO::Compress::Gzip; }; 25 | plan(skip_all => "IO::Compress::Gzip not found") if $@; 26 | 27 | my $t = Test::Nginx->new()->has(qw/http gunzip ssi proxy gzip_static/) 28 | ->plan(4); 29 | 30 | $t->write_file_expand('nginx.conf', <<'EOF'); 31 | 32 | %%TEST_GLOBALS%% 33 | 34 | daemon off; 35 | 36 | events { 37 | } 38 | 39 | http { 40 | %%TEST_GLOBALS_HTTP%% 41 | 42 | server { 43 | listen 127.0.0.1:8080; 44 | server_name localhost; 45 | 46 | location / { 47 | gunzip on; 48 | gzip_vary on; 49 | proxy_pass http://127.0.0.1:8081/; 50 | proxy_set_header Accept-Encoding gzip; 51 | } 52 | 53 | location /t.html { 54 | ssi on; 55 | } 56 | } 57 | 58 | server { 59 | listen 127.0.0.1:8081; 60 | server_name localhost; 61 | 62 | location / { 63 | default_type text/plain; 64 | gzip_static on; 65 | gzip_http_version 1.0; 66 | gzip_types text/plain; 67 | } 68 | } 69 | } 70 | 71 | EOF 72 | 73 | my $in = join('', map { sprintf "X%03dXXXXXX", $_ } (0 .. 99)); 74 | my $out; 75 | 76 | IO::Compress::Gzip::gzip(\$in => \$out); 77 | 78 | $t->write_file('t1.gz', $out); 79 | $t->write_file('t.html', 'xxx xxx'); 80 | 81 | $t->run(); 82 | 83 | ############################################################################### 84 | 85 | my $r = http_get('/t.html'); 86 | unlike($r, qr/Content-Encoding/, 'no content encoding'); 87 | like($r, qr/^xxx (X\d\d\dXXXXXX){100} xxx$/m, 'correct gunzipped response'); 88 | 89 | $r = http_gzip_request('/t.html'); 90 | unlike($r, qr/Content-Encoding/, 'gzip - no content encoding'); 91 | like($r, qr/(X\d\d\dXXXXXX){100}/m, 'gzip - correct gunzipped response'); 92 | 93 | ############################################################################### 94 | -------------------------------------------------------------------------------- /proxy_cache_error.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | # Tests for http proxy cache, "header already sent" alerts on backend errors, 6 | # http://mailman.nginx.org/pipermail/nginx-devel/2018-January/010737.html. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http proxy cache/)->plan(1) 26 | ->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | http { 36 | %%TEST_GLOBALS_HTTP%% 37 | 38 | proxy_cache_path %%TESTDIR%%/cache levels=1:2 39 | keys_zone=NAME:1m; 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | server_name localhost; 44 | 45 | location / { 46 | proxy_pass http://127.0.0.1:8081; 47 | proxy_cache NAME; 48 | 49 | proxy_read_timeout 500ms; 50 | } 51 | } 52 | 53 | server { 54 | listen 127.0.0.1:8081; 55 | server_name localhost; 56 | 57 | location / { 58 | postpone_output 0; 59 | limit_rate 512; 60 | expires 1m; 61 | } 62 | } 63 | } 64 | 65 | EOF 66 | 67 | $t->write_file('big.html', 'x' x 1024); 68 | 69 | $t->run(); 70 | 71 | ############################################################################### 72 | 73 | # make a HEAD request; since cache is enabled, nginx converts HEAD to GET 74 | # and will set u->pipe->downstream_error to suppress sending the response 75 | # body to the client 76 | 77 | like(http_head('/big.html'), qr/200 OK/, 'head request'); 78 | 79 | # once proxy_read_timeout expires, nginx will call 80 | # ngx_http_finalize_upstream_request() with u->pipe->downstream_error set 81 | # and rc = NGX_HTTP_BAD_GATEWAY; after revision 2aa6d7fd6 (1.9.13) this 82 | # will result in ngx_http_finalize_request(NGX_HTTP_BAD_GATEWAY), 83 | # leading to an attempt to return additional error response and 84 | # the "header already sent" alert; fixed in 3377c0011 (1.13.9) 85 | 86 | ############################################################################### 87 | -------------------------------------------------------------------------------- /fastcgi_split.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | # Test for fastcgi backend. 6 | # Incorrect split headers handling after switching to next server, 7 | # as reported by Lucas Molas. 8 | 9 | ############################################################################### 10 | 11 | use warnings; 12 | use strict; 13 | 14 | use Test::More; 15 | use Socket qw/ CR LF CRLF /; 16 | 17 | BEGIN { use FindBin; chdir($FindBin::Bin); } 18 | 19 | use lib 'lib'; 20 | use Test::Nginx; 21 | 22 | ############################################################################### 23 | 24 | select STDERR; $| = 1; 25 | select STDOUT; $| = 1; 26 | 27 | eval { require FCGI; }; 28 | plan(skip_all => 'FCGI not installed') if $@; 29 | plan(skip_all => 'win32') if $^O eq 'MSWin32'; 30 | 31 | my $t = Test::Nginx->new()->has(qw/http fastcgi/)->plan(1) 32 | ->write_file_expand('nginx.conf', <<'EOF'); 33 | 34 | %%TEST_GLOBALS%% 35 | 36 | daemon off; 37 | 38 | events { 39 | } 40 | 41 | http { 42 | %%TEST_GLOBALS_HTTP%% 43 | 44 | upstream u { 45 | server 127.0.0.1:8081; 46 | server 127.0.0.1:8082; 47 | } 48 | 49 | server { 50 | listen 127.0.0.1:8080; 51 | server_name localhost; 52 | 53 | location / { 54 | fastcgi_pass u; 55 | fastcgi_param REQUEST_URI $request_uri; 56 | fastcgi_next_upstream invalid_header; 57 | } 58 | } 59 | } 60 | 61 | EOF 62 | 63 | $t->run_daemon(\&fastcgi_daemon, port(8081)); 64 | $t->run_daemon(\&fastcgi_daemon, port(8082)); 65 | 66 | $t->run(); 67 | 68 | $t->waitforsocket('127.0.0.1:' . port(8081)); 69 | $t->waitforsocket('127.0.0.1:' . port(8082)); 70 | 71 | ############################################################################### 72 | 73 | like(http_get('/'), qr/^Good: header/ms, 'fastcgi next upstream'); 74 | 75 | ############################################################################### 76 | 77 | sub fastcgi_daemon { 78 | my ($port) = @_; 79 | my $socket = FCGI::OpenSocket("127.0.0.1:$port", 5); 80 | my $request = FCGI::Request(\*STDIN, \*STDOUT, \*STDERR, \%ENV, 81 | $socket); 82 | 83 | my $count; 84 | while( $request->Accept() >= 0 ) { 85 | $count++; 86 | 87 | if ($port == port(8081)) { 88 | print 'BAD'; 89 | } 90 | if ($port == port(8082)) { 91 | print 'Good: header' . CRLF . CRLF; 92 | } 93 | } 94 | 95 | FCGI::CloseSocket($socket); 96 | } 97 | 98 | ############################################################################### 99 | -------------------------------------------------------------------------------- /h2_proxy_ssl.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for HTTP/2 protocol with proxy to ssl backend. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | use Test::Nginx::HTTP2; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | my $t = Test::Nginx->new()->has(qw/http http_ssl http_v2 proxy/) 27 | ->has_daemon('openssl')->plan(1); 28 | 29 | $t->write_file_expand('nginx.conf', <<'EOF'); 30 | 31 | %%TEST_GLOBALS%% 32 | 33 | daemon off; 34 | 35 | events { 36 | } 37 | 38 | http { 39 | %%TEST_GLOBALS_HTTP%% 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | listen 127.0.0.1:8081 ssl; 44 | server_name localhost; 45 | 46 | http2 on; 47 | 48 | ssl_certificate_key localhost.key; 49 | ssl_certificate localhost.crt; 50 | 51 | location / { } 52 | location /proxy_ssl/ { 53 | proxy_pass https://127.0.0.1:8081/; 54 | } 55 | } 56 | } 57 | 58 | EOF 59 | 60 | $t->write_file('openssl.conf', <testdir(); 69 | 70 | foreach my $name ('localhost') { 71 | system('openssl req -x509 -new ' 72 | . "-config $d/openssl.conf -subj /CN=$name/ " 73 | . "-out $d/$name.crt -keyout $d/$name.key " 74 | . ">>$d/openssl.out 2>&1") == 0 75 | or die "Can't create certificate for $name: $!\n"; 76 | } 77 | 78 | $t->write_file('index.html', ''); 79 | $t->run(); 80 | 81 | ############################################################################### 82 | 83 | # request body with an empty DATA frame proxied to ssl backend 84 | # "zero size buf in output" alerts seen 85 | 86 | my $s = Test::Nginx::HTTP2->new(); 87 | my $sid = $s->new_stream({ path => '/proxy_ssl/', body_more => 1 }); 88 | $s->h2_body(''); 89 | my $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); 90 | 91 | my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames; 92 | is($frame->{headers}->{':status'}, 200, 'empty request body'); 93 | 94 | ############################################################################### 95 | -------------------------------------------------------------------------------- /gzip.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | # Tests for nginx gzip filter module. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx qw/ :DEFAULT :gzip /; 18 | 19 | ############################################################################### 20 | 21 | select STDERR; $| = 1; 22 | select STDOUT; $| = 1; 23 | 24 | my $t = Test::Nginx->new()->has(qw/http proxy gzip/)->plan(8); 25 | 26 | $t->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | http { 36 | %%TEST_GLOBALS_HTTP%% 37 | 38 | server { 39 | listen 127.0.0.1:8080; 40 | server_name localhost; 41 | location / { 42 | gzip on; 43 | } 44 | location /proxy/ { 45 | gzip on; 46 | proxy_pass http://127.0.0.1:8080/local/; 47 | } 48 | location /local/ { 49 | gzip off; 50 | alias %%TESTDIR%%/; 51 | } 52 | } 53 | } 54 | 55 | EOF 56 | 57 | $t->write_file('index.html', 'X' x 64); 58 | 59 | $t->run(); 60 | 61 | ############################################################################### 62 | 63 | my $r; 64 | 65 | $r = http_gzip_request('/'); 66 | like($r, qr/^Content-Encoding: gzip/m, 'gzip'); 67 | http_gzip_like($r, qr/^X{64}\Z/, 'gzip content correct'); 68 | 69 | $r = http_gzip_request('/proxy/'); 70 | like($r, qr/^Content-Encoding: gzip/m, 'gzip proxied'); 71 | http_gzip_like($r, qr/^X{64}\Z/, 'gzip proxied content'); 72 | 73 | # Accept-Ranges headers should be cleared 74 | 75 | unlike(http_gzip_request('/'), qr/Accept-Ranges/im, 'cleared accept-ranges'); 76 | unlike(http_gzip_request('/proxy/'), qr/Accept-Ranges/im, 77 | 'cleared headers from proxy'); 78 | 79 | # HEAD requests should return correct headers 80 | 81 | like(http_gzip_head('/'), qr/Content-Encoding: gzip/, 'gzip head'); 82 | unlike(http_head('/'), qr/Content-Encoding: gzip/, 'no gzip head'); 83 | 84 | ############################################################################### 85 | 86 | sub http_gzip_head { 87 | my ($uri) = @_; 88 | return http(<new()->has(qw/http proxy limit_conn limit_req/); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | limit_req_zone $binary_remote_addr zone=req:1m rate=30r/m; 40 | limit_conn_zone $binary_remote_addr zone=zone:1m; 41 | 42 | log_format test $uri:$limit_conn_status; 43 | 44 | server { 45 | listen 127.0.0.1:8081; 46 | server_name localhost; 47 | 48 | location /w { 49 | limit_req zone=req burst=10; 50 | } 51 | } 52 | 53 | server { 54 | listen 127.0.0.1:8080; 55 | server_name localhost; 56 | 57 | add_header X-Status $limit_conn_status always; 58 | access_log %%TESTDIR%%/test.log test; 59 | 60 | location /reject { 61 | proxy_pass http://127.0.0.1:8081/w; 62 | limit_conn zone 1; 63 | } 64 | 65 | location /dry { 66 | limit_conn zone 1; 67 | limit_conn_dry_run on; 68 | } 69 | 70 | location / { } 71 | } 72 | } 73 | 74 | EOF 75 | 76 | $t->write_file('w', ''); 77 | $t->run()->plan(6); 78 | 79 | ############################################################################### 80 | 81 | like(http_get('/reject'), qr/ 200 .*PASSED/s, 'passed'); 82 | 83 | my $s = http_get('/reject', start => 1); 84 | like(http_get('/reject'), qr/ 503 .*REJECTED(?!_)/s, 'rejected'); 85 | like(http_get('/dry'), qr/ 404 .*REJECTED_DRY_RUN/s, 'rejected dry run'); 86 | unlike(http_get('/'), qr/X-Status/, 'no limit'); 87 | 88 | close $s; 89 | 90 | $t->stop(); 91 | 92 | like($t->read_file('error.log'), qr/limiting connections, dry/, 'log dry run'); 93 | like($t->read_file('test.log'), qr|^/:-|m, 'log not found'); 94 | 95 | ############################################################################### 96 | -------------------------------------------------------------------------------- /limit_req_dry_run.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for nginx limit_req module, limit_req_dry_run directive. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http limit_req/); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | limit_req_zone $binary_remote_addr zone=one:1m rate=1r/m; 40 | 41 | log_format test $uri:$limit_req_status; 42 | 43 | server { 44 | listen 127.0.0.1:8080; 45 | server_name localhost; 46 | 47 | limit_req_dry_run on; 48 | add_header X-Status $limit_req_status always; 49 | access_log %%TESTDIR%%/test.log test; 50 | 51 | location /delay { 52 | limit_req zone=one burst=2; 53 | } 54 | 55 | location /reject { 56 | limit_req zone=one; 57 | } 58 | 59 | location /reject/off { 60 | limit_req zone=one; 61 | 62 | limit_req_dry_run off; 63 | } 64 | 65 | location / { } 66 | } 67 | } 68 | 69 | EOF 70 | 71 | $t->write_file('delay', 'SEE-THIS'); 72 | $t->write_file('reject', 'SEE-THIS'); 73 | $t->run()->plan(8); 74 | 75 | ############################################################################### 76 | 77 | like(http_get('/delay'), qr/ 200 .*PASSED/ms, 'dry run - passed'); 78 | like(http_get('/delay'), qr/ 200 .*DELAYED_DRY_RUN/ms, 'dry run - delayed'); 79 | like(http_get('/reject'), qr/ 200 .*REJECTED_DRY_RUN/ms, 'dry run - rejected'); 80 | 81 | like(http_get('/reject/off'), qr/ 503 .*REJECTED/ms, 'dry run off - rejected'); 82 | 83 | unlike(http_get('/'), qr/X-Status/, 'no limit'); 84 | 85 | $t->stop(); 86 | 87 | like($t->read_file('error.log'), qr/delaying request, dry/, 'log - delay'); 88 | like($t->read_file('error.log'), qr/limiting requests, dry/, 'log - reject'); 89 | 90 | like($t->read_file('test.log'), qr|^/:-|m, 'log - not found'); 91 | 92 | ############################################################################### 93 | -------------------------------------------------------------------------------- /sub_filter_slice.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for slice filter with sub filter. 7 | 8 | # A response is sent using chunked encoding. 9 | 10 | ############################################################################### 11 | 12 | use warnings; 13 | use strict; 14 | 15 | use Test::More; 16 | 17 | BEGIN { use FindBin; chdir($FindBin::Bin); } 18 | 19 | use lib 'lib'; 20 | use Test::Nginx qw/ :DEFAULT http_content /; 21 | 22 | ############################################################################### 23 | 24 | select STDERR; $| = 1; 25 | select STDOUT; $| = 1; 26 | 27 | my $t = Test::Nginx->new()->has(qw/http proxy slice sub/)->plan(3); 28 | 29 | $t->write_file_expand('nginx.conf', <<'EOF'); 30 | 31 | %%TEST_GLOBALS%% 32 | 33 | daemon off; 34 | 35 | events { 36 | } 37 | 38 | http { 39 | %%TEST_GLOBALS_HTTP%% 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | server_name localhost; 44 | 45 | location / { 46 | sub_filter foo bar; 47 | sub_filter_types *; 48 | 49 | slice 2; 50 | 51 | proxy_pass http://127.0.0.1:8081/; 52 | 53 | proxy_set_header Range $slice_range; 54 | } 55 | } 56 | 57 | server { 58 | listen 127.0.0.1:8081; 59 | server_name localhost; 60 | 61 | location / { } 62 | } 63 | } 64 | 65 | EOF 66 | 67 | $t->write_file('t', '0123456789'); 68 | $t->run(); 69 | 70 | ############################################################################### 71 | 72 | my $r; 73 | 74 | # range filter in subrequests (subrequest_ranges) 75 | 76 | $r = get('/t', 'Range: bytes=2-4'); 77 | unlike($r, qr/\x0d\x0a?0\x0d\x0a?\x0d\x0a?\w/, 'only final chunk'); 78 | 79 | TODO: { 80 | local $TODO = 'not yet'; 81 | 82 | # server is assumed to return the requested range 83 | 84 | $r = get('/t', 'Range: bytes=3-4'); 85 | like($r, qr/ 206 /, 'range request - 206 partial reply'); 86 | is(http_content($r), '34', 'range request - correct content'); 87 | 88 | } 89 | 90 | ############################################################################### 91 | 92 | sub get { 93 | my ($url, $extra) = @_; 94 | return http(<new() 26 | ->has(qw/stream stream_ssl http http_ssl openssl:1.0.2/) 27 | ->has_daemon('openssl'); 28 | 29 | $t->write_file_expand('nginx.conf', <<'EOF'); 30 | 31 | %%TEST_GLOBALS%% 32 | 33 | daemon off; 34 | 35 | events { 36 | } 37 | 38 | stream { 39 | %%TEST_GLOBALS_STREAM%% 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | proxy_pass 127.0.0.1:8081; 44 | proxy_ssl on; 45 | 46 | proxy_ssl_certificate localhost.crt; 47 | proxy_ssl_certificate_key localhost.key; 48 | proxy_ssl_conf_command Certificate override.crt; 49 | proxy_ssl_conf_command PrivateKey override.key; 50 | } 51 | } 52 | 53 | http { 54 | %%TEST_GLOBALS_HTTP%% 55 | 56 | server { 57 | listen 127.0.0.1:8081 ssl; 58 | server_name localhost; 59 | 60 | ssl_certificate localhost.crt; 61 | ssl_certificate_key localhost.key; 62 | ssl_verify_client optional_no_ca; 63 | 64 | add_header X-Cert $ssl_client_s_dn always; 65 | } 66 | } 67 | 68 | EOF 69 | 70 | $t->write_file('openssl.conf', <testdir(); 79 | 80 | foreach my $name ('localhost', 'override') { 81 | system('openssl req -x509 -new ' 82 | . "-config $d/openssl.conf -subj /CN=$name/ " 83 | . "-out $d/$name.crt -keyout $d/$name.key " 84 | . ">>$d/openssl.out 2>&1") == 0 85 | or die "Can't create certificate for $name: $!\n"; 86 | } 87 | 88 | $t->write_file('index.html', ''); 89 | $t->try_run('no ssl_conf_command')->plan(1); 90 | 91 | ############################################################################### 92 | 93 | like(http_get('/'), qr/CN=override/, 'proxy_ssl_conf_command'); 94 | 95 | ############################################################################### 96 | -------------------------------------------------------------------------------- /memcached.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | # Test for memcached backend. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx; 18 | 19 | ############################################################################### 20 | 21 | select STDERR; $| = 1; 22 | select STDOUT; $| = 1; 23 | 24 | eval { require Cache::Memcached; }; 25 | plan(skip_all => 'Cache::Memcached not installed') if $@; 26 | 27 | my $t = Test::Nginx->new()->has(qw/http rewrite memcached/) 28 | ->has_daemon('memcached')->plan(4) 29 | ->write_file_expand('nginx.conf', <<'EOF'); 30 | 31 | %%TEST_GLOBALS%% 32 | 33 | daemon off; 34 | 35 | events { 36 | } 37 | 38 | http { 39 | %%TEST_GLOBALS_HTTP%% 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | server_name localhost; 44 | 45 | location / { 46 | set $memcached_key $uri; 47 | memcached_pass 127.0.0.1:8081; 48 | } 49 | 50 | location /next { 51 | set $memcached_key $uri; 52 | memcached_next_upstream not_found; 53 | memcached_pass 127.0.0.1:8081; 54 | } 55 | } 56 | } 57 | 58 | EOF 59 | 60 | my $memhelp = `memcached -h`; 61 | my @memopts = (); 62 | 63 | if ($memhelp =~ /repcached/) { 64 | # repcached patch adds additional listen socket 65 | push @memopts, '-X', port(8082); 66 | } 67 | if ($memhelp =~ /-U/) { 68 | # UDP port is on by default in memcached 1.2.7+ 69 | push @memopts, '-U', '0'; 70 | } 71 | 72 | $t->run_daemon('memcached', '-l', '127.0.0.1', '-p', port(8081), @memopts); 73 | $t->run(); 74 | 75 | $t->waitforsocket('127.0.0.1:' . port(8081)) 76 | or die "Can't start memcached"; 77 | 78 | ############################################################################### 79 | 80 | my $memd = Cache::Memcached->new(servers => [ '127.0.0.1:' . port(8081) ], 81 | connect_timeout => 1.0); 82 | $memd->set('/', 'SEE-THIS') 83 | or die "can't put value into memcached: $!"; 84 | 85 | like(http_get('/'), qr/SEE-THIS/, 'memcached request'); 86 | 87 | like(http_get('/notfound'), qr/ 404 /, 'memcached not found'); 88 | 89 | like(http_get('/next'), qr/ 404 /, 'not found with memcached_next_upstream'); 90 | 91 | unlike(http_head('/'), qr/SEE-THIS/, 'memcached no data in HEAD'); 92 | 93 | ############################################################################### 94 | -------------------------------------------------------------------------------- /h2_auth_request.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Andrey Zelenkov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for HTTP/2 protocol with auth_request. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | use Test::Nginx::HTTP2; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | my $t = Test::Nginx->new()->has(qw/http http_v2 rewrite proxy auth_request/) 27 | ->plan(2); 28 | 29 | $t->write_file_expand('nginx.conf', <<'EOF'); 30 | 31 | %%TEST_GLOBALS%% 32 | 33 | daemon off; 34 | 35 | events { 36 | } 37 | 38 | http { 39 | %%TEST_GLOBALS_HTTP%% 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | listen 127.0.0.1:8081; 44 | server_name localhost; 45 | 46 | http2 on; 47 | 48 | location / { 49 | return 200; 50 | } 51 | location /auth { 52 | add_header X-Body-File $request_body_file; 53 | client_body_buffer_size 512; 54 | auth_request /auth_request; 55 | proxy_pass http://127.0.0.1:8081/auth_proxy; 56 | } 57 | location /auth_request { 58 | proxy_pass http://127.0.0.1:8081/; 59 | proxy_pass_request_body off; 60 | proxy_set_header Content-Length ""; 61 | } 62 | location /auth_proxy { 63 | add_header X-Body $request_body; 64 | proxy_pass http://127.0.0.1:8081/; 65 | } 66 | } 67 | } 68 | 69 | EOF 70 | 71 | $t->run(); 72 | 73 | ############################################################################### 74 | 75 | my ($s, $sid, $frames, $frame); 76 | 77 | # second stream is used to induce body corruption issue 78 | 79 | $s = Test::Nginx::HTTP2->new(); 80 | $sid = $s->new_stream({ path => '/auth', method => 'POST', body => 'A' x 600 }); 81 | $s->new_stream({ path => '/auth', method => 'POST', body => 'B' x 600 }); 82 | $frames = $s->read(all => [{ sid => $sid, fin => 1 }]); 83 | 84 | ($frame) = grep { $_->{type} eq "HEADERS" && $_->{sid} == $sid } @$frames; 85 | is($frame->{headers}->{'x-body'}, 'A' x 600, 'auth request body'); 86 | isnt($frame->{headers}->{'x-body-file'}, undef, 'auth request body file'); 87 | 88 | ############################################################################### 89 | -------------------------------------------------------------------------------- /limit_conn_complex.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # limit_req based tests for limit_conn module with complex keys. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | use IO::Select; 16 | 17 | BEGIN { use FindBin; chdir($FindBin::Bin); } 18 | 19 | use lib 'lib'; 20 | use Test::Nginx; 21 | 22 | ############################################################################### 23 | 24 | select STDERR; $| = 1; 25 | select STDOUT; $| = 1; 26 | 27 | my $t = Test::Nginx->new()->has(qw/http proxy limit_conn limit_req/) 28 | ->plan(4); 29 | 30 | $t->write_file_expand('nginx.conf', <<'EOF'); 31 | 32 | %%TEST_GLOBALS%% 33 | 34 | daemon off; 35 | 36 | events { 37 | } 38 | 39 | http { 40 | %%TEST_GLOBALS_HTTP%% 41 | 42 | limit_req_zone $binary_remote_addr$arg_r zone=req:1m rate=1r/m; 43 | limit_req_zone $binary_remote_addr zone=re2:1m rate=1r/m; 44 | limit_conn_zone $binary_remote_addr$arg_c zone=conn:1m; 45 | 46 | server { 47 | listen 127.0.0.1:8080; 48 | server_name localhost; 49 | 50 | location / { 51 | limit_conn conn 1; 52 | } 53 | 54 | location /w { 55 | limit_conn conn 1; 56 | proxy_pass http://127.0.0.1:8080/req2; 57 | } 58 | 59 | location /req { 60 | limit_req zone=req burst=2; 61 | } 62 | 63 | location /req2 { 64 | limit_req zone=re2 burst=2; 65 | } 66 | } 67 | } 68 | 69 | EOF 70 | 71 | $t->write_file('req', ''); 72 | $t->run(); 73 | 74 | ############################################################################### 75 | 76 | my $s; 77 | 78 | # charge limit_req 79 | 80 | http_get('/req'); 81 | 82 | # limit_req tests 83 | 84 | $s = http_get('/req', start => 1); 85 | ok(!IO::Select->new($s)->can_read(1), 'limit_req same key'); 86 | 87 | like(http_get('/req?r=2'), qr/200 OK/, 'limit_req different key'); 88 | 89 | # limit_conn tests 90 | 91 | http_get('/req2'); 92 | 93 | $s = http_get('/w', start => 1); 94 | select undef, undef, undef, 0.2; 95 | 96 | like(http_get('/'), qr/^HTTP\/1.. 503 /, 'limit_conn same key'); 97 | unlike(http_get('/?c=2'), qr/^HTTP\/1.. 503 /, 'limit_conn different key'); 98 | 99 | ############################################################################### 100 | -------------------------------------------------------------------------------- /proxy_cache_bypass.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | # Tests for http proxy cache, proxy_cache_bypass. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx; 18 | 19 | ############################################################################### 20 | 21 | select STDERR; $| = 1; 22 | select STDOUT; $| = 1; 23 | 24 | my $t = Test::Nginx->new()->has(qw/http proxy cache rewrite/)->plan(8) 25 | ->write_file_expand('nginx.conf', <<'EOF'); 26 | 27 | %%TEST_GLOBALS%% 28 | 29 | daemon off; 30 | 31 | events { 32 | } 33 | 34 | http { 35 | %%TEST_GLOBALS_HTTP%% 36 | 37 | proxy_cache_path %%TESTDIR%%/cache keys_zone=one:1m; 38 | 39 | server { 40 | listen 127.0.0.1:8080; 41 | server_name localhost; 42 | 43 | location / { 44 | proxy_pass http://127.0.0.1:8081; 45 | 46 | proxy_cache one; 47 | proxy_cache_key $uri; 48 | proxy_cache_bypass $arg_bypass; 49 | proxy_cache_valid any 1y; 50 | 51 | proxy_intercept_errors on; 52 | error_page 404 = @fallback; 53 | } 54 | 55 | location @fallback { 56 | return 403; 57 | } 58 | 59 | add_header X-Cache-Status $upstream_cache_status; 60 | } 61 | 62 | server { 63 | listen 127.0.0.1:8081; 64 | server_name localhost; 65 | 66 | location / { 67 | } 68 | } 69 | } 70 | 71 | EOF 72 | 73 | $t->write_file('t', 'SEE-THIS'); 74 | 75 | $t->run(); 76 | 77 | ############################################################################### 78 | 79 | like(http_get('/t'), qr/SEE-THIS/, 'request'); 80 | 81 | $t->write_file('t', 'NOOP'); 82 | 83 | like(http_get('/t'), qr/SEE-THIS/, 'request cached'); 84 | like(http_get('/t?bypass=1'), qr/NOOP/, 'cache bypassed'); 85 | like(http_get('/t'), qr/NOOP/, 'cached after bypass'); 86 | 87 | # ticket #827, cache item "error" field was not cleared 88 | # on cache bypass 89 | 90 | like(http_get('/t2'), qr/403 Forbidden/, 'intercepted error'); 91 | 92 | $t->write_file('t2', 'NOOP'); 93 | 94 | like(http_get('/t2'), qr/403 Forbidden/, 'error cached'); 95 | like(http_get('/t2?bypass=1'), qr/NOOP/, 'error cache bypassed'); 96 | like(http_get('/t2'), qr/NOOP/, 'error cached after bypass'); 97 | 98 | ############################################################################### 99 | -------------------------------------------------------------------------------- /http_listen.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for listen port ranges. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http proxy rewrite/); 26 | 27 | $t->write_file_expand('nginx.conf', <<'EOF'); 28 | 29 | %%TEST_GLOBALS%% 30 | 31 | daemon off; 32 | 33 | events { 34 | } 35 | 36 | http { 37 | %%TEST_GLOBALS_HTTP%% 38 | 39 | server { 40 | listen 127.0.0.1:8080; 41 | listen 127.0.0.1:%%PORT_8182%%-%%PORT_8183%%; 42 | listen [::1]:%%PORT_8182%%-%%PORT_8183%%; 43 | server_name localhost; 44 | 45 | location / { 46 | proxy_pass http://$arg_b/t; 47 | } 48 | 49 | location /t { 50 | return 200 $server_addr:$server_port; 51 | } 52 | } 53 | 54 | # catch out of range 55 | 56 | server { 57 | listen 127.0.0.1:8181; 58 | listen 127.0.0.1:8184; 59 | listen [::1]:%%PORT_8181%%; 60 | listen [::1]:%%PORT_8184%%; 61 | server_name localhost; 62 | } 63 | } 64 | 65 | EOF 66 | 67 | my $p0 = port(8080); my $p3 = port(8183); 68 | my $p1 = port(8181); my $p4 = port(8184); 69 | my $p2 = port(8182); 70 | 71 | plan(skip_all => 'no requested ranges') 72 | if "$p2$p3" ne "81828183"; 73 | 74 | $t->run()->plan(9); 75 | 76 | ############################################################################### 77 | 78 | like(http_get("/?b=127.0.0.1:$p0"), qr/127.0.0.1:$p0/, 'single'); 79 | unlike(http_get("/?b=127.0.0.1:$p1"), qr/127.0.0.1:$p1/, 'out of range 1'); 80 | like(http_get("/?b=127.0.0.1:$p2"), qr/127.0.0.1:$p2/, 'range 1'); 81 | like(http_get("/?b=127.0.0.1:$p3"), qr/127.0.0.1:$p3/, 'range 2'); 82 | unlike(http_get("/?b=127.0.0.1:$p4"), qr/127.0.0.1:$p4/, 'out of range 2'); 83 | 84 | unlike(http_get("/?b=[::1]:$p1"), qr/::1:$p1/, 'inet6 out of range 1'); 85 | like(http_get("/?b=[::1]:$p2"), qr/::1:$p2/, 'inet6 range 1'); 86 | like(http_get("/?b=[::1]:$p3"), qr/::1:$p3/, 'inet6 range 2'); 87 | unlike(http_get("/?b=[::1]:$p4"), qr/::1:$p4/, 'inet6 out of range 2'); 88 | 89 | ############################################################################### 90 | -------------------------------------------------------------------------------- /proxy_cache_variables.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for http proxy cache, proxy_cache directive with variables. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http proxy cache/)->plan(8) 26 | ->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | http { 36 | %%TEST_GLOBALS_HTTP%% 37 | 38 | proxy_cache_path %%TESTDIR%%/cache1 levels=1:2 39 | keys_zone=NAME1:1m; 40 | proxy_cache_path %%TESTDIR%%/cache2 levels=1:2 41 | keys_zone=NAME2:1m; 42 | 43 | server { 44 | listen 127.0.0.1:8080; 45 | server_name localhost; 46 | 47 | location / { 48 | proxy_pass http://127.0.0.1:8081; 49 | 50 | proxy_cache $arg_c; 51 | 52 | proxy_cache_valid any 1m; 53 | 54 | add_header X-Cache-Status $upstream_cache_status; 55 | } 56 | } 57 | 58 | server { 59 | listen 127.0.0.1:8081; 60 | server_name localhost; 61 | 62 | location / { 63 | } 64 | } 65 | } 66 | 67 | EOF 68 | 69 | $t->write_file('index.html', 'SEE-THIS'); 70 | 71 | $t->run(); 72 | 73 | ############################################################################### 74 | 75 | like(http_get('/?c=NAME1'), qr/MISS.*SEE-THIS/ms, 'proxy request'); 76 | like(http_get('/?c=NAME1'), qr/HIT.*SEE-THIS/ms, 'proxy request cached'); 77 | 78 | unlike(http_head('/?c=NAME1'), qr/SEE-THIS/, 'head request'); 79 | 80 | $t->write_file('index.html', 'SEE-THAT'); 81 | 82 | like(http_get('/?c=NAME2'), qr/MISS.*SEE-THAT/ms, 'proxy request 2'); 83 | like(http_get('/?c=NAME2'), qr/HIT.*SEE-THAT/ms, 'proxy request 2 cached'); 84 | 85 | # some invalid cases 86 | 87 | like(http_get('/?c=NAME'), qr/ 500 /, 'proxy_cache unknown'); 88 | like(http_get('/'), qr/(?write_file('index.html', 'SEE-THOSE'); 91 | 92 | like(http_get('/'), qr/SEE-THOSE/, 'proxy_cache empty - not cached'); 93 | 94 | ############################################################################### 95 | -------------------------------------------------------------------------------- /gunzip_memcached.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | # Tests for gunzip filter module with memcached. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx qw/ :DEFAULT :gzip /; 18 | 19 | ############################################################################### 20 | 21 | select STDERR; $| = 1; 22 | select STDOUT; $| = 1; 23 | 24 | eval { require Cache::Memcached; }; 25 | plan(skip_all => 'Cache::Memcached not installed') if $@; 26 | 27 | eval { require IO::Compress::Gzip; }; 28 | plan(skip_all => "IO::Compress::Gzip not found") if $@; 29 | 30 | my $t = Test::Nginx->new()->has(qw/http gunzip memcached rewrite/) 31 | ->has_daemon('memcached') 32 | ->write_file_expand('nginx.conf', <<'EOF'); 33 | 34 | %%TEST_GLOBALS%% 35 | 36 | daemon off; 37 | 38 | events { 39 | } 40 | 41 | http { 42 | %%TEST_GLOBALS_HTTP%% 43 | 44 | server { 45 | listen 127.0.0.1:8080; 46 | server_name localhost; 47 | 48 | gunzip on; 49 | 50 | location / { 51 | set $memcached_key $uri; 52 | memcached_pass 127.0.0.1:8081; 53 | memcached_gzip_flag 2; 54 | } 55 | } 56 | } 57 | 58 | EOF 59 | 60 | my $memhelp = `memcached -h`; 61 | my @memopts = (); 62 | 63 | if ($memhelp =~ /repcached/) { 64 | # repcached patch adds additional listen socket 65 | push @memopts, '-X', port(8082); 66 | } 67 | if ($memhelp =~ /-U/) { 68 | # UDP port is on by default in memcached 1.2.7+ 69 | push @memopts, '-U', '0'; 70 | } 71 | 72 | $t->run_daemon('memcached', '-l', '127.0.0.1', '-p', port(8081), @memopts); 73 | 74 | $t->run()->plan(2); 75 | 76 | $t->waitforsocket('127.0.0.1:' . port(8081)) 77 | or die "Can't start memcached"; 78 | 79 | # Put compressed value into memcached. This requires compress_threshold to be 80 | # set and compressed value to be at least 20% less than original one. 81 | 82 | my $memd = Cache::Memcached->new(servers => [ '127.0.0.1:' . port(8081) ], 83 | compress_threshold => 1, connect_timeout => 1.0); 84 | $memd->set('/', 'TEST' x 10) 85 | or die "can't put value into memcached: $!"; 86 | 87 | ############################################################################### 88 | 89 | http_gzip_like(http_gzip_request('/'), qr/TEST/, 'memcached response gzipped'); 90 | like(http_get('/'), qr/TEST/, 'memcached response gunzipped'); 91 | 92 | ############################################################################### 93 | -------------------------------------------------------------------------------- /http_include.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for include directive. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http rewrite proxy access/) 26 | ->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | http { 36 | %%TEST_GLOBALS_HTTP%% 37 | 38 | upstream u { 39 | include ups.conf; 40 | } 41 | 42 | server { 43 | listen 127.0.0.1:8080; 44 | server_name localhost; 45 | 46 | if ($arg_s) { 47 | include sif.conf; 48 | } 49 | 50 | location / { 51 | if ($arg_l) { 52 | include lif.conf; 53 | } 54 | } 55 | 56 | location /lmt { 57 | limit_except GET { 58 | include lmt.conf; 59 | } 60 | } 61 | 62 | location /proxy { 63 | add_header X-IP $upstream_addr always; 64 | proxy_pass http://u/backend; 65 | } 66 | 67 | location /backend { } 68 | } 69 | } 70 | 71 | EOF 72 | 73 | my $p = port(8080); 74 | 75 | $t->write_file('sif.conf', 'return 200 SIF;'); 76 | $t->write_file('lif.conf', 'return 200 LIF;'); 77 | $t->write_file('lmt.conf', 'deny all;'); 78 | $t->write_file('ups.conf', "server 127.0.0.1:$p;"); 79 | 80 | $t->run()->plan(5); 81 | 82 | ############################################################################### 83 | 84 | like(http_get('/?s=1'), qr/SIF/, 'include in server if'); 85 | like(http_get('/?l=1'), qr/LIF/, 'include in location if'); 86 | like(http_post('/lmt'), qr/ 403 /, 'include in limit_except'); 87 | like(http_get('/proxy'), qr/X-IP: 127.0.0.1:$p/, 'include in upstream'); 88 | 89 | unlike(http_get('/'), qr/ 200 /, 'no include'); 90 | 91 | ############################################################################### 92 | 93 | sub http_post { 94 | my ($uri) = @_; 95 | http(<new()->has(qw/http sub proxy/)->plan(2) 28 | ->write_file_expand('nginx.conf', <<'EOF'); 29 | 30 | %%TEST_GLOBALS%% 31 | 32 | daemon off; 33 | 34 | events { 35 | } 36 | 37 | http { 38 | %%TEST_GLOBALS_HTTP%% 39 | 40 | server { 41 | listen 127.0.0.1:8080; 42 | server_name localhost; 43 | 44 | proxy_buffering off; 45 | proxy_http_version 1.1; 46 | 47 | sub_filter_types *; 48 | 49 | location /partial { 50 | proxy_pass http://127.0.0.1:8081; 51 | sub_filter za ZA; 52 | } 53 | 54 | location /negative { 55 | proxy_pass http://127.0.0.1:8081; 56 | sub_filter ab AB; 57 | } 58 | } 59 | } 60 | 61 | EOF 62 | 63 | $t->run_daemon(\&http_daemon); 64 | $t->run()->waitforsocket('127.0.0.1:' . port(8081)); 65 | 66 | ############################################################################### 67 | 68 | # partial match: the last byte matching pattern is buffered 69 | 70 | like(http_get('/partial'), qr/xy$/, 'partial match'); 71 | 72 | # no partial match: an entire buffer is sent as is without buffering 73 | 74 | like(http_get('/negative'), qr/xyz/, 'negative match'); 75 | 76 | ############################################################################### 77 | 78 | sub http_daemon { 79 | my $server = IO::Socket::INET->new( 80 | Proto => 'tcp', 81 | LocalHost => '127.0.0.1:' . port(8081), 82 | Listen => 5, 83 | Reuse => 1 84 | ) 85 | or die "Can't create listening socket: $!\n"; 86 | 87 | local $SIG{PIPE} = 'IGNORE'; 88 | 89 | while (my $client = $server->accept()) { 90 | $client->autoflush(1); 91 | 92 | while (<$client>) { 93 | last if /^\x0d?\x0a?$/; 94 | } 95 | 96 | print $client 97 | "HTTP/1.1 200 OK" . CRLF . 98 | "Content-Length: 10" . CRLF . CRLF . 99 | "xyz"; 100 | } 101 | } 102 | 103 | ############################################################################### 104 | -------------------------------------------------------------------------------- /http_resolver_cleanup.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for http resolver, worker process termination. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http proxy/); 26 | 27 | plan(skip_all => 'win32') if $^O eq 'MSWin32'; 28 | 29 | $t->write_file_expand('nginx.conf', <<'EOF')->plan(1); 30 | 31 | %%TEST_GLOBALS%% 32 | 33 | daemon off; 34 | 35 | events { 36 | } 37 | 38 | http { 39 | %%TEST_GLOBALS_HTTP%% 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | server_name localhost; 44 | 45 | location / { 46 | resolver 127.0.0.1:%%PORT_8981_UDP%%; 47 | proxy_pass http://example.net/$args; 48 | } 49 | 50 | location /pid { 51 | add_header X-Pid $pid always; 52 | } 53 | } 54 | } 55 | 56 | EOF 57 | 58 | $t->run_daemon(\&dns_daemon, $t); 59 | $t->run()->waitforfile($t->testdir . '/' . port(8981)); 60 | 61 | ############################################################################### 62 | 63 | # truncated UDP response, no response over TCP 64 | 65 | my $s = http_get('/', start => 1); 66 | 67 | pass('request'); 68 | 69 | sleep 1; 70 | 71 | # retrasmission timer wasn't removed during resolver cleanup, 72 | # while the event memory was freed, resulting in use-after-free 73 | # when later removing timer in TCP connection 74 | 75 | http_get('/pid') =~ qr/X-Pid: (\d+)/; 76 | kill 'TERM', $1; 77 | 78 | ############################################################################### 79 | 80 | sub dns_daemon { 81 | my ($t) = @_; 82 | my ($data); 83 | 84 | my $socket = IO::Socket::INET->new( 85 | LocalAddr => '127.0.0.1', 86 | LocalPort => port(8981), 87 | Proto => 'udp', 88 | ) 89 | or die "Can't create UDP socket: $!\n"; 90 | 91 | # signal we are ready 92 | 93 | open my $fh, '>', $t->testdir() . '/' . port(8981); 94 | close $fh; 95 | 96 | while (1) { 97 | $socket->recv($data, 65536); 98 | # truncation bit set 99 | $data |= pack("n2", 0, 0x8380); 100 | $socket->send($data); 101 | } 102 | } 103 | 104 | ############################################################################### 105 | -------------------------------------------------------------------------------- /proxy_cache_convert_head.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Sergey Kandaurov 4 | # (C) Nginx, Inc. 5 | 6 | # Tests for http proxy cache with proxy_cache_convert_head directive. 7 | 8 | ############################################################################### 9 | 10 | use warnings; 11 | use strict; 12 | 13 | use Test::More; 14 | 15 | BEGIN { use FindBin; chdir($FindBin::Bin); } 16 | 17 | use lib 'lib'; 18 | use Test::Nginx; 19 | 20 | ############################################################################### 21 | 22 | select STDERR; $| = 1; 23 | select STDOUT; $| = 1; 24 | 25 | my $t = Test::Nginx->new()->has(qw/http proxy cache/)->plan(8) 26 | ->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | http { 36 | %%TEST_GLOBALS_HTTP%% 37 | 38 | proxy_cache_path %%TESTDIR%%/cache levels=1:2 39 | keys_zone=NAME:1m; 40 | 41 | server { 42 | listen 127.0.0.1:8080; 43 | server_name localhost; 44 | 45 | proxy_cache NAME; 46 | 47 | proxy_cache_key $request_uri; 48 | 49 | proxy_cache_valid 200 302 2s; 50 | 51 | add_header X-Cache-Status $upstream_cache_status; 52 | 53 | location / { 54 | proxy_pass http://127.0.0.1:8081/t.html; 55 | proxy_cache_convert_head off; 56 | 57 | location /inner { 58 | proxy_pass http://127.0.0.1:8081/t.html; 59 | proxy_cache_convert_head on; 60 | } 61 | } 62 | 63 | location /on { 64 | proxy_pass http://127.0.0.1:8081/t.html; 65 | proxy_cache_convert_head on; 66 | } 67 | } 68 | server { 69 | listen 127.0.0.1:8081; 70 | server_name localhost; 71 | 72 | location / { 73 | add_header X-Method $request_method; 74 | } 75 | } 76 | } 77 | 78 | EOF 79 | 80 | $t->write_file('t.html', 'SEE-THIS'); 81 | $t->run(); 82 | 83 | ############################################################################### 84 | 85 | like(http_get('/'), qr/X-Method: GET/, 'get'); 86 | like(http_head('/?2'), qr/X-Method: HEAD/, 'head'); 87 | like(http_head('/?2'), qr/HIT/, 'head cached'); 88 | unlike(http_get('/?2'), qr/SEE-THIS/, 'get after head'); 89 | 90 | like(http_get('/on'), qr/X-Method: GET/, 'on - get'); 91 | like(http_head('/on?2'), qr/X-Method: GET/, 'on - head'); 92 | 93 | like(http_get('/inner'), qr/X-Method: GET/, 'inner - get'); 94 | like(http_head('/inner?2'), qr/X-Method: GET/, 'inner - head'); 95 | 96 | ############################################################################### 97 | -------------------------------------------------------------------------------- /range_flv.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Maxim Dounin 4 | 5 | # Tests for range filter module. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | BEGIN { use FindBin; chdir($FindBin::Bin); } 15 | 16 | use lib 'lib'; 17 | use Test::Nginx; 18 | 19 | ############################################################################### 20 | 21 | select STDERR; $| = 1; 22 | select STDOUT; $| = 1; 23 | 24 | my $t = Test::Nginx->new()->has(qw/http flv/)->plan(12); 25 | 26 | $t->write_file_expand('nginx.conf', <<'EOF'); 27 | 28 | %%TEST_GLOBALS%% 29 | 30 | daemon off; 31 | 32 | events { 33 | } 34 | 35 | http { 36 | %%TEST_GLOBALS_HTTP%% 37 | 38 | server { 39 | listen 127.0.0.1:8080; 40 | server_name localhost; 41 | location / { 42 | flv; 43 | } 44 | } 45 | } 46 | 47 | EOF 48 | 49 | $t->write_file('t1.flv', 50 | join('', map { sprintf "X%03dXXXXXX", $_ } (0 .. 99))); 51 | $t->run(); 52 | 53 | ############################################################################### 54 | 55 | my $t1; 56 | 57 | # FLV has 13 byte header at start. 58 | 59 | $t1 = http_get_range('/t1.flv?start=100', 'Range: bytes=0-9'); 60 | like($t1, qr/ 206 /, 'first bytes - 206 partial reply'); 61 | like($t1, qr/Content-Length: 10/, 'first bytes - correct length'); 62 | like($t1, qr/Content-Range: bytes 0-9\/913/, 'first bytes - content range'); 63 | like($t1, qr/^FLV.{7}$/m, 'first bytes - correct content'); 64 | 65 | $t1 = http_get_range('/t1.flv?start=100', 'Range: bytes=-10'); 66 | like($t1, qr/ 206 /, 'final bytes - 206 partial reply'); 67 | like($t1, qr/Content-Length: 10/, 'final bytes - content length'); 68 | like($t1, qr/Content-Range: bytes 903-912\/913/, 69 | 'final bytes - content range'); 70 | like($t1, qr/^X099XXXXXX$/m, 'final bytes - correct content'); 71 | 72 | $t1 = http_get_range('/t1.flv?start=100', 'Range: bytes=0-99'); 73 | like($t1, qr/ 206 /, 'multi buffers - 206 partial reply'); 74 | like($t1, qr/Content-Length: 100/, 'multi buffers - content length'); 75 | like($t1, qr/Content-Range: bytes 0-99\/913/, 'multi buffers - content range'); 76 | like($t1, qr/^FLV.{10}X010XXXXXX(X01[1-7]XXXXXX){7}X018XXX$/m, 77 | 'multi buffers - correct content'); 78 | 79 | ############################################################################### 80 | 81 | sub http_get_range { 82 | my ($url, $extra) = @_; 83 | return http(<new()->has(qw/http proxy cache/)->plan(2); 27 | 28 | $t->write_file_expand('nginx.conf', <<'EOF'); 29 | 30 | %%TEST_GLOBALS%% 31 | 32 | daemon off; 33 | 34 | events { 35 | } 36 | 37 | http { 38 | %%TEST_GLOBALS_HTTP%% 39 | 40 | proxy_cache_path %%TESTDIR%%/cache keys_zone=NAME:1m; 41 | 42 | server { 43 | listen 127.0.0.1:8080; 44 | server_name localhost; 45 | 46 | location / { 47 | proxy_pass http://127.0.0.1:8081; 48 | proxy_http_version 1.1; 49 | proxy_cache NAME; 50 | proxy_cache_valid any 1m; 51 | add_header X-Status $upstream_cache_status; 52 | } 53 | } 54 | } 55 | 56 | EOF 57 | 58 | $t->run_daemon(\&http_chunked_daemon); 59 | $t->run()->waitforsocket('127.0.0.1:' . port(8081)); 60 | 61 | ############################################################################### 62 | 63 | like(http_get("/"), qr/SEE-THIS/s, "chunked"); 64 | like(http_get("/"), qr/SEE-THIS.*HIT/s, "chunked cached"); 65 | 66 | ############################################################################### 67 | 68 | sub http_chunked_daemon { 69 | my $server = IO::Socket::INET->new( 70 | Proto => 'tcp', 71 | LocalAddr => '127.0.0.1:' . port(8081), 72 | Listen => 5, 73 | Reuse => 1 74 | ) 75 | or die "Can't create listening socket: $!\n"; 76 | 77 | local $SIG{PIPE} = 'IGNORE'; 78 | 79 | while (my $client = $server->accept()) { 80 | $client->autoflush(1); 81 | 82 | while (<$client>) { 83 | last if (/^\x0d?\x0a?$/); 84 | } 85 | 86 | print $client <<'EOF'; 87 | HTTP/1.1 200 OK 88 | X-Test: SEE-THIS 89 | Connection: close 90 | Transfer-Encoding: chunked 91 | 92 | EOF 93 | print $client "85" . CRLF; 94 | select undef, undef, undef, 0.1; 95 | print $client "FOO" . ("0123456789abcdef" x 8) . CRLF . CRLF; 96 | 97 | print $client "0" . CRLF . CRLF; 98 | close $client; 99 | } 100 | } 101 | 102 | ############################################################################### 103 | -------------------------------------------------------------------------------- /debug_connection_syslog.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # (C) Nginx, Inc. 4 | 5 | # Tests for debug_connection with syslog. 6 | 7 | ############################################################################### 8 | 9 | use warnings; 10 | use strict; 11 | 12 | use Test::More; 13 | 14 | use IO::Select; 15 | 16 | BEGIN { use FindBin; chdir($FindBin::Bin); } 17 | 18 | use lib 'lib'; 19 | use Test::Nginx; 20 | 21 | ############################################################################### 22 | 23 | select STDERR; $| = 1; 24 | select STDOUT; $| = 1; 25 | 26 | my $t = Test::Nginx->new()->has(qw/http --with-debug proxy/); 27 | 28 | $t->write_file_expand('nginx.conf', <<'EOF'); 29 | 30 | %%TEST_GLOBALS%% 31 | 32 | daemon off; 33 | 34 | events { 35 | debug_connection ::1; 36 | } 37 | 38 | http { 39 | %%TEST_GLOBALS_HTTP%% 40 | 41 | error_log syslog:server=127.0.0.1:%%PORT_8981_UDP%% alert; 42 | error_log syslog:server=127.0.0.1:%%PORT_8982_UDP%% alert; 43 | 44 | server { 45 | listen 127.0.0.1:8080; 46 | listen [::1]:%%PORT_8080%%; 47 | server_name localhost; 48 | 49 | location /debug { 50 | proxy_pass http://[::1]:%%PORT_8080%%/; 51 | } 52 | } 53 | } 54 | 55 | EOF 56 | 57 | $t->try_run('no inet6 support')->plan(5); 58 | 59 | ############################################################################### 60 | 61 | my ($s1, $s2) = map { 62 | IO::Socket::INET->new( 63 | Proto => 'udp', 64 | LocalAddr => "127.0.0.1:$_" 65 | ) 66 | or die "Can't open syslog socket $_: $!"; 67 | } port(8981), port(8982); 68 | 69 | is(get_syslog('/', $s1), '', 'no debug_connection syslog 1'); 70 | is(get_syslog('/', $s2), '', 'no debug_connection syslog 2'); 71 | 72 | my @msgs = get_syslog('/debug', $s1, $s2); 73 | like($msgs[0], qr/\[debug\]/, 'debug_connection syslog 1'); 74 | like($msgs[1], qr/\[debug\]/, 'debug_connection syslog 2'); 75 | is($msgs[0], $msgs[1], 'debug_connection syslog1 syslog2 match'); 76 | 77 | ############################################################################### 78 | 79 | sub get_syslog { 80 | my ($uri, @s) = @_; 81 | my @data; 82 | 83 | http_get($uri); 84 | 85 | map { 86 | my $data = ''; 87 | IO::Select->new($_)->can_read(1); 88 | while (IO::Select->new($_)->can_read(0.1)) { 89 | my ($buffer); 90 | sysread($_, $buffer, 4096); 91 | $data .= $buffer; 92 | } 93 | push @data, $data; 94 | } (@s); 95 | 96 | return $data[0] if scalar @data == 1; 97 | return @data; 98 | } 99 | 100 | ############################################################################### 101 | --------------------------------------------------------------------------------