Mercurial > hg > nginx-tests
view proxy_keepalive.t @ 1990:85d88cd5091c
Tests: SSI include stub tests.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 04 Jul 2024 17:42:55 +0300 |
parents | 882267679006 |
children | d329b05e20fa |
line wrap: on
line source
#!/usr/bin/perl # (C) Maxim Dounin # Tests for proxy with keepalive. ############################################################################### use warnings; use strict; use Test::More; use IO::Socket::INET; use Socket qw/ CRLF /; BEGIN { use FindBin; chdir($FindBin::Bin); } use lib 'lib'; use Test::Nginx; ############################################################################### select STDERR; $| = 1; select STDOUT; $| = 1; my $t = Test::Nginx->new()->has(qw/http proxy upstream_keepalive ssi rewrite/) ->plan(49)->write_file_expand('nginx.conf', <<'EOF'); %%TEST_GLOBALS%% daemon off; events { } http { %%TEST_GLOBALS_HTTP%% upstream backend { server 127.0.0.1:8081; keepalive 1; } server { listen 127.0.0.1:8080; server_name localhost; proxy_http_version 1.1; proxy_set_header Connection ""; location / { proxy_pass http://backend; } location /unbuffered/ { proxy_pass http://backend; proxy_buffering off; } location /inmemory/ { ssi on; rewrite ^ /ssi.html break; } } } EOF $t->write_file('ssi.html', '<!--#include virtual="/include$request_uri" set="x" -->' . 'set: <!--#echo var="x" -->'); $t->run_daemon(\&http_daemon); $t->run(); $t->waitforsocket('127.0.0.1:' . port(8081)) or die "Can't start test backend"; ############################################################################### # There are 3 mostly independent modes of upstream operation: # # 1. Buffered, i.e. normal mode with "proxy_buffering on;" # 2. Unbuffered, i.e. "proxy_buffering off;". # 3. In memory, i.e. ssi <!--#include ... set --> # # These all should be tested. my ($r, $n); # buffered like($r = http_get('/buffered/length1'), qr/SEE-THIS/, 'buffered'); $r =~ m/X-Connection: (\d+)/; $n = $1; like(http_get('/buffered/length2'), qr/X-Connection: $n.*SEE/ms, 'buffered 2'); like($r = http_get('/buffered/chunked1'), qr/SEE-THIS/, 'buffered chunked'); $r =~ m/X-Connection: (\d+)/; $n = $1; like(http_get('/buffered/chunked2'), qr/X-Connection: $n/, 'buffered chunked 2'); like($r = http_get('/buffered/complex1'), qr/(0123456789){100}/, 'buffered complex chunked'); $r =~ m/X-Connection: (\d+)/; $n = $1; like(http_get('/buffered/complex2'), qr/X-Connection: $n/, 'buffered complex chunked 2'); like($r = http_get('/buffered/chunk01'), qr/200 OK/, 'buffered 0 chunk'); $r =~ m/X-Connection: (\d+)/; $n = $1; like(http_get('/buffered/chunk02'), qr/X-Connection: $n/, 'buffered 0 chunk 2'); like($r = http_head('/buffered/length/head1'), qr/(?!SEE-THIS)/, 'buffered head'); $r =~ m/X-Connection: (\d+)/; $n = $1; like(http_head('/buffered/length/head2'), qr/X-Connection: $n/, 'buffered head 2'); like($r = http_get('/buffered/empty1'), qr/200 OK/, 'buffered empty'); $r =~ m/X-Connection: (\d+)/; $n = $1; like(http_get('/buffered/empty2'), qr/X-Connection: $n/, 'buffered empty 2'); like($r = http_get('/buffered/304nolen1'), qr/304 Not/, 'buffered 304'); $r =~ m/X-Connection: (\d+)/; $n = $1; like(http_get('/buffered/304nolen2'), qr/X-Connection: $n/, 'buffered 304 2'); like($r = http_get('/buffered/304len1'), qr/304 Not/, 'buffered 304 with length'); $r =~ m/X-Connection: (\d+)/; $n = $1; like(http_get('/buffered/304len2'), qr/X-Connection: $n/, 'buffered 304 with length 2'); # unbuffered like($r = http_get('/unbuffered/length1'), qr/SEE-THIS/, 'unbuffered'); $r =~ m/X-Connection: (\d+)/; $n = $1; like(http_get('/unbuffered/length2'), qr/X-Connection: $n/, 'unbuffered 2'); like($r = http_get('/unbuffered/chunked1'), qr/SEE-THIS/, 'unbuffered chunked'); $r =~ m/X-Connection: (\d+)/; $n = $1; like(http_get('/unbuffered/chunked2'), qr/X-Connection: $n/, 'unbuffered chunked 2'); like($r = http_get('/unbuffered/complex1'), qr/(0123456789){100}/, 'unbuffered complex chunked'); $r =~ m/X-Connection: (\d+)/; $n = $1; like(http_get('/unbuffered/complex2'), qr/X-Connection: $n/, 'unbuffered complex chunked 2'); like($r = http_get('/unbuffered/chunk01'), qr/200 OK/, 'unbuffered 0 chunk'); $r =~ m/X-Connection: (\d+)/; $n = $1; like(http_get('/unbuffered/chunk02'), qr/X-Connection: $n/, 'unbuffered 0 chunk 2'); like($r = http_get('/unbuffered/empty1'), qr/200 OK/, 'unbuffered empty'); $r =~ m/X-Connection: (\d+)/; $n = $1; like(http_get('/unbuffered/empty2'), qr/X-Connection: $n/, 'unbuffered empty 2'); like($r = http_head('/unbuffered/length/head1'), qr/(?!SEE-THIS)/, 'unbuffered head'); $r =~ m/X-Connection: (\d+)/; $n = $1; like(http_head('/unbuffered/length/head2'), qr/X-Connection: $n/, 'unbuffered head 2'); like($r = http_get('/unbuffered/304nolen1'), qr/304 Not/, 'unbuffered 304'); $r =~ m/X-Connection: (\d+)/; $n = $1; like(http_get('/unbuffered/304nolen2'), qr/X-Connection: $n/, 'unbuffered 304 2'); like($r = http_get('/unbuffered/304len1'), qr/304 Not/, 'unbuffered 304 with length'); $r =~ m/X-Connection: (\d+)/; $n = $1; like(http_get('/unbuffered/304len2'), qr/X-Connection: $n/, 'unbuffered 304 with length 2'); # in memory like($r = http_get('/inmemory/length1'), qr/SEE-THIS/, 'inmemory'); $r =~ m/SEE-THIS(\d+)/; $n = $1; like(http_get('/inmemory/length2'), qr/SEE-THIS$n/, 'inmemory 2'); like($r = http_get('/inmemory/empty1'), qr/200 OK/, 'inmemory empty'); $r =~ m/SEE-THIS(\d+)/; $n = $1; like(http_get('/inmemory/empty2'), qr/200 OK/, 'inmemory empty 2'); like($r = http_get('/inmemory/chunked1'), qr/SEE-THIS/, 'inmemory chunked'); $r =~ m/SEE-THIS(\d+)/; $n = $1; like(http_get('/inmemory/chunked2'), qr/SEE-THIS$n/, 'inmemory chunked 2'); like($r = http_get('/inmemory/complex1'), qr/(0123456789){100}/, 'inmemory complex chunked'); $r =~ m/SEE-THIS(\d+)/; $n = $1; like(http_get('/inmemory/complex2'), qr/SEE-THIS$n/, 'inmemory complex chunked 2'); like(http_get('/inmemory/chunk01'), qr/set: $/, 'inmemory 0 chunk'); like(http_get('/inmemory/chunk02'), qr/set: $/, 'inmemory 0 chunk 2'); # closed connection tests like(http_get('/buffered/closed1'), qr/200 OK/, 'buffered closed 1'); like(http_get('/buffered/closed2'), qr/200 OK/, 'buffered closed 2'); like(http_get('/unbuffered/closed1'), qr/200 OK/, 'unbuffered closed 1'); like(http_get('/unbuffered/closed2'), qr/200 OK/, 'unbuffered closed 2'); like(http_get('/inmemory/closed1'), qr/200 OK/, 'inmemory closed 1'); like(http_get('/inmemory/closed2'), qr/200 OK/, 'inmemory closed 2'); # check for errors, shouldn't be any like(`grep -F '[error]' ${\($t->testdir())}/error.log`, qr/^$/s, 'no errors'); ############################################################################### sub http_daemon { my $server = IO::Socket::INET->new( Proto => 'tcp', LocalHost => '127.0.0.1:' . port(8081), Listen => 5, Reuse => 1 ) or die "Can't create listening socket: $!\n"; my $ccount = 0; my $rcount = 0; # dumb server which is able to keep connections alive while (my $client = $server->accept()) { Test::Nginx::log_core('||', "connection from " . $client->peerhost()); $client->autoflush(1); $ccount++; while (1) { my $headers = ''; my $uri = ''; while (<$client>) { Test::Nginx::log_core('||', $_); $headers .= $_; last if (/^\x0d?\x0a?$/); } last if $headers eq ''; $rcount++; $uri = $1 if $headers =~ /^\S+\s+([^ ]+)\s+HTTP/i; if ($uri =~ m/length/) { print $client "HTTP/1.1 200 OK" . CRLF . "X-Request: $rcount" . CRLF . "X-Connection: $ccount" . CRLF . "Content-Length: 26" . CRLF . CRLF; print $client "TEST-OK-IF-YOU-SEE-THIS" . sprintf("%03d", $ccount) unless $headers =~ /^HEAD/i; } elsif ($uri =~ m/empty/) { print $client "HTTP/1.1 200 OK" . CRLF . "X-Request: $rcount" . CRLF . "X-Connection: $ccount" . CRLF . "Content-Length: 0" . CRLF . CRLF; } elsif ($uri =~ m/304nolen/) { print $client "HTTP/1.1 304 Not Modified" . CRLF . "X-Request: $rcount" . CRLF . "X-Connection: $ccount" . CRLF . CRLF; } elsif ($uri =~ m/304len/) { print $client "HTTP/1.1 304 Not Modified" . CRLF . "X-Request: $rcount" . CRLF . "X-Connection: $ccount" . CRLF . "Content-Length: 100" . CRLF . CRLF; } elsif ($uri =~ m/chunked/) { print $client "HTTP/1.1 200 OK" . CRLF . "X-Request: $rcount" . CRLF . "X-Connection: $ccount" . CRLF . "Transfer-Encoding: chunked" . CRLF . CRLF; print $client "1a" . CRLF . "TEST-OK-IF-YOU-SEE-THIS" . sprintf("%03d", $ccount) . CRLF . "0" . CRLF . CRLF unless $headers =~ /^HEAD/i; } elsif ($uri =~ m/complex/) { print $client "HTTP/1.1 200 OK" . CRLF . "X-Request: $rcount" . CRLF . "X-Connection: $ccount" . CRLF . "Transfer-Encoding: chunked" . CRLF . CRLF; if ($headers !~ /^HEAD/i) { for my $n (1..100) { print $client "a" . CRLF . "0123456789" . CRLF; select undef, undef, undef, 0.01 if $n % 50 == 0; } print $client "1a" . CRLF . "TEST-OK-IF-YOU-SEE-THIS" . sprintf("%03d", $ccount) . CRLF . "0" . CRLF; select undef, undef, undef, 0.05; print $client CRLF; } } elsif ($uri =~ m/chunk0/) { print $client "HTTP/1.1 200 OK" . CRLF . "X-Request: $rcount" . CRLF . "X-Connection: $ccount" . CRLF . "Transfer-Encoding: chunked" . CRLF . CRLF; print $client "0" . CRLF . CRLF unless $headers =~ /^HEAD/i; } elsif ($uri =~ m/closed/) { print $client "HTTP/1.1 200 OK" . CRLF . "X-Request: $rcount" . CRLF . "X-Connection: $ccount" . CRLF . "Connection: close" . CRLF . "Content-Length: 12" . CRLF . CRLF . "0123456789" . CRLF; last; } else { print $client "HTTP/1.1 404 Not Found" . CRLF . "X-Request: $rcount" . CRLF . "X-Connection: $ccount" . CRLF . "Connection: close" . CRLF . CRLF . "Oops, '$uri' not found" . CRLF; last; } } close $client; } } ###############################################################################