ht t p: apache.snake.net m cb m y_php_script .php ht t p: t om cat .snake.net : 8080 m cb m y_j sp_script .j sp
Youll need t o change t he host nam e and port num ber appropriat ely for pages served by your own servers.
16.3 Using Apache to Run Web Scripts
16.3.1 Problem
You want t o run Perl, PHP, or Pyt hon program s in a web environm ent .
16.3.2 Solution
Execut e t hem using t he Apache server.
16.3.3 Discussion
This sect ion describes how t o configure Apache for running Perl, PHP, and Pyt hon script s, and illust rat es how t o writ e web-based script s in each language.
There are t ypically several direct ories under t he Apache root direct ory, which I ll assum e here t o be usr local apache. These direct ories include:
bin Cont ains ht t pd—t hat is, Apache it self—and ot her Apache- relat ed execut able program s
conf For configurat ion files, not ably ht t pd.conf, t he prim ary file used by Apache
htdocs The root of t he docum ent t ree
logs For log files
To configure Apache for script execut ion, edit t he ht t pd.conf file in t he conf direct ory. Typically, execut able script s are ident ified eit her by locat ion or by filenam e suffix. A locat ion
can be eit her language- neut ral or language-specific.
Apache configurat ions oft en have a cgi- bin direct ory under t he server root direct ory where you can inst all script s t hat should run as ext ernal program s. I t s configured using a
ScriptAlias
dir ect ive: ScriptAlias cgi-bin usrlocalapachecgi-bin
The second argum ent is t he act ual locat ion of t he script direct ory in your filesyst em , and t he first is t he pat hnam e in URLs t hat corresponds t o t hat direct ory. Thus, t he direct ive j ust shown
associat es script s locat ed in usr local apache cgi- bin wit h URLs t hat have cgi-bin following t he host nam e. For exam ple, if you inst all t he script m yscript .py in t he direct ory
usr local apache cgi-bin on t he host apache.snake.net , youd request it w it h t his URL: ht t p: apache.snake.net cgi-bin m yscript .py
When configured t his way, t he cgi- bin direct ory can cont ain script s writ t en in any language. Because of t his, t he direct ory is language- neut ral, so Apache needs t o be able t o figure out
w hich language processor t o use t o execut e each script t hat is inst alled t here. To provide t his inform at ion, t he first line of t he script should begin wit h
followed by t he pat hnam e t o t he program t hat execut es t he script , and possibly som e opt ions. For exam ple, a script t hat begins
wit h t he following line will be run by Perl, and t he - w opt ion t ells Perl t o warn about quest ionable language const ruct s:
usrbinperl -w Under Unix, you m ust also m ake t he script execut able use chm od + x , or it wont run
properly. The line j ust shown is appropriat e for a syst em t hat has Perl inst alled as
usr bin perl. I f your Perl int erpret er is inst alled som ewhere else, m odify t he line accordingly. I f youre on a Windows m achine wit h Perl inst alled as D: \ Per l\ bin\ perl.exe, t he
line should look like t his:
D:\Perl\bin\perl -w For Windows users, anot her opt ion t hat is sim pler is t o set up a filenam e ext ension associat ion
bet w een script nam es t hat end w it h a .pl suffix and t he Perl int erpret er. Then t he script can begin like t his:
perl -w A
ScriptAlias
direct ive set s up a direct ory t hat can be used for script s writ t en in any language. I t s also possible t o associat e a direct ory wit h a specific language processor, so t hat
any script found t here is assum ed t o be writ t en in a part icular language. For exam ple, t o designat e usr local apache cgi- perl as a m od_perl direct ory, you m ight configure Apache like
t his: IfModule mod_perl.c
Alias cgi-perl usrlocalapachecgi-perl Location cgi-perl
SetHandler perl-script PerlHandler Apache::Registry
PerlSendHeader on Options +ExecCGI
Location IfModule
I n t his case, Perl script s locat ed in t he designat ed direct ory would be invoked as follows: http:apache.snake.netcgi-perlmyscript.pl
Using m od_perl is beyond t he scope of t his book, so I wont say any m ore about it . Check Appendix C
for som e useful m od_perl resources. Direct ories used only for script s generally are placed out side of your Apache docum ent t ree.
As an alt ernat ive t o using specific direct ories for script s, you can ident ify script s by filenam e ext ension, so t hat files wit h a part icular suffix becom e associat ed wit h a specific language
processor. I n t his case, you can place t hem anywhere in t he docum ent t ree. This is t he m ost com m on way t o use PHP. For exam ple, if you have Apache configured wit h PHP support built
in using t he m od_php m odule, you can t ell it t hat script s having nam es ending wit h .php should be int erpret ed as PHP script s. To do so, add t his line t o ht t pd.conf:
AddType applicationx-httpd-php .php Then if you inst all a PHP script m yscript .php under ht docs t he Apache docum ent root
direct ory , t he URL for invoking t he script becom es: ht t p: apache.snake.net m yscript .php
I f PHP runs as an ext ernal st andalone program , youll need t o t ell Apache where t o find it . For exam ple, if youre running Windows and you have PHP inst alled as D: \ Php\ php.exe, put t he
following lines in ht t pd.conf not e t he use of forward slashes in t he pat hnam es rat her t han backslashes :
ScriptAlias php D:Php AddType applicationx-httpd-php .php
Action applicationx-httpd-php phpphp.exe
For purposes of showing URLs in exam ples, I m going t o assum e t hat Perl and Pyt hon script s are in your cgi- bin direct ory, and t hat PHP script s are in t he m cb direct ory of your docum ent
t ree, ident ified by t he .php ext ension. This m eans t hat URLs for script s in t hese languages will look like t his:
ht t p: apache.snake.net cgi-bin m yscript .pl ht t p: apache.snake.net cgi-bin m yscript .py
ht t p: apache.snake.net m cb m yscript .php I f you plan t o use a sim ilar set up, m ake sure you have a cgi- bin direct ory under your Apache
root , and an m cb direct ory under your Apache docum ent root . Then, t o deploy Perl or Pyt hon web script s, copy t hem t o t he cgi- bin direct ory. To deploy PHP script s, copy t hem t o t he m cb
direct ory. I f you request a web script and get an error page in response, have a look at t he Apache error
log, which can be a useful source of diagnost ic inform at ion when youre t rying t o figure out why a script doesnt work. A com m on nam e for t his log is error_log in t he logs direct ory. I f
you dont find any such file, check ht t pd.conf for an
ErrorLog
direct ive t o see w here Apache logs it s errors.
Web Security Note
Under Unix, script s run wit h part icular user and group I Ds. Script s t hat you execut e from t he com m and line run wit h your user and group I Ds, and have t he filesyst em
privileges associat ed wit h your account . However, script s execut ed by a web server probably wont run wit h your user and group I D, nor will t hey have your user
privileges. I nst ead, t hey run under t he user and group I D of t he account t he web server has been set t o run as, and wit h t hat account s privileges. To det erm ine what
account t his is, look for
User
and
Group
direct ives in t he ht t pd.conf configurat ion file. This m eans t hat if you expect web script s t o read and writ e files,
t hose files m ust be accessible t o t he account used t o run t he web server. For exam ple, if your server runs under t he
nobody
account and you w ant a scr ipt t o be able t o st ore uploaded im age files int o a direct ory called uploads in t he docum ent
t ree, you m ust m ake t hat direct ory readable t o and writ able by t he
nobody
user . Anot her im plicat ion is t hat if ot her people can writ e script s for your web server,
t hose script s t oo will run as
nobody
and t hey can read and writ e t he sam e files as your own script s. Solut ions t o t his problem include using t he suEXEC m echanism for
Apache 1.x, or using Apache 2.x, which allows you t o designat e which user and group I Ds t o use for running a given set of script s.
Aft er Apache has been configured t o support script execut ion, you can begin t o writ e script s t hat generat e web pages. The rem ainder of t his sect ion describes how t o do so for Perl, PHP,
and Pyt hon. The exam ples for each language connect t o t he MySQL server, run a
SHOW TABLES
quer y, and display t he result s in a web page. The script s shown here indicat e any addit ional m odules or libraries t hat web script s t ypically need t o include. Lat er on, I ll
generally assum e t hat t he proper m odules have been referenced and show only script fragm ent s.
16.3.3.1 Perl
Our first w eb-based Perl script , show_t ables.pl, is shown below. I t produces an appropriat e
Content-Type:
header, a blank line t o separat e t he header from t he page cont ent , and t he init ial part of t he page. Then it ret rieves and displays a list of t ables in t he
cookbook
dat abase. The t able list is followed by t he t railing HTML t ags t hat close t he page: usrbinperl -w
show_tables.pl - Issue SHOW TABLES query, display results by generating HTML directly
use strict; use lib qwusrlocalapachelibperl;
use Cookbook; Print header, blank line, and initial part of page
print EOF; Content-Type: texthtml
html head
titleTables in cookbook Databasetitle head
body bgcolor=white pTables in cookbook database:p
EOF Connect to database, display table list, disconnect
my dbh = Cookbook::connect ; my sth = dbh-prepare SHOW TABLES;
sth-execute ; while my row = sth-fetchrow_array
{ print row[0]br \n;
} dbh-disconnect ;
Print page trailer print EOF;
body html
EOF exit 0;
To t ry out t he script , inst all it in your cgi-bin direct ory and invoke it from your browser as follows:
ht t p: apache.snake.net cgi-bin show_t ables.pl
show_t ables.pl generat es HTML by including lit eral t ags in print st at em ent s. Anot her approach t o web page generat ion is t o use t he CGI .pm m odule, which m akes it easy t o writ e web script s
wit hout writ ing t ags lit erally. CGI .pm provides an obj ect -orient ed int erface and a funct ion call int erface, so you can use it t o writ e web pages in eit her of t wo st yles. Heres a script ,
show_t ables_oo.pl, t hat uses t he CGI .pm obj ect - orient ed int erface t o produce t he sam e report as show_t ables.pl:
usrbinperl -w show_tables_oo.pl - Issue SHOW TABLES query, display results
using the CGI.pm object-oriented interface use strict;
use lib qwusrlocalapachelibperl; use CGI;
use Cookbook; Create CGI object for accessing CGI.pm methods
my cgi = new CGI; Print header, blank line, and initial part of page
print cgi-header ; print cgi-start_html -title = Tables in cookbook Database,
-bgcolor = white; print cgi-p Tables in cookbook database:;
Connect to database, display table list, disconnect my dbh = Cookbook::connect ;
my sth = dbh-prepare SHOW TABLES; sth-execute ;
while my row = sth-fetchrow_array {
print row[0] . cgi-br ; }
dbh-disconnect ; Print page trailer
print cgi-end_html ; exit 0;
The script includes t he CGI .pm m odule wit h a
use CGI
st at em ent , t hen creat es a
CGI
obj ect ,
cgi
, t hrough which it invokes t he various HTML-generat ion calls.
header
generat es t he
Content-Type:
header and
start_html
produces t he init ial page t ags up t hrough t he opening
body
t ag. Aft er generat ing t he first part of t he page, show_t ables_oo.pl ret rieves and displays inform at ion from t he server. Each t able nam e is
follow ed by a
br
t ag, produced by invoking t he
br
m et hod.
end_html
produces t he closing
body
and
html
t ags. When you inst all t he script in your
cgi- bin direct ory and invoke it from a browser, you can see t hat it generat es t he sam e t ype of page as show_t ables.pl.
CGI .pm calls oft en t ake m ult iple param et ers, m any of which are opt ional. To allow you t o specify j ust t hose param et ers you need, CGI .pm underst ands
-name =
value
not at ion in param et er list s. For exam ple, in t he
start_html
call, t he
title
param et er set s t he page t it le and
bgcolor
set s t he background color. The
-name =
value
not at ion also allows param et ers t o be specified in any order, so t hese t wo st at em ent s are equivalent :
print cgi-start_html -title = My Page Title, -bgcolor = white; print cgi-start_html -bgcolor = white, -title = My Page Title;
To use t he CGI .pm funct ion call int erface rat her t han t he obj ect -orient ed int erface, you m ust writ e script s a lit t le different ly. The
use
line t hat references CGI .pm im port s t he m et hod nam es int o your script s nam espace so t hat you can invoke t hem direct ly as funct ions wit hout
having t o creat e a CGI obj ect . For exam ple, t o im port t he m ost com m only used m et hods, t he script should include t his st at em ent :
use CGI qw:standard; The follow ing script , show_t ables_fc.pl, is t he funct ion call equivalent of t he show_t ables_oo.pl
script j ust shown. I t uses t he sam e CGI .pm calls, but invokes t hem as st andalone funct ions rat her t han t hrough a
cgi
obj ect : usrbinperl -w
show_tables_fc.pl - Issue SHOW TABLES query, display results using the CGI.pm function-call interface
use strict; use lib qwusrlocalapachelibperl;
use CGI qw:standard; import standard method names into script namespace
use Cookbook; Print header, blank line, and initial part of page
print header ; print start_html -title = Tables in cookbook Database,
-bgcolor = white; print p Tables in cookbook database:;
Connect to database, display table list, disconnect my dbh = Cookbook::connect ;
my sth = dbh-prepare SHOW TABLES; sth-execute ;
while my row = sth-fetchrow_array {
print row[0] . br ; }
dbh-disconnect ; Print page trailer
print end_html ; exit 0;
I nst all t he show_t ables_fc.pl script in your cgi- bin direct ory and t ry it out t o verify t hat it produces t he sam e out put as show_t ables_oo.pl.
This book uses t he CGI .pm funct ion call int erface for Perl- based web script s from t his point on. You can get m ore inform at ion about CGI .pm at t he com m and line by using t he following
com m ands t o read t he inst alled docum ent at ion:
perldoc CGI perldoc CGI::Carp
Ot her references for t his m odule, bot h online and in print form , are list ed in Appendix C
.
16.3.3.2 PHP
PHP doesnt provide m uch in t he way of t ag short cut s, which is surprising given it s web orient at ion. On t he ot her hand, because PHP is an em bedded language, you can sim ply writ e
your HTML lit erally in your script wit hout using
print
st at em ent s. Heres a script show_t ables.php t hat shift s back and fort h bet ween HTML m ode and PHP m ode:
?php show_tables.php - Issue SHOW TABLES query, display results
include Cookbook.php; ?
html head
titleTables in cookbook Databasetitle head
body bgcolor=white pTables in cookbook database:p
?php Connect to database, display table list, disconnect
conn_id = cookbook_connect ; result_id = mysql_query SHOW TABLES, conn_id;
while list tbl_name = mysql_fetch_row result_id print tbl_namebr \n;
mysql_free_result result_id; mysql_close conn_id;
?
body html
To t ry t he script , put it in t he m cb direct ory of your web servers docum ent t ree and invoke it as follow s:
ht t p: apache.snake.net m cb show_t ables.php Unlike t he Perl versions of t he MySQL show- t ables script , t he PHP script includes no code t o
produce t he
Content-Type:
header, because PHP produces it aut om at ically. I f you w ant t o override t his behavior and produce your own headers, consult t he
header
funct ion sect ion in t he PHP m anual. Except for t he break t ags, show_t ables.php includes HTML cont ent by writ ing it out side of t he
?php
and
?
t ags so t hat t he PHP int erpret er sim ply writ es it wit hout int erpret at ion. Heres a different version of t he script t hat produces all t he HTML using
print
st at em ent s: ?php
show_tables_print.php - Issue SHOW TABLES query, display results using print to generate all HTML
include Cookbook.php; print html\n;
print head\n; print titleTables in cookbook Databasetitle\n;
print head\n; print body bgcolor=\white\\n;
print pTables in cookbook database:p\n; Connect to database, display table list, disconnect
conn_id = cookbook_connect ; result_id = mysql_query SHOW TABLES, conn_id;
while list tbl_name = mysql_fetch_row result_id print tbl_namebr \n;
mysql_free_result result_id; mysql_close conn_id;
print body\n; print html\n;
?
Som et im es it m akes sense t o use one approach, som et im es t he ot her—and som et im es bot h wit hin t he sam e script . I f a sect ion of HTML doesnt refer t o any variable or expression values,
it can be clearer t o writ e it in HTML m ode. Ot herwise it m ay be clearer t o writ e it using
print
or
echo
st at em ent s, t o avoid swit ching bet ween HTML and PHP m odes frequent ly.
16.3.3.3 Python
A st andard inst allat ion of Pyt hon includes
cgi
and
urllib
m odules t hat are useful for web program m ing. However, we dont act ually need t hem yet , because t he only web- relat ed
act ivit y of our first Pyt hon web script is t o generat e som e sim ple HTML. Heres a Pyt hon version of t he MySQL st at us script :
usrbinpython show_tables.py - Issue SHOW TABLES query, display results
import sys sys.path.insert 0, usrlocalapachelibpython
import MySQLdb import Cookbook
Print header, blank line, and initial part of page print Content-Type: texthtml
html head
titleTables in cookbook Databasetitle head
body bgcolor=white pTables in cookbook database:p
Connect to database, display table list, disconnect conn = Cookbook.connect
cursor = conn.cursor cursor.execute SHOW TABLES
for tbl_name, in cursor.fetchall : print tbl_name + br
cursor.close conn.close
Print page trailer print
body html
Put t he script in Apaches cgi- bin direct ory and invoke it like t his: ht t p: apache.snake.net cgi-bin show_t ables.py
16.4 Using Tomcat to Run Web Scripts