| 1 | ashd-wsgi3(1) |
| 2 | ============= |
| 3 | |
| 4 | NAME |
| 5 | ---- |
| 6 | ashd-wsgi3 - WSGI adapter for ashd(7) |
| 7 | |
| 8 | SYNOPSIS |
| 9 | -------- |
| 10 | *ashd-wsgi3* [*-hAL*] [*-m* 'PDM-SPEC'] [*-p* 'MODPATH'] [*-t* 'HANDLING-MODEL'] 'HANDLER-MODULE' ['ARGS'...] |
| 11 | |
| 12 | DESCRIPTION |
| 13 | ----------- |
| 14 | |
| 15 | The *ashd-wsgi3* handler translates *ashd*(7) requests to WSGI |
| 16 | requests, and passes them to a specified Python handler module. The |
| 17 | precise Python convention for doing so is described in the PROTOCOL |
| 18 | section, below. |
| 19 | |
| 20 | *ashd-wsgi3* is a persistent handler, as defined in *ashd*(7). It uses |
| 21 | multithreaded dispatching in a single Python interpreter, which means |
| 22 | that WSGI applications that use it need to be thread-safe, but that |
| 23 | they can also share all Python data structures and global variables |
| 24 | between requests. More precisely, *ashd-wsgi* implements a couple of |
| 25 | slightly different ways to handle requests and threads, which can be |
| 26 | configured using the *-t* option, as described in the REQUEST HANDLING |
| 27 | section, below. |
| 28 | |
| 29 | The Python module that *ashd-wsgi3* comes with also contains a |
| 30 | standard handler module, `ashd.wsgidir`, which serves individual WSGI |
| 31 | applications directly from the files in which they reside and as such |
| 32 | makes this program useful as a *dirplex*(1) handler. Please see its |
| 33 | Python documentation for further details. |
| 34 | |
| 35 | *ashd-wsgi3* requires the `ashd.proto` and `ashd.util` modules, which |
| 36 | are only available for CPython. If you want to use some other Python |
| 37 | implementation instead, you may want to use the *scgi-wsgi*(1) program |
| 38 | instead, along with *callscgi*(1). |
| 39 | |
| 40 | OPTIONS |
| 41 | ------- |
| 42 | |
| 43 | *-h*:: |
| 44 | |
| 45 | Print a brief help message to standard output and exit. |
| 46 | |
| 47 | *-A*:: |
| 48 | |
| 49 | Use the convention used by Apache's mod_wsgi module to find |
| 50 | the WSGI application object. See the PROTOCOL section, below, |
| 51 | for details. |
| 52 | |
| 53 | *-L*:: |
| 54 | By default, *ashd-wsgi3* sets up the Python logging with a |
| 55 | logging format and for logging to standard error. The *-L* |
| 56 | option suppresses that behavior, so that any handler module |
| 57 | may set up logging itself. |
| 58 | |
| 59 | *-p* 'MODPATH':: |
| 60 | |
| 61 | Prepend 'MODPATH' to Python's `sys.path`; can be given multiple |
| 62 | times. Note that the working directory of *ashd-wsgi3* is not |
| 63 | on Python's module path by default, so if you want to use a |
| 64 | module in that directory, you will need to specify "`-p .`". |
| 65 | |
| 66 | *-t* 'HANDLING-MODEL':: |
| 67 | |
| 68 | Specify the way *ashd-wsgi* handles requests. See below, under |
| 69 | REQUEST HANDLING. |
| 70 | |
| 71 | *-m* 'PDM-SPEC':: |
| 72 | |
| 73 | If the PDM library is installed on the system, create a |
| 74 | listening socket for connecting PDM clients according to |
| 75 | 'PDM-SPEC'. |
| 76 | |
| 77 | PROTOCOL |
| 78 | -------- |
| 79 | |
| 80 | When starting, *ashd-wsgi3* will attempt to import the module named by |
| 81 | 'HANDLER-MODULE', look for an object named `wmain` in that module, |
| 82 | call that object passing the 'ARGS' (as Python strings) as positional |
| 83 | parameters, and use the returned object as the WSGI application |
| 84 | object. If the *-A* option was specified, it will look for an object |
| 85 | named `application` instead of `wmain`, and use that object directly |
| 86 | as the WSGI application object. |
| 87 | |
| 88 | When calling the WSGI application, a new thread is started for each |
| 89 | request, in which the WSGI application object is called (but see |
| 90 | below, under REQUEST HANDLING, for details). All requests run in the |
| 91 | same interpreter, so it is guaranteed that data structures and global |
| 92 | variables can be shared between requests. |
| 93 | |
| 94 | The WSGI environment is the standard CGI environment, including the |
| 95 | `SCRIPT_FILENAME` variable whenever the `X-Ash-File` header was |
| 96 | included in the request. |
| 97 | |
| 98 | REQUEST HANDLING |
| 99 | ---------------- |
| 100 | |
| 101 | *ashd-wsgi3* can be configured to handle requests in various ways, |
| 102 | using the *-t* command-line option. The argument to the *-t* option |
| 103 | takes the form 'HANDLER'[*:*'PAR'[*=*'VAL'][(*,*'PAR'[*=*'VAL'])...]], |
| 104 | in order to specify the handler model, along with parameters to the |
| 105 | same (using the same syntax as the port specifications of |
| 106 | *htparser*(1)). The 'HANDLER' can be any of the following: |
| 107 | |
| 108 | *free*[*:max=*'MAX-THREADS'*,timeout=*'TIMEOUT']:: |
| 109 | |
| 110 | The *free* handler, which is the default, starts a new thread |
| 111 | for every incoming request, which runs the whole request in |
| 112 | its entirety, from running the WSGI handler function to |
| 113 | sending the contents of the response iterator. Optionally, |
| 114 | 'MAX-THREADS' may be specified to an integer, in which case no |
| 115 | more than that many request-handler threads will be allowed to |
| 116 | run at any one time (by default, any number of threads are |
| 117 | allowed to run, without limit). If further requests come in |
| 118 | while 'MAX-THREADS' handlers are running, the request dispatch |
| 119 | thread itself will block until one exits, making new requests |
| 120 | queue up in the socket over which they arrive, eventually |
| 121 | filling up its buffers if no threads exit, in turn making the |
| 122 | parent handler either block or receive *EAGAIN* errors. Also, |
| 123 | if 'MAX-THREADS' is specified, 'TIMEOUT' may also be |
| 124 | specified, to tell the dispatcher thread to never block more |
| 125 | than so many seconds for a handler thread to exit. If it is |
| 126 | forced to wait longer than 'TIMEOUT' seconds, it will assume |
| 127 | the whole process is somehow foobar and will *abort*(3). |
| 128 | |
| 129 | *rplex*[*:max=*'MAX-THREADS']:: |
| 130 | |
| 131 | The *rplex* handler starts a new thread for every incoming |
| 132 | request, but unlike the *free* handler, only the WSGI handler |
| 133 | function runs in that thread. Whenever any such thread, then, |
| 134 | returns its response iterator, all such iterators will be |
| 135 | passed to a single independent thread which sends their |
| 136 | contents to the clients, multiplexing between them whenever |
| 137 | their respective clients are ready to receive data. Like the |
| 138 | *free* handler, a 'MAX-THREADS' argument may be given to |
| 139 | specify how many handler threads are allowed to run at the |
| 140 | same time. The main advantage, compared to the *free* handler, |
| 141 | is that the *rplex* handler allows an arbitrary number of |
| 142 | response iterators to run simultaneously without tying up |
| 143 | handler threads, therefore not counting towards 'MAX-THREADS', |
| 144 | which may be necessary for applications handling large |
| 145 | files. However, it must be noted that no response iterators in |
| 146 | the application may block on returning data, since that would |
| 147 | also block all other running responses. Also, the *rplex* |
| 148 | handler does not support the `write` function returned by |
| 149 | `start_request`, according to the WSGI specification. |
| 150 | |
| 151 | *single*:: |
| 152 | |
| 153 | The *single* handler starts no threads at all, running all |
| 154 | received requests directly in the main dispatch thread. It is |
| 155 | probably not good for much except as the simplest possible |
| 156 | example of a request handling model. |
| 157 | |
| 158 | EXAMPLES |
| 159 | -------- |
| 160 | |
| 161 | The following *dirplex*(1) configuration can be used for serving WSGI |
| 162 | modules directly from the filesystem. |
| 163 | |
| 164 | -------- |
| 165 | child wsgidir |
| 166 | exec ashd-wsgi3 ashd.wsgidir |
| 167 | match |
| 168 | filename *.wsgi |
| 169 | xset python-handler chain |
| 170 | handler wsgidir |
| 171 | -------- |
| 172 | |
| 173 | Since *ashd-wsgi3* is a persistent handler, it can be used directly as |
| 174 | a root handler for *htparser*(1). For instance, if the directory |
| 175 | `/srv/www/foo` contains a `wsgi.py` file, which declares a standard |
| 176 | WSGI `application` object, it can be served with the following |
| 177 | command: |
| 178 | |
| 179 | -------- |
| 180 | htparser plain:port=8080 -- ashd-wsgi3 -Ap /srv/www/foo wsgi |
| 181 | -------- |
| 182 | |
| 183 | AUTHOR |
| 184 | ------ |
| 185 | Fredrik Tolf <fredrik@dolda2000.com> |
| 186 | |
| 187 | SEE ALSO |
| 188 | -------- |
| 189 | *scgi-wsgi3*(1), *ashd*(7), <http://wsgi.org/> |