Editor's note: In his previous article, Apache Web-Serving with Mac OS X: Part 1, Kevin Hemenway showed you how to easily start serving web pages from your Mac OS X computer. In this article, he explores the world of CGI access. To gain the most from what Kevin has to offer here, you'll need some familiarity with the Terminal application. If you haven't explored that feature yet, I recommend that you first read our companion article, Learning the Mac OS X Terminal: Part 1. Once you're comfortable using the command line, you can return here and dig deeper into Apache.
So, after the work we did in the last article, we've got a prettier URL, but still a rather boring site. We need features to impress the boss, and to turn them on we're going to have to start fiddling with Mac OS X's Terminal. We're going to assume you know how to edit and save files via the command line, either through a native shell editor (like vi or emacs) or via a GUI editor such as BBEdit. Our examples below assume BBEdit 6.5 and its shell utility.
Before we turn on features, we need to know where Apache's configuration file lives. To find out, we'll query the Apache web server itself, with the following command line:
This will spit out a screen of information specific to your Apache installation (this will work in any Apache install -- for Mac, Linux, or Windows). On an OS X 10.1.1 machine, we find out that we're using Apache 1.3.20 (in the soon-to-be-released 10.1.2, Apache will be upgraded to 1.3.22.):
Server version: Apache/1.3.20 (Darwin)
As well as where the configuration file is located:
We'll also score two very helpful bits of information:
-D DEFAULT_XFERLOG="/var/log/httpd/access_log" -D DEFAULT_ERRORLOG="/var/log/httpd/error_log"
These are the log files for Apache -- every request and every error message will show up within these logs. You'll find them insanely useful for debugging, as well as making sure our upcoming features are working correctly.
It's now time to fiddle with the most common feature available to a web server: CGI. Without getting overly esoteric, CGI allows us to install thousands of different scripts that can be accessed through a normal web browser. CGI scripts are often written in Perl (also installed by default) and can allow users to access databases, use interactive forms, chat in bulletin boards, and so on.
Apache comes with two simple scripts that can verify CGI is configured correctly. Before we test them, however, let's see what we can learn from the Apache configuration file. To start, open up your config file in your favorite text editor (the example below assumes BBEdit 6.5):
Be forewarned: The Apache configuration file is rather large, but also well documented. Take its introductory warning to heart: "Do not simply read the instructions ... without understanding what they do. They're here only as hints or reminders. If you are unsure consult the online docs. You have been warned." For your own reference, the online docs are available at the Apache web site.
The quickest way to find and learn about the Apache configuration file is to search for the feature you want to enable. In our case, we'll start looking for "CGI". The first entry we find is:
LoadModule cgi_module libexec/httpd/mod_cgi.so
Followed shortly by:
You'll see a number of these lines
within the Apache config file. If you've ever worked with a plug-in-based
program, you'll easily recognize their intent -- these lines load different
features into the Apache web server. Apache calls these "modules", and you'll
see a lot of module names start with
mod_, such as
Lines that are commented out (that is to say lines that are prefaced with a #
character) are inactive.
Because our CGI lines are already active, we'll continue searching:
ScriptAlias /cgi-bin/ "/Library/WebServer/CGI-Executables/" <Directory "/Library/WebServer/CGI-Executables"> AllowOverride None Options None Order allow,deny Allow from all </Directory>
ScriptAlias directive allows us to
map a URL to a location on our hard drive. In this case, Apache is mapping
http://127.0.0.1/cgi-bin/ to the
folder. If you browse to that folder now, you'll see the two CGI scripts I
oft-handedly mentioned above:
isn't that important right now, so we'll move on to our next search
# AddHandler cgi-script .cgi
|Now that we're in a little deeper, let's talk about your Apache experience on Mac OS X.|
is your first major decision concerning your Apache installation. When a
certain directory has been
ScriptAlias'ed (as our CGI-Executables directory
has, above), the files within that directory are always executed as CGI
scripts. If the files were moved out of that directory (say, into our
DocumentRoot directory), they'd be served as normal text files.
uncommenting the above line, you're telling Apache to execute any file that
.cgi. This can happen from any directory and from any user, and is
often considered a security hazard.
In a default installation of Apache on
Mac OS X, CGI scripts are only allowed within
/Library/Webserver/CGI-Executables/. Uncommenting the above line (removing the "#" character) allows CGI scripts to be executed from any user
directory, such as
/Users/morbus/Sites. In our case, because we aren't using the
User directories (because they create ugly URLs for GatesMcFarlaneCo's
intranet), we're going to leave the line commented.
If CGI access
is turned on already, we should be able to reach
http://127.0.0.1/cgi-bin/test-cgi and see a happy result, right? If you
went to that URL, however, you were probably greeted by a not so joyous
response: "FORBIDDEN". Apache screams, "You don't have permission to access
Huh? Why didn't this work? Now is a perfect
time to prove how useful the Apache web server logs can be. If you recall
the results of our
httpd -V command above, Apache's access file is located
/var/log/httpd/access_log. Let's look at the very last lines of that
file, easily reached with this command:
You'll see that the last line looks similar to:
127.0.0.1 - - [19/Nov/2001:21:59:46-0500] "GET /cgi-bin/test-cgi HTTP/1.1" 403 292
Quickly, this line shows where the access request came
127.0.0.1), the time the file was requested, the protocol used
(HTTP/1.1), the response code (403), and the size of the response (292
bytes). This is all fine and dandy, but doesn't tell us what went wrong.
For this, we'll dip into our error log (also pinpointed by the
And we see:
[Mon Nov 19 21:59:46 2001] [error] [client 127.0.0.1] file permissions deny server execution: /Library/WebServer/CGI-Executables/test-cgi
tells us exactly what went wrong -- the file permissions were incorrect.
For Apache to run a CGI script, the script in question needs to have
"execute" permissions. To give the
test-cgi file the correct permissions,
cd /Library/WebServer/CGI-Executables chmod 755 test-cgi
After doing the above, load the URL again, and
you should be happily greeted with gobs of environment information. (To
learn more about permissions, the
chmod utility, and the server
environment, consult your favorite search engine, friendly geek, or
With the basics of CGI out of the way, you can now install CGI-based applications to complement your intranet. Need a content management system for the developers to keep everyone up to date on their coding progress and discussions? Try Movable Type.
Server-side includes, better known as SSIs, allow you to include content from other files or scripts into the page currently being served. This is done by Apache before the page is actually shown to the user -- they'll never know what you've included or where.
Commonly, SSIs are used to include things such as headers, footers, and "what's new" features across an entire site. When you need to change the background color of your site, for instance, you can change the header file only, and the color will be reflected immediately wherever you've included that file.
SSIs, by default, are turned off. To turn them on, we're going to use the same "search for the feature" trick we did above. Open your Apache configuration file, and search for "server side." Our only match grants us the following:
# To use server-parsed HTML files # # AddType text/html .shtml # AddHandler server-parsed .shtml
Happily, this is exactly what we're looking for.
Those simple "Add" lines tell us a lot. They establish a pattern based on
what we already know about CGI. If you recall above, we could have turned
on the CGI feature for files ending in
.cgi -- in other words, any file you
created with the
.cgi extension (whether it was a CGI program or not),
would be treated as an executable script.
Likewise, these lines are
telling us that we can turn on the server-side include feature for files
.shtml. Whether we actually use the SSI feature in these files
doesn't matter -- they'd still be treated and processed as if they
This is important. You may be thinking "If SSIs are so great,
why not enable them for
.html filenames?" Ultimately, it's a matter of
speed. If you have 3,000
.html files, and only 1,000 of them actually use
SSI, Apache will still look for SSI instructions in the other 2,000. That's
a waste of resources. Granted, processing SSI incurs very little
overhead, but if you're being hit 50,000 times a second, it can certainly
add up. This isn't too worrisome for our GatesMcFarlaneCo intranet, but is
good to know for your future Apache projects.
For now, uncomment
AddHandler lines. This will turn on the SSI mojo power. But where? When we were learning about CGI, we saw a
configuration setting that said our CGIs lived in
/Library/Webserver/CGI-Executables/ -- we now have to tell Apache where we
want our SSI capability to take place.
Because we've building an
intranet, that's going to live in
where we want our SSI capability to be active. Go to the top of your Apache
configuration file and search for "/Library/Webserver/Documents/". The
second result looks like the following (we've removed the commented lines
from this example):
<Directory "/Library/WebServer/Documents"> Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny Allow from all </Directory>
You'll notice that
this looks similar to the
<Directory> entry we saw when we were
looking into CGI. As before, we're going to skip the brunt of it (we'll pay
attention to our ignored lines a little bit later in our series). For
now, add the word
Includes to the
Options is an Apache
directive that can turn on or off different features for the
<Directory> and all subdirectories beneath it. Subdirectories can
override their parent configuration.
Because we've made changes to
Apache's configuration file, we now need to restart Apache. The easiest way to do
this is via our Sharing preference panel. Much like we started the sharing preference in part one of this series, we can
start to enable our changes. Do this now. Chuckle once or twice, if you must.
To test that our SSIs are working properly, rename your
index.html file to
.shtml is the only extension we've enabled SSIs for), and edit to match the snippet below:
<html> <body> <h1>Gleefully Served By Mac OS X</h1> <pre><!--#include virtual="/cgi-bin/test-cgi"--> </pre> </body> </html>
Here, we're including the test CGI script into the contents of our main index
page. When you load
http://127.0.0.1/ into your browser, you'll see our
"Gleefully Served" message, as well as the output of the CGI script itself.
We could just have easily created a static web page (say,
"navigation.html"), and included that within our page instead.
SSI is configured and working, but what can you do with it? What if your marketing department wants to create an image gallery of the newest ads they've planned? That's quite easy using this SSI Image Gallery article, also written by yours truly.
In my next installment, I'll show you how to turn on PHP. Until then, good luck working with CGI. And if you have questions ... comment below and the author will get back to you.
Kevin Hemenway is the coauthor of Mac OS X Hacks, author of Spidering Hacks, and the alter ego of the pervasively strange Morbus Iff, creator of disobey.com, which bills itself as "content for the discontented."
Return to the Mac DevCenter.
Copyright © 2009 O'Reilly Media, Inc.