You are viewing a plain text version of this content. The canonical link for it is here.
Posted to mod_python-commits@quetz.apache.org by gr...@apache.org on 2006/10/27 08:02:43 UTC

svn commit: r468288 - /httpd/mod_python/trunk/Doc/modpython6.tex

Author: grahamd
Date: Thu Oct 26 23:02:43 2006
New Revision: 468288

URL: http://svn.apache.org/viewvc?view=rev&rev=468288
Log:
(MODPYTHON-104) Contributed personal article on using Python code with SSI
under mod_python. The original article was sourced from
'http://www.dscpl.com.au/wiki/ModPython/Articles/BasicsOfServerSideIncludes'.


Modified:
    httpd/mod_python/trunk/Doc/modpython6.tex

Modified: httpd/mod_python/trunk/Doc/modpython6.tex
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/Doc/modpython6.tex?view=diff&rev=468288&r1=468287&r2=468288
==============================================================================
--- httpd/mod_python/trunk/Doc/modpython6.tex (original)
+++ httpd/mod_python/trunk/Doc/modpython6.tex Thu Oct 26 23:02:43 2006
@@ -1,3 +1,264 @@
+\chapter{Server Side Includes\label{ssi}}
+
+\section{Overview of SSI\label{ssi-overview}}
+
+SSI (Server Side Includes) are directives that are placed in HTML pages,
+and evaluated on the server while the pages are being served. They let you
+add dynamically generated content to an existing HTML page, without having
+to serve the entire page via a CGI program, or other dynamic technology
+such as a mod_python handler.
+
+SSI directives have the following syntax:
+
+\begin{verbatim}
+<!--#element attribute=value attribute=value ... -->
+\end{verbatim}
+
+It is formatted like an HTML comment, so if you don't have SSI correctly
+enabled, the browser will ignore it, but it will still be visible in the
+HTML source. If you have SSI correctly configured, the directive will be
+replaced with its results.
+
+For a more thorough description of the SSI mechanism and how to enable it,
+see the \citetitle[http://httpd.apache.org/docs/2.0/howto/ssi.html]{SSI
+tutorial} provided with the Apache documentation.
+
+Version 3.3 of mod_python introduces support for using Python code within
+SSI files. Note that mod_python honours the intent of the Apache
+\code{IncludesNOEXEC} option to the \code{Options} directive. That is, if
+\code{IncludesNOEXEC} is enabled, then Python code within a SSI file will
+not be executed.
+
+\section{Using Python Code\label{ssi-python-code}}
+
+The extensions to mod_python to allow Python code to be used in conjunction
+with SSI introduces the new SSI directive called 'python'. This directive
+can be used in two forms, these being 'eval' and 'exec' modes. In the case
+of 'eval', a Python expression is used and it is the result of that
+expression which is substituted in place into the page.
+
+\begin{verbatim}
+<!--#python eval="10*'HELLO '" -->
+<!--#python eval="len('HELLO')" -->
+\end{verbatim}
+
+Where the result of the expression is not a string, the value will be
+automatically converted to a string by applying \code{str()} to the value.
+
+In the case of 'exec' a block of Python code may be included. For any
+output from this code to appear in the page, it must be written back
+explicitly as being part of the response. As SSI are processed by an Apache
+output filter, this is done by using an instance of the mod_python
+\code{filter} object which is pushed into the global data set available to
+the code.
+
+\begin{verbatim}
+<!--#python exec="
+filter.write(10*'HELLO ')
+filter.write(str(len('HELLO')))
+" -->
+\end{verbatim}
+
+Any Python code within the 'exec' block must have a zero first level
+indent. You cannot start the code block with an arbitrary level of indent
+such that it lines up with any indenting used for surrounding HTML
+elements.
+
+Although the mod_python \code{filter} object is not a true file object, that
+it provides the \code{write()} method is sufficient to allow the \code{print}
+statement to be used on it directly. This will avoid the need to explicitly
+convert non string objects to a string before being output.
+
+\begin{verbatim}
+<!--#python exec="
+print >> filter, len('HELLO')
+" -->
+\end{verbatim}
+
+\section{Scope of Global Data\label{ssi-data-scope}}
+
+Multiple instances of 'eval' or 'exec' code blocks may be used within the
+one page. Any changes to or creation of global data which is performed
+within one code block will be reflected in any following code blocks.
+Global data constitutes variables as well as module imports, function and
+class definitions.
+
+\begin{verbatim}
+<!--#python exec="
+import cgi, time, os
+def _escape(object):
+    return cgi.escape(str(object))
+now = time.time() 
+" -->
+<html>
+<body>
+<pre>
+<!--#python eval="_escape(time.asctime(time.localtime(now)))"-->
+
+<!--#python exec="
+keys = os.environ.keys()
+keys.sort()
+for key in keys:
+    print >> filter, _escape(key),
+    print >> filter, '=',
+    print >> filter, _escape(repr(os.environ.get(key)))
+" -->
+</pre>
+</body>
+</html>
+\end{verbatim}
+
+The lifetime of any global data is for the current request only. If data
+must persist between requests, it must reside in external modules and as
+necessary be protected against multithreaded access in the event that a
+multithreaded Apache MPM is used.
+
+\section{Pre-propulating Globals\label{ssi-globals}}
+
+Any Python code which appears within the page has to be compiled each time
+the page is accessed before it is executed. In other words, the compiled
+code is not cached between requests. To limit such recompilation and to
+avoid duplication of common code amongst many pages, it is preferable to
+pre-populate the global data from within a mod_python handler prior to the
+page being processed.
+
+In most cases, a fixup handler would be used for this purpose. For this to
+work, first need to configure Apache so that it knows to call the fixup
+handler.
+
+\begin{verbatim}
+PythonFixupHandler _handlers
+\end{verbatim}
+
+The implementation of the fixup handler contained in \code{_handlers.py}
+then needs to create an instance of a Python dictionary, store that in the
+mod_python request object as \code{ssi_globals} and then populate that
+dictionary with any data to be available to the Python code executing
+within the page.
+
+\begin{verbatim}
+from mod_python import apache
+
+import cgi, time
+
+def _escape(object):
+    return cgi.escape(str(object))
+
+def _header(filter):
+    print >> filter, '...'
+
+def _footer(filter):
+    print >> filter, '...'
+
+def fixuphandler(req):
+    req.ssi_globals = {}
+    req.ssi_globals['time'] = time
+    req.ssi_globals['_escape'] = _escape
+    req.ssi_globals['_header'] = _header
+    req.ssi_globals['_footer'] = _footer
+    return apache.OK
+\end{verbatim}
+
+This is most useful where it is necessary to insert common information such
+as headers, footers or menu panes which are dynamically generated into many
+pages.
+
+\begin{verbatim}
+<!--#python exec="
+now = time.time()
+" -->
+<html>
+<body>
+<!--#python exec="_header(filter)" -->
+<pre>
+<!--#python eval="_escape(time.asctime(time.localtime(now)))"-->
+</pre>
+<!--#python exec="_footer(filter)" -->
+</body>
+</html>
+\end{verbatim}
+
+\section{Conditional Expressions\label{ssi-conditionals}}
+
+SSI allows for some programmability in its own right through the use of
+conditional expressions. The structure of this conditional construct is:
+
+\begin{verbatim}
+<!--#if expr="test_condition" -->
+<!--#elif expr="test_condition" -->
+<!--#else -->
+<!--#endif -->
+\end{verbatim}
+
+A test condition can be any sort of logical comparison, either comparing
+values to one another, or testing the 'truth' of a particular value.
+
+The source of variables used in conditional expressions is distinct from
+the set of global data used by the Python code executed within a page.
+Instead, the variables are sourced from the \code{subprocess_env} table
+object contained within the request object. The values of these variables
+can be set from within a page using the SSI 'set' directive, or by a range
+of other Apache directives within the Apache configuration files such as
+\code{BrowserMatchNoCase} and \code{SetEnvIf}.
+
+To set these variables from within a mod_python handler, the
+\code{subprocess_env} table object would be manipulated directly through
+the request object.
+
+\begin{verbatim}
+from mod_python import apache
+
+def fixuphandler(req):
+    debug = req.get_config().get('PythonDebug', '0')
+    req.subprocess_env['DEBUG'] = debug
+    return apache.OK
+\end{verbatim}
+
+If being done from within Python code contained within the page itself, the
+request object would first have to be accessed via the filter object.
+
+\begin{verbatim}
+<!--#python exec="
+debug = filter.req.get_config().get('PythonDebug', '0')
+filter.req.subprocess_env['DEBUG'] = debug
+" -->
+<html>
+<body>
+<!--#if expr="${DEBUG} != 0" -->
+DEBUG ENABLED
+<!--#else -->
+DEBUG DISABLED
+<!--#endif -->
+</body>
+</html>
+\end{verbatim}
+
+\section{Enabling INCLUDES Filter\label{ssi-output-filter}}
+
+SSI is traditionally enabled using the \code{AddOutputFilter} directive in
+the Apache configuration files. Normally this would be where the request
+mapped to a static file.
+
+\begin{verbatim}
+AddOutputFilter INCLUDES .shtml
+\end{verbatim}
+
+When mod_python is being used, the ability to dynamically enable output
+filters for the current request can instead be used. This could be done
+just for where the request maps to a static file, but may just as easily be
+carried out where the content of a response is generated dynamically. In
+either case, to enable SSI for the current request, the
+\code{add_output_filter()} method of the mod_python request object would be
+used.
+
+\begin{verbatim}
+from mod_python import apache
+
+def fixuphandler(req):
+    req.add_output_filter('INCLUDES')
+    return apache.OK
+\end{verbatim}
+
 \chapter{Standard Handlers\label{handlers}}
 
 \section{Publisher Handler\label{hand-pub}}