Running a file without extension as CGI-script outside /cgi-bin

It seems like I'm the first person wanting to do this... It was really easy to solve with lighttpd, but with apache this seems impossible. Basically I want to run a cgi-file without extension outsite cgi-bin. Now unfortunately apache ignores it if I set the filename under AddHandler cgi-script filename. The other option is to mark the whole directory using SetHandler cgi-script, but then, it ignores static files in that directory and in subdirectories.

How do I convince apache 2.4 to treat one exact file as a CGI file?


This is the solution:

<FilesMatch filename$>
    SetHandler cgi-script
</FilesMatch>

Add this to the section of the httpd.conf where settings of the corresponding directory are defined.‏‏‏‏‏


Here is a general solution that will treat any file without extension as a script:

<FilesMatch "^[^\.]+$">
  SetHandler cgi-script
</FilesMatch>

As you would hope, this skips folder names with no extension. Only filenames that match the regex are handled with the "cgi-script" handler. The downside is, if you give names that don't have extensions to non-script (i.e. static) files, within any directory where this directive is active, it will give you an Internal Server Error. But that's a very small price to pay.

In addition, you can make a no-extension file the default page in that folder--i.e. if only the name of the directory is typed in the browser's address window--using DirectoryIndex. This is helpful if, for example, you want to run a perl script (called "show" in this example,) that would mimic the behavior of php: each *.html page in the folder could be a template, and "show" is the script that prints the templates.

DirectoryIndex show

Then, if the user types http://example.com/path-to-show/show/content.html, the server will run the "show" program, and in the $ENV{PATH_INFO}, you'll have the value "/content.html", which you can then use to open the template.

show.pl:

#!/usr/bin/perl
print "Content-type: text/html\n\n";
use Text::Template;
($page = $ENV{PATH_INFO}) =~ s/^\///; # not very secure, here for example only
print Text::Template->new(TYPE => 'FILE', SOURCE => $page)->fill_in();

One example of many uses for this behavior. For years I have not used a separate cgi-bin directory for scripts, as I think it looks stupid in the address bar, and I don't like adding ".pl" or ".cgi" to my programs, as I don't want to give potentially malicious visitors any more information than I have to. The configuration above is now the default on my server.

It should be noted, you can add both of these directives into the httpd.conf file or into the .htaccess file on a per-directory basis if you are using shared hosting.