CGI-Tiny
view release on metacpan or search on metacpan
local $ENV{QUERY_STRING} = 'foo=bar';
local $ENV{REMOTE_ADDR} = '127.0.0.1';
local $ENV{REMOTE_HOST} = 'localhost';
local $ENV{REMOTE_IDENT} = 'somebody';
local $ENV{REMOTE_USER} = 'user';
local $ENV{REQUEST_METHOD} = 'POST';
local $ENV{SCRIPT_NAME} = '/test.cgi';
local $ENV{SERVER_NAME} = 'localhost';
local $ENV{SERVER_PORT} = '80';
local $ENV{SERVER_PROTOCOL} = 'HTTP/1.0';
local $ENV{SERVER_SOFTWARE} = "CGI::Tiny/$CGI::Tiny::VERSION";
my $auth_str = encode_base64 'user:password', '';
local $ENV{HTTP_AUTHORIZATION} = "Basic $auth_str";
local $ENV{HTTP_CONTENT_LENGTH} = length $text;
local $ENV{HTTP_CONTENT_TYPE} = 'text/plain;charset=UTF-8';
open my $in_fh, '<', \$text or die "failed to open handle for input: $!";
open my $out_fh, '>', \my $out_data or die "failed to open handle for output: $!";
my ($headers, $auth_header, $content_length_header, %vars);
cgi {
$_->set_input_handle($in_fh);
$_->set_output_handle($out_fh);
foreach my $key ((map { lc } @env_keys), qw(method path query)) { $vars{$key} = $_->$key }
$headers = $_->headers;
$auth_header = $_->header('Authorization');
$content_length_header = $_->header('Content-Length');
$_->render;
};
ok length($out_data), 'response rendered';
my $response = _parse_response($out_data);
ok defined($response->{headers}{date}), 'Date set';
like $response->{status}, qr/^200\b/, '200 response status';
is $vars{auth_type}, 'Basic', 'right AUTH_TYPE';
is $vars{content_length}, length($text), 'right CONTENT_LENGTH';
is $vars{content_type}, 'text/plain;charset=UTF-8', 'right CONTENT_TYPE';
is $vars{gateway_interface}, 'CGI/1.1', 'right GATEWAY_INTERFACE';
is $vars{path_info}, '/foo', 'right PATH_INFO';
is $vars{path_translated}, '/path/to/foo', 'right PATH_TRANSLATED';
is $vars{query_string}, 'foo=bar', 'right QUERY_STRING';
is $vars{remote_addr}, '127.0.0.1', 'right REMOTE_ADDR';
is $vars{remote_host}, 'localhost', 'right REMOTE_HOST';
is $vars{remote_ident}, 'somebody', 'right REMOTE_IDENT';
is $vars{remote_user}, 'user', 'right REMOTE_USER';
is $vars{request_method}, 'POST', 'right REQUEST_METHOD';
is $vars{script_name}, '/test.cgi', 'right SCRIPT_NAME';
is $vars{server_name}, 'localhost', 'right SERVER_NAME';
is $vars{server_port}, '80', 'right SERVER_PORT';
is $vars{server_protocol}, 'HTTP/1.0', 'right SERVER_PROTOCOL';
is $vars{server_software}, "CGI::Tiny/$CGI::Tiny::VERSION", 'right SERVER_SOFTWARE';
is $vars{method}, 'POST', 'right method';
is $vars{path}, '/foo', 'right path';
is $vars{query}, 'foo=bar', 'right query';
is $headers->{authorization}, "Basic $auth_str", 'right Authorization header';
is $headers->{'content-length'}, length($text), 'right Content-Length header';
is $headers->{'content-type'}, 'text/plain;charset=UTF-8', 'right Content-Type header';
is $auth_header, "Basic $auth_str", 'right Authorization header';
is $content_length_header, length($text), 'right Content-Length header';
};
subtest 'Cookies' => sub {
local @ENV{@env_keys} = ('')x@env_keys;
local $ENV{PATH_INFO} = '/';
local $ENV{REQUEST_METHOD} = 'GET';
local $ENV{SCRIPT_NAME} = '/';
local $ENV{SERVER_PROTOCOL} = 'HTTP/1.0';
local $ENV{HTTP_COOKIE} = 'a=b; c=42; x=; a=c';
open my $in_fh, '<', \(my $in_data = '') or die "failed to open handle for input: $!";
open my $out_fh, '>', \my $out_data or die "failed to open handle for output: $!";
my ($cookies, $cookie_names, $a_cookie, $a_cookies, $b_cookie);
cgi {
$_->set_input_handle($in_fh);
$_->set_output_handle($out_fh);
$cookies = $_->cookies;
$cookie_names = $_->cookie_names;
$a_cookie = $_->cookie('a');
$a_cookies = $_->cookie_array('a');
$b_cookie = $_->cookie('b');
$_->render;
};
ok length($out_data), 'response rendered';
my $response = _parse_response($out_data);
ok defined($response->{headers}{date}), 'Date set';
like $response->{status}, qr/^200\b/, '200 response status';
is_deeply $cookies, [['a', 'b'], ['c', 42], ['x', ''], ['a', 'c']], 'right cookies';
is_deeply $cookie_names, ['a', 'c', 'x'], 'right cookie names';
is $a_cookie, 'c', 'right cookie value';
is_deeply $a_cookies, ['b', 'c'], 'right cookie values';
ok !defined $b_cookie, 'no cookie value';
};
subtest 'Not found' => sub {
local @ENV{@env_keys} = ('')x@env_keys;
local $ENV{PATH_INFO} = '/';
local $ENV{REQUEST_METHOD} = 'GET';
local $ENV{SCRIPT_NAME} = '/';
local $ENV{SERVER_PROTOCOL} = 'HTTP/1.0';
open my $in_fh, '<', \(my $in_data = '') or die "failed to open handle for input: $!";
open my $out_fh, '>', \my $out_data or die "failed to open handle for output: $!";
cgi {
$_->set_input_handle($in_fh);
$_->set_output_handle($out_fh);
$_->set_response_status(404);
$_->render(text => '');
};
ok length($out_data), 'response rendered';
my $response = _parse_response($out_data);
ok !defined($response->{headers}{'content-type'}), 'Content-Type not set';
is $response->{headers}{'content-length'}, 0, 'right Content-Length';
like $response->{status}, qr/^404\b/, '404 response status';
ok !length($response->{body}), 'empty response body';
};
subtest 'Data response (fixed length)' => sub {
local @ENV{@env_keys} = ('')x@env_keys;
local $ENV{PATH_INFO} = '/';
local $ENV{REQUEST_METHOD} = 'GET';
local $ENV{SCRIPT_NAME} = '/';
local $ENV{SERVER_PROTOCOL} = 'HTTP/1.0';
open my $in_fh, '<', \(my $in_data = '') or die "failed to open handle for input: $!";
open my $out_fh, '>', \my $out_data or die "failed to open handle for output: $!";
my $url = '/foo';
cgi {
$_->set_input_handle($in_fh);
$_->set_output_handle($out_fh);
$_->set_response_status(100)->render(redirect => $url);
};
ok length($out_data), 'response rendered';
my $response = _parse_response($out_data);
ok !defined($response->{headers}{'content-type'}), 'Content-Type not set';
is $response->{headers}{'content-length'}, 0, 'right Content-Length';
is $response->{headers}{location}, $url, 'Location set';
like $response->{status}, qr/^302\b/, '302 response status';
ok defined($response->{headers}{date}), 'Date set';
ok defined(CGI::Tiny::date_to_epoch $response->{headers}{date}), 'valid HTTP date';
ok !length($response->{body}), 'empty response body';
};
subtest 'Response headers' => sub {
local @ENV{@env_keys} = ('')x@env_keys;
local $ENV{PATH_INFO} = '/';
local $ENV{REQUEST_METHOD} = 'GET';
local $ENV{SCRIPT_NAME} = '/';
local $ENV{SERVER_PROTOCOL} = 'HTTP/1.0';
open my $in_fh, '<', \(my $in_data = '') or die "failed to open handle for input: $!";
open my $out_fh, '>', \my $out_data or die "failed to open handle for output: $!";
my @headers = (
['X-Test', 'some value'],
['X-test', 'another value'],
);
my @cookies = (
['foo', 'bar', Domain => 'example.com', HttpOnly => 1, 'Max-Age' => 3600, Path => '/test', SameSite => 'Strict', Secure => 1],
['x', '', Expires => 'Sun, 06 Nov 1994 08:49:37 GMT', HttpOnly => 0, SameSite => 'Lax', Secure => 0],
);
cgi {
$_->set_input_handle($in_fh);
$_->set_output_handle($out_fh);
foreach my $header (@headers) { $_->add_response_header(@$header) }
foreach my $cookie (@cookies) { $_->add_response_cookie(@$cookie) }
$_->set_response_type('image/gif');
$_->set_response_disposition(attachment => 'foo.gif');
$_->set_response_status(202);
$_->render;
};
ok length($out_data), 'response rendered';
my $response = _parse_response($out_data);
ok defined($response->{headers}{'content-type'}), 'Content-Type set';
is $response->{headers}{'content-type'}, 'image/gif', 'right content type';
is $response->{headers}{'content-disposition'}, 'attachment; filename="foo.gif"; filename*=UTF-8\'\'foo.gif', 'right Content-Disposition';
like $response->{status}, qr/^202\b/, '202 response status';
is_deeply $response->{headers}{'x-test'}, ['some value', 'another value'], 'right custom headers';
is_deeply $response->{headers}{'set-cookie'},
['foo=bar; Domain=example.com; HttpOnly; Max-Age=3600; Path=/test; SameSite=Strict; Secure',
'x=; Expires=Sun, 06 Nov 1994 08:49:37 GMT; SameSite=Lax'], 'right Set-Cookie headers';
};
subtest 'Reset response headers' => sub {
local @ENV{@env_keys} = ('')x@env_keys;
local $ENV{PATH_INFO} = '/';
local $ENV{REQUEST_METHOD} = 'GET';
local $ENV{SCRIPT_NAME} = '/';
local $ENV{SERVER_PROTOCOL} = 'HTTP/1.0';
open my $in_fh, '<', \(my $in_data = '') or die "failed to open handle for input: $!";
open my $out_fh, '>', \my $out_data or die "failed to open handle for output: $!";
my @headers = (
['X-Test', 'some value'],
['X-test', 'another value'],
);
my @cookies = (
['foo', 'bar'],
);
cgi {
$_->set_input_handle($in_fh);
$_->set_output_handle($out_fh);
foreach my $header (@headers) { $_->add_response_header(@$header) }
foreach my $cookie (@cookies) { $_->add_response_cookie(@$cookie) }
$_->set_response_type('image/gif');
$_->set_response_status(400);
$_->set_response_disposition(attachment => 'foo.gif');
$_->reset_response_headers;
$_->set_response_type(undef);
$_->set_response_status(200);
$_->set_response_disposition('inline');
$_->render;
};
ok length($out_data), 'response rendered';
my $response = _parse_response($out_data);
ok !defined($response->{headers}{'content-type'}), 'Content-Type not set';
ok !defined $response->{headers}{'content-disposition'}, 'Content-Disposition not set';
like $response->{status}, qr/^200\b/, '200 response status';
ok !defined $response->{headers}{'x-test'}, 'custom headers reset';
ok !defined $response->{headers}{'set-cookie'}, 'Set-Cookie headers reset';
};
subtest 'NPH response' => sub {
local @ENV{@env_keys} = ('')x@env_keys;
local $ENV{PATH_INFO} = '/';
local $ENV{REQUEST_METHOD} = 'GET';
local $ENV{SCRIPT_NAME} = '/';
local $ENV{SERVER_PROTOCOL} = 'HTTP/1.0';
local $ENV{SERVER_SOFTWARE} = "CGI::Tiny/$CGI::Tiny::VERSION";
open my $in_fh, '<', \(my $in_data = '') or die "failed to open handle for input: $!";
open my $out_fh, '>', \my $out_data or die "failed to open handle for output: $!";
cgi {
$_->set_input_handle($in_fh);
$_->set_output_handle($out_fh);
$_->set_nph;
$_->render;
};
ok length($out_data), 'response rendered';
my $response = _parse_response($out_data, 1);
like $response->{start_line}, qr/^HTTP\/1.0\b/, 'right start line';
ok !defined($response->{headers}{'content-type'}), 'Content-Type not set';
is $response->{headers}{server}, "CGI::Tiny/$CGI::Tiny::VERSION", 'right Server header';
like $response->{status}, qr/^200\b/, '200 response status';
ok defined($response->{headers}{date}), 'Date set';
ok defined(CGI::Tiny::date_to_epoch $response->{headers}{date}), 'valid HTTP date';
ok !length($response->{body}), 'empty response body';
};
subtest 'NPH error response' => sub {
local @ENV{@env_keys} = ('')x@env_keys;
local $ENV{PATH_INFO} = '/';
local $ENV{REQUEST_METHOD} = 'GET';
local $ENV{SCRIPT_NAME} = '/';
local $ENV{SERVER_PROTOCOL} = 'HTTP/1.0';
open my $in_fh, '<', \(my $in_data = '') or die "failed to open handle for input: $!";
open my $out_fh, '>', \my $out_data or die "failed to open handle for output: $!";
cgi {
$_->set_input_handle($in_fh);
$_->set_output_handle($out_fh);
$_->set_nph(1);
$_->set_response_status(404);
$_->set_response_type('text/plain');
$_->render;
};
ok length($out_data), 'response rendered';
my $response = _parse_response($out_data, 1);
like $response->{start_line}, qr/^HTTP\/1.0\b/, 'right start line';
ok defined($response->{headers}{'content-type'}), 'Content-Type set';
is $response->{headers}{'content-type'}, 'text/plain', 'right content type';
like $response->{status}, qr/^404\b/, '404 response status';
ok !length($response->{body}), 'empty response body';
};
done_testing;
( run in 1.898 second using v1.01-cache-2.11-cpan-39bf76dae61 )