1#!perl 2 3use strict; 4use warnings; 5 6use Test::More qw[no_plan]; 7use lib 't'; 8use Util qw[tmpfile rewind $CRLF $LF]; 9use HTTP::Tiny; 10 11sub _header { 12 return [ @{$_[0]}{qw/status reason headers protocol/} ] 13} 14 15{ 16 no warnings 'redefine'; 17 sub HTTP::Tiny::Handle::can_read { 1 }; 18 sub HTTP::Tiny::Handle::can_write { 1 }; 19} 20 21{ 22 my $response = join $CRLF, 'HTTP/1.1 200 OK', 'Foo: Foo', 'Bar: Bar', '', ''; 23 my $fh = tmpfile($response); 24 my $handle = HTTP::Tiny::Handle->new(fh => $fh); 25 my $exp = [ 200, 'OK', { foo => 'Foo', bar => 'Bar' }, 'HTTP/1.1' ]; 26 is_deeply(_header($handle->read_response_header), $exp, "->read_response_header CRLF"); 27} 28 29{ 30 my $response = join $LF, 'HTTP/1.1 200 OK', 'Foo: Foo', 'Bar: Bar', '', ''; 31 my $fh = tmpfile($response); 32 my $handle = HTTP::Tiny::Handle->new(fh => $fh); 33 my $exp = [ 200, 'OK', { foo => 'Foo', bar => 'Bar' }, 'HTTP/1.1' ]; 34 is_deeply(_header($handle->read_response_header), $exp, "->read_response_header LF"); 35} 36 37{ 38 # broken status-line 39 my $response = join $LF, "HTTP/08.15 66x Foo\nbar", 'Foo: Foo', 'Bar: Bar', '', ''; 40 my $fh = tmpfile($response); 41 my $handle = HTTP::Tiny::Handle->new(fh => $fh); 42 my $res = eval{ $handle->read_response_header }; 43 my $err = $@; 44 like $err, qr/Malformed Status-Line: /, '->read_response_header diagnoses malformed status line'; 45} 46 47{ 48 my $response = join $LF, "HTTP/2.0 200 Okish", 'Foo: Foo', 'Bar: Bar', '', ''; 49 my $fh = tmpfile($response); 50 my $handle = HTTP::Tiny::Handle->new(fh => $fh); 51 my $res = eval{ $handle->read_response_header }; 52 my $err = $@; 53 like $err, qr/Unsupported HTTP protocol: /, '->read_response_header unsupported HTTP protocol'; 54} 55 56{ 57 # strict RFC7230#3.1.2 compliance, require space after code 58 my $response = join $LF, 'HTTP/1.1 200 ', 'Foo: Foo', 'Bar: Bar', '', ''; 59 my $fh = tmpfile($response); 60 my $handle = HTTP::Tiny::Handle->new(fh => $fh); 61 my $exp = [ 200, '', { foo => 'Foo', bar => 'Bar' }, 'HTTP/1.1' ]; 62 is_deeply(_header($handle->read_response_header), $exp, "->read_response_header empty phrase preceded by SP"); 63} 64 65{ 66 # practical RFC7230#3.1.2 interpretation, require space after code 67 # only if there is a reason-phrase 68 my $response = join $LF, 'HTTP/1.1 200', 'Foo: Foo', 'Bar: Bar', '', ''; 69 my $fh = tmpfile($response); 70 my $handle = HTTP::Tiny::Handle->new(fh => $fh); 71 my $exp = [ 200, '', { foo => 'Foo', bar => 'Bar' }, 'HTTP/1.1' ]; 72 is_deeply(_header($handle->read_response_header), $exp, "->read_response_header empty phrase without preceding SP"); 73} 74