use strict; use warnings FATAL => 'all'; use Apache::Test; use Apache::TestRequest; use Apache::TestUtil qw(t_write_file); # test content-length header in byterange-requests # test invalid range headers my $url = "/apache/chunked/byteranges.txt"; my $file = Apache::Test::vars('serverroot') . "/htdocs$url"; my $content = ""; $content .= sprintf("%04d", $_) for (1 .. 10000); t_write_file($file, $content); my $real_clen = length($content); # # test cases # # check content-length for (multi-)range responses my @tc_ranges_cl = ( 1, 2, 10, 50, 100); # send 200 response if range invalid my @tc_invalid = ("", ",", "7-1", "foo", "1-4,x", "1-4,5-2", "100000-110000,5-2"); # send 416 if no range satisfiable my %tc_416 = ( "100000-110000" => 416, "100000-110000,200000-" => 416, "1000-200000" => 206, # should be truncated until end "100000-110000,1000-2000" => 206, # should ignore unsatifiable range "100000-110000,2000-1000" => 200, # invalid, should ignore whole header ); plan tests => scalar(@tc_ranges_cl) + 2 * scalar(@tc_invalid) + scalar(keys %tc_416), need need_lwp; foreach my $num (@tc_ranges_cl) { my @ranges; foreach my $i (0 .. ($num-1)) { push @ranges, sprintf("%d-%d", $i * 100, $i * 100 + 1); } my $range = join(",", @ranges); my $result = GET $url, "Range" => "bytes=$range"; print_result($result); if ($result->code != 206) { print "did not get 206\n"; ok(0); next; } my $clen = $result->header("Content-Length"); my $body = $result->content; my $blen = length($body); if ($blen == $real_clen) { print "Did get full content, should have gotten only parts\n"; ok(0); next; } print "body length $blen\n"; if (defined $clen) { print "Content-Length: $clen\n"; if ($blen != $clen) { print "Content-Length does not match body\n"; ok(0); next; } } ok(1); } # test invalid range headers, with and without "bytes=" my @tc_invalid2 = map { "bytes=" . $_ } @tc_invalid; foreach my $range (@tc_invalid, @tc_invalid2) { my $result = GET $url, "Range" => "$range"; print_result($result); my $code = $result->code; if ($code == 206) { print "got partial content response with invalid range header '$range'\n"; ok(0); } elsif ($code == 200) { my $body = $result->content; if ($body != $content) { print "Body did not match expected content\n"; ok(0); } ok(1); } else { print "Huh?\n"; ok(0); } } # test unsatisfiable ranges headers foreach my $range (sort keys %tc_416) { print "Sending '$range', expecting $tc_416{$range}\n"; my $result = GET $url, "Range" => "bytes=$range"; print_result($result); ok($result->code == $tc_416{$range}); } sub print_result { my $result = shift; my $code = $result->code; my $cr = $result->header("Content-Range"); my $ct = $result->header("Content-Type"); my $msg = "Got $code"; $msg .= " multipart/byteranges" if (defined $ct && $ct =~ m{^multipart/byteranges}); $msg .= " Range: '$cr'" if defined $cr; print "$msg\n"; }