| #!/usr/bin/perl |
| |
| # (C) Maxim Dounin |
| |
| # Tests for range filter module. |
| |
| ############################################################################### |
| |
| 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 charset/)->plan(41); |
| |
| $t->write_file_expand('nginx.conf', <<'EOF'); |
| |
| %%TEST_GLOBALS%% |
| |
| daemon off; |
| |
| events { |
| } |
| |
| http { |
| %%TEST_GLOBALS_HTTP%% |
| |
| charset_map B A { |
| 58 59; # X -> Y |
| } |
| |
| server { |
| listen 127.0.0.1:8080; |
| server_name localhost; |
| |
| location /t2.html { |
| charset A; |
| source_charset B; |
| } |
| |
| location /t3.html { |
| max_ranges 2; |
| } |
| |
| location /t4.html { |
| max_ranges 0; |
| } |
| } |
| } |
| |
| EOF |
| |
| $t->write_file('t1.html', |
| join('', map { sprintf "X%03dXXXXXX", $_ } (0 .. 99))); |
| $t->write_file('t2.html', |
| join('', map { sprintf "X%03dXXXXXX", $_ } (0 .. 99))); |
| $t->write_file('t3.html', |
| join('', map { sprintf "X%03dXXXXXX", $_ } (0 .. 99))); |
| $t->write_file('t4.html', |
| join('', map { sprintf "X%03dXXXXXX", $_ } (0 .. 99))); |
| $t->run(); |
| |
| ############################################################################### |
| |
| my $t1; |
| |
| $t1 = http_get_range('/t1.html', 'Range: bytes=0-8'); |
| like($t1, qr/ 206 /, 'range request - 206 partial reply'); |
| like($t1, qr/Content-Length: 9/, 'range request - correct length'); |
| like($t1, qr/Content-Range: bytes 0-8\/1000/, 'range request - content range'); |
| like($t1, qr/^X000XXXXX$/m, 'range request - correct content'); |
| |
| $t1 = http_get_range('/t1.html', 'Range: bytes=-10'); |
| like($t1, qr/ 206 /, 'final bytes - 206 partial reply'); |
| like($t1, qr/Content-Length: 10/, 'final bytes - content length'); |
| like($t1, qr/Content-Range: bytes 990-999\/1000/, |
| 'final bytes - content range'); |
| like($t1, qr/^X099XXXXXX$/m, 'final bytes - correct content'); |
| |
| $t1 = http_get_range('/t1.html', 'Range: bytes=990-'); |
| like($t1, qr/ 206 /, 'final bytes explicit - 206 partial reply'); |
| like($t1, qr/Content-Length: 10/, 'final bytes explicit - content length'); |
| like($t1, qr/Content-Range: bytes 990-999\/1000/, |
| 'final bytes explicit - content range'); |
| like($t1, qr/^X099XXXXXX$/m, 'final bytes explicit - correct content'); |
| |
| $t1 = http_get_range('/t1.html', 'Range: bytes=990-1990'); |
| like($t1, qr/ 206 /, 'more than length - 206 partial reply'); |
| like($t1, qr/Content-Length: 10/, 'more than length - content length'); |
| like($t1, qr/Content-Range: bytes 990-999\/1000/, |
| 'more than length - content range'); |
| like($t1, qr/^X099XXXXXX$/m, 'more than length - correct content'); |
| |
| $t1 = http_get_range('/t2.html', 'Range: bytes=990-1990'); |
| like($t1, qr/ 206 /, 'recoded - 206 partial reply'); |
| like($t1, qr/Content-Length: 10/, 'recoded - content length'); |
| like($t1, qr/Content-Range: bytes 990-999\/1000/, 'recoded - content range'); |
| like($t1, qr/^Y099YYYYYY$/m, 'recoded - correct content'); |
| |
| $t1 = http_get_range('/t1.html', 'Range: bytes=0-9, -10, 10-19'); |
| like($t1, qr/ 206 /, 'multipart - 206 partial reply'); |
| like($t1, qr/Content-Type: multipart\/byteranges; boundary=/, |
| 'multipart - content type'); |
| like($t1, qr/X000XXXXXX/m, 'multipart - content 0-9'); |
| like($t1, qr/^X099XXXXXX\x0d?$/m, 'multipart - content -10 aka 990-999'); |
| like($t1, qr/X001XXXXXX\x0d?$/m, 'multipart - content 10-19'); |
| |
| $t1 = http_get_range('/t1.html', 'Range: bytes=0-9, -10, 100000-, 10-19'); |
| like($t1, qr/ 206 /, 'multipart big - 206 partial reply'); |
| like($t1, qr/Content-Type: multipart\/byteranges; boundary=/, |
| 'multipart big - content type'); |
| like($t1, qr/X000XXXXXX/m, 'multipart big - content 0-9'); |
| like($t1, qr/^X099XXXXXX\x0d?$/m, 'multipart big - content -10 aka 990-999'); |
| like($t1, qr/X001XXXXXX\x0d?$/m, 'multipart big - content 10-19'); |
| |
| like(http_get_range('/t1.html', 'Range: bytes=100000-'), qr/ 416 /, |
| 'not satisfiable - too big first byte pos'); |
| like(http_get_range('/t1.html', 'Range: bytes=alpha'), qr/ 416 /, |
| 'not satisfiable - alpha in first byte pos'); |
| like(http_get_range('/t1.html', 'Range: bytes=10-alpha'), qr/ 416 /, |
| 'not satisfiable - alpha in last byte pos'); |
| like(http_get_range('/t1.html', 'Range: bytes=10'), qr/ 416 /, |
| 'not satisfiable - no hyphen'); |
| like(http_get_range('/t1.html', 'Range: bytes=10-11 12-'), qr/ 416 /, |
| 'not satisfiable - no comma'); |
| |
| # last-byte-pos is taken to be equal to one less than the current length |
| # of the entity-body in bytes -- rfc2616 sec 14.35. |
| |
| like(http_get_range('/t1.html', 'Range: bytes=0-10001'), qr/ 206 /, |
| 'satisfiable - last byte pos adjusted'); |
| |
| # total size of all ranges is greater than source response size |
| |
| like(http_get_range('/t1.html', 'Range: bytes=0-10001, 0-0'), qr/ 200 /, |
| 'not satisfiable - malicious byte ranges'); |
| |
| like(http_get_range('/t3.html', 'Range: bytes=0-9, -10'), qr/ 206 /, |
| 'max_ranges not reached'); |
| like(http_get_range('/t3.html', 'Range: bytes=0-9, -10, 10000-'), qr/ 206 /, |
| 'max_ranges not reached bad range'); |
| unlike(http_get_range('/t3.html', 'Range: bytes=0-9, -10, 10-19'), |
| qr/ 206 /, 'max_ranges reached'); |
| unlike(http_get_range('/t4.html', 'Range: bytes=0-9'), qr/ 206 /, |
| 'max_ranges zero'); |
| |
| ############################################################################### |
| |
| sub http_get_range { |
| my ($url, $extra) = @_; |
| return http(<<EOF); |
| GET $url HTTP/1.1 |
| Host: localhost |
| Connection: close |
| $extra |
| |
| EOF |
| } |
| |
| ############################################################################### |