The Configuration File
All configuration of maki is done in one or more XML config files. The main config file is MAKI_DIR/maki-conf.xml. Before I describe the file in detail, be aware that maki re-reads the config file whenever it changes. There are both pros and cons to this. On the positive side, it allows you to easily make and test changes to the config file. On the negative side, if you screw up the config file, the effects are immediate.
The document element of the config file is named <config>.
It may contain a <debug-level>, a <default-transformer>, any number of <alias>es, any number of <rule>s, and any number of <zone>s.
debug-level
If the child <debug-level> exists, it must contain a number between 0 and 2. maki writes to a log file (MAKI_DIR/maki.log) as it runs. If you do not explicitly set the debug-level, it will default to 2 (very verbose).
When the level is 2, lots of debugging messages are logged which may be of interest if you are trying to track down a bug in maki or are just really interested in seeing how your request is handled. When the level is 1, a small amount of logging is done as each step is executed. This may be interesting if you want to watch maki apply a rule to each request and see how long each step takes. When the level is 0, there are no execution trace messages.
No matter what the debug-level is set to, errors are always logged. Also, any <debug> steps will cause the document to be dumped to the log.
Finally, inside a <process> step you can call MAKI_log(string) to write to the log (for example, MAKI_log("Hello World!")).
default-transformer
<default-transformer> must contain either the text '4xslt', 'Sablot', 'libxslt' (for the Python bindings by Daniel Veillard distributed with the main libxslt library), 'libxsltmod' (for the Python bindings by Dave Kuhlman), or 'Pyana'.
alias
You can create any number of <alias>es. Each one must have a @name and @value.
Aliases may be used as a sort of shorthand in the following places:
- rule/@match
- stylesheet/@file
- zone/@match
- zone/@file
- alias/@value
(<rule>, <stylesheet>, and <zone> will all be described in detail later in this document.)
To use an alias in any of these attribute values, simply use a dollar-sign followed by the alias name.
For instance, if you defined this alias:
<alias name="LOGICSHEETS" value="/usr/local/maki/logicsheets"/>
|
|
Then you could use it in a stylesheet step like so:
<stylesheet file="$LOGICSHEETS/sql.xsl" />
|
|
Rules
Each <rule> must have a @match. The value of @match is a path-matching pattern (either a fnmath wildcard pattern or a regular expression, depending on @matchType. When a request comes into maki the value of the PATH_TRANSLATED environment variable is determined. maki then searches starting from the end of the rule list for the first rule that matches the path. In other words, you should list your rules in the config file such that the most general rules come first, followed by the more specific ones.
Each <rule> may optionally have some other attributes too. The following table lists all recognized attributes.
<rule> Attributes
name |
value |
required? |
default |
match |
A pattern for matching the path of the requested XML file. |
yes |
none |
matchType |
If 'fn', then the value of @match is treated as a fnmatch wildcard pattern. If 're', then the value of @match is treated as a regular expression. |
no |
'fn' |
|
Each <rule> may contain any number of step elements, where each step is identified by the name of the element. Valid steps names are: <stylesheet>, <process>, <write>, and <debug>. I will discuss each in turn.
The <stylesheet> Step
Each <stylesheet> indicates that a stylesheet is to be applied to the current document. If no attributes are specified, then the default stylesheet is applied. The default stylesheet is a file in the same directory as the source XML file, but with the file extension replaced by 'xsl'. (If the file has no extension, then '.xsl' is appended.) To apply a stylesheet other than the default, specify the path to the stylesheet as the value of @file. By default, the default-transformer is used. To override this, specify a value for @transformer.
If you do not know ahead of time what stylesheet to use, you can specify the stylesheet in a (dynamically generated) xml-stylesheet processing instruction in the XML source document. If you want to do this, you must specify @use-pi='yes' in the <stylesheet> step, and be sure that your XML document has an xml-stylesheet PI before the document element with the name of the stylesheet file specified as the value of the @href, like this: <?xml-stylesheet href='my_stylesheet.xsl' type='text/xml'?>.
Finally, if you ever want to see what the stylesheet looks like (after any <maki:include> processing has been done) with line numbers, you can set @debug to "yes". This will cause the stylesheet content to be dumped to the log, and can be very useful when you are getting XSLT error messages that contain line numbers.
<stylesheet> Attributes
name |
value |
required? |
default |
file |
Path to the stylesheet. If the path isn't absolute then, it is treated as a path relative to the source document. |
no |
source file with extension replaced by 'xsl' |
use-pi |
If 'yes', then try to obtain the name of the stylesheet file from the href of an xml-stylesheet PI in the XML source document. If 'no', use the value of @file, or the default stylesheet. |
no |
'no' |
transformer |
The name of the XSLT transformer to use. '4xslt', 'Sablot', 'libxslt', 'libxsltmod', or 'Pyana'. |
no |
default-transformer |
debug |
If set to "yes", the contents of the stylesheet will be dumped to the log file when the stylesheet is applied. |
no |
"no" |
|
The <process> Step
Each <process> indicates that the current document is to be passed to a processor. The default processor is spb.makiLogic. makiLogic's main function is named 'process'. It searches the document for elements in the maki namespace that specify that text, elements, and/or attributes are to be dynamically added to the document by evaluating embedded Python code.
By default, process output is not cached. To override that, specify a non-negative number for @cacheTime. A value of zero means cache forever. A positive value is an amount of time. By default, the value of @cacheTime is considered a number of seconds. To override that, specify a value for @cacheUnit. For easier readability, you can use the special value 'forever' as an alias for '0', or the special value 'never' as an alias for '-1'.
If caching is enabled, in general the query parameters are used as part of the cache key, but cookies and the environment are not. You can override this behavior by using the attributes @cacheOnParms, @cacheOnCookies, and @cacheOnEnviron. The first one is a boolean value that defaults to 'yes'. The other two are semicolon-delimited lists of names.
If you want to use a processor other than the default one, then you can specify one or both of the following attributes. @module names the Python module that contains the processor. @function names the function in that module to which the document (as a string), an output stream, and a variable dictionary are to be passed.
<process> Attributes
name |
value |
required? |
default |
module |
Name of a Python module. |
no |
'spb.makiLogic' |
function |
Name of a function in that module. |
no |
'process' |
cacheTime |
Zero ('0') or 'forever' means to cache forever. A positive number represents an amount of time to cache. A negative number or 'never' forbids caching. |
no |
-1 ('never') |
cacheUnit |
'seconds' or 'minutes' or 'hours' or 'days' |
no |
'seconds' |
cacheOnParms |
Determines whether or not query parameters are used in the cache key. |
no |
'yes' |
cacheOnEnviron |
The value is a semicolon-delimited list of the names of environment variables which are to be used as part of the cache key. |
no |
empty string |
cacheOnCookies |
The value is a semicolon-delimited list of the names of cookies which are to be used as part of the cache key. |
no |
empty string |
|
If I discover the need, I may write other processors later. Or you can write your own. maki expects each processor to have a function that takes three arguments: a string containing the input XML, a stream your process should write its output to, and a variable namespace dictionary.
The function must take all three arguments, but it could ignore the third argument if it doesn't need it. The function must write its output to the stream that was passed as the second argument.
Currently maki places two variables and two functions in the variable dictionary (the third argument). The variables are: MAKI_trans (an instance of one of the subclasses of genericHttpTransaction) and MAKI_persistDict (a dictionary that persists across requests). The functions are: MAKI_log (a function you can call with a string argument if you want to write messages to maki's log file) and MAKI_return (a function that you can call if you want to bailout of a rule early).
Finally, if you need to be sure some code is run at the end of your process step even if an exception is thrown, you can define a function with the name MAKI_cleanup. This function must not take any arguments. If you need to do some cleanup that can't be done with a try-finally construct (because the "try" would be in one <maki:logic> tag and the "finally" in another) then defining MAKI_cleaup() inside your <maki:logic> tag will probably meet your needs.
The <write> Step
Each <write> indicates that the current document is to be written out to the HTTP response stream. By default, the content type is set to 'text/html'. To override that, specify a value for @contentType.
<write> Attributes
name |
value |
required? |
default |
contentType |
Value to use in the response Content-Type header. |
no |
'text/html' |
|
The <debug> Step
Each <debug> indicates that the current document is to be written out to the log. If you are curious to see the document between two steps, insert a debug step between the two, then hit the page and look at the log file.
Sometimes you may want to see if the document can be parsed (this is particularly useful if the previous step was a process step that produced invalid XML and the next step is a stylesheet step, but your XSLT transformer doesn't provide a descriptive error message). Specify @parse='yes' to request a parse of the document.
<debug> Attributes
name |
value |
required? |
default |
parse |
If set to "yes", the document will be parsed after it is dumped and any parse errors will be logged. |
no |
'no' |
|
Zones
If you have more than one site to serve, you will find the need to group the rules for each site separately. maki allows this with a concept called "zones".
In the main config file, you can declare any number of zones.
Each <zone> must have a @match which specifies an absolute path to a directory (note that the attribute value is a simple string, not a regular expression). Any requests that start with that path will match the zone. Each <zone> must also have a @file, which tells maki the location of the rule file for that zone.
<zone> Attributes
name |
value |
required? |
default |
match |
A string for matching the start of the path of the requested XML file. |
yes |
none |
file |
Specifies the path to a file containing the rules for the zone. |
yes |
none |
|
The matching procedure is similar to the way maki searched for rules. maki searches for a matching zone starting from the end of the config file searching backwards. Within the matching zone, maki searches backwards from the last rule.
When you installed maki, it created one example zone file for the examples and the manual. Look at maki-conf.xml and example-conf.xml to see how to setup a zone file.
|