CGI::Compile(3pm)

🌸 CGI::Compile β€” from the CGI::Compile(3pm) page, User Contributed Perl Documentation 🌸

hiii bestie πŸ’– welcome to the doc page for CGI::Compile(3pm) β€” yes that's the manual name, that's the section of the perl docs we're in, and yes we're gonna read the whole thing together. grab a snack. πŸ“


✨ NAME ✨

CGI::Compile β€” it compiles .cgi scripts into a code reference, exactly like ModPerl::Registry does. that's the whole pitch. πŸ‘‘


πŸŽ€ SYNOPSIS πŸŽ€

use CGI::Compile;
my $sub = CGI::Compile->compile("/path/to/script.cgi");

πŸ’– DESCRIPTION πŸ’–

okay so CGI::Compile is a utility that takes your CGI scripts and compiles them into a code reference β€” one that can run over and over again inside its own namespace, as long as your script is chill about living in a persistent environment. no cap. πŸ¦‹

NOTE: for best results, load CGI::Compile before any modules that your CGIs use. like, before. iykyk. πŸ™ˆ

🌈 RUN ON PSGI 🌈

team up with CGI::Emulate::PSGI and your CGI script gets turned into a persistent PSGI application, like this:

use CGI::Emulate::PSGI;
use CGI::Compile;

my $cgi_script = "/path/to/foo.cgi";
my $sub = CGI::Compile->compile($cgi_script);
my $app = CGI::Emulate::PSGI->handler($sub);

# $app is a PSGI application

main character transformation fr fr ✨


πŸ’€ CAVEATS πŸ’€

if your CGI script has a subroutine that references a lexical scope variable from outside the subroutine, you're gonna see warnings like:

Variable "$q" is not available at ...
Variable "$counter" will not stay shared at ...

this is just how the module do β€” it compiles the whole script into one big sub. to fix it, you have to update your code so you pass the lexical variables around, or swap my for our. there's also more detail at http://perl.apache.org/docs/1.0/guide/porting.html#The_First_Mystery if you wanna go deeper. 🧚


πŸ’… METHODS πŸ’…

πŸ’œ new

you don't need to call this one. you only call it if you want to set your own namespace_root for the generated packages that the CGIs get compiled into.

otherwise, just call compile as a class method and the object gets instantiated for you with a namespace_root of CGI::Compile::ROOT. easy. 🫢

you can also set return_exit_val β€” peep RETURN CODE below for the deets.

Example:

my $compiler = CGI::Compile->new(namespace_root => 'My::CGIs');
my $cgi      = $compiler->compile('/var/www/cgi-bin/my.cgi');

🌟 compile

takes either a path to a perl CGI script or some source code, plus some other optional params, and wraps the whole thing into a coderef for execution. ✨

can be called as either a class method or an instance method β€” see new above.

Parameters:

  • $cgi_script β€” path to the perl CGI script file, or a scalar reference containing the source code of the CGI script. required.
  • $package β€” optional. the package to install the script into. defaults to the path parts of the script joined with _, with all special characters converted to _%2x, and prepended with CGI::Compile::ROOT::.

E.g.:

/var/www/cgi-bin/foo.cgi

becomes:

CGI::Compile::ROOT::var_www_cgi_2dbin_foo_2ecgi

Returns:

  • $coderef β€” $cgi_script or $$code compiled into a coderef.

πŸ¦‹ SCRIPT ENVIRONMENT πŸ¦‹

🌸 ARGUMENTS

stuff like the query string and form data should generally live in the appropriate environment variables β€” the ones that things like CGI expect. πŸ“¬

you can also pass arguments to the generated coderef, and they get locally aliased to @_ and @ARGV. cute, right?

πŸŽ€ "BEGIN" and "END" blocks

"BEGIN" blocks are called once, when the script is compiled. "END" blocks are called when the Perl interpreter is unloaded. ⏳

this can cause surprising effects, no cap. suppose, for instance, a script that runs in a forking web server and is loaded in the parent process. "END" blocks will be called once for each worker process and another time for the parent process β€” while "BEGIN" blocks are called only by the parent process. πŸ’€

🧚 %SIG

the %SIG hash is preserved, meaning the script can change signal handlers whenever it wants. the next invocation gets a pristine %SIG again. clean slate every time, slay. ✨

πŸ’… "exit" and exceptions

calls to "exit" are intercepted and converted into exceptions. when the script calls exit 19, an exception is thrown and $@ contains a reference pointing to the array:

["EXIT\n", 19]

naturally, "$^S" in perlvar (exceptions being caught) is always "true" during script runtime.

if you really want to exit the process, call CORE::exit or set $CGI::Compile::USE_REAL_EXIT to true before calling exit:

$CGI::Compile::USE_REAL_EXIT = 1;
exit 19;

other exceptions are propagated out of the generated coderef. the coderef's caller is responsible for catching them, or the process will exit. no pressure bestie 😭

πŸ‘‘ Return Code

the generated coderef's exit value is either the parameter that was passed to "exit" or the value of the last statement of the script. the return code gets converted into an integer.

on a 0 exit, the coderef returns 0.

on an explicit non-zero exit, by default an exception is thrown of the form:

exited nonzero: <n>

where "n" is the exit value.

this only happens for an actual call to "exit" in perfunc β€” not if the last statement value is non-zero, which just gets returned from the coderef. subtle but important. πŸ’…

if you'd rather have explicit non-zero exit values returned instead of thrown, pass:

return_exit_val => 1

in your call to "new".

alternately, you can change this behavior globally by setting:

$CGI::Compile::RETURN_EXIT_VAL = 1;

πŸ“ Current Working Directory

if CGI::Compile->compile was passed a script file, then the script's directory becomes the current working directory during the runtime of the script. 🏠

NOTE: to be able to switch back to the original directory, the compiled coderef must establish the current working directory. this operation may cause an additional flush operation on file handles. ⚠️

🌈 "STDIN" and "STDOUT"

these file handles are not touched by CGI::Compile. hands off. πŸ™Œ

πŸ’– The "DATA" file handle

if the script reads from the "DATA" file handle, it reads the "__DATA__" section provided by the script, just like a normal script would. but note β€” the file handle is a memory handle. so "fileno DATA" will return -1. πŸ™ˆ

⭐ CGI.pm integration

if the subroutine CGI::initialize_globals is defined at script runtime, it gets called first thing by the compiled coderef. iconic behaviour honestly.


πŸ”₯ PROTECTED METHODS πŸ”₯

these methods define some of the internal functionality of CGI::Compile, and you can overload them if you need to subclass this module. go off, subclass bestie. πŸ’…

🌸 _read_source

reads the source of a CGI script.

Parameters:

  • $file_path β€” path to the file whose contents are to be read.

Returns:

  • $source β€” the contents of the file as a scalar string.

πŸŽ€ _build_subname

creates a package name and a coderef name that the CGI coderef will be compiled into. the package name gets prepended with $self->{namespace_root}. ✨

Parameters:

  • $file_path β€” the path to the CGI script file. the package name is generated based on this path.

Returns:

  • $package β€” the generated package name.
  • $subname β€” the generated coderef name, based on the file name (without the directory) of the CGI file path.

🧚 _eval

takes the generated perl code β€” which is the contents of the CGI script plus some other things we add to make everything work smoother β€” and returns the evaluated coderef.

currently this is done by writing the code out to a temp file and reading it back in with "do" in perlfunc, so that there are no issues with lexical context or source filters. πŸͺ„

Parameters:

  • $code β€” the generated code that will make the coderef for the CGI.

Returns:

  • $coderef β€” the coderef that results from evaluating the generated perl code.

πŸ’œ AUTHOR πŸ’œ

Tatsuhiko Miyagawa <miyagawa@bulknews.net>

πŸ¦‹ CONTRIBUTORS πŸ¦‹

Rafael Kitover <rkitover@gmail.com>

Hans Dieter Pearcey <hdp@cpan.org>

kocoureasy <igor.bujna@post.cz>

Torsten FΓΆrtsch <torsten.foertsch@gmx.net>

JΓΆrn Reder <jreder@dimedis.de>

Pavel Mateja <pavel@verotel.cz>

lestrrat <lestrrat+github@gmail.com>

Copyright (c) 2023 Tatsuhiko Miyagawa <miyagawa@bulknews.net>

this library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

🌟 SEE ALSO 🌟

ModPerl::RegistryCooker and CGI::Emulate::PSGI β€” go read those next, bestie, they're the whole squad. 🫢


and that's a wrap on CGI::Compile(3pm) πŸ’– this page came from perl v5.40.0, dated 2025-01-11, and it lives in the User Contributed Perl Documentation. mwah. 😘✨

πŸ“¦ where this page comes from