CGI-Tiny
view release on metacpan or search on metacpan
1.003 2024-06-11 05:56:03 EDT
- Update messages of HTTP status codes 413 and 422 based on RFC 9110
1.002 2021-06-09 00:33:32 EDT
- Documentation updates
1.001 2021-06-07 23:16:34 EDT
- Move "EXTENDING" examples to CGI::Tiny::Cookbook and examples/
1.000 2021-05-30 17:09:42 EDT
- Remove experimental status
0.020 2021-05-30 00:05:56 EDT
- Replace set_discard_form_files method with more generic set_multipart_form_options
- Improved test coverage
0.019 2021-05-25 23:52:51 EDT
- Add params, param_names, param, and param_array general request parameter accessors
examples/logging.cgi
examples/routing.cgi
examples/sessions-basic.cgi
examples/sessions-cookie.cgi
examples/templates/index.html.ep
examples/templates/index.tx
examples/templating-mojo.cgi
examples/templating-xslate.cgi
lib/CGI/Tiny.pm
lib/CGI/Tiny.pod
lib/CGI/Tiny/Cookbook.pod
lib/CGI/Tiny/Multipart.pm
lib/CGI/Tiny/Multipart.pod
lib/CGI/Tiny/_Debug.pm
prereqs.yml
t/00-report-prereqs.dd
t/00-report-prereqs.t
t/cgi.t
t/functions.t
t/multipart.t
xt/author/pod-coverage.t
in non-CGI code), load the module with use CGI::Tiny (); or require
CGI::Tiny;.
NOTE: The cgi block's current implementation as a regular exported
subroutine is an implementation detail, and future implementations
reserve the right to provide it as an XSUB or keyword for performance
reasons. Don't call it as CGI::Tiny::cgi, don't rely on @_ being set,
and don't use return to exit the block; use exit to end a CGI script
early after rendering a response.
See CGI::Tiny::Cookbook for advanced usage examples.
DATA SAFETY
CGI::Tiny does not provide any special affordances for taint mode as it
is overeager, imprecise, and can significantly impact performance. Web
developers should instead proactively take care not to use any request
data (including request headers, form fields, or other request content)
directly in an unsafe manner, as it can make the program vulnerable to
injections that cause undesired or dangerous behavior. The most common
risks to watch out for include:
the m// or s/// operators, or the first argument to split. Data can
be safely included in a regex to match it as an exact string by
escaping it with the quotemeta function or equivalent \Q escape
sequence.
* HTML
Do not interpolate arbitrary data into HTML. Data can be safely
included in HTML by escaping it with "escape_html", or passing it to
an HTML template engine with an auto-escape feature; see "Templating"
in CGI::Tiny::Cookbook.
METHODS
The following methods can be called on the CGI::Tiny object provided to
the cgi block.
Setup
set_error_handler
$cgi = $cgi->add_response_cookie($name => $value,
Expires => 'Sun, 06 Nov 1994 08:49:37 GMT',
HttpOnly => 1,
'Max-Age' => 3600,
Path => '/foo',
SameSite => 'Strict',
Secure => 1,
);
Adds a Set-Cookie response header. No effect after response headers
have been rendered.
Cookie values should consist only of simple ASCII text; see "Cookies"
in CGI::Tiny::Cookbook for methods of storing more complex strings and
data structures.
Optional cookie attributes are specified in key-value pairs after the
cookie name and value. Cookie attribute names are case-insensitive.
Domain
Domain for which cookie is valid. Defaults to the host of the current
document URL, not including subdomains.
Expires
Expiration date string for cookie. Defaults to persisting for the
current browser session. "epoch_to_date" can be used to generate the
escape_html
my $escaped = CGI::Tiny::escape_html $text;
Escapes characters that are unsafe for embedding in HTML text. The
characters &<>"' will each be replaced with the corresponding HTML
character reference (HTML entity).
This functionality is built into most HTML template engines; see
"Templating" in CGI::Tiny::Cookbook. For more general HTML entity
escaping and unescaping use HTML::Entities.
ENVIRONMENT
CGI::Tiny recognizes the following environment variables, in addition
to the standard CGI environment variables.
CGI_TINY_REQUEST_BODY_BUFFER
Default value for "set_request_body_buffer".
human-readable status message itself.
* Response setters are distinct methods from request accessors in
CGI::Tiny. "content_type", "header", and "cookie" are used to access
request data, and "set_response_type", "add_response_header", and
"add_response_cookie" are used to set response headers for the
pending response before the first call to "render" or "render_chunk".
* CGI::Tiny does not provide any HTML generation helpers, as this
functionality is much better implemented by other robust
implementations on CPAN; see "Templating" in CGI::Tiny::Cookbook.
* CGI::Tiny does not do any implicit encoding of cookie values or the
Expires header or cookie attribute. See "Cookies" in
CGI::Tiny::Cookbook for examples of encoding and decoding cookie
values. The "epoch_to_date" convenience function is provided to
render appropriate Expires date values.
There are a number of alternatives to CGI.pm but they do not
sufficiently address the design issues; primarily, none of them
gracefully handle exceptions or failure to render a response, and
several of them have no features for rendering responses.
* CGI::Simple shares all of the interface design problems of CGI.pm,
though it does not reimplement the HTML generation helpers.
lib/CGI/Tiny.pm view on Meta::CPAN
Carp::croak "Attempted to set unknown cookie attribute '$key' for HTTP response cookie '$name'";
} elsif ($has_value) {
$cookie_str .= "; $key=$val" if defined $val;
} else {
$cookie_str .= "; $key" if $val;
}
} continue {
$i += 2;
}
Carp::croak "Newline characters not allowed in HTTP response cookie '$name'" if $cookie_str =~ tr/\r\n//;
push @{$self->{response_headers}}, ['Set-Cookie', $cookie_str];
}
return $self;
}
}
sub reset_response_headers { delete $_[0]{response_headers}; $_[0] }
sub response_status_code {
my ($self) = @_;
if (defined $self->{response_status} and $self->{response_status} =~ m/\A([0-9]+)/) {
lib/CGI/Tiny.pod view on Meta::CPAN
available (such as to use convenience L</"FUNCTIONS"> in non-CGI code), load
the module with C<use CGI::Tiny ();> or C<require CGI::Tiny;>.
B<NOTE:> The C<cgi> block's current implementation as a regular exported
subroutine is an implementation detail, and future implementations reserve the
right to provide it as an XSUB or keyword for performance reasons. Don't call
it as C<CGI::Tiny::cgi>, don't rely on C<@_> being set, and don't use C<return>
to exit the block; use C<exit> to end a CGI script early after rendering a
response.
See L<CGI::Tiny::Cookbook> for advanced usage examples.
=head1 DATA SAFETY
CGI::Tiny does not provide any special affordances for
L<taint mode|perlsec/"Taint mode"> as it is overeager, imprecise, and can
significantly impact performance. Web developers should instead proactively
take care not to use any request data (including request headers, form fields,
or other request content) directly in an unsafe manner, as it can make the
program vulnerable to injections that cause undesired or dangerous behavior.
The most common risks to watch out for include:
lib/CGI/Tiny.pod view on Meta::CPAN
Do not interpolate arbitrary data into regular expressions, such as the C<m//>
or C<s///> operators, or the first argument to C<split>. Data can be safely
included in a regex to match it as an exact string by escaping it with
the C<quotemeta> function or equivalent C<\Q> escape sequence.
=item * HTML
Do not interpolate arbitrary data into HTML. Data can be safely included in
HTML by escaping it with L</"escape_html">, or passing it to an HTML template
engine with an auto-escape feature; see L<CGI::Tiny::Cookbook/"Templating">.
=back
=head1 METHODS
The following methods can be called on the CGI::Tiny object provided to the
C<cgi> block.
=head2 Setup
lib/CGI/Tiny.pod view on Meta::CPAN
$cgi = $cgi->add_response_cookie($name => $value,
Expires => 'Sun, 06 Nov 1994 08:49:37 GMT',
HttpOnly => 1,
'Max-Age' => 3600,
Path => '/foo',
SameSite => 'Strict',
Secure => 1,
);
Adds a C<Set-Cookie> response header. No effect after response headers have
been rendered.
Cookie values should consist only of simple ASCII text; see
L<CGI::Tiny::Cookbook/"Cookies"> for methods of storing more complex strings
and data structures.
Optional cookie attributes are specified in key-value pairs after the cookie
name and value. Cookie attribute names are case-insensitive.
=over
=item Domain
Domain for which cookie is valid. Defaults to the host of the current document
URL, not including subdomains.
=item Expires
lib/CGI/Tiny.pod view on Meta::CPAN
=head2 escape_html
my $escaped = CGI::Tiny::escape_html $text;
Escapes characters that are unsafe for embedding in HTML text. The characters
C<&E<lt>E<gt>"'> will each be replaced with the corresponding HTML character
reference (HTML entity).
This functionality is built into most HTML template engines; see
L<CGI::Tiny::Cookbook/"Templating">. For more general HTML entity escaping and
unescaping use L<HTML::Entities>.
=head1 ENVIRONMENT
CGI::Tiny recognizes the following environment variables, in addition to the
standard CGI environment variables.
=over
=item CGI_TINY_REQUEST_BODY_BUFFER
lib/CGI/Tiny.pod view on Meta::CPAN
Response setters are distinct methods from request accessors in CGI::Tiny.
L</"content_type">, L</"header">, and L</"cookie"> are used to access request
data, and L</"set_response_type">, L</"add_response_header">, and
L</"add_response_cookie"> are used to set response headers for the pending
response before the first call to L</"render"> or L</"render_chunk">.
=item *
CGI::Tiny does not provide any HTML generation helpers, as this functionality
is much better implemented by other robust implementations on CPAN; see
L<CGI::Tiny::Cookbook/"Templating">.
=item *
CGI::Tiny does not do any implicit encoding of cookie values or the C<Expires>
header or cookie attribute. See L<CGI::Tiny::Cookbook/"Cookies"> for examples
of encoding and decoding cookie values. The L</"epoch_to_date"> convenience
function is provided to render appropriate C<Expires> date values.
=back
There are a number of alternatives to CGI.pm but they do not sufficiently
address the design issues; primarily, none of them gracefully handle
exceptions or failure to render a response, and several of them have no
features for rendering responses.
lib/CGI/Tiny/Cookbook.pod view on Meta::CPAN
=pod
=encoding UTF-8
=head1 NAME
CGI::Tiny::Cookbook - Recipes for advanced CGI::Tiny usage
=head1 DESCRIPTION
L<CGI::Tiny> is a minimal interface to the CGI protocol, but common tasks can
be simplified with the use of other CPAN modules and techniques.
=head1 RECIPES
=head2 Dependencies
lib/CGI/Tiny/Cookbook.pod view on Meta::CPAN
$cgi->set_response_status(404)->render(text => 'Not Found');
exit;
}
my $basename = decode_utf8 $filepath->basename;
my $mime = MIME::Types->new->mimeTypeOf($basename);
$cgi->set_response_type($mime->type) if defined $mime;
$cgi->set_response_disposition(attachment => $basename)->render(file => $filepath);
};
=head2 Cookies
Cookie values should only consist of ASCII characters and may not contain any
control characters, space characters, or the characters C<",;\>. More complex
strings can be encoded to UTF-8 and L<base64|MIME::Base64> for transport.
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use CGI::Tiny;
use Unicode::UTF8 qw(decode_utf8 encode_utf8);
use MIME::Base64 qw(decode_base64 encode_base64);
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);
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: $!";
$_->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: $!";
( run in 2.052 seconds using v1.01-cache-2.11-cpan-e9199f4ba4c )