The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Apache::Voodoo::basics - The Basics of Voodoo setup and operation

SETUP

There are a three setup steps to begin writing a site with Voodoo. The following sections describe those steps. Some basic understanding of Apache administration is necessary ;)

1) Apache Configuration

The first thing we need to do is modify Apache's configuration file to load Voodoo, and to setup our site.

Example Configuration

  # load these at server start (optional, slightly quicker startup time)
  PerlModule Apache::Session
  PerlModule HTML::Template

  # load Apache::Voodoo
  PerlModule Apache::Voodoo::Handler

  <Directory /data/apache/sites/my_app/html>
    SetHandler perl-script
    PerlHandler Apache::Voodoo::Handler
    PerlSetVar ID my_app

    Options Indexes Includes FollowSymLinks
    AllowOverride None

    Order allow,deny
    Allow from all
  </Directory>

The directory block may be repeated as many times as necessary to setup multiple sites. Directory Aliases and Virtual Hosts may also be used in the same manner.

PerlModule Apache::Voodoo::Handler

Loads Voodoo. This line must be present somewhere inside the 'main' section of the apache configuration file...IE. not within a <directory> or <virtual> block.

SetHandle perl-script

Tells Apache that a mod_perl is going to be use for this directory or virtual host

PerlHandler Apache::Voodoo::Handler

Tells Apache what method to call to handle requests for this directory

PerlSetVar ID name_of_site

This let's Voodoo know what site is attached to this directory.

Names matching /[a-z][a-z0-9_-]*/i are valid.

2) Voodoo Configuration File

Each Voodoo site has it's own configuration file that is kept in:

        <ServerRoot>/sites/<name_of_site>/etc/voodoo.conf

The "name_of_site" directory must match the value of the ID parameter. In our example above, it would be "my_app".

This is also used as the top level package name that Voodoo will use in loading all other modules. This can be overridden with the optional BASE_PACKAGE directive.

Voodoo uses the "General" in Config module for its configuration files. See its documentation for more information on its syntax rules.

Example Configuration

        cookie_name  = my_app_SID
        session_timeout = 0
        shared_cache    = 0
        session_dir  = /usr/local/apache/sessions/my_app
        debug = 1

        <database>
                connect  = "dbi:mysql:database=my_app;host=127.0.0.1;mysql_connect_timeout=2"
                username = "test_user"
                password = "test_password"
        </database>
        
        <modules>
                login
                admin::login_history
        </modules>

        <includes>
                date
                main_menu
        </includes>

        <template_conf>
                <default>
                        skeleton = skeleton.tmpl
                        pre_include = date
                        post_include = main_menu
                </default>
        </template_conf>

This is a optional parameter that sets the name of the cookie used by Voodoo for session identification. If it is not supplied the cookie name will the value of the ID parameter with "_SID" appended.

session_timeout

Number of minutes before a cookie expires. Set to 0 for no expiration.

shared_cache

Whether or not to use Shared memory for caching of templates. Typically 0 for development and 1 for production.

database

This is a list of database connect info. Databases are connected to in the order listed. If the first connection fails the next in the list is used. An error message is generated in the Apache error log file on a failed connection, but no other action is taken. There are good database monitoring packages out there :) . The contents of each array element is passed directly to DBI->connect.

session_dir

This is the directory that Apache::Session will use to store session information. This directory must be present and writable by whatever user Apache runs as.

debug

Enables or disables the debug() method from Apache::Voodoo and its associated output on each page. See Apache::Voodoo::Debug for more information.

halt_on_errors

If set to 1, this causes the server to return a 503 (server temporary unavailable) message for the host if any modules fail to load. Defaults to 0

modules

This contains the list of page handling modules that will be loaded by Voodoo.

Note that the modules names do not contain the base package name. "my_app::index" becomes "index", this saves a bunch of typing, but more importantly prevents accidental cross-site module loading.

These modules must reside in <ServerRoot>/sites/<name_of_site>/code, and of course follow Perl's conventions for directory and file names. mod_perl appends <ServerRoot>/lib/perl to @INC and this is used as a convenient directory to symlink in the path to the site's modules. This method saves us the hassle fiddling with @INC and doesn't increase the number of directories the loader must search through.

includes

This contains a list of modules that can be used on a per page basis to inject extra info into the output. For example, if you wish to have the current date and time appear on every page, create a module that returns that info, include it in this list and add it to the template_conf section accordingly.

template_conf

The entries here are regular expression entries that match one or more page with the site. Each section may be used to control certain aspects of how Voodoo presents the page. The magic entry <default> matches any page that doesn't have another matching entry. Standard items are:

skeleton

Which skeleton template to use

pre_include

A list of include modules to call on this page, BEFORE the main page handling module. These will be called in the order given in the list.

post_include

A list of include modules to call on this page, AFTER the main page handling module. These will be called in the order given in the list.

content-type

Content type for the output. Defaults to text/html

Any other params will be passed to the template directly, and will be accessible to page handling modules via $p->{'template_conf'}

3) Basic Templates

In <ServerRoot>/sites/<name_of_site>/html directory, create a file named 'skeleton.tmpl' (or whatever you specified in the 'skeleton' parameter above), and place (at least) this in it:

        <html>
        <TMPL_VAR _MAIN_BODY_>
        <TMPL_VAR _DEBUG_>
        </html>

Here's the logic. The vast majority of the time, every page on a site has the same basic look; the same header, the same footer, the same menu, etc. What changes page to page is the core content, the meat so to speak. Why write the HTML for the headers, etc over and over? Why have to remember to include header and footer templates in every file? Why have to go back and edit every file if you want to move the menu from the left to the right side?

This method allows you to write all header/footer stuff once and have a single point of alteration for it. The core content (your other template files), are simply inlined where _MAIN_BODY_ is in the skeleton.

Let's say your index.tmpl file contains:

        <h1>Hello, welcome to my site</h1>
        Enjoy your stay.

The resulting html as sent to the browser would be:

        <html>
        <h1>Hello, welcome to my site</h1>
        Enjoy your stay.
        <!-- Voodoo Debug info omitted for clarity-->
        </html>

Any HTML::Template directives in the skeleton can be controlled by the page modules. You can think of it this way: The individual page template is inserted into the skeleton first and then normal HTML::Template processing is done on the entire thing.

Only files that end in .tmpl are processed by Voodoo. It ignores any other files and leaves them for Apache to handle natively. The .tmpl is optional in the URLs, http://yoursite.com/index.tmpl and http://yoursite.com/index are functionally identical.

4) Module Location

All the .pm's for your site go in <ServerRoot>/sites/<name_of_site>/code and follow Perl's naming convention as they appear in the voodoo.conf file. In other words, the module's package name might be "my_app::login" but it belongs in <ServerRoot>/sites/my_app/code/login.pm

EXAMPLE SITE LAYOUT

etc, html, and code are the three directories whose locations are fixed, you can create other "top level" directories as you need them. For example, this layout has worked well for myself and others.

    <ServerRoot>/sites/my_app
        |_ bin
        |   |_ a_cron_job.pl
        |   |_ a_utility_program.pl
        |_ code
        |   |_ skeleton.pm
        |   |_ login.pm
        |_ db
        |   |_ database_schema.sql
        |_ docs
        |   |_ who_are_we_kidding_right_guys.doc
        |_ etc
        |   |_ voodoo.conf
                |_ html
        |   |_ skeleton.tmpl
        |   |_ login.tmpl
        |   |_ images
        |   |_ logo.gif
        |_ tests
            |_ a_test_script.t

AUTOMATING INSTALLS/UPGRADES

Voodoo has a automated install/upgrade system for sites developed within it. See the program "voodoo-control".

FIXME: loads of docs needed here.

TEMPLATE TO PAGE MODULE MAPPING

Voodoo matches templates to code according to two rules.

1) /my/url/path => base_package::my::url::path->handle

If a module exists that matches the URL and it has a method named 'handle', it is called. If that fails then it looks for...

2) /my/url/foo_path => base_package::my::url::path->foo

It removes the file name up to the first '_', looks for module matching that URL containing a method named whatever was removed.

If neither of these rules match, then template is just inserted into the skeleton as is. This allows you to create static content without having to make a module that basically does nothing.

The interesting side effect of rule two is that you can't make page handling methods that have a _ in them. They would never match the criteria of rule two. This allows you to make methods that have no way of accidentally being mapped to a URL by simply add an underscore to them.

Examples

        my_app::index->handle        /index                     
        my_app::foo::bar->handle     /foo/bar           
        my_app::foo::bar_baz->handle /foo/bar_baz    
        my_app::foo::bar->qux        /foo/qux_bar       
        my_app::foo::bar->_foo       # won't match any url, it contains an underscore

MODULE API

The details of how to write modules are covered in Apache::Voodoo::api.

AUTHOR

Maverick, /\/\averick@smurfbaneDOTorg

COPYRIGHT

Copyright (c) 2005 Steven Edwards. All rights reserved.

You may use and distribute Voodoo under the terms described in the LICENSE file include in this package or Apache::Voodoo::license. The summary is it's a legalese version of the Artistic License :)

1 POD Error

The following errors were encountered while parsing the POD:

Around line 199:

You forgot a '=back' before '=head1'