Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,018 changes: 1,018 additions & 0 deletions proxy_http2.t

Large diffs are not rendered by default.

189 changes: 189 additions & 0 deletions proxy_http2_cache.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
#!/usr/bin/perl

# (C) Zhidao HONG
# (C) Nginx, Inc.

# Tests for HTTP/2 proxy backend with cache support.

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

use warnings;
use strict;

use Test::More;

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

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

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

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

my $t = Test::Nginx->new()->has(qw/http rewrite http_v2 proxy cache/)
->has(qw/upstream_keepalive/)->plan(3);

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

%%TEST_GLOBALS%%

daemon off;

events {
}

http {
%%TEST_GLOBALS_HTTP%%

proxy_cache_path %%TESTDIR%%/cache levels=1:2
keys_zone=NAME:1m;

server {
listen 127.0.0.1:8080 http2;
server_name localhost;

location / {
proxy_pass http://127.0.0.1:8081;
proxy_http_version 2;
proxy_request_buffering off;
proxy_set_header TE "trailers";
proxy_pass_trailers on;

proxy_cache NAME;
proxy_cache_valid 200 302 2s;

add_header X-Cache-Status $upstream_cache_status;
}
}
}

EOF

# suppress deprecation warning

open OLDERR, ">&", \*STDERR; close STDERR;
$t->run();
open STDERR, ">&", \*OLDERR;

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

my $p = port(8081);
my $f = proxy_http2();

# Test basic caching functionality - first request should be MISS

my $frames = $f->{http_start}('/');
my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
ok($frame, 'cache test - got first response');

$f->{data}('Hello');
$frames = $f->{http_end}();
($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
like($frame->{headers}{'x-cache-status'}, qr/MISS/, 'cache test - MISS on first request');

# Second request - should be HIT from cache

$frames = $f->{request}('/');
($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
like($frame->{headers}{'x-cache-status'}, qr/HIT/, 'cache test - HIT on second request');

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

sub proxy_http2 {
my ($server, $client, $f, $s, $c, $sid, $csid);
my $n = 0;

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

$f->{http_start} = sub {
my ($uri, %extra) = @_;
my $body_more = 1;
my $meth = $extra{method} || 'GET';
$s = Test::Nginx::HTTP2->new() if !defined $s;
$csid = $s->new_stream({ body_more => $body_more, headers => [
{ name => ':method', value => $meth, mode => !!$meth },
{ name => ':scheme', value => 'http', mode => 0 },
{ name => ':path', value => $uri, },
{ name => ':authority', value => 'localhost' },
{ name => 'content-type', value => 'text/plain' },
{ name => 'te', value => 'trailers', mode => 2 }]});

if (IO::Select->new($server)->can_read(5)) {
$client = $server->accept();
} else {
log_in("timeout");
return undef;
}

log2c("(new connection $client)");
$n++;

$client->sysread(my $buf, 24) == 24 or return; # preface

$c = Test::Nginx::HTTP2->new(1, socket => $client,
pure => 1, preface => "") or return;

my $frames = $c->read(all => [{ fin => 4 }]);

$c->h2_settings(0);
$c->h2_settings(1);

my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
$sid = $frame->{sid};
return $frames;
};
$f->{data} = sub {
my ($body, %extra) = @_;
$s->h2_body($body, { %extra });
return $c->read(all => [{ sid => $sid,
length => length($body) }]);
};
$f->{http_end} = sub {
my (%extra) = @_;

my $h = [
{ name => ':status', value => '200',
mode => $extra{mode} || 0 },
{ name => 'content-type', value => 'text/plain',
mode => $extra{mode} || 1, huff => 1 },
{ name => 'x-connection', value => $n,
mode => 2, huff => 1 }];
push @$h, { name => 'content-length', value => $extra{cl} }
if $extra{cl};
$c->new_stream({ body_more => 1, headers => $h, %extra }, $sid);

$c->h2_body('Hello world', { body_more => 1,
body_padding => $extra{body_padding} });
$c->new_stream({ headers => [
{ name => 'x-status', value => '0',
mode => 2, huff => 1 },
{ name => 'x-message', value => '',
mode => 2, huff => 1 },
]}, $sid);

return $s->read(all => [{ fin => 1 }]);
};
$f->{request} = sub {
my ($uri) = @_;
$s = Test::Nginx::HTTP2->new() if !defined $s;
my $sid = $s->new_stream({ path => $uri });
return $s->read(all => [{ fin => 1 }]);
};
return $f;
}

sub log2i { Test::Nginx::log_core('|| <<', @_); }
sub log2o { Test::Nginx::log_core('|| >>', @_); }
sub log2c { Test::Nginx::log_core('||', @_); }

###############################################################################
143 changes: 143 additions & 0 deletions proxy_http2_cache_2.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#!/usr/bin/perl

# (C) Zhidao HONG
# (C) Nginx, Inc.

# Tests for HTTP/2 proxy backend with cache support.

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

use warnings;
use strict;

use Test::More;

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 cache http_v2/)
->plan(15);

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

%%TEST_GLOBALS%%

daemon off;

events {
}

http {
%%TEST_GLOBALS_HTTP%%

proxy_cache_path %%TESTDIR%%/cache levels=1:2
keys_zone=NAME:1m;

server {
listen 127.0.0.1:8080;
server_name localhost;

location / {
proxy_pass http://127.0.0.1:8081;
proxy_http_version 2;

proxy_cache NAME;

proxy_cache_valid 200 302 2s;
proxy_cache_valid 301 1d;
proxy_cache_valid any 1m;

proxy_cache_min_uses 1;

proxy_cache_use_stale error timeout invalid_header http_500
http_404;

proxy_no_cache $arg_e;

add_header X-Cache-Status $upstream_cache_status;
}
}

server {
listen 127.0.0.1:8081;
server_name localhost;

http2 on;

location / {
root %%TESTDIR%%;
}
}
}

EOF

$t->write_file('t.html', 'SEE-THIS');
$t->write_file('t2.html', 'SEE-THIS');
$t->write_file('empty.html', '');
$t->write_file('big.html', 'x' x 1024);

$t->run();

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

like(http_get('/t.html'), qr/SEE-THIS/, 'proxy request');

$t->write_file('t.html', 'NOOP');
like(http_get('/t.html'), qr/SEE-THIS/, 'proxy request cached');

unlike(http_head('/t2.html'), qr/SEE-THIS/, 'head request');
like(http_get('/t2.html'), qr/SEE-THIS/, 'get after head');
unlike(http_head('/t2.html'), qr/SEE-THIS/, 'head after get');

like(http_head('/empty.html?head'), qr/MISS/, 'empty head first');
like(http_head('/empty.html?head'), qr/HIT/, 'empty head second');

like(http_get_range('/t.html', 'Range: bytes=4-'), qr/^THIS/m, 'cached range');
like(http_get_range('/t.html', 'Range: bytes=0-2,4-'), qr/^SEE.*^THIS/ms,
'cached multipart range');

like(http_get('/empty.html'), qr/MISS/, 'empty get first');
like(http_get('/empty.html'), qr/HIT/, 'empty get second');

select(undef, undef, undef, 3.1);
unlink $t->testdir() . '/t.html';
like(http_get('/t.html'), qr/STALE/, 'non-empty get stale');

unlink $t->testdir() . '/empty.html';
like(http_get('/empty.html'), qr/STALE/, 'empty get stale');

# no client connection close with response on non-cacheable HEAD requests

my $s = http(<<EOF, start => 1);
HEAD /big.html?e=1 HTTP/1.1
Host: localhost

EOF

my $r = http_get('/t.html', socket => $s);

like($r, qr/Connection: keep-alive/, 'non-cacheable head - keepalive');
like($r, qr/SEE-THIS/, 'non-cacheable head - second');

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

sub http_get_range {
my ($url, $extra) = @_;
return http(<<EOF);
GET $url HTTP/1.1
Host: localhost
Connection: close
$extra

EOF
}

###############################################################################
Loading