$Revision: 1.99 $ ($Date: 2010/12/10 10:13:45 $)
Please note that this document refers to a version of the product which has been deprecated, and declared "end of life", in favor of the more recent version of the server. Information obtained here is likely to be outdated and inaccurate.
The latest version of this FAQ is available on the HTTP Server Wiki, at <http://httpd.apache.org/docs/1.3/misc/FAQ.html>. This version is no longer maintained, and contains inaccurate and grossly outdated information.
ErrorDocument
and SSI to simplify customized
error messages?Apache recognizes all files in a directory named as a ScriptAlias as being eligible for execution rather than processing as normal documents. This applies regardless of the file name, so scripts in a ScriptAlias directory don't need to be named "*.cgi" or "*.pl" or whatever. In other words, all files in a ScriptAlias directory are scripts, as far as Apache is concerned.
To persuade Apache to execute scripts in other locations, such as in directories where normal documents may also live, you must tell it how to recognize them - and also that it's okay to execute them. For this, you need to use something like the AddHandler directive.
AddHandler cgi-script .cgi
The server will then recognize that all files in that location (and its logical descendants) that end in ".cgi" are script files, not documents.
In some situations, you might not want to actually allow all files named "*.cgi" to be executable. Perhaps all you want is to enable a particular file in a normal directory to be executable. This can be alternatively accomplished via mod_rewrite and the following steps:
RewriteEngine on
RewriteBase /~foo/bar/
RewriteRule ^quux\.cgi$ -
[T=application/x-httpd-cgi]
It means just what it says: the server was expecting a complete set of HTTP headers (one or more followed by a blank line), and didn't get them.
The most common cause of this problem is the script
dying before sending the complete set of headers, or
possibly any at all, to the server. To see if this is the
case, try running the script standalone from an interactive
session, rather than as a script under the server. If you
get error messages, this is almost certainly the cause of
the "premature end of script headers" message. Even if the
CGI runs fine from the command line, remember that the
environment and permissions may be different when running
under the web server. The CGI can only access resources
allowed for the User
and Group
specified in your Apache configuration. In addition, the
environment will not be the same as the one provided on the
command line, but it can be adjusted using the directives
provided by mod_env.
The second most common cause of this (aside from people
not outputting the required headers at all) is a result of
an interaction with Perl's output buffering. To make Perl
flush its buffers after each output statement, insert the
following statements around the print
or
write
statements that send your HTTP
headers:
{
local ($oldbar) = $|;
$cfh = select (STDOUT);
$| = 1;
#
# print your HTTP headers here
#
$| = $oldbar;
select ($cfh);
}
This is generally only necessary when you are calling
external programs from your script that send output to
stdout, or if there will be a long delay between the time
the headers are sent and the actual content starts being
emitted. To maximize performance, you should turn
buffer-flushing back off (with $| = 0
or the equivalent) after the statements that send the
headers, as displayed above.
If your script isn't written in Perl, do the equivalent
thing for whatever language you are using
(e.g., for C, call fflush()
after
writing the headers).
Another cause for the "premature end of script headers" message are the RLimitCPU and RLimitMEM directives. You may get the message if the CGI script was killed due to a resource limit.
In addition, a configuration problem in suEXEC, mod_perl, or another third party module can often interfere with the execution of your CGI and cause the "premature end of script headers" message.
This is almost always due to Apache not being configured to treat the file you are trying to POST to as a CGI script. You can not POST to a normal HTML file; the operation has no meaning. See the FAQ entry on CGIs outside ScriptAliased directories for details on how to configure Apache to treat the file in question as a CGI.
As of Apache 1.3, CGI scripts are essentially not
buffered. Every time your script does a "flush" to output
data, that data gets relayed on to the client. Some
scripting languages, for example Perl, have their own
buffering for output - this can be disabled by setting the
$|
special variable to 1. Of course this does
increase the overall number of packets being transmitted,
which can result in a sense of slowness for the end
user.
Prior to 1.3, you needed to use "nph-" scripts to accomplish non-buffering. Today, the only difference between nph scripts and normal scripts is that nph scripts require the full HTTP headers to be sent.
The Common Gateway Interface (CGI) specification can be found at the original NCSA site < http://hoohoo.ncsa.uiuc.edu/cgi/interface.html>. This version hasn't been updated since 1995, and there have been some efforts to update it.
A new draft is being worked on with the intent of making it an informational RFC; you can find out more about this project at <http://web.golux.com/coar/cgi/>.
The simple answer is that it was becoming too difficult to keep the version being included with Apache synchronized with the master copy at the FastCGI web site. When a new version of Apache was released, the version of the FastCGI module included with it would soon be out of date.
You can still obtain the FastCGI module for Apache from the master FastCGI web site.
SSI (an acronym for Server-Side Include) directives allow static HTML documents to be enhanced at run-time (e.g., when delivered to a client by Apache). The format of SSI directives is covered in the mod_include manual; suffice it to say that Apache supports not only SSI but xSSI (eXtended SSI) directives.
Processing a document at run-time is called parsing it; hence the term "parsed HTML" sometimes used for documents that contain SSI instructions. Parsing tends to be resource-consumptive compared to serving static files, and is not enabled by default. It can also interfere with the cachability of your documents, which can put a further load on your server. (See the next question for more information about this.)
To enable SSI processing, you need to
AddHandler server-parsed .shtml
This indicates that all files ending in ".shtml" in that location (or its descendants) should be parsed. Note that using ".html" will cause all normal HTML files to be parsed, which may put an inordinate load on your server.
For additional information, see the Apache Week article on Using Server Side Includes.
Since the server is performing run-time processing of your SSI directives, which may change the content shipped to the client, it can't know at the time it starts parsing what the final size of the result will be, or whether the parsed result will always be the same. This means that it can't generate Content-Length or Last-Modified headers. Caches commonly work by comparing the Last-Modified of what's in the cache with that being delivered by the server. Since the server isn't sending that header for a parsed document, whatever's doing the caching can't tell whether the document has changed or not - and so fetches it again to be on the safe side.
You can work around this in some cases by causing an Expires header to be generated. (See the mod_expires documentation for more details.) Another possibility is to use the XBitHack Full mechanism, which tells Apache to send (under certain circumstances detailed in the XBitHack directive description) a Last-Modified header based upon the last modification time of the file being parsed. Note that this may actually be lying to the client if the parsed file doesn't change but the SSI-inserted content does; if the included content changes often, this can result in stale copies being cached.
So you want to include SSI directives in the output from your CGI script, but can't figure out how to do it? The short answer is "you can't." This is potentially a security liability and, more importantly, it can not be cleanly implemented under the current server API. The best workaround is for your script itself to do what the SSIs would be doing. After all, it's generating the rest of the content.
This is a feature The Apache Group hopes to add in the next major release after 1.3.
This is almost always due to having some setting in your config file that sets "Options Includes" or some other setting for your DocumentRoot but not for other directories. If you set it inside a Directory section, then that setting will only apply to that directory.
ErrorDocument
and SSI to simplify
customized error messages?
Have a look at this
document. It shows in example form how you can a
combination of XSSI and negotiation to tailor a set of
ErrorDocument
s to your personal taste, and
returning different internationalized error responses based
on the client's native language.
This variable is set and thus available in SSI or CGI scripts if and only if the requested document was protected by access authentication. For an explanation on how to implement these restrictions, see Apache Week's articles on Using User Authentication or DBM User Authentication.
Hint: When using a CGI script to receive the data of a HTML FORM notice that protecting the document containing the FORM is not sufficient to provide REMOTE_USER to the CGI script. You have to protect the CGI script, too. Or alternatively only the CGI script (then authentication happens only after filling out the form).
Remember that CGI execution does not need to be restricted only to cgi-bin directories. You can allow CGI script execution in arbitrary parts of your filesystem.
There are many ways to give each user directory a cgi-bin directory such that anything requested as http://example.com/~user/cgi-bin/program will be executed as a CGI script. Two alternatives are:
ScriptAliasMatch ^/~([^/]*)/cgi-bin/(.*)
/home/$1/cgi-bin/$2
<Directory
/home/*/public_html/cgi-bin>
Options ExecCGI
SetHandler cgi-script
</Directory>
If you are using suexec, the first technique will not work
because CGI scripts must be stored under the public_html
directory.