Problem Solution Discussion Using Apache to Run Web Scripts

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