view t/delay_body.t @ 1:7c2d64d9c656

Working delay body and tests. Depends on rb->filter_need_buffering and rb->buffered, as well as corresponding changes in the request body reading code to work. Might not be the best solution, as current body reading code relies on rb->buffered to be properly set at various stages. Notably, rb->buffered must be cleared when calling the next filter, since the save body filter relies on it. Possible future improvements: implement last buffer checking in the save body filter instead of checking for (rb->rest == 0 && !rb->buffered). The code uses its own event to implement delay timer. To remove the timer in case of abnormal request termination a cleanup handler is added. While in theory it is possible to use a timer on c->read instead, this implies additional changes to the request body reading code. Custom event was chosen to reduce complexity of changes needed.
author Maxim Dounin <mdounin@mdounin.ru>
date Fri, 20 Aug 2021 22:35:05 +0300
parents a386f95c5ae9
children
line wrap: on
line source

#!/usr/bin/perl

# (C) Maxim Dounin

# Tests for delay body filter module.

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

use warnings;
use strict;

use Test::More;
use Test::Nginx;

use Socket qw/ CRLF /;

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

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

my $t = Test::Nginx->new()->has(qw/http proxy rewrite/)
	->write_file_expand('nginx.conf', <<'EOF');

%%TEST_GLOBALS%%

daemon off;

events {
}

http {
    %%TEST_GLOBALS_HTTP%%

    server {
        listen       127.0.0.1:8080;
        server_name  localhost;

        location / {
            delay_body 1s;
            add_header X-Time $request_time;
            proxy_pass http://127.0.0.1:8080/empty;
        }

        location /no {
            delay_body 0s;
            add_header X-Time $request_time;
            proxy_pass http://127.0.0.1:8080/empty;
        }

        location /empty {
            return 200 "test response body\n";
        }
    }
}

EOF

$t->try_run('no delay_body')->plan(4);

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

like(get_body('/', '123456'), qr/200 OK.*X-Time: 1/ms, 'delay');
like(get_body('/no', '123456'), qr/200 OK.*X-Time: 0/ms, 'no delay');

# pipelining

like(get_body('/', '123456', '12345X'),
	qr/200 OK.*X-Time: 1.*200 OK.*X-Time: 1/ms,
	'pipelining delay');

# pipelining with chunked

like(get_chunked('/', '123456', '12345X'),
	qr/200 OK.*X-Time: 1.*200 OK.*X-Time: 1/ms,
	'pipelining chunked delay');

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

sub get_body {
	my $uri = shift;
	my $last = pop;
	return http( join '', (map {
		my $body = $_;
		"GET $uri HTTP/1.1" . CRLF
		. "Host: localhost" . CRLF
		. "Content-Length: " . (length $body) . CRLF . CRLF
		. $body
	} @_),
		"GET $uri HTTP/1.1" . CRLF
		. "Host: localhost" . CRLF
		. "Connection: close" . CRLF
		. "Content-Length: " . (length $last) . CRLF . CRLF
		. $last
	);
}

sub get_chunked {
	my $uri = shift;
	my $last = pop;
	return http( join '', (map {
		my $body = $_;
		"GET $uri HTTP/1.1" . CRLF
		. "Host: localhost" . CRLF
		. "Transfer-Encoding: chunked" . CRLF . CRLF
		. sprintf("%x", length $body) . CRLF
		. $body . CRLF
		. "0" . CRLF . CRLF
	} @_),
		"GET $uri HTTP/1.1" . CRLF
		. "Host: localhost" . CRLF
		. "Connection: close" . CRLF
		. "Transfer-Encoding: chunked" . CRLF . CRLF
		. sprintf("%x", length $last) . CRLF
		. $last . CRLF
		. "0" . CRLF . CRLF
	);
}

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