========
ajp-wsgi
========
.. contents::

Introduction
------------
``ajp-wsgi`` is a WSGI [1]_ server/gateway that implements AJP 1.3 [2]_
to communicate with a web server [3]_. It is written in C and embeds a
Python interpreter to run the actual application. Since all of the
low-level transport code is in C, ``ajp-wsgi`` is significantly faster
than flup's [4]_ pure-Python ajp server.

``ajp-wsgi`` supports both threading and forking.

.. [1] http://www.python.org/dev/peps/pep-0333/
.. [2] http://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html
.. [3] Typically, you would use
       `tomcat-connectors <http://tomcat.apache.org/connectors-doc/>`_ (for
       Apache HTTPD 1.3.x, 2.0.x, or even IIS) or
       `mod_proxy_ajp <http://httpd.apache.org/docs/2.2/mod/mod_proxy_ajp.html>`_
       (included with Apache HTTPD 2.2.x) to connect your web server to
       ``ajp-wsgi``.
.. [4] http://www.saddi.com/software/flup/

Features
--------

 * Wholly written in C - the Python Global Interpreter Lock only enters
   the picture when calling the WSGI application, allowing greater
   concurrency.
 * If the iterable returned by the WSGI application has a length and
   that length is 1, the Content-Length header is automatically
   deduced.
 * Supports the wsgi.file_wrapper feature. On some platforms (i.e.
   FreeBSD), it is implemented using the OS-level sendfile(2) syscall.

Downloading
-----------
The latest version of ``ajp-wsgi`` may be found at
http://www.saddi.com/software/ajp-wsgi/dist/

Building
--------
First execute ``configure.py`` with the version of Python you wish
to embed. So far ``ajp-wsgi`` has been tested with Python 2.3, 2.4,
2.5, 2.6, and 2.7.

::

    python configure.py

Next, execute ``make``. If everything goes well, you should have
an ``ajp-wsgi`` executable that's ready to use.

At this time, ``ajp-wsgi`` is only confirmed to compile/work on
FreeBSD 6.x, Mac OS X 10.6, and (Gentoo) Linux. Other Linux distros
probably work as well. Patches and/or suggestions to improve portability
are highly welcome!

Using
-----
Before using ``ajp-wsgi``, you most likely want to set two important
environment variables: ``PYTHONHOME`` and ``PYTHONPATH``.

``PYTHONHOME`` determines where ``ajp-wsgi`` will import its standard
Python modules. If you are using a "virtual" Python installation, set
this to the base directory of your installation. Otherwise, leave it
unset to use your default Python's modules (the Python found in your
``PATH``).

For example::

    export PYTHONHOME=/home/myusername

``PYTHONPATH`` is any additional directories to search for Python
modules. Note that the current directory is always searched first.
For example, to search the directories named ``mymodules`` and
``othermodules`` in your home directory::

    export PYTHONPATH=$HOME/mymodules:$HOME/othermodules

Note that other standard Python environment variables are also accepted
by the embedded interpreter, e.g. ``PYTHONOPTIMIZE``.

Finally, to actually use ``ajp-wsgi``, simply execute it with the name
of the module for your WSGI application, and the name of your application's
object within that module::

    ajp-wsgi myappmodule app

By default, ajp-wsgi will listen on port 8009.

Options
+++++++
The ``ajp-wsgi`` command-line options take the following form::

    ajp-wsgi [-BFQVv] [-l <logFile>]
             [-h <ifname>] [-p <port>]
             [-n <maxConnections>]
             <moduleName> <appName> [<scriptName>]

Where:

    -V                 Report version and exit.

    -v                 Run verbosely.

    -B                 Run in the background. It is strongly recommended that
                       you use the ``-l`` *logFile* option as well.

    -F                 Use a new process (fork) for each AJP connection, rather
                       than a new thread.

    -Q                 Do not attempt to decode REQUEST_URI/PATH_INFO. [6]_

    -l logFile         Redirect stderr to *logFile*. stderr is where most of
                       the useful diagnostic messages (tracebacks, etc.) go.

    -h ifname          Bind to interface *ifname* rather than ``localhost``.
                       May be a resolvable name or an IPv4/IPv6 address.

    -p port            Listen on port *port* rather than 8009.

    -n maxConnections  Maximum number of threads or processes. When threading,
                       default is MAX_INT, i.e. effectively unlimited. When
                       forking, the default is 16. Note that the ``-t``
                       option served the same purpose in previous versions.
                       As of 1.1, it is deprecated, but it will still set
                       *maxConnections* correctly.

    moduleName
        Name of the Python module to import. ``sys.path`` (which includes
	the current directory) will be searched for the module. Use the
        ``PYTHONPATH`` environment variable to add more search paths.

    appName
        Name of the application object within the module. This must be
        a Python callable object that takes 2 arguments. See [1]_ for
        more information.

    scriptName
        By default, ``ajp-wsgi`` assumes your application is mounted
        at the virtual host root. If it isn't, you will need to specify
        its mount point (aka context) as the third argument to
        ``ajp-wsgi``.

        For example::

            ajp-wsgi myappmodule app /foo

        If the application is mounted at http://example.com/foo

        Not setting this correctly will result in an erroneous PATH_INFO
        being passed to your application... which will probably break it.

.. [6] If using mod_jk with the ``ForwardURICompat`` option (the default),
       this option is needed to ensure that the ``REQUEST_URI`` is not decoded
       twice. If using mod_proxy_ajp or mod_jk with the ``ForwardURIEscaped``
       option, there is no need to use this option.

Exit Codes
++++++++++
``ajp-wsgi`` exits 0 if it received a SIGINT or SIGTERM; 1 if there is a
problem with the command-line arguments; 2 if there is a general problem
(e.g. socket errors, thread errors, out of memory); and 3 if it received
a SIGHUP.

License
-------
``ajp-wsgi`` is licensed under a standard 2-clause BSD license, reproduced
below::

    Copyright (c) 2006 Allan Saddi <allan@saddi.com>
    All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
    1. Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    SUCH DAMAGE.

Support
-------
Please direct any questions to me at <allan@saddi.com>.

Please submit bug reports or patches at my `general Trac site
<http://trac.saddi.com/projects>`_.

Now and then, there may be ``ajp-wsgi`` related news under the
`Python category <http://www.saddi.com/software/news/categories/2-Python>`_
of my projects blog.
