diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 00000000..0b3f7c77 --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,3 @@ + +See LICENSE file. + diff --git a/CREDITS b/CREDITS new file mode 100644 index 00000000..3551b892 --- /dev/null +++ b/CREDITS @@ -0,0 +1,84 @@ + +The following is a list of people who have contributed to the +development of mod_python. + +Anyone who has contributed code or otherwise made contributions that were +constructive to the development of the project may have his name listed +here. Note that the decision on whether or not a name goes on this list is +initially taken by me (grisha@modpython.org) and that I can be wrong. So +if you feel that you should be credited as well, or if you feel that you +should not be listed, please e-mail me. + +The names are listed alphabetically by last name. + +Ron Alford + +Richard Barrett + +Gary Benson + +Stéphane Bidoul + +Gregory Bond + +Graham Dumpleton + +Justin Erenkrantz + +David Fraser + +Jim Gallacher + +Damjan Georgievski + +James Gessling + +Bob Ippolito + +Indrek Järve + +Mads Kiilerich + +Jørgen Frøjk Kjærsgaard + +Nicolas Lehuen + +Miguel Marques + +Thom May + +Robin Munn + +Brendan O'Connor + +Barry Pearce + +Barry Pederson + +Sean Reifschneider + +Conrad Steenberg + +Sean Treadway + +Chris Trengove + +Jarkko Torppa + +Ville Skyttä + +Greg Stein + +Dr. L.A. Timochouk + +Gregory Trubetskoy + +Sean True + +Sebastian Tusk + +Enrique Vaamonde + +Dave Wallace + + diff --git a/Doc/Makefile.in b/Doc/Makefile.in new file mode 100644 index 00000000..0ce52c45 --- /dev/null +++ b/Doc/Makefile.in @@ -0,0 +1,173 @@ + # Copyright 2004 Apache Software Foundation + # + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. + # + # Originally developed by Gregory Trubetskoy. + # + # + # Makefile for mod_python documentation + # --------------------------------- + # + # See also the README file. + # + +# You need to set this manually +# or ./configure --with-python-src=path/to/python/src +PYTHON_SRC=@PYTHON_SRC@ + +# This is the *documentation* release, and is used to construct the file +# names of the downloadable tarballs. +RELEASE= 2.7 + +MKHOWTO= $(PYTHON_SRC)/Doc/tools/mkhowto + +# These must be declared phony since there +# are directories with matching names: +.PHONY: html + +# This can be changed to a4 +PAPER= letter + +MPFILES= modpython.tex \ + copyright.tex \ + modpython1.tex \ + modpython2.tex \ + modpython3.tex \ + modpython5.tex \ + modpython6.tex \ + appendixa.tex \ + appendixb.tex + +# this target pukes if we don't have PYTHON_SRC set +src_set: + @if test -z "$(PYTHON_SRC)"; then \ + echo; \ + echo "Please edit Makefile and set PYTHON_SRC to where Python sources are."; \ + echo; \ + exit 1; \ + fi + +# Main target +all: pdf + +dvi: $(MPFILES) src_set + $(MKHOWTO) --dvi modpython.tex + +pdf: $(MPFILES) src_set + $(MKHOWTO) --pdf --$(PAPER) modpython.tex + +ps: $(MPFILES) src_set + $(MKHOWTO) --ps --$(PAPER) modpython.tex + +html: $(MPFILES) src_set + $(MKHOWTO) --html modpython.tex + mkdir -p modpython/icons + cp $(PYTHON_SRC)/Doc/html/icons/* modpython/icons/ + rm -f modpython/modpython.how +# the iconserver option of mkhowto is broken since it writes +# it to the end if the init_file where they aren't useful anymore, +# so we work around it: + for f in `find modpython -type f`; do \ + cat $$f | sed s/\.\.\\/icons/icons/g > $${f}2; \ + mv $${f}2 $$f; \ + done + +world: ps pdf html tarballs + +# Release packaging targets: + +pdf-$(PAPER)-$(RELEASE).tgz: pdf + tar cf - *.pdf | gzip -9 >$@ + +pdf-$(PAPER)-$(RELEASE).tar.bz2: pdf + tar cf - *.pdf | bzip2 -9 >$@ + +pdf-$(PAPER)-$(RELEASE).zip: pdf + rm -f $@ + zip -q -9 $@ *.pdf + +postscript-$(PAPER)-$(RELEASE).tar.bz2: ps + tar cf - *.ps | bzip2 -9 >$@ + +postscript-$(PAPER)-$(RELEASE).tgz: ps + tar cf - *.ps | gzip -9 >$@ + +postscript-$(PAPER)-$(RELEASE).zip: ps + rm -f $@ + zip -q -9 $@ *.ps + +html-$(RELEASE).tgz: html + tar cf - modpython | gzip -9 >$@ + +html-$(RELEASE).tar.bz2: html + tar cf - modpython | bzip2 -9 >$@ + +html-$(RELEASE).zip: html + rm -f $@ + zip -q -9 $@ modpython + +# convenience targets: + +tarhtml: html-$(RELEASE).tgz +tarps: postscript-$(PAPER)-$(RELEASE).tgz +tarpdf: pdf-$(PAPER)-$(RELEASE).tgz + +tarballs: tarpdf tarps tarhtml + +ziphtml: html-$(RELEASE).zip +zipps: postscript-$(PAPER)-$(RELEASE).zip +zippdf: pdf-$(PAPER)-$(RELEASE).zip + +zips: zippdf zipps ziphtml + +bziphtml: html-$(RELEASE).tar.bz2 +bzipps: postscript-$(PAPER)-$(RELEASE).tar.bz2 +bzippdf: pdf-$(PAPER)-$(RELEASE).tar.bz2 + +bzips: bzippdf bzipps bziphtml + + +# Housekeeping targets + +# Remove temporary files; all except the following: +# - sources: .tex, .bib, .sty, *.cls +# - useful results: .dvi, .pdf, .ps, .texi, .info +clean: + rm -f *~ *.aux *.idx *.ilg *.ind *.log *.toc *.bkm *.syn *.pla api.tex + +# Remove temporaries as well as final products +clobber: clean + rm -rf modpython + rm -f html-$(RELEASE).tgz + rm -f pdf-$(RELEASE).tgz postscript-$(RELEASE).tgz + rm -f html-$(RELEASE).zip + rm -f pdf-$(RELEASE).zip postscript-$(RELEASE).zip + +realclean: clobber +distclean: clobber + rm -f Makefile + +# HTML in the doc directory +dist: version html + rm -rf ../doc-html + mv modpython ../doc-html + +# Version substitution +version: ../src/include/mpversion.h + DATE="`date +'%B %d, %Y'`"; \ + VERSION="`awk '/MPV_STRING/ {print $$3}' ../src/include/mpversion.h`"; \ + VERSION="`echo $$VERSION | sed s/\\"//g`"; \ + cat modpython.tex | sed "s/\\\release.*/\\\release\{$$VERSION\}/" >modpython.tex2; \ + cat modpython.tex2 | sed s/\\date.*/\\date\{"$$DATE"\}/ >modpython.tex + + diff --git a/Doc/README b/Doc/README new file mode 100644 index 00000000..1e203610 --- /dev/null +++ b/Doc/README @@ -0,0 +1,25 @@ + +This directory contains the mod_python documentation sources. + +If you're looking for documentation, go to the ../doc-html +directory, or http://www.modpython.org/. + +This directory is mainly for LaTeX geeks. + +In order for anything here to be functional, you must have +configured mod_python with the --with-python option. + +You also need to have all the necessary tools installed, see +"Documenting Python" by Fred L. Drake. + +If everything is in place, you should be able to generate PDF, +HTML, DVI as well as Postscript file by simply typing one +of the following commands: + +make pdf +make html +make dvi +make ps + +Good Luck! + diff --git a/Doc/appendixa.tex b/Doc/appendixa.tex new file mode 100644 index 00000000..7d125b0d --- /dev/null +++ b/Doc/appendixa.tex @@ -0,0 +1,143 @@ +\chapter{Windows Installation\label{app-wininst}} +\indexii{windows}{installation} + +Notes originally created by Enrique Vaamonde \email{evaamo@loquesea.com} + +\emph{Your mileage may vary with these instructions} + +You need to have the following packages properly installed and +configured in your system: + +\begin{itemize} + +\item +Python 1.5.2 or 2.0 +\item +Apache 1.3 +\item +Winzip 6.x or later. + +\end{itemize} + + +You need to download both the mod_python.dll and the mod_python-x.tgz +(where x is the version number) files from the main page. Once you +have all the things above mentioned we're good to go. + +\begin{enumerate} + +\item +Installing mod_python libraries + +\begin{itemize} + +\item +Use Winzip to extract the distribution file (mod_python-x.tgz) into a +temporary folder (i.e \code{C:\e temp}): + +\item +NOTE: If Winzip shows this warning "Archive contains one file, should +Winzip decompress it to a temporary folder?" just click on Yes, the +content of the file should appear in Winzip right after. + +\item +Select all the files in Winzip and click on the Extract button, then +type-in the path or just browse your way to the temporary folder and +click extract. + +\item +Open your Windows Explorer and locate the temporary folder where you +extracted the distribution file, you should have a new folder in your +temporary folder (\code{C:\e temp\e mod_python-x}). + +\item +Move (or just drag \& drop) the mod_python-x folder into the Python lib +folder (i.e \code{C:\e Program Files\e Python\e lib}). + +\item +Move the files in the folder lib inside the mod_python folder +(\code{C:\e Program Files\e Python\e lib\e mod_python-x\e lib\e mod_python}) to the +\code{C:\e Program Files\e Python\e lib\e mod_python} folder. It's safe to delete +these folders we just emptied. + +\end{itemize} + +\item +Integrating it with Apache + + +Once the distribution file is correctly extracted and later moved into +the Python directory, it's time to modify your Apache configuration +(httpd.conf) and integrate the server with mod_python. These are a few +steps we must do first: + +\begin{itemize} + +\item +Locate the file mod_python.dll that you downloaded before and move it +to Apache's modules folder (i.e \code{C:\e Program Files\e Apache Group\e Apache\e modules}). + +\item +Go to the Apache configuration folder (i.e \code{C:\e Program Files\e Apache Group\e Apache\e conf\e }) and edit the httpd.conf file. + +Add the following line in the section "Dynamic Shared Object (DSO) +Support" of the httpd.conf file: + +\begin{verbatim} +LoadModule python_module modules/mod_python.dll +\end{verbatim} + +\item +Add the following lines in the section ScriptAlias and CGI of the httpd.conf: + +\begin{verbatim} +/python"> + AddHandler mod_python .py + PythonHandler mptest + PythonDebug on + +\end{verbatim} + + +NOTE: Replace the above with the Document Root +you specified on the DocumentRoot directive in the Apache's httpd.conf +file. + +\item +Last, create a folder under your Document Root called python. + +\end{itemize} + +\item +Testing + +\begin{itemize} + +\item +Create a text file in the folder we created above and call it mptest.py +(you can use Notepad for this). + +\item +Insert the following lines and save the file (Make sure it gets saved +with the .py extension): + +\begin{verbatim} +from mod_python import apache + +def handler(req): + req.content_type = "text/plain" + req.write("Hello World!") + return apache.OK +\end{verbatim} + +\item +Make sure Apache is running (or launch it!) and then point your +browser to the URL referring to the mptest.py, you should see "Hello +World!". + +\end{itemize} +\end{enumerate} + +That's it, you're ready to roll!! If you don't see the "Hello World!" +message, the next section is for you. + diff --git a/Doc/appendixb.tex b/Doc/appendixb.tex new file mode 100644 index 00000000..cc5fd963 --- /dev/null +++ b/Doc/appendixb.tex @@ -0,0 +1,136 @@ +\chapter{VMS installation\label{app-vnsinst}} + +\indexii{VMS}{installation} + +\begin{verbatim} + +How to build and install mod_python on a VMS system + +James Gessling Fri, 3 Nov 2000 + +This assumes apache and python already installed successfully. I tested +Compaq's CSWS version and 1.3.12 version's of Apache. Python was 1.5.2 from +http://decus.decus.de/~zessin/python. + +0) download current release (wrote this for 2.6.3) from www.modpython.org. + +1) create directories on a VMS system something like: + +dka0:[mod_python.src.include] + +2) put the .c files in src, the .h in include + +3) Cut the script off the end of this file, save it in the src directory. +Edit as necessary and use it to compile and link mod_python.exe. Sorry, +I didn't make much effort to make it very sophisticated. + +4) Under your python lib directory, add a subdirectory [.mod_python]. + +For example: dka100:[python.python-1_5_2.lib] + +5) Populate this subdirectory with mod_python .py files. +This allows for module importing like: + + import mod_python.apache + +which will find apache.py +\end{verbatim} +\begin{verbatim} +6) Edit apache$root:[conf]httpd.conf to add line: + + Include /apache$root/conf/mod_python.conf + +(typically at the end of the file) + +7) create apache$root:[conf]mod_python.conf containing: + +############################################################################ +## +# Mod_Python config +############################################################################ +## +# +# Load the dynamic MOD_PYTHON module +# note pythonpath must be in python list literal format +# +LoadModule PYTHON_MODULE modules/mod_python.exe + + + AddHandler mod_python .py + PythonHandler mptest + PythonDebug On + PythonPath +"['/dka100/python/python-1_5_2/lib','/dka100/python/python-1_5_2/ +vms/tools','/apache$root/htdocs/python']" + +# + +8) put mod_python.exe into apache$common:[modules] so it can be found and +loaded. (create the directory if required). + +9) fire up the web server with @sys$startup:apache$startup + +10) Create a file mptest.py in a python subdirectory of your document root, +Typically apache$common:[htdocs.python]. Like this: + + from mod_python import apache + + def handler(req): + req.write("Hello World!") + return apache.OK + +( watch your indenting, as usual ) + +11) point browser to: http://node.place.com/python/mptest.py + +12) enjoy "hello world" +\end{verbatim} +\begin{verbatim} +$! build script, edit as needed to match the directories where your +$! files are located. Note /nowarning on cc, this is +$! required because of a #define clash between apache +$! and python. If not used, the .exe is marked as +$! having compilation warnings and won't load. Apache +$! should already have been started to create apache$httpd_shr +$! logical name, Running the apache server with the -X flag +$! as an interactive process can be used for debugging if +$! necessary. +$ set noon +$ library/create mod_python_lib +$ cc :== cc /nowarning/prefix=all/include=(dka100:[python.python-1_5_2],- + dka100:[python.python-1_5_2.include],- + dka0:[],- + dka200:[apache.apache.src.include],- + dka200:[apache.apache.src.os.openvms]) +$ cc _apachemodule +$ library/insert mod_python_lib _apachemodule +$ cc connobject +$ library/insert mod_python_lib connobject +$ cc mod_python +$ cc requestobject +$ library/insert mod_python_lib requestobject +$ cc serverobject +$ library/insert mod_python_lib serverobject +$ cc tableobject +$ library/insert mod_python_lib tableobject +$ cc util +$ library/insert mod_python_lib util +$! mod_python +$ link/share/sysexe mod_python,sys$input/opt +SYMBOL_VECTOR=(PYTHON_MODULE=DATA) +mod_python_lib/lib +apache$httpd_shr/share +dka100:[python.python-1_5_2.vms.o_alpha]python_d00/lib +dka100:[python.python-1_5_2.vms.o_alpha]modules_d00/lib +dka100:[python.python-1_5_2.vms.o_alpha]vms_macro_d00/lib +dka100:[python.python-1_5_2.vms.o_alpha]objects_d00/lib +dka100:[python.python-1_5_2.vms.o_alpha]parser_d00/lib +dka100:[python.python-1_5_2.vms.o_alpha]vms_d00/lib +dka100:[python.python-1_5_2.vms.o_alpha]modules_d00/lib +dka100:[python.python-1_5_2.vms.o_alpha]vms_macro_d00/lib +dka100:[python.python-1_5_2.vms.o_alpha]vms_d00/lib +case_sensitive=no +$! +$ exit + +\end{verbatim} \ No newline at end of file diff --git a/Doc/appendixc.tex b/Doc/appendixc.tex new file mode 100644 index 00000000..6518b66a --- /dev/null +++ b/Doc/appendixc.tex @@ -0,0 +1,257 @@ +\chapter{Changes from Version (3.2.8)\label{app-changes}} + +\indexii{Changes from}{version 3.2.8} + + New Features + + \begin{itemize} + \item + (\citetitle[http://issues.apache.org/jira/browse/MODPYTHON-78]{MODPYTHON-78}) + Added support for Apache 2.2. + \item + (\citetitle[http://issues.apache.org/jira/browse/MODPYTHON-94]{MODPYTHON-94}) + New \code{req.is_https()} and \code{req.ssl_var_lookup()} methods. + These communicate direct with the Apache mod_ssl module, allowing + it to be determined if the connection is using SSL/TLS and what the + values of internal ssl variables are. + \item + (\citetitle[http://issues.apache.org/jira/browse/MODPYTHON-137]{MODPYTHON-137}) + New \code{req.server.get_options()} method. This returns the subset + of Python options set at global scope within the Apache configuration. + That is, outside of the context of any VirtualHost, Location, Directory + or Files directives. + \item + (\citetitle[http://issues.apache.org/jira/browse/MODPYTHON-131]{MODPYTHON-131}) + The directory used for mutex locks can now be specified at + at compile time using \code{./configure --with-mutex-dir value} + or at run time with \code{PythonOption mod_python.mutex_directory value}. + \item + (\citetitle[http://issues.apache.org/jira/browse/MODPYTHON-145]{MODPYTHON-145}) + The number of mutex locks can now be specified at run time with + \code{PythonOption mod_python.mutex_locks value}. + \item + (\citetitle[http://issues.apache.org/jira/browse/MODPYTHON-172]{MODPYTHON-172}) + Fixed three memory leaks that were found in _apachemodule.parse_qsl, req.readlines + and util.cfgtree_walk. + \end{itemize} + + Improvements + + \begin{itemize} + \item + (\citetitle[http://issues.apache.org/jira/browse/MODPYTHON-77]{MODPYTHON-77}) + Third party C modules that use the simplified API for the Global + Interpreter Lock (GIL), as described in PEP 311, can now be used. The + only requirement is that such modules can only be used in the context + of the \samp{main_interpreter}. + \item + (\citetitle[http://issues.apache.org/jira/browse/MODPYTHON-119]{MODPYTHON-119}) + DbmSession unit test no longer uses the default directory for the dbm file, + so the test will not interfer with the user's current apache instance. + \item + (\citetitle[http://issues.apache.org/jira/browse/MODPYTHON-158]{MODPYTHON-158}) + Added additional debugging and logging output for where mod_python + cannot initialise itself properly due to Python or mod_python version + mismatches or missing Python module code files. + \end{itemize} + + Bug Fixes + + \begin{itemize} + \item + (\citetitle[http://issues.apache.org/jira/browse/MODPYTHON-122]{MODPYTHON-122}) + Fixed configure problem when using bash 3.1.x. + \item + (\citetitle[http://issues.apache.org/jira/browse/MODPYTHON-173]{MODPYTHON-173}) + Fixed DbmSession to create db file with mode 0640. + \item + (\citetitle[http://issues.apache.org/jira/browse/MODPYTHON-84]{MODPYTHON-84}) + Fixed request.sendfile() bug for symlinked files on Win32. + \end{itemize} + +\chapter{Changes from Version (3.2.7)\label{app-changes}} + +\indexii{Changes from}{version 3.2.7} + + Security Fix + + \begin{itemize} + \item + (\citetitle[http://issues.apache.org/jira/browse/MODPYTHON-135]{MODPYTHON-135}) + + Fixed possible directory traversal attack in FileSession. The session + id is now checked to ensure it only contains valid characters. This + check is performed for all sessions derived from the BaseSession + class. + \end{itemize} + +\chapter{Changes from Version (3.1.4)\label{app-changes}} + +\indexii{Changes from}{version 3.1.4} + + New Features + + \begin{itemize} + \item + New \code{apache.register_cleanup()} method. + \item + New \code{apache.exists_config_define()} method. + \item + New file-based session manager class. + \item + Session cookie name can be specified. + \item + The maximum number of mutexes mod_python uses for session locking + can now be specifed at compile time using + \code{configure --with-max-locks}. + \item + New a version attribute in mod_python module. + \item + New test handler \code{testhandler.py} has been added. + \end{itemize} + + Improvements + + \begin{itemize} + \item + Autoreload of a module using \code{apache.import_module()} now works if + modification time for the module is different from the file. + Previously, the module was only reloaded if the the modification + time of the file was more recent. This allows for a more graceful + reload if a file with an older modification time needs to be + restored from backup. + \item + Fixed the publisher traversal security issue + \item + Objects hierarchy a la CherryPy can now be published. + \item + \code{mod_python.c} now logs reason for a 500 error + \item + Calls to \code{PyErr_Print} in \code{mod_python.c} are now followed by \code{fflush()} + \item + Using an empty value with PythonOption will unset a PythonOption key. + \item + \code{req.path_info} is now a read/write member. + \item + Improvements to FieldStorage allow uploading of large files. Uploaded + files are now streamed to disk, not to memory. + \item + Path to flex is now discovered at configuration time or can be + specifed using \code{configure --with-flex=/path/to/flex}. + \item + \code{sys.argv} is now initialized to \code{["mod_python"]} so that modules + like numarray and pychart can work properly. + \end{itemize} + + Bug Fixes + + \begin{itemize} + \item + Fixed memory leak which resulted from circular references starting + from the request object. + \item + Fixed memory leak resulting from multiple PythonOption directives. + \item + Fixed Multiple/redundant interpreter creation problem. + \item + Cookie attributes with attribute names prefixed with + \$ are now ignored. See Section \ref{pyapi-cookie} for more + information. + \item + Bug in setting up of config_dir from Handler directives fixed. + \item + mod_python.publisher will now support modules with the same name + but in different directories + \item + Fixed continual reloading of modules problem + \item + Fixed big marshalled cookies error. + \item + Fixed mod_python.publisher extension handling + \item + mod_python.publisher default index file traversal + \item + mod_python.publisher loading wrong module and giving no + warning/error + \item + \code{apply_fs_data()} now works with "new style" objects + \item + File descriptor fd closed after \code{ap_send_fd()} in \code{req_sendfile()} + \item + Bug in mem_cleanup in MemorySession fixed. + \item + Fixed bug in \code{_apache._global_lock()} which could cause a segfault + if the lock index parameter is greater number of mutexes created + at mod_python startup. + \item + Fixed bug where \code{local_ip} and \code{local_host} in connection object + were returning \code{remote_ip} and \code{remote_host} instead + \item + Fixed install_dso Makefile rule so it only installs the dso, not the + python files + \item + Potential deadlock in psp cache handling fixed + \item + Fixed bug where sessions are used outside directive. + \item + Fixed compile problem on IRIX. \code{ln -s} requires both TARGET and LINK_NAME + on IRIX. ie. \code{ln -s TARGET LINK_NAME} + \item + Fixed \code{./configure} problem on SuSE Linux 9.2 (x86-64). Python libraries + are in lib64/ for this platform. + \item + Fixed \code{req.sendfile()} problem where \code{sendfile(filename)} sends the incorrect + number of bytes when filename is a symlink. + \item + Fixed problem where util.FieldStorage was not correctly checking the mime + types of POSTed entities + \item + Fixed \code{conn.local_addr} and \code{conn.remote_addr} for a better IPv6 support. + \item + Fixed \code{psp_parser.l} to properly escape \code{backslash-n}, \code{backslash-t} + and \code{backslash-r} character sequences. + \item + Fixed segfault bug when accessing some request object members + (allowed_methods, allowed_xmethods, content_languages) and some server + object members (names, wild_names). + \item + Fixed request.add_handler() segfault bug when adding a handler to an empty + handler list. + \item + Fixed PythonAutoReload directive so that AutoReload can be turned off. + \item + Fixed connection object read() bug on FreeBSD. + \item + Fixed potential buffer corruption bug in connection object read(). +\end{itemize} + +\chapter{Changes from Previous Major Version (2.x)\label{app-changes}} + +\indexii{Changes from}{version 2.x} + + \begin{itemize} + + \item + Mod_python 3.0 no longer works with Apache 1.3, only Apache 2.x is + supported. + \item + Mod_python no longer works with Python versions less than 2.2.1 + \item + Mod_python now supports Apache filters. + \item + Mod_python now supports Apache connection handlers. + \item + Request object supports internal_redirect(). + \item + Connection object has read(), readline() and write(). + \item + Server object has get_config(). + \item + \index{Httpdapy} \index{httpdapi} + Httpdapi handler has been deprecated. + \item + \index{ZPublisher} + Zpublisher handler has been deprecated. + \item + Username is now in req.user instead of req.connection.user + \end{itemize} diff --git a/Doc/copyright.tex b/Doc/copyright.tex new file mode 100644 index 00000000..4340bdbe --- /dev/null +++ b/Doc/copyright.tex @@ -0,0 +1,16 @@ +\centerline{\strong{Copyright \copyright\ 2004 Apache Software Foundation.}} + +Licensed under the Apache License, Version 2.0 (the ``License''); you +may not use this file except in compliance with the License. You may +obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an ``AS IS'' BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + + + diff --git a/Doc/modpython.tex b/Doc/modpython.tex new file mode 100644 index 00000000..b066da4f --- /dev/null +++ b/Doc/modpython.tex @@ -0,0 +1,67 @@ +\documentclass{manual} + +\title{Mod\_python Manual} + +\author{Gregory Trubetskoy} + +% Please at least include a long-lived email address; +% the rest is at your discretion. +\authoraddress{ + E-mail: \email{grisha@apache.org} +} + +% do not mess with the 2 lines below, they are written by make dist +\release{3.1.3} +\date{February 17, 2004} + +\makeindex % tell \index to actually write the .idx file +\makemodindex % If this contains a lot of module sections. + + +\begin{document} + +\maketitle + +% This makes the contents more accessible from the front page of the HTML. +\ifhtml +\chapter*{Front Matter\label{front}} +\fi + +\input{copyright} + +\begin{abstract} + +\noindent +Mod_python allows embedding Python within the Apache server for a considerable +boost in performance and added flexibility in designing web based +applications. + +This document aims to be the only necessary and authoritative source of +information about mod_python, usable as a comprehensive reference, a user guide +and a tutorial all-in-one. + +\begin{seealso} + \seetitle[http://www.python.org/] + {Python Language Web Site}{for information on the Python language} + \seetitle[http://httpd.apache.org/] + {Apache Server Web Site}{for information on the Apache server} +\end{seealso} + +\end{abstract} + +\tableofcontents + +\input{modpython1} % Introduction +\input{modpython2} % Installation +\input{modpython3} % Tutorial +\input{modpython4} % Python API +\input{modpython5} % Apache directives +\input{modpython6} % Handlers +\appendix +%\input{appendixa} % Windows Install +%\input{appendixb} % VMS Install +\input{appendixc} % Changes + +\input{modpython.ind} + +\end{document} diff --git a/Doc/modpython1.tex b/Doc/modpython1.tex new file mode 100644 index 00000000..bb466734 --- /dev/null +++ b/Doc/modpython1.tex @@ -0,0 +1,105 @@ +\chapter{Introduction\label{introduction}} + +\section{Performance\label{intr-performance}} + + One of the main advantages of mod_python is the increase in + performance over traditional CGI. Below are results of a very crude + test. The test was done on a 1.2GHz Pentium machine running Red Hat + Linux + 7.3. \citetitle[http://httpd.apache.org/docs-2.0/programs/ab.html]{Ab} + was used to poll 4 kinds of scripts, all of which imported the + standard cgi module (because this is how a typical Python cgi script + begins), then output a single word \samp{Hello!}. The results are + based on 10000 requests with concurrency of 1. + +\begin{verbatim} + + Standard CGI: 23 requests/s + Mod_python cgihandler: 385 requests/s + Mod_python publisher: 476 requests/s + Mod_python handler: 1203 requests/s + +\end{verbatim} + +\section{Flexibility\label{intr-flexibility}} + + Apache processes requests in phases (e.g. read the request, parse + headers, check access, etc.). These phases can be implemented by + functions called handlers. Traditionally, handlers are written in C + and compiled into Apache modules. Mod_python provides a way to + extend Apache functionality by writing Apache handlers in + Python. For a detailed description of the Apache request processing + process, see the \citetitle[http://dev.apache.org/API.html]{Apache + API Notes}, as well as the + \citetitle[http://www.modpython.org/python10/]{Mod_python - + Integrating Python with Apache} paper. + + To ease migration from CGI, a standard mod_python handler is + provided that simulates the CGI environment allowing a user to run + legacy scripts under mod_python with no changes to the code (in most + cases). + +\begin{seealso} + \seeurl{http://dev.apache.org/}{Apache Developer Resources} + \seeurl{http://www.modpython.org/python10/}{Mod_Python - Integrating Python with Apache, presented at Python 10} +\end{seealso} + +\section{History\label{intr-history}} + + Mod_python originates from a project called + \citetitle[http://www.ispol.com/home/grisha/httpdapy/]{Httpdapy} + (1997). For a long time Httpdapy was not called mod_python because + Httpdapy was not meant to be Apache-specific. Httpdapy was designed + to be cross-platform and in fact was initially written for the + Netscape server (back then it was called Nsapy (1997). + + This excerpt from the Httpdapy README file describes well the + challenges and the solution provided by embedding Python within the + HTTP server: + +\begin{verbatim} + +While developing my first WWW applications a few years back, I found +that using CGI for programs that need to connect to relational +databases (commercial or not) is too slow because every hit requires +loading of the interpreter executable which can be megabytes in size, +any database libraries that can themselves be pretty big, plus, the +database connection/authentication process carries a very significant +overhead because it involves things like DNS resolutions, encryption, +memory allocation, etc.. Under pressure to speed up the application, I +nearly gave up the idea of using Python for the project and started +researching other tools that claimed to specialize in www database +integration. I did not have any faith in MS's ASP; was quite +frustrated by Netscape LiveWire's slow performance and bugginess; Cold +Fusion seemed promising, but I soon learned that writing in html-like +tags makes programs as readable as assembly. Same is true for +PHP. Besides, I *really* wanted to write things in Python. + +Around the same time the Internet Programming With Python book came +out and the chapter describing how to embed Python within Netscape +server immediately caught my attention. I used the example in my +project, and developed an improved version of what I later called +Nsapy that compiled on both Windows NT and Solaris. + +Although Nsapy only worked with Netscape servers, it was a very +intelligent generic OO design that, in the spirit of Python, that lent +itself for easy portability to other web servers. + +Incidently, the popularity of Netscape's servers was taking a turn +south, and so I set out to port Nsapy to other servers starting with +the most popular one, Apache. And so from Nsapy was born Httpdapy. + +\end{verbatim} + + ...continuing this saga, yours truly later learned that writing + Httpdapy for every server is a task a little bigger and less + interesting than I originally imagined. + + Instead, it seemed like providing a Python counterpart to the + popular Perl Apache extension mod_perl that would give Python users + the same (or better) capability would be a much more exciting thing + to do. + + And so it was done. The first release of mod_python happened in May + of 2000. + diff --git a/Doc/modpython2.tex b/Doc/modpython2.tex new file mode 100644 index 00000000..87cbb676 --- /dev/null +++ b/Doc/modpython2.tex @@ -0,0 +1,460 @@ +\chapter{Installation\label{installation}} +\indexii{installation}{UNIX} +\indexii{mod_python}{mailing list} + +\begin{notice} + By far the best place to get help with installation and other issues + is the mod_python mailing list. Please take a moment to join the + mod_python mailing list by sending an e-mail with the word + \samp{subscribe} in the subject to + \email{mod_python-request@modpython.org}. +\end{notice} + +\section{Prerequisites\label{inst-prerequisites}} + +\begin{itemize} +\item + Python 2.2.1 or later. Earlier versions of Python will not work. +\item + Apache 2.0.47 or later (For Apache 1.3.x, use mod_python version 2.7.x). +\end{itemize} + +In order to compile mod_python you will need to have the include files +for both Apache and Python, as well as the Python library installed on +your system. If you installed Python and Apache from source, then you +already have everything needed. However, if you are using prepackaged +software (e.g. Red Hat Linux RPM, Debian, or Solaris packages from +sunsite, etc) then chances are, you have just the binaries and not the +sources on your system. Often, the Apache and Python include files and +libraries necessary to compile mod_python are part of separate +``development'' package. If you are not sure whether you have all the +necessary files, either compile and install Python and Apache from +source, or refer to the documentation for your system on how to get +the development packages. + +\section{Compiling\label{inst-compiling}} +\indexii{compiling}{mod_python} + +There are two ways in which modules can be compiled and linked to +Apache - statically, or as a DSO (Dynamic Shared Object). + +\dfn{DSO} is a more popular approach nowadays and is the recommended +one for mod_python. The module gets compiled as a shared library which +is dynamically loaded by the server at run time. + +The advantage of DSO is that a module can be installed without +recompiling Apache and used as needed. A more detailed description of +the Apache DSO mechanism is available at +\url{http://httpd.apache.org/docs-2.0/dso.html}. + +\emph{At this time only DSO is supported by mod_python.} + +\dfn{Static} linking is an older approach. With dynamic linking +available on most platforms it is used less and less. The main +drawback is that it entails recompiling Apache, which in many +instances is not a favorable option. + +\subsection{Running ./configure\label{inst-configure}} +\index{./configure} + +The \program{./configure} script will analyze your environment and create custom +Makefiles particular to your system. Aside from all the standard +autoconf stuff, \program{./configure} does the following: + +\begin{itemize} + +\item + \index{apxs} + \index{./configure!\longprogramopt{with-apxs}} + %\indexii{./configure}{\longprogramopt{with-apxs}} + Finds out whether a program called \program{apxs} is available. This + program is part of the standard Apache distribution, and is necessary + for DSO compilation. If apxs cannot be found in your \envvar{PATH} or in + \filenq{/usr/local/apache/bin}, DSO compilation will not be available. + + You can manually specify the location of apxs by using the + \longprogramopt{with-apxs} option, e.g.: + + \begin{verbatim} + $ ./configure --with-apxs=/usr/local/apache/bin/apxs + \end{verbatim} + %$ keep emacs happy + + It is recommended that you specify this option. + +\item + \index{libpython.a} + Checks your Python version and attempts to figure out where + \program{libpython} is by looking at various parameters compiled into + your Python binary. By default, it will use the \program{python} + program found in your \envvar{PATH}. + + \index{./configure!\longprogramopt{with-python}} + %\indexii{./configure}{\longprogramopt{with-python}} + If the first Python binary in the path is not suitable or not the one + desired for mod_python, you can specify an alternative location with the + \longprogramopt{with-python} option, e.g: + + \begin{verbatim} + $ ./configure --with-python=/usr/local/bin/python2.3 + \end{verbatim} + %$ keep emacs happy + +\item + \index{./configure!\longprogramopt{with-mutex-dir}} + %\indexii{./configure}{\longprogramopt{with-mutex-dir}} + Sets the directory for the apache mutex locks. The default is + \filenq{/tmp}. The directory must exist and be writable by the + owner of the apache process. + + Use \longprogramopt{with-mutex-dir} option, e.g: + + \begin{verbatim} + $ ./configure --with-mutex-dir=/var/run/mod_python + \end{verbatim} + + The mutex directory can also be specified in using a + \citetitle[dir-other-po.html]{PythonOption} directive. + See \citetitle[inst-apacheconfig.html]{Configuring Apache}. + + \emph{Back ported from version 3.3.0} + +\item + \index{./configure!\longprogramopt{with-max-locks}} + Sets the maximum number of locks reserved by mod_python. + + The mutexes used for locking are a limited resource on some + systems. Increasing the maximum number of locks may increase performance + when using session locking. The default is 8. A reasonable number for + higher performance would be 32. + Use \longprogramopt{with-max-locks} option, e.g: + + \begin{verbatim} + $ ./configure --with-max-locks=32 + \end{verbatim} + + The number of locks can also be specified in using a + \citetitle[dir-other-po.html]{PythonOption} directive. + See \citetitle[inst-apacheconfig.html]{Configuring Apache}. + + New in version 3.2.0 + +\item + \index{flex} + Attempts to locate \program{flex} and determine its version. + If \program{flex} cannot be found in your \envvar{PATH} \program{configure} + will fail. If the wrong version is found \program{configure} will generate a warning. + You can generally ignore this warning unless you need to re-create + \filenq{src/psp_parser.c}. + + The parser used by psp (See \ref{pyapi-psp}) is written in C generated using + \program{flex}. This requires a reentrant version of \program{flex} which + at this time is 2.5.31. Most platforms however ship with version 2.5.4 + which is not suitable, so a pre-generated copy of psp_parser.c is included + with the source. If you do need to compile \filenq{src/psp_parser.c} you + must get the correct \program{flex} version. + + \index{./configure!\longprogramopt{with-flex}} + %\indexii{./configure}{\longprogramopt{with-flex}} + If the first flex binary in the path is not suitable or not the one desired + you can specify an alternative location with the \longprogramopt{with-flex} + option, e.g: + + \begin{verbatim} + $ ./configure --with-flex=/usr/local/bin/flex + \end{verbatim} + %$ keep emacs happy + + New in version 3.2.0 + +\item + \index{python-src} + The python source is required to build the mod_python documentation. + + \index{./configure!\longprogramopt{with-python-src}} + %\indexii{./configure}{\longprogramopt{with-python-src}} + You can safely ignore this option unless you want to build the the + documentation. If you want to build the documentation, specify the path + to your python source with the \longprogramopt{with-python-src} option, eg. + + \begin{verbatim} + $ ./configure --with-python-src=/usr/src/python2.3 + \end{verbatim} + %$ keep emacs happy + + New in version 3.2.0 + +\end{itemize} + +\subsection{Running make\label{inst-make}} + +\begin{itemize} + +\item + %If possible, the \program{./configure} script will default to DSO + %compilation, otherwise, it will default to static. To stay with + %whatever \program{./configure} decided, simply run + To start the build process, simply run + \begin{verbatim} + $ make + \end{verbatim} + %$ emacs happy + +\end{itemize} + +\section{Installing\label{inst-installing}} + +\subsection{Running make install\label{inst-makeinstall}} + +\begin{itemize} + +\item + This part of the installation needs to be done as root. + \begin{verbatim} + $ su + # make install + \end{verbatim} + %$ emacs happy + + \begin{itemize} + + \item + %For DSO, this will simply copy the library into your Apache \filenq{libexec} + This will simply copy the library into your Apache \filenq{libexec} + directory, where all the other modules are. + + %\item + %For static, it will copy some files into your Apache source tree. + + \item + Lastly, it will install the Python libraries in \filenq{site-packages} and + compile them. + + \end{itemize} + + \indexii{make targets}{install_py_lib} + %\indexii{make targets}{install_static} + \indexii{make targets}{install_dso} + \strong{NB:} If you wish to selectively install just the Python libraries + %the static library or the DSO (which may not always require superuser + or the DSO (which may not always require superuser + privileges), you can use the following \program{make} targets: + \programopt{install_py_lib} and \programopt{install_dso} + %\programopt{install_static} and \programopt{install_dso} + +\end{itemize} + +\subsection{Configuring Apache\label{inst-apacheconfig}} + +\begin{description} + +\item \strong{LoadModule} \indexii{LoadModule}{apache configuration} + + If you compiled mod_python as a DSO, you will need to tell Apache to + load the module by adding the following line in the Apache + configuration file, usually called \filenq{httpd.conf} or + \filenq{apache.conf}: + + \begin{verbatim} + LoadModule python_module libexec/mod_python.so + \end{verbatim} + + \index{mod_python.so} + The actual path to \program{mod_python.so} may vary, but make install + should report at the very end exactly where \program{mod_python.so} + was placed and how the \code{LoadModule} directive should appear. + +\item \strong{Mutex Directory} \indexii{mutex directory}{apache configuration} + + The default directory for mutex lock files is \filenq{/tmp}. The + default value can be be specified at compile time using + \citetitle[inst-configure.html]{./configure ----with-mutex-dir}. + + Alternatively this value can be overriden at apache startup using + a \citetitle[dir-other-po.html]{PythonOption}. + + \begin{verbatim} + PythonOption mod_python.mutex_directory "/tmp" + \end{verbatim} + + This may only be used in the server configuration context. + It will be ignored if used in a directory, virtual host, + htaccess or location context. The most logical place for this + directive in your apache configuration file is immediately + following the \strong{LoadModule} directive. + + \emph{Back ported from version 3.3.0} + +\item \strong{Mutex Locks} \indexii{apache configuration}{mutex locks} + + Mutexes are used in mod_python for session locking. The default + value is 8. + + On some systems the locking mechanism chosen uses valuable + system resources. Notably on RH 8 sysv ipc is used, which + by default provides only 128 semaphores system-wide. + On many other systems flock is used which may result in a relatively + large number of open files. + + The optimal number of necessary locks is not clear. + Increasing the maximum number of locks may increase performance + when using session locking. A reasonable number for + higher performance might be 32. + + The maximum number of locks can be specified at compile time + using \citetitle[inst-configure.html]{./configure ----with-max-locks}. + + Alternatively this value can be overriden at apache startup using + a \citetitle[dir-other-po.html]{PythonOption}. + + \begin{verbatim} + PythonOption mod_python.mutex_locks 8 + \end{verbatim} + + This may only be used in the server configuration context. + It will be ignored if used in a directory, virtual host, + htaccess or location context. The most logical place for this + directive in your apache configuration file is immediately + following the \strong{LoadModule} directive. + + \emph{Back ported from version 3.3.0} + +\end{description} + +\section{Testing\label{inst-testing}} + +\strong{Warning :} These instructions are meant to be followed if you are +using mod_python 3.x or later. If you are using mod_python 2.7.x (namely, +if you are using Apache 1.3.x), please refer to the proper documentation. + +\begin{enumerate} + +\item + Make some directory that would be visible on your web site, for + example, htdocs/test. + +\item + Add the following Apache directives, which can appear in either the + main server configuration file, or \filenq{.htaccess}. If you are + going to be using the \filenq{.htaccess} file, you will not need the + \code{} tag below (the directory then becomes the one in + which the \filenq{.htaccess} file is located), and you will need to + make sure the \code{AllowOverride} directive applicable to this + directory has at least \code{FileInfo} specified. (The default is + \code{None}, which will not work.) + % the above has been verified to be still true for Apache 2.0 + + \begin{verbatim} + + AddHandler mod_python .py + PythonHandler mptest + PythonDebug On + + \end{verbatim} + + (Substitute \filenq{/some/directory} above for something applicable to + your system, usually your Apache ServerRoot) + +\item + This redirects all requests for URLs ending in \filenq{.py} to the mod_python + handler. mod_python receives those requests and looks for an appropriate + PythonHandler to handle them. Here, there is a single PythonHandler + directive defining mptest as the python handler to use. We'll see next + how this python handler is defined. + +\item + At this time, if you made changes to the main configuration file, you + will need to restart Apache in order for the changes to take effect. + +\item + Edit \filenq{mptest.py} file in the \filenq{htdocs/test} directory so + that is has the following lines (be careful when cutting and pasting + from your browser, you may end up with incorrect indentation and a + syntax error): + + \begin{verbatim} + from mod_python import apache + + def handler(req): + req.content_type = 'text/plain' + req.write("Hello World!") + return apache.OK + \end{verbatim} + +\item + Point your browser to the URL referring to the \filenq{mptest.py}; + you should see \samp{Hello World!}. If you didn't - refer to the + troubleshooting section next. + +\item + Note that according to the configuration written above, you can + also point your browser to any URL ending in .py in the test directory. + You can for example point your browser to \filenq{/test/foobar.py} + and it will be handled by \filenq{mptest.py}. That's because you + explicitely set the handler to always be \filenq{mptest}, whatever the + requested file was. If you want to have many handler files named + \filenq{handler1.py}, \filenq{handler2.py} + and so on, and have them accessible on \filenq{/test/handler1.py}, + \filenq{/test/handler2.py}, etc., then you have to use a higher level + handler system such as the mod_python publisher (see \ref{tut-pub}), + mpservlets or Vampire. Those are just special mod_python handler + that know how to map requests to a dynamically loaded handler. + +\item + If everything worked well, move on to Chapter \ref{tutorial}, + \citetitle[tutorial.html]{Tutorial}. + +\end{enumerate} + +\begin{seealso} + \seeurl{http://home.comcast.net/~d.popowich/mpservlets}{mpservlets} + \seeurl{http://www.dscpl.com.au/projects/vampire}{Vampire} +\end{seealso} + +\section{Troubleshooting\label{inst-trouble}} + +There are a few things you can try to identify the problem: + +\begin{itemize} + +\item Carefully study the error output, if any. + +\item Check the server error log file, it may contain useful clues. + +\item Try running Apache from the command line in single process mode: + \begin{verbatim} + ./httpd -X + \end{verbatim} + This prevents it from backgrounding itself and may provide some useful + information. + +\item Beginning with mod_python 3.2.0, you can use the mod_python.testhandler + to diagnose your configuration. Add this to your \filenq{httpd.conf} file : + + \begin{verbatim} + + SetHandler mod_python + PythonHandler mod_python.testhandler + + \end{verbatim} + + Now point your browser to the \filenq{/mpinfo} URL + (e.g. \filenq{http://localhost/mpinfo}) and note down the information given. + This will help you reporting your problem to the mod_python list. + +\item + Ask on the mod_python list. Make sure to provide specifics such as: + + \begin{itemize} + + \item Mod_python version. + \item Your operating system type, name and version. + \item Your Python version, and any unusual compilation options. + \item Your Apache version. + \item Relevant parts of the Apache config, .htaccess. + \item Relevant parts of the Python code. + + \end{itemize} + +\end{itemize} + diff --git a/Doc/modpython3.tex b/Doc/modpython3.tex new file mode 100644 index 00000000..89d0e135 --- /dev/null +++ b/Doc/modpython3.tex @@ -0,0 +1,470 @@ +\chapter{Tutorial\label{tutorial}} + +\begin{flushright} + \emph{So how can I make this work?} +\end{flushright} + +\emph{This is a quick guide to getting started with mod_python + programming once you have it installed. This is \textbf{not} an + installation manual!} + +\emph{It is also highly recommended to read (at least the top part of) + Section \ref{pythonapi}, \citetitle[pythonapi.html]{Python API} after + completing this tutorial.} + +\section{A Quick Start with the Publisher Handler\label{tut-pub}} + +This section provides a quick overview of the Publisher handler for +those who would like to get started without getting into too much +detail. A more thorough explanation of how mod_python handlers work +and what a handler actually is follows on in the later sections of the +tutorial. + +The \code{publisher} handler is provided as one of the standard +mod_python handlers. To get the publisher handler working, you will +need the following lines in your config: + +\begin{verbatim} + AddHandler mod_python .py + PythonHandler mod_python.publisher + PythonDebug On +\end{verbatim} + +The following example will demonstrate a simple feedback form. The +form will ask for the name, e-mail address and a comment and construct +an e-mail to the webmaster using the information submitted by the +user. This simple application consists of two files: +\filenq{form.html} - the form to collect the data, and +\filenq{form.py} - the target of the form's action. + +Here is the html for the form: + +\begin{verbatim} + + Please provide feedback below: +

+

+ + Name:
+ Email:
+ Comment:
+ + +
+ +\end{verbatim} + +Note the \code{action} element of the \code{
} tag points to +\code{form.py/email}. We are going to create a file called +\filenq{form.py}, like this: + +\begin{verbatim} +import smtplib + +WEBMASTER = "webmaster" # webmaster e-mail +SMTP_SERVER = "localhost" # your SMTP server + +def email(req, name, email, comment): + + # make sure the user provided all the parameters + if not (name and email and comment): + return "A required parameter is missing, \ + please go back and correct the error" + + # create the message text + msg = """\ +From: %s +Subject: feedback +To: %s + +I have the following comment: + +%s + +Thank You, + +%s + +""" % (email, WEBMASTER, comment, name) + + # send it out + conn = smtplib.SMTP(SMTP_SERVER) + conn.sendmail(email, [WEBMASTER], msg) + conn.quit() + + # provide feedback to the user + s = """\ + + +Dear %s,
+Thank You for your kind comments, we +will get back to you shortly. + +""" % name + + return s +\end{verbatim} + +When the user clicks the Submit button, the publisher handler will +load the \function{email} function in the \module{form} module, +passing it the form fields as keyword arguments. It will also pass the +request object as \code{req}. + +Note that you do not have to have \code{req} as one of the arguments +if you do not need it. The publisher handler is smart enough to pass +your function only those arguments that it will accept. + +The data is sent back to the browser via the return value of the +function. + +Even though the Publisher handler simplifies mod_python programming a +great deal, all the power of mod_python is still available to this +program, since it has access to the request object. You can do all the +same things you can do with a ``native'' mod_python handler, e.g. set +custom headers via \code{req.headers_out}, return errors by raising +\exception{apache.SERVER_ERROR} exceptions, write or read directly to +and from the client via \method{req.write()} and \method{req.read()}, +etc. + +Read Section \ref{hand-pub} \citetitle[hand-pub.html]{Publisher Handler} +for more information on the publisher handler. + +\section{Quick Overview of how Apache Handles Requests\label{tut-overview}} + +If you would like delve in deeper into the functionality of +mod_python, you need to understand what a handler is. + +Apache processes requests in \dfn{phases}. For example, the first +phase may be to authenticate the user, the next phase to verify +whether that user is allowed to see a particular file, then (next +phase) read the file and send it to the client. A typical static file +request involves three phases: (1) translate the requested URI to a +file location (2) read the file and send it to the client, then (3) +log the request. Exactly which phases are processed and how varies +greatly and depends on the configuration. + +A \dfn{handler} is a function that processes one phase. There may be +more than one handler available to process a particular phase, in +which case they are called by Apache in sequence. For each of the +phases, there is a default Apache handler (most of which by default +perform only very basic functions or do nothing), and then there are +additional handlers provided by Apache modules, such as mod_python. + +Mod_python provides every possible handler to Apache. Mod_python +handlers by default do not perform any function, unless specifically +told so by a configuration directive. These directives begin with +\samp{Python} and end with \samp{Handler} +(e.g. \code{PythonAuthenHandler}) and associate a phase with a Python +function. So the main function of mod_python is to act as a dispatcher +between Apache handlers and Python functions written by a developer +like you. + +The most commonly used handler is \code{PythonHandler}. It handles the +phase of the request during which the actual content is +provided. Because it has no name, it is sometimes referred to as as +\dfn{generic} handler. The default Apache action for this handler is +to read the file and send it to the client. Most applications you will +write will override this one handler. To see all the possible +handlers, refer to Section \ref{directives}, +\citetitle[directives.html]{Apache Directives}. + +\section{So what Exactly does Mod-python do?\label{tut-what-it-do}} + +Let's pretend we have the following configuration: +\begin{verbatim} + + AddHandler mod_python .py + PythonHandler myscript + PythonDebug On + +\end{verbatim} + +\strong{NB:} \filenq{/mywebdir} is an absolute physical path. + +And let's say that we have a python program (Windows users: substitute +forward slashes for backslashes) \file{/mywedir/myscript.py} that looks like +this: + +\begin{verbatim} +from mod_python import apache + +def handler(req): + + req.content_type = "text/plain" + req.write("Hello World!") + + return apache.OK +\end{verbatim} + +Here is what's going to happen: The \code{AddHandler} directive tells +Apache that any request for any file ending with \file{.py} in the +\file{/mywebdir} directory or a subdirectory thereof needs to be +processed by mod_python. The \samp{PythonHandler myscript} directive +tells mod_python to process the generic handler using the +\code{myscript} script. The \samp{PythonDebug On} directive instructs +mod_python in case of an Python error to send error output to the +client (in addition to the logs), very useful during development. + +When a request comes in, Apache starts stepping through its request +processing phases calling handlers in mod_python. The mod_python +handlers check whether a directive for that handler was specified in +the configuration. (Remember, it acts as a dispatcher.) In our +example, no action will be taken by mod_python for all handlers except +for the generic handler. When we get to the generic handler, +mod_python will notice \samp{PythonHandler myscript} directive and do +the following: + +\begin{enumerate} + +\item + If not already done, prepend the directory in which the + \code{PythonHandler} directive was found to \code{sys.path}. + +\item + Attempt to import a module by name \code{myscript}. (Note that if + \code{myscript} was in a subdirectory of the directory where + \code{PythonHandler} was specified, then the import would not work + because said subdirectory would not be in the \code{sys.path}. One + way around this is to use package notation, e.g. \samp{PythonHandler + subdir.myscript}.) + +\item + Look for a function called \code{handler} in \code{myscript}. + +\item + Call the function, passing it a request object. (More on what a + request object is later) + +\item + At this point we're inside the script: + + \begin{itemize} + + \item + \begin{verbatim} +from mod_python import apache + \end{verbatim} + + This imports the apache module which provides us the interface to + Apache. With a few rare exceptions, every mod_python program will have + this line. + + \item + \begin{verbatim} +def handler(req): + \end{verbatim} + + \index{handler} This is our \dfn{handler} function declaration. It + is called \samp{handler} because mod_python takes the name of the + directive, converts it to lower case and removes the word + \samp{python}. Thus \samp{PythonHandler} becomes + \samp{handler}. You could name it something else, and specify it + explicitly in the directive using \samp{::}. For example, if the + handler function was called \samp{spam}, then the directive would + be \samp{PythonHandler myscript::spam}. + + Note that a handler must take one argument - the request + object. The request object is an object that provides all of the + information about this particular request - such as the IP of + client, the headers, the URI, etc. The communication back to the + client is also done via the request object, i.e. there is no + ``response'' object. + + \item + \begin{verbatim} +req.content_type = "text/plain" + \end{verbatim} + + This sets the content type to \samp{text/plain}. The default is usually + \samp{text/html}, but since our handler doesn't produce any html, + \samp{text/plain} is more appropriate. + \strong{Important:} you should \strong{always} make sure this is set + \strong{before} any call to \samp{req.write}. When you first call + \samp{req.write}, the response HTTP header is sent to the client and all + subsequent changes to the content type (or other HTTP headers) are simply + lost. + + \item + \begin{verbatim} +req.write("Hello World!") + \end{verbatim} + + This writes the \samp{Hello World!} string to the client. (Did I really + have to explain this one?) + + \item + \begin{verbatim} +return apache.OK + \end{verbatim} + + This tells Apache that everything went OK and that the request has + been processed. If things did not go OK, that line could be return + \constant{apache.HTTP_INTERNAL_SERVER_ERROR} or return + \constant{apache.HTTP_FORBIDDEN}. When things do not go OK, Apache + will log the error and generate an error message for the client. + \end{itemize} +\end{enumerate} + +\strong{Some food for thought:} If you were paying attention, you +noticed that the text above didn't specify that in order for the +handler code to be executed, the URL needs to refer to +\filenq{myscript.py}. The only requirement was that it refers to a +\filenq{.py} file. In fact the name of the file doesn't matter, and +the file referred to in the URL doesn't have to exist. So, given the +above configuration, \samp{http://myserver/mywebdir/myscript.py} and +\samp{http://myserver/mywebdir/montypython.py} would give the exact +same result. The important thing to understand here is that a handler +augments the server behaviour when processing a specific type of file, +not an individual file. + +\emph{At this point, if you didn't understand the above paragraph, go + back and read it again, until you do.} + +\section{Now something More Complicated - Authentication\label{tut-more-complicated}} + +Now that you know how to write a primitive handler, let's try +something more complicated. + +Let's say we want to password-protect this directory. We want the +login to be \samp{spam}, and the password to be \samp{eggs}. + +First, we need to tell Apache to call our \emph{authentication} +handler when authentication is needed. We do this by adding the +\code{PythonAuthenHandler}. So now our config looks like this: + +\begin{verbatim} + + AddHandler mod_python .py + PythonHandler myscript + PythonAuthenHandler myscript + PythonDebug On + +\end{verbatim} + +Notice that the same script is specified for two different +handlers. This is fine, because if you remember, mod_python will look +for different functions within that script for the different handlers. + +Next, we need to tell Apache that we are using Basic HTTP +authentication, and only valid users are allowed (this is fairly basic +Apache stuff, so we're not going to go into details here). Our config +looks like this now: + +\begin{verbatim} + + AddHandler mod_python .py + PythonHandler myscript + PythonAuthenHandler myscript + PythonDebug On + AuthType Basic + AuthName "Restricted Area" + require valid-user + +\end{verbatim} + +Now we need to write an authentication handler function in +\file{myscript.py}. A basic authentication handler would look like +this: + +\begin{verbatim} + +from mod_python import apache + +def authenhandler(req): + + pw = req.get_basic_auth_pw() + user = req.user + + if user == "spam" and pw == "eggs": + return apache.OK + else: + return apache.HTTP_UNAUTHORIZED +\end{verbatim} + +Let's look at this line by line: + +\begin{itemize} + +\item + \begin{verbatim} +def authenhandler(req): + \end{verbatim} + + This is the handler function declaration. This one is called + \code{authenhandler} because, as we already described above, + mod_python takes the name of the directive + (\code{PythonAuthenHandler}), drops the word \samp{Python} and converts + it lower case. + +\item + \begin{verbatim} + pw = req.get_basic_auth_pw() + \end{verbatim} + + This is how we obtain the password. The basic HTTP authentication + transmits the password in base64 encoded form to make it a little + bit less obvious. This function decodes the password and returns it + as a string. Note that we have to call this function before obtaining + the user name. + +\item + \begin{verbatim} + user = req.user + \end{verbatim} + + This is how you obtain the username that the user entered. + +\item + \begin{verbatim} + if user == "spam" and pw == "eggs": + return apache.OK + \end{verbatim} + + We compare the values provided by the user, and if they are what we + were expecting, we tell Apache to go ahead and proceed by returning + \constant{apache.OK}. Apache will then consider this phase of the + request complete, and proceed to the next phase. (Which in this case + would be \function{handler()} if it's a \code{.py} file). + +\item + \begin{verbatim} + else: + return apache.HTTP_UNAUTHORIZED + \end{verbatim} + + Else, we tell Apache to return \constant{HTTP_UNAUTHORIZED} to the + client, which usually causes the browser to pop a dialog box asking + for username and password. + +\end{itemize} + +\section{Your Own 404 Handler\label{tut-404-handler}} + +In some cases, you may wish to return a 404 (\constant{HTTP_NOT_FOUND}) or +other non-200 result from your handler. There is a trick here. if you +return \constant{HTTP_NOT_FOUND} from your handler, Apache will handle +rendering an error page. This can be problematic if you wish your handler +to render it's own error page. + +In this case, you need to set \code{req.status = apache.HTTP_NOT_FOUND}, +render your page, and then \code{return(apache.OK)}: + +\begin{verbatim} + from mod_python import apache + + def handler(req): + if req.filename[-17:] == 'apache-error.html': + # make Apache report an error and render the error page + return(apache.HTTP_NOT_FOUND) + if req.filename[-18:] == 'handler-error.html': + # use our own error page + req.status = apache.HTTP_NOT_FOUND + pagebuffer = 'Page not here. Page left, not know where gone.' + else: + # use the contents of a file + pagebuffer = open(req.filename, 'r').read() + + # fall through from the latter two above + req.write(pagebuffer) + return(apache.OK) +\end{verbatim} diff --git a/Doc/modpython4.tex b/Doc/modpython4.tex new file mode 100644 index 00000000..287752bd --- /dev/null +++ b/Doc/modpython4.tex @@ -0,0 +1,2683 @@ + +\chapter{Python API\label{pythonapi}} + +\section{Multiple Interpreters\label{pyapi-interps}} + +When working with mod_python, it is important to be aware of a feature +of Python that is normally not used when using the language for +writing scripts to be run from command line. This feature is not +available from within Python itself and can only be accessed through +the \citetitle[http://www.python.org/doc/current/api/api.html]{C +language API}. + +Python C API provides the ability to create \dfn{subinterpreters}. A +more detailed description of a subinterpreter is given in the +documentation for the +\citetitle[http://www.python.org/doc/current/api/initialization.html]{\cfunction{Py_NewInterpreter()}} +function. For this discussion, it will suffice to say that each +subinterpreter has its own separate namespace, not accessible from +other subinterpreters. Subinterpreters are very useful to make sure +that separate programs running under the same Apache server do not +interfere with one another. + +At server start-up or mod_python initialization time, mod_python +initializes an interpreter called \dfn{main} interpreter. The main +interpreter contains a dictionary of subinterpreters. Initially, this +dictionary is empty. With every request, as needed, subinterpreters +are created, and references to them are stored in this dictionary. The +dictionary is keyed on a string, also known as \emph{interpreter +name}. This name can be any string. The main interpreter is named +\samp{main_interpreter}. The way all other interpreters are named can +be controlled by \code{PythonInterp*} directives. Default behaviour is +to name interpreters using the Apache virtual server name +(\code{ServerName} directive). This means that all scripts in the same +virtual server execute in the same subinterpreter, but scripts in +different virtual servers execute in different subinterpreters with +completely separate namespaces. +\citetitle[dir-other-ipd.html]{\code{PythonInterpPerDirectory}} and +\citetitle[dir-other-ipdv.html]{\code{PythonInterpPerDirective}} +directives alter the naming convention to use the absolute path of the +directory being accessed, or the directory in which the +\code{Python*Handler} was encountered, respectively. +\citetitle[dir-other-pi.html]{\code{PythonInterpreter}} can be used to +force the interpreter name to a specific string overriding any naming +conventions. + +Once created, a subinterpreter will be reused for subsequent requests. +It is never destroyed and exists until the Apache process dies. + +You can find out the name of the interpreter under which you're +running by peeking at \member{req.interpreter}. + +Note that if any third party module is being used which has a C code +component that uses the simplified API for access to the Global +Interpreter Lock (GIL) for Python extension modules, then the interpreter +name must be forcibly set to be \samp{main_interpreter}. This is necessary +as such a module will only work correctly if run within the context of +the first Python interpreter created by the process. If not forced to +run under the \samp{main_interpreter}, a range of Python errors can arise, +each typically referring to code being run in \emph{restricted mode}. + +\begin{seealso} + \seetitle[http://www.python.org/doc/current/api/api.html] + {Python C Language API}{Python C Language API} + \seetitle[http://www.python.org/peps/pep-0311.html] + {PEP 0311 - Simplified Global Interpreter Lock Acquisition for Extensions}{PEP 0311 - Simplified Global Interpreter Lock Acquisition for Extensions} +\end{seealso} + +\section{Overview of a Request Handler\label{pyapi-handler}} +\indexii{request}{handler} + +A \dfn{handler} is a function that processes a particular phase of a +request. Apache processes requests in phases - read the request, +process headers, provide content, etc. For every phase, it will call +handlers, provided by either the Apache core or one of its modules, +such as mod_python which passes control to functions provided by the +user and written in Python. A handler written in Python is not any +different from a handler written in C, and follows these rules: + +\index{req} \indexii{request}{object} A handler function will always +be passed a reference to a request object. (Throughout this manual, +the request object is often referred to by the \code{req} variable.) + +Every handler can return: + +\begin{itemize} + +\item + \constant{apache.OK}, meaning this phase of the request was handled by this + handler and no errors occurred. + +\item + \constant{apache.DECLINED}, meaning this handler has not handled this + phase of the request to completion and Apache needs to look for + another handler in subsequent modules. + +\item + \constant{apache.\emph{HTTP_ERROR}}, meaning an HTTP error occurred. + \var{HTTP_ERROR} can be any of the following: + + \begin{verbatim} + HTTP_CONTINUE = 100 + HTTP_SWITCHING_PROTOCOLS = 101 + HTTP_PROCESSING = 102 + HTTP_OK = 200 + HTTP_CREATED = 201 + HTTP_ACCEPTED = 202 + HTTP_NON_AUTHORITATIVE = 203 + HTTP_NO_CONTENT = 204 + HTTP_RESET_CONTENT = 205 + HTTP_PARTIAL_CONTENT = 206 + HTTP_MULTI_STATUS = 207 + HTTP_MULTIPLE_CHOICES = 300 + HTTP_MOVED_PERMANENTLY = 301 + HTTP_MOVED_TEMPORARILY = 302 + HTTP_SEE_OTHER = 303 + HTTP_NOT_MODIFIED = 304 + HTTP_USE_PROXY = 305 + HTTP_TEMPORARY_REDIRECT = 307 + HTTP_BAD_REQUEST = 400 + HTTP_UNAUTHORIZED = 401 + HTTP_PAYMENT_REQUIRED = 402 + HTTP_FORBIDDEN = 403 + HTTP_NOT_FOUND = 404 + HTTP_METHOD_NOT_ALLOWED = 405 + HTTP_NOT_ACCEPTABLE = 406 + HTTP_PROXY_AUTHENTICATION_REQUIRED= 407 + HTTP_REQUEST_TIME_OUT = 408 + HTTP_CONFLICT = 409 + HTTP_GONE = 410 + HTTP_LENGTH_REQUIRED = 411 + HTTP_PRECONDITION_FAILED = 412 + HTTP_REQUEST_ENTITY_TOO_LARGE = 413 + HTTP_REQUEST_URI_TOO_LARGE = 414 + HTTP_UNSUPPORTED_MEDIA_TYPE = 415 + HTTP_RANGE_NOT_SATISFIABLE = 416 + HTTP_EXPECTATION_FAILED = 417 + HTTP_UNPROCESSABLE_ENTITY = 422 + HTTP_LOCKED = 423 + HTTP_FAILED_DEPENDENCY = 424 + HTTP_INTERNAL_SERVER_ERROR = 500 + HTTP_NOT_IMPLEMENTED = 501 + HTTP_BAD_GATEWAY = 502 + HTTP_SERVICE_UNAVAILABLE = 503 + HTTP_GATEWAY_TIME_OUT = 504 + HTTP_VERSION_NOT_SUPPORTED = 505 + HTTP_VARIANT_ALSO_VARIES = 506 + HTTP_INSUFFICIENT_STORAGE = 507 + HTTP_NOT_EXTENDED = 510 + \end{verbatim} + +\end{itemize} + +As an alternative to \emph{returning} an HTTP error code, handlers can +signal an error by \emph{raising} the \constant{apache.SERVER_RETURN} +exception, and providing an HTTP error code as the exception value, +e.g. + +\begin{verbatim} +raise apache.SERVER_RETURN, apache.HTTP_FORBIDDEN +\end{verbatim} + +Handlers can send content to the client using the \method{req.write()} +method. + +Client data, such as POST requests, can be read by using the +\method{req.read()} function. + +\begin{notice} + The directory of the Apache \code{Python*Handler} + directive in effect is prepended to the \code{sys.path}. If the + directive was specified in a server config file outside any + \code{}, then the directory is unknown and not prepended. +\end{notice} + +An example of a minimalistic handler might be: + +\begin{verbatim} +from mod_python import apache + +def requesthandler(req): + req.content_type = "text/plain" + req.write("Hello World!") + return apache.OK +\end{verbatim} + +\section{Overview of a Filter Handler\label{pyapi-filter}} +\indexii{filter}{handler} + +A \dfn{filter handler} is a function that can alter the input or the +output of the server. There are two kinds of filters - \dfn{input} and +\dfn{output} that apply to input from the client and output to the +client respectively. + +At this time mod_python supports only request-level filters, meaning +that only the body of HTTP request or response can be filtered. Apache +provides support for connection-level filters, which will be supported +in the future. + +A filter handler receives a \emph{filter} object as its argument. The +request object is available as well via \code{filter.req}, but all +writing and reading should be done via the filter's object read and +write methods. + +Filters need to be closed when a read operation returns None +(indicating End-Of-Stream). + +The return value of a filter is ignored. Filters cannot decline +processing like handlers, but the same effect can be achieved +by using the \method{filter.pass_on()} method. + +Filters must first be registered using \code{PythonInputFilter} or +\code{PythonOutputFilter}, then added using the Apache +\code{Add/SetInputFilter} or \code{Add/SetOutputFilter} directives. + +Here is an example of how to specify an output filter, it tells the +server that all .py files should processed by CAPITALIZE filter: + +\begin{verbatim} + PythonOutputFilter capitalize CAPITALIZE + AddOutputFilter CAPITALIZE .py +\end{verbatim} + +And here is what the code for the \file{capitalize.py} might look +like: + +\begin{verbatim} +from mod_python import apache + +def outputfilter(filter): + + s = filter.read() + while s: + filter.write(s.upper()) + s = filter.read() + + if s is None: + filter.close() + +\end{verbatim} + +When writing filters, keep in mind that a filter will be called any +time anything upstream requests an IO operation, and the filter has no +control over the amount of data passed through it and no notion of +where in the request processing it is called. For example, within a +single request, a filter may be called once or five times, and there +is no way for the filter to know beforehand that the request is over +and which of calls is last or first for this request, thought +encounter of an EOS (None returned from a read operation) is a fairly +strong indication of an end of a request. + +Also note that filters may end up being called recursively in +subrequests. To avoid the data being altered more than once, always +make sure you are not in a subrequest by examining the \code{req.main} +value. + +For more information on filters, see +\citetitle[http://httpd.apache.org/docs-2.0/developer/filters.html]{http://httpd.apache.org/docs-2.0/developer/filters.html}. + +\section{Overview of a Connection Handler\label{pyapi-conn}} +\indexii{connection}{handler} + +A \dfn{connection handler} handles the connection, starting almost +immediately from the point the TCP connection to the server was +made. + +Unlike HTTP handlers, connection handlers receive a \emph{connection} +object as an argument. + +Connection handlers can be used to implement protocols. Here is an +example of a simple echo server: + +Apache configuration: +\begin{verbatim} + PythonConnectionHandler echo +\end{verbatim} + +Contents of \filenq{echo.py} file: + +\begin{verbatim} +from mod_python import apache + +def connectionhandler(conn): + + while 1: + conn.write(conn.readline()) + + return apache.OK +\end{verbatim} + +\section{\module{apache} -- Access to Apache Internals.} +\declaremodule[apache]{extension}{apache} +\modulesynopsis{Access to Apache Internals} +\moduleauthor{Gregory Trubetskoy}{grisha@apache.org} + +The Python interface to Apache internals is contained in a module +appropriately named \module{apache}, located inside the +\module{mod_python} package. This module provides some important +objects that map to Apache internal structures, as well as some useful +functions, all documented below. (The request object also provides an +interface to Apache internals, it is covered in its own section of +this manual.) + +\indexii{_apache}{module} The \module{apache} module can only be +imported by a script running under mod_python. This is because it +depends on a built-in module \module{_apache} provided by +mod_python. + +It is best imported like this: + +\begin{verbatim} +from mod_python import apache +\end{verbatim} + +\module{mod_python.apache} module defines the following functions and +objects. For a more in-depth look at Apache internals, see the +\citetitle[http://httpd.apache.org/dev/]{Apache Developer page} + +\subsection{Functions\label{pyapi-apmeth}} + +\begin{funcdesc}{log_error}{message\optional{, level, server}} + An interface to the Apache \code{ap_log_error()} + function. \var{message} is a string with the error message, + \var{level} is one of the following flags constants: + + \begin{verbatim} + APLOG_EMERG + APLOG_ALERT + APLOG_CRIT + APLOG_ERR + APLOG_WARNING + APLOG_NOTICE + APLOG_INFO + APLOG_DEBUG + APLOG_NOERRNO + \end{verbatim} + + \var{server} is a reference to a \member{req.server} object. If + \var{server} is not specified, then the error will be logged to the + default error log, otherwise it will be written to the error log for + the appropriate virtual server. When \var{server} is not specified, + the setting of LogLevel does not apply, the LogLevel is dictated by + an httpd compile-time default, usually \code{warn}. + + If you have a reference to a request object available, consider using + \method{req.log_error} instead, it will prepend request-specific + information such as the source IP of the request to the log entry. +\end{funcdesc} + +\begin{funcdesc}{import_module}{module_name\optional{, autoreload=1, log=0, path=None}} + This function can be used to import modules taking advantage of + mod_python's internal mechanism which reloads modules automatically + if they have changed since last import. + + \var{module_name} is a string containing the module name (it can + contain dots, e.g. \code{mypackage.mymodule}); \var{autoreload} + indicates whether the module should be reloaded if it has changed since + last import; when \var{log} is true, a message will be written to + the logs when a module is reloaded; \var{path} allows restricting + modules to specific paths. + + Example: + + \begin{verbatim} + from mod_python import apache + mymodule = apache.import_module('mymodule', log=1) + \end{verbatim} +\end{funcdesc} + +\begin{funcdesc}{allow_methods}{\optional{*args}} + A convenience function to set values in \member{req.allowed}. + \member{req.allowed} is a bitmask that is used to construct the + \samp{Allow:} header. It should be set before returning a + \code{HTTP_NOT_IMPLEMENTED} error. + + Arguments can be one or more of the following: + \begin{verbatim} + M_GET + M_PUT + M_POST + M_DELETE + M_CONNECT + M_OPTIONS + M_TRACE + M_PATCH + M_PROPFIND + M_PROPPATCH + M_MKCOL + M_COPY + M_MOVE + M_LOCK + M_UNLOCK + M_VERSION_CONTROL + M_CHECKOUT + M_UNCHECKOUT + M_CHECKIN + M_UPDATE + M_LABEL + M_REPORT + M_MKWORKSPACE + M_MKACTIVITY + M_BASELINE_CONTROL + M_MERGE + M_INVALID + \end{verbatim} + +\end{funcdesc} + +\begin{funcdesc}{exists_config_define}{name} + This function returns True if the Apache server was launched + with the definition with the given \var{name}. This means + that you can test whether Apache was launched with the \code{-DFOOBAR} + parameter by calling \code{apache.exists_config_define('FOOBAR')}. +\end{funcdesc} + +\begin{methoddesc}[server]{register_cleanup}{handler\optional{, data}} + Registers a cleanup. Equivalent to \function{req.register_cleanup()} + or \function{req.server.register_cleanup()}, except that a server or request + object is not required. +\end{methoddesc} + +\begin{funcdesc}{config_tree}{} + Returns the server-level configuration tree. This tree does not + include directives from .htaccess files. This is a \emph{copy} of + the tree, modifying it has no effect on the actual configuration. +\end{funcdesc} + +\begin{funcdesc}{server_root}{} + Returns the value of ServerRoot. +\end{funcdesc} + +\begin{funcdesc}{make_table}{} + This function is obsolete and is an alias to \class{table} (see below). +\end{funcdesc} + +\begin{funcdesc}{mpm_query}{code} + Allows querying of the MPM for various parameters such as numbers of + processes and threads. The return value is one of three constants: + \begin{verbatim} +AP_MPMQ_NOT_SUPPORTED = 0 # This value specifies whether + # an MPM is capable of + # threading or forking. +AP_MPMQ_STATIC = 1 # This value specifies whether + # an MPM is using a static # of + # threads or daemons. +AP_MPMQ_DYNAMIC = 2 # This value specifies whether + # an MPM is using a dynamic # of + # threads or daemons. + \end{verbatim} + + The \var{code} argument must be one of the following: + \begin{verbatim} +AP_MPMQ_MAX_DAEMON_USED = 1 # Max # of daemons used so far +AP_MPMQ_IS_THREADED = 2 # MPM can do threading +AP_MPMQ_IS_FORKED = 3 # MPM can do forking +AP_MPMQ_HARD_LIMIT_DAEMONS = 4 # The compiled max # daemons +AP_MPMQ_HARD_LIMIT_THREADS = 5 # The compiled max # threads +AP_MPMQ_MAX_THREADS = 6 # # of threads/child by config +AP_MPMQ_MIN_SPARE_DAEMONS = 7 # Min # of spare daemons +AP_MPMQ_MIN_SPARE_THREADS = 8 # Min # of spare threads +AP_MPMQ_MAX_SPARE_DAEMONS = 9 # Max # of spare daemons +AP_MPMQ_MAX_SPARE_THREADS = 10 # Max # of spare threads +AP_MPMQ_MAX_REQUESTS_DAEMON= 11 # Max # of requests per daemon +AP_MPMQ_MAX_DAEMONS = 12 # Max # of daemons by config + \end{verbatim} + +Example: + \begin{verbatim} +if apache.mpm_query(apache.AP_MPMQ_IS_THREADED): + # do something +else: + # do something else + \end{verbatim} +\end{funcdesc} + +\subsection{Table Object (mp_table)\obindex{table}\label{pyapi-mptable}} + +\index{table} +\begin{classdesc}{table}{\optional{mapping-or-sequence}} + Returns a new empty object of type \code{mp_table}. See Section + \ref{pyapi-mptable} for description of the table object. The + \var{mapping-or-sequence} will be used to provide initial values for + the table. + + The table object is a wrapper around the Apache APR table. The table + object behaves very much like a dictionary (including the Python 2.2 + features such as support of the \code{in} operator, etc.), with the + following differences: + + \begin{itemize} + \item + Both keys and values must be strings. + \item + Key lookups are case-insensitive. + \item + Duplicate keys are allowed (see \method{add()} below). When there is + more than one value for a key, a subscript operation returns a list. + \end{itemize} + + Much of the information that Apache uses is stored in tables. For + example, \member{req.headers_in} and \member{req.headers_out}. + + All the tables that mod_python provides inside the request + object are actual mappings to the Apache structures, so changing the + Python table also changes the underlying Apache table. + + In addition to normal dictionary-like behavior, the table object also + has the following method: + + \begin{methoddesc}[table]{add}{key, val} + \function{add()} allows for creating duplicate keys, which is useful + when multiple headers, such as \code{Set-Cookie:} are required. + \end{methoddesc} + + \versionadded{3.0} +\end{classdesc} + +\subsection{Request Object\index{request}\label{pyapi-mprequest}} + +The request object is a Python mapping to the Apache +\code{request_rec} structure. When a handler is invoked, it is always +passed a single argument - the request object. + +You can dynamically assign attributes to it as a way to communicate +between handlers. + +\subsubsection{Request Methods\label{pyapi-mprequest-meth}} + +\begin{methoddesc}[request]{add_common_vars}{} + Calls the Apache \cfunction{ap_add_common_vars()} function. After a + call to this method, \member{req.subprocess_env} will contain a + lot of CGI information. +\end{methoddesc} + +\begin{methoddesc}[request]{add_handler}{htype, handler\optional{, dir}} + + Allows dynamic handler registration. \var{htype} is a string + containing the name of any of the apache request (but not filter or + connection) handler directives, + e.g. \samp{PythonHandler}. \var{handler} is a string containing the + name of the module and the handler function. Optional \var{dir} is + a string containing the name of the directory to be added to the + pythonpath. If no directory is specified, then, if there is already + a handler of the same type specified, its directory is inherited, + otherwise the directory of the presently executing handler is + used. If there is a \code{PythonPath} directive in effect, then + \code{sys.path} will be set exactly according to it (no directories + added, the \var{dir} argument is ignored). + + A handler added this way only persists throughout the life of the + request. It is possible to register more handlers while inside the + handler of the same type. One has to be careful as to not to create + an infinite loop this way. + + Dynamic handler registration is a useful technique that allows the + code to dynamically decide what will happen next. A typical example + might be a \code{PythonAuthenHandler} that will assign different + \code{PythonHandlers} based on the authorization level, something + like: + + \begin{verbatim} +if manager: + req.add_handler("PythonHandler", "menu::admin") +else: + req.add_handler("PythonHandler", "menu::basic") + \end{verbatim} + + \begin{notice} + If you pass this function an invalid handler, an exception will be + generated at the time an attempt is made to find the handler. + \end{notice} +\end{methoddesc} + +\begin{methoddesc}[request]{allow_methods}{methods\optional{, reset}} + Adds methods to the \member{req.allowed_methods} list. This list + will be passed in \code{Allowed:} header if + \constant{HTTP_METHOD_NOT_ALLOWED} or \constant{HTTP_NOT_IMPLEMENTED} + is returned to the client. Note that Apache doesn't do anything to + restrict the methods, this list is only used to construct the + header. The actual method-restricting logic has to be provided in the + handler code. + + \var{methods} is a sequence of strings. If \var{reset} is 1, then + the list of methods is first cleared. +\end{methoddesc} + +\begin{methoddesc}[request]{document_root}{} + Returns DocumentRoot setting. +\end{methoddesc} + +\begin{methoddesc}[request]{get_basic_auth_pw}{} + Returns a string containing the password when Basic authentication is + used. +\end{methoddesc} + +\begin{methoddesc}[request]{get_config}{} + Returns a reference to the table object containing the mod_python + configuration in effect for this request except for + \code{Python*Handler} and \code{PythonOption} (The latter can be + obtained via \method{req.get_options()}. The table has directives as + keys, and their values, if any, as values. +\end{methoddesc} + +\begin{methoddesc}[request]{get_remote_host}{\optional{type, str_is_ip}} + + This method is used to determine remote client's DNS name or IP + number. The first call to this function may entail a DNS look up, but + subsequent calls will use the cached result from the first call. + + The optional \var{type} argument can specify the following: + + \begin{itemize} + + \item + \code{apache.REMOTE_HOST} Look up the DNS name. Return None if Apache + directive \code{HostNameLookups} is \code{off} or the hostname cannot + be determined. + + \item + \code{apache.REMOTE_NAME} \emph{(Default)} Return the DNS name if + possible, or the IP (as a string in dotted decimal notation) + otherwise. + + \item + \code{apache.REMOTE_NOLOOKUP} Don't perform a DNS lookup, return an + IP. Note: if a lookup was performed prior to this call, then the + cached host name is returned. + + \item + \code{apache.REMOTE_DOUBLE_REV} Force a double-reverse lookup. On + failure, return None. + + \end{itemize} + + If \var{str_is_ip} is \code{None} or unspecified, then the return + value is a string representing the DNS name or IP address. + + If the optional \var{str_is_ip} argument is not \code{None}, then the + return value is an \code{(address, str_is_ip)} tuple, where \var{str_is_ip} + is non-zero if \code{address} is an IP address string. + + On failure, \code{None} is returned. + +\end{methoddesc} + +\begin{methoddesc}[request]{get_options}{} + Returns a reference to the table object containing the options set by + the \code{PythonOption} directives. +\end{methoddesc} + +\begin{methoddesc}[request]{internal_redirect}{new_uri} + Internally redirects the request to the \var{new_uri}. \var{new_uri} + must be a string. + + The httpd server handles internal redirection by creating a new + request object and processing all request phases. Within an internal + redirect, \code{req.prev} will contain a reference to a request + object from which it was redirected. + +\end{methoddesc} + +\begin{methoddesc}[request]{is_https}{} + Returns non-zero if the connection is using SSL/TLS. Will always return + zero if the mod_ssl Apache module is not loaded. + + You can use this method during any request phase, unlike looking for + the \code{HTTPS} variable in the \code{subprocess_env} member dictionary. + This makes it possible to write an authentication or access handler + that makes decisions based upon whether SSL is being used. + + Note that this method will not determine the quality of the + encryption being used. For that you should call the \code{ssl_var_lookup} + method to get one of the \code{SSL_CIPHER*} variables. + +\end{methoddesc} + +\begin{methoddesc}{log_error}{message\optional{, level}} + An interface to the Apache \code{ap_log_rerror} + function. \var{message} is a string with the error message, + \var{level} is one of the following flags constants: + + \begin{verbatim} + APLOG_EMERG + APLOG_ALERT + APLOG_CRIT + APLOG_ERR + APLOG_WARNING + APLOG_NOTICE + APLOG_INFO + APLOG_DEBUG + APLOG_NOERRNO + \end{verbatim} + + If you need to write to log and do not have a reference to a request object, + use the \function{apache.log_error} function. +\end{methoddesc} + +\begin{methoddesc}[request]{meets_conditions}{} + Calls the Apache \cfunction{ap_meets_conditions()} function which + returns a status code. If \var{status} is \constant{apache.OK}, generate + the content of the response normally. If not, simply return \var{status}. + Note that \member{req.headers_out} should be set prior to calling this + function. The same goes for \member{req.status} if the status differs + from \constant{apache.OK}. + + Example: + \begin{verbatim} +... +r.headers_out['ETag'] = "1130794f-3774-4584-a4ea-0ab19e684268" +r.headers_out['Last-Modified'] = 'Wed, 23 Feb 2005 00:00:00 GMT' +r.headers_out['Expires'] = 'Mon, 18 Apr 2005 17:30:00 GMT' + +status = r.meets_conditions() +if status != apache.OK: + return status + +... do expensive generation of the response content ... +\end{verbatim} + +\end{methoddesc} + + +\begin{methoddesc}[request]{requires}{} + + Returns a tuple of strings of arguments to \code{require} directive. + + For example, with the following apache configuration: + \begin{verbatim} +AuthType Basic +require user joe +require valid-user + \end{verbatim} + \method{requires()} would return \code{('user joe', 'valid-user')}. + +\end{methoddesc} + +\begin{methoddesc}[request]{read}{\optional{len}} + + Reads at most \var{len} bytes directly from the client, returning a + string with the data read. If the \var{len} argument is negative or + omitted, reads all data given by the client. + + This function is affected by the \code{Timeout} Apache configuration + directive. The read will be aborted and an \exception{IOError} + raised if the \code{Timeout} is reached while reading client data. + + This function relies on the client providing the \code{Content-length} + header. Absence of the \code{Content-length} header will be treated as + if \code{Content-length: 0} was supplied. + + Incorrect \code{Content-length} may cause the function to try to read + more data than available, which will make the function block until a + \code{Timeout} is reached. + +\end{methoddesc} + +\begin{methoddesc}[request]{readline}{\optional{len}} + Like \function{read()} but reads until end of line. + + \begin{notice} + In accordance with the HTTP specification, most clients will + be terminating lines with \samp{\e r\e n} rather + than simply \samp{\e n}. + \end{notice} + +\end{methoddesc} + +\begin{methoddesc}[request]{readlines}{\optional{sizehint}} + Reads all or up to \var{sizehint} bytes of lines using + \method{readline} and returns a list of the lines read. +\end{methoddesc} + +\begin{methoddesc}[request]{register_cleanup}{callable\optional{, data}} + + Registers a cleanup. Argument \var{callable} can be any callable + object, the optional argument \var{data} can be any object (default is + \code{None}). At the very end of the request, just before the actual + request record is destroyed by Apache, \var{callable} will be called + with one argument, \var{data}. + + It is OK to pass the request object as data, but keep in mind that + when the cleanup is executed, the request processing is already + complete, so doing things like writing to the client is completely + pointless. + + If errors are encountered during cleanup processing, they should be in + error log, but otherwise will not affect request processing in any + way, which makes cleanup bugs sometimes hard to spot. + + If the server is shut down before the cleanup had a chance to run, + it's possible that it will not be executed. + +\end{methoddesc} + +\begin{methoddesc}[request]{sendfile}{path\optional{, offset, len}} + Sends \var{len} bytes of file \var{path} directly to the client, + starting at offset \var{offset} using the server's internal + API. \var{offset} defaults to 0, and \var{len} defaults to -1 (send + the entire file). + + Returns the number of bytes sent, or raises an IOError exception + on failure. + + This function provides the most efficient way to send a file to the + client. +\end{methoddesc} + +\begin{methoddesc}[request]{ssl_var_lookup}{var_name} + Looks up the value of the named SSL variable. This method queries + the mod_ssl Apache module directly, and may therefore be used in + early request phases (unlike using the \code{subprocess_env} member. + + If the mod_ssl Apache module is not loaded or the variable is not + found then \code{None} is returned. + + If you just want to know if a SSL or TLS connection is being used, + you may consider calling the \code{is_https} method instead. + + It is unfortunately not possible to get a list of all available + variables with the current mod_ssl implementation, so you must know + the name of the variable you want. Some of the potentially useful + ssl variables are listed below. For a complete list of variables + and a description of their values see the mod_ssl documentation. + + \begin{verbatim} + SSL_CIPHER + SSL_CLIENT_CERT + SSL_CLIENT_VERIFY + SSL_PROTOCOL + SSL_SESSION_ID + \end{verbatim} + + \begin{notice} + Not all SSL variables are defined or have useful values in every + request phase. Also use caution when relying on these values for + security purposes, as SSL or TLS protocol parameters can often be + renegotiated at any time during a request. + \end{notice} + +\end{methoddesc} + +\begin{methoddesc}[request]{write}{string\optional{, flush=1}} + Writes \var{string} directly to the client, then flushes the buffer, + unless flush is 0. +\end{methoddesc} + +\begin{methoddesc}[request]{flush}{} + Flushes the output buffer. +\end{methoddesc} + +\begin{methoddesc}[request]{set_content_length}{len} + Sets the value of \member{req.clength} and the \samp{Content-Length} + header to len. Note that after the headers have been sent out (which + happens just before the first byte of the body is written, + i.e. first call to \member{req.write()}), calling the method is + meaningless. +\end{methoddesc} + + +\subsubsection{Request Members\label{pyapi-mprequest-mem}} + +\begin{memberdesc}[request]{connection} + A \code{connection} object associated with this request. See + Connection Object below for details. + \emph{(Read-Only)} +\end{memberdesc} + +\begin{memberdesc}[request]{server} + A server object associate with this request. See Server Object below + for details. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{next} + If this is an internal redirect, the request object we redirect to. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{prev} + If this is an internal redirect, the request object we redirect from. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{main} + If this is a sub-request, pointer to the main request. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{the_request} + String containing the first line of the request. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{assbackwards} + Indicates an HTTP/0.9 ``simple'' request. This means that the + response will contain no headers, only the body. Although this + exists for backwards compatibility with obsolescent browsers, some + people have figred out that setting assbackwards to 1 can be a + useful technique when including part of the response from an + internal redirect to avoid headers being sent. +\end{memberdesc} + +\begin{memberdesc}[request]{proxyreq} + A proxy request: one of \constant{apache.PROXYREQ_*} values. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{header_only} + A boolean value indicating HEAD request, as opposed to GET. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{protocol} + Protocol, as given by the client, or \samp{HTTP/0.9}. Same as CGI \envvar{SERVER_PROTOCOL}. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{proto_num} + Integer. Number version of protocol; 1.1 = 1001 + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{hostname} + String. Host, as set by full URI or Host: header. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{request_time} + A long integer. When request started. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{status_line} + Status line. E.g. \samp{200 OK}. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{status} + Status. One of \constant{apache.HTTP_*} values. +\end{memberdesc} + +\begin{memberdesc}[request]{method} + A string containing the method - 'GET', 'HEAD', 'POST', etc. + Same as CGI \envvar{REQUEST_METHOD}. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{method_number} + Integer containing the method number. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{allowed} + Integer. A bitvector of the allowed methods. Used to construct the + Allowed: header when responding with + \constant{HTTP_METHOD_NOT_ALLOWED} or + \constant{HTTP_NOT_IMPLEMENTED}. This field is for Apache's internal + use, to set the Allowed: methods use \method{req.allow_methods()} + method, described in section \ref{pyapi-mprequest-meth}. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{allowed_xmethods} + Tuple. Allowed extension methods. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{allowed_methods} + Tuple. List of allowed methods. Used in relation with + \constant{METHOD_NOT_ALLOWED}. This member can be modified via \method{req.allow_methods()} + described in section \ref{pyapi-mprequest-meth}. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{sent_bodyct} + Integer. Byte count in stream is for body. (?) + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{bytes_sent} + Long integer. Number of bytes sent. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{mtime} + Long integer. Time the resource was last modified. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{chunked} + Boolean value indicating when sending chunked transfer-coding. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{range} + String. The \code{Range:} header. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{clength} + Long integer. The ``real'' content length. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{remaining} + Long integer. Bytes left to read. (Only makes sense inside a read + operation.) + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{read_length} + Long integer. Number of bytes read. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{read_body} + Integer. How the request body should be read. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{read_chunked} + Boolean. Read chunked transfer coding. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{expecting_100} + Boolean. Is client waiting for a 100 (\constant{HTTP_CONTINUE}) response. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{headers_in} + A table object containing headers sent by the client. +\end{memberdesc} + +\begin{memberdesc}[request]{headers_out} + A \code{table} object representing the headers to be sent to the + client. +\end{memberdesc} + +\begin{memberdesc}[request]{err_headers_out} + These headers get send with the error response, instead of + headers_out. +\end{memberdesc} + +\begin{memberdesc}[request]{subprocess_env} + A \code{table} object containing environment information typically usable for CGI. + You may have to call \member{req.add_common_vars()} first to fill in the information + you need. +\end{memberdesc} + +\begin{memberdesc}[request]{notes} + A \code{table} object that could be used to store miscellaneous + general purpose info that lives for as long as the request lives. If + you need to pass data between handlers, it's better to simply add + members to the request object than to use \member{notes}. +\end{memberdesc} + +\begin{memberdesc}[request]{phase} + The phase currently being being processed, e.g. \samp{PythonHandler}. + \emph{(Read-Only)} +\end{memberdesc} + +\begin{memberdesc}[request]{interpreter} + The name of the subinterpreter under which we're running. + \emph{(Read-Only)} +\end{memberdesc} + +\begin{memberdesc}[request]{content_type} + String. The content type. Mod_python maintains an internal flag + (\member{req._content_type_set}) to keep track of whether + \member{content_type} was set manually from within Python. The + publisher handler uses this flag in the following way: when + \member{content_type} isn't explicitly set, it attempts to guess the + content type by examining the first few bytes of the output. +\end{memberdesc} + +\begin{memberdesc}[request]{content_languages} + Tuple. List of strings representing the content languages. +\end{memberdesc} + +\begin{memberdesc}[request]{handler} + The name of the handler currently being processed. This is the handler + set by mod_mime, not the mod_python handler. In most cases it will be + "\samp{mod_python}. \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{content_encoding} + String. Content encoding. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{vlist_validator} + Integer. Variant list validator (if negotiated). + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{user} + If an authentication check is made, this will hold the user + name. Same as CGI \envvar{REMOTE_USER}. + \emph{(Read-Only}) + \begin{notice} + \method{req.get_basic_auth_pw()} must be called prior to using this value. + \end{notice} +\end{memberdesc} + +\begin{memberdesc}[request]{ap_auth_type} + Authentication type. Same as CGI \envvar{AUTH_TYPE}. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{no_cache} + Boolean. No cache if true. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{no_local_copy} + Boolean. No local copy exists. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{unparsed_uri} + The URI without any parsing performed. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{uri} + The path portion of the URI. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{filename} + String. File name being requested. +\end{memberdesc} + +\begin{memberdesc}[request]{canonical_filename} + String. The true filename (\member{req.filename} is canonicalized if + they don't match). \emph{(Read-Only)} +\end{memberdesc} + +\begin{memberdesc}[request]{path_info} + String. What follows after the file name, but is before query args, if + anything. Same as CGI \envvar{PATH_INFO}. +\end{memberdesc} + +\begin{memberdesc}[request]{args} + String. Same as CGI \envvar{QUERY_ARGS}. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{finfo} + Tuple. A file information structure, analogous to POSIX stat, + describing the file pointed to by the URI. \code{(mode, ino, + dev, nlink, uid, gid, size, atime, mtime, ctime, fname, + name)}. The \code{apache} module defines a set of \constant{FINFO_*} + constants that should be used to access elements of this + tuple. Example: + \begin{verbatim} +fname = req.finfo[apache.FINFO_FNAME] + \end{verbatim} + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{parsed_uri} + Tuple. The URI broken down into pieces. + \code{(scheme, hostinfo, user, password, hostname, port, path, query, fragment)}. + The \code{apache} module defines a set of \constant{URI_*} constants that + should be used to access elements of this tuple. Example: + \begin{verbatim} +fname = req.parsed_uri[apache.URI_PATH] + \end{verbatim} + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{used_path_info} + Flag to accept or reject path_info on current request. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[request]{eos_sent} + Boolean. EOS bucket sent. + \emph{(Read-Only}) +\end{memberdesc} + +\subsection{Connection Object (mp_conn)\obindex{connection}\label{pyapi-mpconn}} + +The connection object is a Python mapping to the Apache conn_rec +structure. + +\subsubsection{Connection Methods\label{pyapi-mpconn-meth}} + +\begin{methoddesc}[connection]{read}{\optional{length}} + Reads at most \var{length} bytes from the client. The read blocks + indefinitely until there is at least one byte to read. If length is + -1, keep reading until the socket is closed from the other end (This + is known as \code{EXHAUSTIVE} mode in the http server code). + + This method should only be used inside \emph{Connection Handlers}. + + \begin{notice} + The behaviour of this method has changed since version 3.0.3. In + 3.0.3 and prior, this method would block until \var{length} bytes + was read. + \end{notice} + +\end{methoddesc} + +\begin{methoddesc}[connection]{readline}{\optional{length}} + + Reads a line from the connection or up to \var{length} bytes. + + This method should only be used inside \emph{Connection Handlers}. + +\end{methoddesc} + +\begin{methoddesc}[connection]{write}{string} + + Writes \var{string} to the client. + + This method should only be used inside \emph{Connection Handlers}. + +\end{methoddesc} + +\subsubsection{Connection Members\label{pyapi-mpconn-mem}} + +\begin{memberdesc}[connection]{base_server} + A \code{server} object for the physical vhost that this connection came in + through. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[connection]{local_addr} + The (address, port) tuple for the server. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[connection]{remote_addr} + The (address, port) tuple for the client. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[connection]{remote_ip} + String with the IP of the client. Same as CGI \envvar{REMOTE_ADDR}. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[connection]{remote_host} + String. The DNS name of the remote client. None if DNS has not been + checked, \code{""} (empty string) if no name found. Same as CGI \envvar{REMOTE_HOST}. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[connection]{remote_logname} + Remote name if using RFC1413 (ident). Same as CGI \envvar{REMOTE_IDENT}. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[connection]{aborted} + Boolean. True is the connection is aborted. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[connection]{keepalive} + Integer. 1 means the connection will be kept for the next request, 0 means + ``undecided'', -1 means ``fatal error''. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[connection]{double_reverse} + Integer. 1 means double reverse DNS lookup has been performed, 0 means + not yet, -1 means yes and it failed. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[connection]{keepalives} + The number of times this connection has been used. (?) + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[connection]{local_ip} + String with the IP of the server. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[connection]{local_host} + DNS name of the server. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[connection]{id} + Long. A unique connection id. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[connection]{notes} + A \code{table} object containing miscellaneous general purpose info that lives for + as long as the connection lives. +\end{memberdesc} + +\subsection{Filter Object (mp_filter)\obindex{filter}\label{pyapi-mpfilt}} + +A filter object is passed to mod_python input and output filters. It +is used to obtain filter information, as well as get and pass +information to adjacent filters in the filter stack. + +\subsubsection{Filter Methods\label{pyapi-mpfilt-meth}} + +\begin{methoddesc}[filter]{pass_on}{} + Passes all data through the filter without any processing. +\end{methoddesc} + +\begin{methoddesc}[filter]{read}{\optional{length}} + Reads at most \var{len} bytes from the next filter, returning a string + with the data read or None if End Of Stream (EOS) has been reached. A + filter \emph{must} be closed once the EOS has been encountered. + + If the \var{len} argument is negative or omitted, reads all data + currently available. +\end{methoddesc} + +\begin{methoddesc}[filter]{readline}{\optional{length}} + Reads a line from the next filter or up to \var{length} bytes. +\end{methoddesc} + +\begin{methoddesc}[filter]{write}{string} + Writes \var{string} to the next filter. +\end{methoddesc} + +\begin{methoddesc}[filter]{flush}{} + Flushes the output by sending a FLUSH bucket. +\end{methoddesc} + +\begin{methoddesc}[filter]{close}{} + Closes the filter and sends an EOS bucket. Any further IO operations on + this filter will throw an exception. +\end{methoddesc} + +\begin{methoddesc}[filter]{disable}{} + Tells mod_python to ignore the provided handler and just pass the data + on. Used internally by mod_python to print traceback from exceptions + encountered in filter handlers to avoid an infinite loop. +\end{methoddesc} + +\subsubsection{Filter Members\label{pyapi-mpfilt-mem}} + +\begin{memberdesc}[filter]{closed} + A boolean value indicating whether a filter is closed. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[filter]{name} + String. The name under which this filter is registered. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[filter]{req} + A reference to the request object. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[filter]{is_input} + Boolean. True if this is an input filter. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[filter]{handler} + String. The name of the Python handler for this filter as specified in + the configuration. + \emph{(Read-Only}) +\end{memberdesc} + +\subsection{Server Object (mp_server)\obindex{server}\label{pyapi-mpserver}} + +The request object is a Python mapping to the Apache \code{request_rec} +structure. The server structure describes the server (possibly virtual +server) serving the request. + +\subsubsection{Server Methods\label{pyapi-mpsrv-meth}} + +\begin{methoddesc}[server]{get_config}{} + Similar to \code{req.get_config()}, but returns a config pointed to + by \code{server->module_config} Apache config vector. +\end{methoddesc} + +\begin{methoddesc}[server]{get_options}{} + Similar to \code{req.get_options()}, but returns a table object holding + only the mod_python options defined at global scope within the Apache + configuration. That is, outside of the context of any VirtualHost, Location, + Directory or Files directives. +\end{methoddesc} + +\begin{methoddesc}[server]{register_cleanup}{request, callable\optional{, data}} + Registers a cleanup. Very similar to \function{req.register_cleanup()}, except + this cleanup will be executed at child termination time. This function + requires one extra argument - the request object. +\end{methoddesc} + +\subsubsection{Server Members\label{pyapi-mpsrv-mem}} + +\begin{memberdesc}[server]{defn_name} + String. The name of the configuration file where the server definition + was found. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[server]{defn_line_number} + Integer. Line number in the config file where the server definition is + found. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[server]{server_admin} + Value of the \code{ServerAdmin} directive. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[server]{server_hostname} + Value of the \code{ServerName} directive. Same as CGI \envvar{SERVER_NAME}.\emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[server]{names} + Tuple. List of normal server names specified in the \code{ServerAlias} + directive. This list does not include wildcarded names, which are listed + separately in \code{wild_names}. \emph{(Read-Only)} +\end{memberdesc} + +\begin{memberdesc}[server]{wild_names} + Tuple. List of wildcarded server names specified in the \code{ServerAlias} + directive. \emph{(Read-Only)} +\end{memberdesc} + +\begin{memberdesc}[server]{port} + Integer. TCP/IP port number. Same as CGI \envvar{SERVER_PORT}. + \emph{This member appears to be 0 on Apache 2.0, look at req.connection.local_addr instead} + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[server]{error_fname} + The name of the error log file for this server, if any. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[server]{loglevel} + Integer. Logging level. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[server]{is_virtual} + Boolean. True if this is a virtual server. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[server]{timeout} + Integer. Value of the \code{Timeout} directive. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[server]{keep_alive_timeout} + Integer. Keepalive timeout. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[server]{keep_alive_max} + Maximum number of requests per keepalive. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[server]{keep_alive} + Use persistent connections? + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[server]{path} + String. Path for \code{ServerPath} + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[server]{pathlen} + Integer. Path length. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[server]{limit_req_line} + Integer. Limit on size of the HTTP request line. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[server]{limit_req_fieldsize} + Integer. Limit on size of any request header field. + \emph{(Read-Only}) +\end{memberdesc} + +\begin{memberdesc}[server]{limit_req_fields} + Integer. Limit on number of request header fields. + \emph{(Read-Only}) +\end{memberdesc} + +\section{\module{util} -- Miscellaneous Utilities\label{pyapi-util}} +\declaremodule[util]{extension}{util} +\modulesynopsis{Miscellaneous Utilities} +\moduleauthor{Gregory Trubetskoy}{grisha@apache.org} + +The \module{util} module provides a number of utilities handy to a web +application developer similar to those in the standard library +\module{cgi} module. The implementations in the \module{util} module +are much more efficient because they call directly into Apache API's +as opposed to using CGI which relies on the environment to pass +information. + +The recommended way of using this module is: +\begin{verbatim} +from mod_python import util +\end{verbatim} + +\begin{seealso} + \seetitle[http://CGI-Spec.Golux.Com/] + {Common Gateway Interface RFC Project Page} + {for detailed information on the CGI specification} +\end{seealso} + +\subsection{FieldStorage class\label{pyapi-util-fstor}} + +Access to form data is provided via the \class{FieldStorage} +class. This class is similar to the standard library module +\module{cgi} \class{FieldStorage}. + +\begin{classdesc}{FieldStorage}{req\optional{, keep_blank_values, strict_parsing, file_callback, field_callback}} + This class provides uniform access to HTML form data submitted by the + client. \var{req} is an instance of the mod_python request object. + + The optional argument \var{keep_blank_values} is a flag indicating + whether blank values in URL encoded form data should be treated as + blank strings. The default is false, which means that blank values are + ignored as if they were not included. + + The optional argument \var{strict_parsing} is not yet implemented. + + The optional argument \var{file_callback} allows the application to override + both file creation/deletion semantics and location. See + \ref{pyapi-util-fstor-examples} ``FieldStorage Examples'' for additional + information. \emph{New in version 3.2} + + The optional argument \var{field_callback} allows the application to override + both the creation/deletion semantics and behaviour. \emph{New in version 3.2} + + During initialization, \class{FieldStorage} class reads all of the + data provided by the client. Since all data provided by the client is + consumed at this point, there should be no more than one + \class{FieldStorage} class instantiated per single request, nor should + you make any attempts to read client data before or after + instantiating a \class{FieldStorage}. + + The data read from the client is then parsed into separate fields and + packaged in \class{Field} objects, one per field. For HTML form inputs + of type \code{file}, a temporary file is created that can later be + accessed via the \member{file} attribute of a \class{Field} object. + + The \class{FieldStorage} class has a mapping object interface, i.e. it + can be treated like a dictionary. When used as a mapping, the keys are + form input names, and the returned dictionary value can be: + + \begin{itemize} + \item + An instance of \class{StringField}, containing the form input + value. This is only when there is a single value corresponding to the + input name. \class{StringField} is a subclass of \class{str} which + provides the additional \member{value} attribute for compatibility + with standard library \module{cgi} module. + \item + An instance of a \class{Field} class, if the input is a file upload. + \item + A list of \class{StringField} and/or \class{Field} objects. This is + when multiple values exist, such as for a \code{