HTTP-Handy

 view release on metacpan or  search on metacpan

lib/HTTP/Handy.pm  view on Meta::CPAN

The caller is responsible for encoding the JSON string.
Default status is 200.

  use mb::JSON;  # or any JSON encoder that works with Perl 5.5.3
  return HTTP::Handy->response_json(encode_json(\%data));

=head2 C<response_redirect($location [, $code])>

Build a redirect response with a C<Location> header.
Default status is 302.

  return HTTP::Handy->response_redirect('/new/path');
  return HTTP::Handy->response_redirect('https://example.com/', 301);

=head1 ERROR HANDLING

=over 4

=item * If the application C<die>s, a 500 response is sent to the client
and the error message is printed to STDERR. The server continues running.

=item * An unsupported HTTP method returns a 405 response.

=item * A POST body exceeding C<max_post_size> (default 10 MB) returns a 413 response.

=item * Socket errors are printed to STDERR and the server continues
to the next request.

=back

=head1 STATIC FILES, CGI, AND HTMX

HTTP::Handy can serve static files and handle dynamic routes in the same
application, making it self-contained with no external web server needed.

  my $app = sub {
      my $env = shift;
      my $path = $env->{PATH_INFO};

      # Dynamic API route (used as HTMX target)
      if ($path =~ m{^/api/}) {
          my $html_fragment = compute_fragment($env);
          return HTTP::Handy->response_html($html_fragment);
      }

      # Static files (HTML, CSS, JS)
      return HTTP::Handy->serve_static($env, './htdocs');
  };

When used with HTMX, the server simply returns HTML fragments for
C<hx-get> / C<hx-post> requests. No special support is required.

Reading POST body (equivalent to CGI's C<STDIN>):

  my $body = '';
  $env->{'psgi.input'}->read($body, $env->{CONTENT_LENGTH} || 0);
  my %post = HTTP::Handy->parse_query($body);

=head1 HTTPS

HTTP::Handy does not support HTTPS. TLS requires C<IO::Socket::SSL> and
OpenSSL, which depend on Perl 5.8+ and external C libraries.

For local personal use, this is not a problem: modern browsers treat
C<127.0.0.1> and C<localhost> as secure contexts and do not show
HTTPS warnings for HTTP on these addresses.

For LAN or internet use, place a reverse proxy in front of HTTP::Handy:

  Browser <--HTTPS--> Caddy / nginx / Apache <--HTTP--> HTTP::Handy

A minimal Caddy configuration:

  localhost {
      reverse_proxy 127.0.0.1:8080
  }

=head1 PSGI COMPATIBILITY NOTES

HTTP::Handy implements a strict I<subset> of the PSGI/1.1 specification.
The following keys defined by the PSGI spec are B<not> set in C<$env>:

  psgi.version        (PSGI requires [1,1]; not set)
  psgi.multithread    (not set; effectively false)
  psgi.multiprocess   (not set; effectively false)
  psgi.run_once       (not set; effectively false)
  psgi.nonblocking    (not set; always blocking)
  psgi.streaming      (not set; not supported)

Applications that check for these keys must treat their absence as false.
For full PSGI/1.1 compliance use L<Plack> (requires Perl 5.8+).

=head1 SECURITY

HTTP::Handy is designed for B<personal use and local development only>.
It is not hardened for production or internet-facing deployment.

=over 4

=item * B<No authentication or access control.>
Any client that can reach the listening port has unrestricted access.

=item * B<No rate limiting or DoS protection.>
A slow or malicious client can occupy the single-threaded server indefinitely.

=item * B<No HTTPS.>
All traffic is transmitted in plaintext (see L</HTTPS>).

=item * B<POST body capped at 10 MB by default.>
Requests exceeding C<max_post_size> receive a 413 response, but there is no
timeout on slow uploads.

=back

Recommended practice: bind to C<127.0.0.1> (loopback only) and place a
hardened reverse proxy in front of HTTP::Handy for any LAN or internet use.

=head1 LIMITATIONS

=over 4



( run in 1.700 second using v1.01-cache-2.11-cpan-39bf76dae61 )