How can I use Apache2 module in CGI mode? - perl

my $r = shift || Apache2::RequestUtil->request;
my $request = Apache2::Request->new($r, #_);
I know it was designed to be used with mod_perl,
but is there a workaround so that it can also be used in CGI mode?

Have you tried replacing those two lines with ...
my $request = CGI->new();
The Apache2::Request module wraps the mod_perl API in order to "mimic the CGI.pm routines for parsing query parameters". So any code that uses the raw $r won't work, but code using $request might.
But in answer to your bigger question, the answer is no there isn't an easy way to run code written for mod_perl under CGI instead. When writing new code you should either use a framework or write to the PSGI API which can then me deployed using CGI, FastCGI or mod_perl without changing the code.

Related

How can I pass variables from one CGI script to another?

I have a CGI perl script called install-app-pl.cgi:
#!/usr/bin/perl -w
print header('text/html');
use strict;
use CGI ':standard';
# Get me some vars
my #params = param();
my $APP_NAME = param('app_name');
my $APP_WEB_PORT = param('app_web_port');
my $APP_WEB_USER = param('app_web_user');
my $APP_WEB_PASS = param('app_web_pass');
my $DOWNLOAD_DIR = param('download_dir');
my $CONFIG_DIR = param('config_dir');
my $LIBRARY_DIR = param('library_dir');
my $TEMP_DOWNLOAD_DIR = param('temp_download_dir');
# Run another script
if ( $APP_NAME ) {
print "Installing $APP_NAME...";
print "<pre>";
system ("perl /var/www/mysite.local/public_html/lib/$APP_NAME/install-$APP_NAME.pl");
print "</pre>" ;
}
else {
print "No app specified, check the error log";
}
I'm trying to get it to pass the variables defined from the CGI parameters to install-$APP_NAME.pl
#!/usr/bin/perl -w
print header('text/html');
use strict;
use CGI ':standard';
require "/var/www/mysite.local/public_html/cgi-bin/install-app-pl.cgi"
# Echo my vars
print "$CONFIG_DIR $DOWNLOAD_DIR $LIBRARY_DIR $PGID $PUID $TZ $APP_WEB_PORT";
But I'm not sure of the best way to pass those on.
Are you sure that install-app-pl.cgi is a CGI program? Are you sure that it's not just a Perl command-line program? I mean, I see how it's named, but it seems very strange to call a CGI program using system() like that.
And the difference is crucial here. CGI programs access their parameters in a different way command-line programs.
If it really is a CGI program, then you have a few options:
Make an HTTP request to it (using something from the LWP bundle of modules).
Use CGI.pm's debugging mechanism to call it the same way as you're currently calling it, but passing the CGI parameters like foo=xxx&bar=yyy&baz=zzz (see the DEBUGGING section of the CGI.pm documentation for details). This, of course, relies on the program using CGI.pm and it feels a bit hacky to me.
Ask yourself if the program really needs to be a CGI program if you're calling from another program using system(). And then decide to rewrite it as a command-line program. If you want both a CGI version and a command-line version, then you could move most of the code to a module which could be used by two thin wrappers which just extract the parameters.
A few other points about your code.
Perl 5.6 (released in 2000) introduced a use warnings pragma. Most people now use that in place of -w on the shebang line.
It seems weird to call the header() function before loading the CGI module that defines it. It works, because the use is handled at compile time, but it would be nice to re-order that code to make more sense.
Similarly. most people would have use strict (and use warnings) as the very first things in their program. Immediately after the shebang line.
system() returns the return value from the process. If your second program produces useful output that you want displayed on the web page, you should use backticks instead.
If all of your output is going to be in a <pre> element, why not just remove that element and return a content type of "text/plain" instead?
Update: And I'd be remiss if I didn't reiterate what many people have already said in comments on your original question - this sounds like a terrible idea.

Accept POST parameters with FCGI

I am trying to get URL parameters using CGI and FCGI.
When executing the script on my browser I am only getting parameters of my first request, but the request $count does increment.
use CGI;
use FCGI;
my $fcgiRequest = FCGI::Request();
while ($fcgiRequest->Accept() >= 0)
{
print("Content-type: text/html\r\n\r\n", ++$count);
my $q = new CGI;
print "name = " . $q->param("name") ;
print "\n";
}
You can't use CGI.pm and FCGI.pm together like this. You need some glue-code in between, because CGI needs to read stuff from the environment, and it can't in the way you invoke it.
There is a module CGI::Fast included with Perl that does this for you. Instead of using CGI and FCGI, you just use CGI::Fast and change a bit of code.
use strict;
use warnings;
use CGI::Fast;
my $count;
while (my $q = CGI::Fast->new) {
# $q is a fresh CGI object for the current request
print("Content-type: text/html\r\n\r\n", ++$count);
print "name = " . $q->param("name") ;
print "\n";
}
If you already have a CGI script, you could put that in a function and call it inside of that loop.
If you're interested in how CGI::Fast works, feel free to take a look at its source code on CPAN. The main thing is that the environment and the file handles (for STDOUT and STDERR) need to be mapped to each new request, while your implementation has CGI always parse the first one.
Please note that the examples in both the perldoc and on CPAN that I have linked are very out-of-date and don't represent modern Perl code.
Today, you would probably not use CGI any more, as it has been removed from current Perl releases. Instead, you could take a look at the PSGI interface specification and Plack on how to implement it. The good thing about that is that it provides a clear interface across different deployment-technologies (such as CGI and Fast CGI). You can just let your program run as a simple CGI with Apache or nginx, or as a persistent FCGI process with Apache or other webservers, or as a standalone application through various Plack webservers that are written in Perl and are tailored for specific purposes.
Once a CGI.pm object is created for a request, it's reused there on out.
You can reset CGI.pm by adding the following to the end of the loop:
CGI::_reset_globals();

how to use utf-8 in a perl cgi-bin script?

I have the following cgi bin script:
#! /usr/bin/perl
#
use utf8;
use CGI;
my $q = CGI->new();
my %params = $q->Vars;
print $q->header('text/html');
$w = $params{"words"};
print "$w\n";
I want to be able to call it as cgi-bin/script.pl?words=É for example, but when I do that, what's printed is not UTF-8, but instead garbled:
É
Is there any way to use cgi-bin with utf8?
Your line use utf8 doesn't do anything for you, other than allowing UTF-8 characters in the source file itself. You must make sure that the output handles (on STDOUT as well as any files) are set to utf8. One easy way to handle this is the utf8::all module. Also, make sure you are sending the correct headers, and use the -utf8 CGI pragma to treat incoming parameters as UTF-8. Finally, as always, be sure to use strict and warnings.
The following should get you started:
#!/usr/bin/perl
use strict;
use warnings;
use utf8::all;
use CGI qw(-utf8);
my $q = CGI->new;
print $q->header("text/html;charset=UTF-8");
print $q->param("words");
exit;
I have been having this problem of intermittent failure of utf8 encoding with my CGI script.
I tried everything but couldn't reliably repeat the problem.
I finally discovered that is is absolutely critical to be consistent with you use of the utf8 pragma throughout every module that uses CGI
use CGI qw(-utf8);
What seems to happen is that modperl invokes the CGI module just once per requests. If there is inconsistent including of the CGI module - say for some utility function that is just using a redirect function and you haven't bothered to set the utf8 pragma. Then this invocation can be the one that modperl decides to use to decode requests.
You will save yourself a lot of pain in the long run if you start out by reading the perlunitut and perlunicode documentation pages. They will give you the basics on exactly what Unicode and character encodings are, and how to work with them in Perl.
Also, what you're asking for is more complex than you think. There are many layers hidden in the phrase "use cgi-bin with utf8", starting with your interface to whatever tool you're using to send requests to the web server and ending with that tool having parsed a response and presenting it to you. You need to understand all those layers well enough to at least be able to tell if the problem lies in your CGI script or not. For example, it doesn't help if your script works perfectly if the problem is that bash and curl don't agree on the encoding of your command line arguments.

How to listen to URL routes in perl

I'm starting my first perl project, and wanted to know how to listen to different end points, I.e. example.com/home (how do you load an HTML page when someone visits this home route?
Just a note that I'm not interested in using a framework for this particular project. Thanks
Well, I guess you could have a CGI program that interprets the path and takes the appropriate action. You could then combine that with a mod_rewrite rule that diverts all requests into that program.
But it's all looking a bit kludgy and a framework would be a much better solution.
The simplest way to talk to a server is CGI.
This is not Perl specific, but Perl was commonly used for it. It is very slow, but simple.
Here is small demo. You put this in the cgi-bin directory of your server, and go go http://www.example.com/cgi-bin/cgidemo.cgi and back pops the content of the Perl #INC array.
To hook it up to /home you could alias it in your .htaccess file.
Of course, this is all ancient and slow stuff and has been far surpassed and sped up by fastcgi, mod_perl, and lots of other stuff. I like the Mojolicous framework myself.
#!/usr/bin/perl
# cgidemo.cgi - minimal CGI program
use strict;
use warnings;
# Headers
print "Content-type: text/plain\n";
# Blank line after header
print "\n";
# Body
print "Perl Include Path:\n";
print join("\n", #INC), "\n";

Proper way to use Ack inside Perl scripts?

I've begun to use ack because it seems to be a nice way to implement unix rgrep in a Perl script, easily. Thought, I use it through a Perl back-quoted system command:
# Searching for 'use' something
my $pattern = "^use ";
my $path = "./path/to/libs/";
#Only pm files
my $parameters = "--perl";
my #uses = `ack $parameters $pattern $path`;
I know ack is pure Perl, but it seems to be designed for a command line use, not like an API or a Perl module. Is there a way to use it from a Perl script, I mean a module that makes possible to use ack like a Perl function :
# My phantasm
use ack;
my #uses = ack($parameters $pattern $path);
... or another method, timtowtdi.
You can't.
Maybe I should put "No user-serviceable parts inside" in the modules. It's really not meant for being used programatically. It really only uses modules for ease of maintainability for those working on it, and for ease of installing through the CPAN shell.
The file finding part is pretty simple to do. It's just calls to an iterator from File::Next.
Why do you want to call ack things from inside another Perl program? What's your use case?
Maybe this would be better taken up on the ack-users mailing list over on Google Groups.
The module behind ack is App::Ack, but as you can see from the documentation, it's not really any kind of a programmatic interface at all, and not meant for public consumption. You could talk to Andy about making it better, but short of that you're probably best off using the commandline or re-inventing your own.