| Author: | Graham Dumpleton |
|---|---|
| Contact: | grahamd@dscpl.com.au |
| Updated: | 27/04/2005 |
This article provides instructions on how to configure Apache to make use of Vampire.
To enable use of Vampire in its mode as an enhanced dispatch system for basic content handlers, add the following Apache directives into the main server configuration file.
<Directory /some/directory> SetHandler python-program PythonHandler vampire PythonDebug On </Directory>
Substitute "/some/directory" with the name of the actual directory containing the files which are to be managed by Vampire. "The PythonDebug" directive is recommended during development but should be set to "Off" in a production system to avoid revealing internal details of any Python code when an error occurs.
The above will work for both versions 2.7 and 3.1 of mod_python. In version 3.1, the name of the mod_python handler reference has actually been changed. If you have no need to support older versions of mod_python you can use "mod_python" instead of "python-program" with the "SetHandler" directive.
If you are going to enable use of Vampire from within a ".htaccess" file instead of the main server configuration file, you will not need the enclosing "<Directory>" tag. In this case the directory the settings apply to is that in which the ".htaccess" file is located.
SetHandler python-program PythonHandler vampire PythonDebug On
If using a ".htaccess" file, you will however need to make sure the "AllowOverride" directive applicable to this directory has at least "FileInfo" specified. If this isn't specified Apache will reject the "SetHandler" directive and any request against the directory will result in an internal server error response. This override ability has to be set within the main server configuration files.
AllowOverride FileInfo
It is also necessary to ensure that the "MultiViews" option is not enabled for the directory. This is necessary as otherwise the mod_negotiation Apache extension will be applied to requests and Apache may as a result rewrite request URLs that it shouldn't and confuse Vampire.
Options -MultiViews
Finally, it is also recommended that "Indexes" not be enabled for the directory. If "Indexes" are enabled a remote person would be able to view what source code files may exist in a directory even if they can't access the contents of the files themselves.
Options -Indexes
Note that if using the main server configuration file, Vampire should not be enabled at global scope, nor enclosed only within a "<Location>" tag. If this were done, the Vampire configuration mechanism will not work correctly and the general operation of Vampire may also be affected.
After having made any changes to the main server configuration files you must restart Apache, otherwise the changes will not be picked up.
If using Apache 1.3, setting "DirectoryIndex" to a specific resource to be used when a directory is accessed works, albeit with the caveat that the target file must exist. If the resource is actually a virtual resource created on demand by a content handler, this means one will need to create a dummy file as a place marker for the resource to ensure that mod_dir works correctly.
When using Apache 2.0, the "DirectoryIndex" directive does not get applied at all to directories being managed by a handler such as Vampire. As a result, Vampire provides its own means of redirecting requests against a directory to a specific resource. This is enabled by using the "PythonOption" directive to set a value for the "VampireDirectoryIndex" option.
PythonOption VampireDirectoryIndex index.html
When using this feature however, unlike the "DirectoryIndex" directive, you can only specify a single target resource. It is not possible to supply a list of resources with the first one found being used.
If the version of mod_python being used supports internal redirects within Apache, that mechanism will be used to redirect the request to the specified resource. If internal redirects aren't supported by the version of mod_python being used, then a HTTP redirect response is returned and the browser is expected to deal with it.
Note that options set using the "PythonOption" directive are inherited by subdirectories beneath the directory where the option is set. This means that you do not have to set the option for every single directory, only the common parent directory. If different subdirectories needed to use a different resource, then each directory should set "VampireDirectoryIndex" themselves. If it was necessary to eliminate the inherited value of the option, it should be set to ".".
PythonOption VampireDirectoryIndex .
It is necessary to use "." as mod_python has a bug in it which doesn't allow you to unset an option or set it to an empty value.
If using Apache 1.3 and the "DirectoryIndex" directive, there doesn't seem to be any way at all of disabling it within a subdirectory once set in the context of a parent directory.
When using default directory index files, you should avoid having any corresponding handler accept form parameters. This is because form parameters submitted using the POST method will not survive the internal redirect performed by Apache to add the trailing slash to a directory.
For each request, Vampire will look for a content handler to execute to generate a response. If it cannot find one, the request is passed back to Apache for handling. If Apache finds a physical file matching the requested resource, it will then return the raw contents of that file as the response to the request.
Normally, each resource where a generated response is required needs to have a unique content handler. If however you have many resources where the code is the same and only the input differs, then a default handler can be used.
Because of the additional overhead involved in checking for a default handler, this feature is usually switched off. To enable checks for default handlers, the Python option "VampireDefaultHandlers" should be set to "On":
PythonOption VampireDefaultHandlers On
With this feature enabled, if a handler specific to a resource cannot be found, instead of immediately passing the request back to Apache, an additional check is performed to see if a default handler is defined for that resource type. The type of resource is determined by looking at any extension present in the last part of the URL.
The actual location of any default handlers need to be specified in the Vampire configuration file. By default the name of this file would be ".vampire" and it would be placed into the root directory for which use of Vampire is enabled. A typical entry within this file would be:
[Handlers] handler_html = %(__config_root__)s/_handlers.py
This indicates that if a request for a resource arrives where the URL used an extension of ".html", and there was not a dedicated content handler for the resource, that the "handler_html()" function contained within the "_handlers.py" Python code file should be executed to handle the request.
The value reference of "%(__config_root__)s" is special and is replaced with the name of the directory where the Vampire configuration file was found. This means that absolute pathnames do not have to be encoded into the configuration file.
The default name of ".vampire" for the configuration file can be overridden by setting the Python option "VampireHandlersConfig". The default name of the section within the configuration file which is consulted for the location of default handlers can be overridden by setting the Python option "VampireHandlersSection". The two default values for these settings are the equivalent of having set:
PythonOption VampireHandlersConfig .vampire PythonOption VampireHandlersSection Handlers
When the "PythonHandler" directive is specified for a directory, mod_python will add that directory to the beginning of the Python module search path. This can be problematic because it means that if you choose a name for a resource which matches that of a standard Python module, any code which attempts to import the standard module may incorrectly pick up the Python code file corresponding to your resource.
Because Vampire implements its own module loading system which doesn't rely on the standard Python "__import__" function or on "sys.path", it is highly recommended that the modification of the Python module search path to include the directory where "PythonHandler" was applied be disabled. This can be done by using the "PythonPath" directive to fix the path to the current value of the Python module search path.
PythonPath 'sys.path'
Note that once this is set for a directory, this fixed path is inherited by any subdirectories, even those which may set "PythonHandler" again. Thus once set, it cannot be changed within a subdirectory even if within the context of a different Python interpreter.
Because some third party packages are dependent on being able to use the standard Python "import" statement and cannot be made to use the Vampire module loading system directly, fixing the path in this way may cause such a package to fail. This is the case where the Cheetah templates package is being used in conjunction with Vampire.
To counter this, Vampire can optionally install an import hook which will cause the Python "import" statement to make use of the Vampire module loading system under certain circumstances. To enable this feature, it is necessary to set the Python option "VampireImportHooks" to "On".
PythonOption VampireImportHooks On
The Vampire module loading system will be triggered for the "import" statement if the request to import the module is performed at global scope from a module which was previously imported using the Vampire module loading system, and the module to be imported is located in the same directory as the code file in which the "import" statement is contained.
If the desired module is not in the same directory, a search of directories specified by "sys.path" will be done, however the the standard Python import system and not the Vampire module loading system will still be used to load the module.
Where additional modules which form a part of the web application are contained in a separate directory, Vampire can be configured to search those additional directories in addition to the directory the original code file is located in. The list of directories to search needs to be defined within the "Modules" section of the Vampire configuration file. The name of the variable to set is "path".
[Modules] modules = %(__config_root__)s/modules templates = %(__config_root__)s/templates path = %(modules)s:%(templates)s
If multiple directories are specified, they must be separated by a ":". Using the string interpolation feature of the configuration file, other variables defined in that section of the configuration file can be referenced, as can the default variables.
The default name of the configuration file which is consulted in relation to this specific feature can be overridden by setting the Python option "VampireModulesConfig". The default name of the section within the configuration file which is consulted for the module search path can be overridden by setting the Python option "VampireModulesSection". The two default values for these settings are the equivalent of having set:
PythonOption VampireModulesConfig .vampire PythonOption VampireModulesSection Modules
Note that the list of directories should not include any directories which also appear in the standard Python module search path as defined by "sys.path". The mechanism will also not work where a module is actually a package. Any application specific modules should therefore not be structured as packages.
When the use of mod_python has been configured using the "SetHandler" directive, if a handler declines to service the request and passes it back to Apache, Apache will only apply its default handler. This means that if the request is for a PHP file, the raw content of that PHP file will be returned as the response. That is, the content of the PHP file will not be processed through the Apache PHP module.
If using the "SetHandler" directive to enable use of mod_python, but still needing to support use of PHP in the same directory, you will need to selectively disable use of mod_python for a request with a ".php" extension. This can be achieved by using the following Apache configuration:
SetHandler python-program PythonHandler vampire <Files *.php> SetHandler None </Files>
This technique could also be used if you have a lot of graphics files present in a directory and where a mod_python handler isn't actually being used to generate them. By avoiding invocation of mod_python you avoid it doing any unnecessary processing:
SetHandler python-program PythonHandler vampire <Files ~ "\.(php|gif|jpe?g|png)$"> SetHandler None </Files>
If mod_python is only being used to generate content for certain types of resources, instead of using "SetHandler" it is also possible to instead use the "AddHandler" directive. Thus, if the only requests which needed to be passed through mod_python were those with a ".html" extension, it would be possible to use:
AddHandler python-program .html PythonHandler vampire
Because only ".html" requests are processed by mod_python, any requests for PHP files with a ".php" extension will work fine.
Note that since not all requests are processed by mod_python, the checks that exist in Vampire to prevent access to Python code files will not be triggered. Therefore, if using "AddHandler" it is highly recommended to block direct access to ".py" and ".pyc" files, as well as other files such as configuration files:
<Files ~ "\.(py|pyc)$"> deny from all </Files> <Files .vampire> deny from all </Files>
Vampire provides its own implementation of the publisher handler which should be able to be used in most cases as a drop in replacement for mod_python.publisher. To make use of this handler the "PythonHandler" directive should be set to reference the Vampire implementation rather than the mod_python.publisher version.
PythonHandler vampire::publisher
As with the original mod_python.publisher, either the "SetHandler" or "AddHandler" directives can be used to enable generation of content for a request by mod_python. Either a ".py" extension or no extension at all may also be specified as appropriate.
Because Vampire provides an extended mechanism for interpreting form parameters, it may be necessary to modify the names of form parameters where a conflict occurs. Alternatively, this extended mechanism can be disabled. This can be done by setting the "VampireStructuredForms" option to "Off".
PythonOption VampireStructuredForms Off
To make best use of Vampire, any direct use of the Python "import" statement or the "apache.import_module()" function to import modules which are a part of the web application, should be changed to use the Vampire import mechanism instead. This will provide a more reliable way of having modules reloaded when changes are made and lift the various constraints imposed by using the standard Python module import system.