CGI-Alternatives

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN

    use warnings;
    use CGI::Tiny;

    cgi {
        my $cgi = $_;
        my $input = $cgi->param('user_input');

        $cgi->render(html => qq{
            <html>
            <body>
                <form method="post">
                    <input name="user_input" type="text" />
                    <input type="submit" />
                </form>
                } . ($input ? "<p>You wrote: $input</p>" : '') . q{
            </body>
            </html>
        });
    };

For more information: [https://blogs.perl.org/users/grinnz/2025/02/cgitiny---perl-cgi-but-modern.html](https://blogs.perl.org/users/grinnz/2025/02/cgitiny---perl-cgi-but-modern.html)

# MODERN DEPLOYMENT PRACTICES

## PSGI Servers

All modern Perl web frameworks support PSGI. Here are the recommended PSGI
servers for production:

- [Starman](https://metacpan.org/pod/Starman) - High-performance preforking PSGI server (recommended for most uses)
- [Gazelle](https://metacpan.org/pod/Gazelle) - Preforking Plack handler for performance freaks
- [Twiggy](https://metacpan.org/pod/Twiggy) - AnyEvent-based PSGI server for real-time applications

Example production deployment with Starman:

    plackup -s Starman \
        --workers=10 \
        --port=5000 \
        --daemonize \
        --pid=/var/run/myapp.pid \
        bin/app.psgi

## Reverse Proxy

In production, run your PSGI app behind a reverse proxy like nginx or Apache:

nginx example:

    upstream myapp {
        server 127.0.0.1:5000;
    }

    server {
        listen 80;
        server_name myapp.example.com;

        location / {
            proxy_pass http://myapp;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }

# Dependency Management

This is a whole other topic, but given CGI.pm is no longer in the perl core
you would have to install it anyway. It would be a good idea to do this the
right way from beginning. I'm not going to cover this in detail here, there are
many many good sources of information on the web. Here are some links to get
you started:

## Managing Perl Versions

- [https://github.com/tokuhirom/plenv](https://github.com/tokuhirom/plenv) - plenv: Perl binary manager
- [https://perlbrew.pl/](https://perlbrew.pl/) - perlbrew: Manage multiple perl installations

## Managing Perl Modules

- [https://metacpan.org/release/App-cpanminus](https://metacpan.org/release/App-cpanminus) - cpanm: Fast, lightweight CPAN client
- [https://metacpan.org/release/App-cpm](https://metacpan.org/release/App-cpm) - cpm: Fast, parallel CPAN module installer (3x faster than cpanm)
- [https://metacpan.org/release/Carton](https://metacpan.org/release/Carton) - Carton: Perl module dependency manager (like bundler for Ruby)
- [https://metacpan.org/release/local-lib](https://metacpan.org/release/local-lib) - local::lib: Use a local lib/ directory for modules

Modern approach using cpanfile and cpm:

Create a cpanfile:

    requires 'Dancer2', '0.400000';
    requires 'Template', '2.26';
    requires 'Starman', '0.4015';

Install dependencies:

    # Fast parallel installation
    cpm install

    # Or with cpanm
    cpanm --installdeps .

Lock dependencies with Carton:

    carton install
    carton exec plackup bin/app.psgi

# TESTING

One major advantage of modern frameworks is testability. All the frameworks
mentioned support easy testing:

    use Test::More;
    use Plack::Test;
    use HTTP::Request::Common;

    my $app = MyApp->to_app;

    test_psgi $app, sub {
        my $cb = shift;
        my $res = $cb->(GET "/example_form");
        is $res->code, 200;
        like $res->content, qr/Say something/;



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