view proxy-noclose.t @ 25:fbda19df2fc4

Tests: more proxy-noclose tests. 1. Make sure data got from upstream are flushed in case of upstream timeout (and so everything is ok even if we got no Content-Length). 2. Additional test that checks if nginx actually uses Content-Length info. This one will fail if nginx will wait for upstream timeout instead of sending response as soon as it got full body.
author Maxim Dounin <mdounin@mdounin.ru>
date Tue, 30 Sep 2008 22:58:25 +0400
parents e6b7c3b5389c
children 71ea39729fa0
line wrap: on
line source

#!/usr/bin/perl

# (C) Maxim Dounin

# Test for http backend not closing connection properly after sending full
# reply.  This is in fact backend bug, but it seems common, and anyway
# correct handling is required to support persistent connections.

# There are actually 2 nginx problems here:
#
# 1. It doesn't send reply in-time even if got Content-Length and all the data.
#
# 2. If upstream times out some data may be left in input buffer and won't be
#    sent to downstream.

###############################################################################

use warnings;
use strict;

use Test::More tests => 4;

use IO::Select;

BEGIN { use FindBin; chdir($FindBin::Bin); }

use lib 'lib';
use Test::Nginx;

###############################################################################

select STDERR; $| = 1;
select STDOUT; $| = 1;

my $t = Test::Nginx->new();

$t->write_file_expand('nginx.conf', <<'EOF');

master_process off;
daemon         off;

events {
    worker_connections  1024;
}

http {
    access_log    off;
    root          %%TESTDIR%%;

    server {
        listen       localhost:8080;
        server_name  localhost;

        location / {
            proxy_pass http://localhost:8081;
            proxy_read_timeout 1s;
        }

        location /uselen {
            proxy_pass http://localhost:8081;

            # test will wait only 2s for reply, we it will fail if
            # Content-Length not used as a hint
 
            proxy_read_timeout 10s;
        }
    }
}

EOF

$t->run_daemon(\&http_noclose_daemon);
$t->run();

###############################################################################

TODO: {
local $TODO = 'not fixed yet, patches under review';

like(http_request('/'), qr/SEE-THIS/, 'request to bad backend');
like(http_request('/multi'), qr/AND-THIS/, 'bad backend - multiple packets');
like(http_request('/nolen'), qr/SEE-THIS/, 'bad backend - no content length');
like(http_request('/uselen'), qr/SEE-THIS/, 'content-length actually used');

}

###############################################################################

sub http_request {
	my ($url) = @_;
	my $r = http(<<EOF);
GET $url HTTP/1.1
Host: localhost
Connection: close

EOF
}

sub http_noclose_daemon {
	my $server = IO::Socket::INET->new(
        	Proto => 'tcp',
        	LocalPort => 8081,
        	Listen => 5,
        	Reuse => 1
	)
        	or die "Can't create listening socket: $!\n";

	while (my $client = $server->accept()) {
        	$client->autoflush(1);

		my $multi = 0;
		my $nolen = 0;

        	while (<$client>) {
			$multi = 1 if /multi/;
			$nolen = 1 if /nolen/;
                	last if (/^\x0d?\x0a?$/);
        	}

		if ($nolen) {

			print $client <<'EOF';
HTTP/1.1 200 OK
Connection: close

TEST-OK-IF-YOU-SEE-THIS
EOF
		} elsif ($multi) {

        		print $client <<"EOF";
HTTP/1.1 200 OK
Content-Length: 32
Connection: close

TEST-OK-IF-YOU-SEE-THIS
EOF

			select undef, undef, undef, 0.1;
			print $client 'AND-THIS';

		} else {

        		print $client <<"EOF";
HTTP/1.1 200 OK
Content-Length: 24
Connection: close

TEST-OK-IF-YOU-SEE-THIS
EOF
		}

		my $select = IO::Select->new($client);
        	$select->can_read(10);
        	close $client;
	}
}

###############################################################################