| 1 | patplex(1) |
| 2 | ========== |
| 3 | |
| 4 | NAME |
| 5 | ---- |
| 6 | patplex - Request pattern matcher for ashd(7) |
| 7 | |
| 8 | SYNOPSIS |
| 9 | -------- |
| 10 | *patplex* [*-hN*] 'CONFIGFILE' |
| 11 | |
| 12 | DESCRIPTION |
| 13 | ----------- |
| 14 | |
| 15 | The *patplex* handler matches requests against the rules specified in |
| 16 | 'CONFIGFILE', and dispatches them to the specified handlers |
| 17 | accordingly. See CONFIGURATION below for a description of how requests |
| 18 | are matched. |
| 19 | |
| 20 | *patplex* is a persistent handler, as defined in *ashd*(7). |
| 21 | |
| 22 | OPTIONS |
| 23 | ------- |
| 24 | |
| 25 | *-h*:: |
| 26 | |
| 27 | Print a brief help message to standard output and exit. |
| 28 | |
| 29 | *-N*:: |
| 30 | |
| 31 | Do not read the global configuration file `patplex.rc`. |
| 32 | |
| 33 | CONFIGURATION |
| 34 | ------------- |
| 35 | |
| 36 | In addition to the 'CONFIGFILE' specified on the command-line, |
| 37 | *patplex* also attempts to find and read a global configuration file |
| 38 | called `patplex.rc`, unless the *-N* option is given. It looks in |
| 39 | `$HOME/.ashd/etc`, and then in all directories named by the *PATH* |
| 40 | environment variable, appended with `../etc/ashd`. For example, then, |
| 41 | if *PATH* is `/usr/local/bin:/bin:/usr/bin`, the directories |
| 42 | `$HOME/.ashd/etc`, `/usr/local/etc/ashd`, `/etc/ashd` and |
| 43 | `/usr/etc/ashd` are searched for `patplex.rc`, in that order. Only the |
| 44 | first file found is used, should there exist several. If the given |
| 45 | 'CONFIGFILE' contains any slashes, it is opened by that exact |
| 46 | name. Otherwise, it is searched for in the same manner as the global |
| 47 | configuration file. |
| 48 | |
| 49 | Should the global and the given configuration files conflict, the |
| 50 | directives from the given file take precedence. |
| 51 | |
| 52 | The configuration files follow the same general format as for |
| 53 | *dirplex*(1), though the recognized stanzas differ. The *child*, |
| 54 | *fchild* and *include* stanzas are also shared with *dirplex*(1), so |
| 55 | see its manpage for a description thereof. |
| 56 | |
| 57 | *patplex* recognizes the *match* stanza, which takes no arguments, but |
| 58 | must contain at least one follow-up line to specify match rules. All |
| 59 | rules must match for the stanza as a whole to match. The following |
| 60 | rules are recognized: |
| 61 | |
| 62 | *point* 'REGEX' 'FLAGS':: |
| 63 | |
| 64 | 'REGEX' must be an extended regular expression. The rule is |
| 65 | considered to match if 'REGEX' matches the rest string of the |
| 66 | request. If 'FLAGS' contain the character `i`, 'REGEX' is |
| 67 | matched case-independently. If the *match* stanza as a whole |
| 68 | matches and contains no *restpat* line (as described below), |
| 69 | the rest string of the request is replaced by the remainder of |
| 70 | the rest string after the portion that was matched by |
| 71 | 'REGEX'. See also URL UNQUOTING, below. |
| 72 | |
| 73 | *url* 'REGEX' 'FLAGS':: |
| 74 | |
| 75 | 'REGEX' must be an extended regular expression. The rule is |
| 76 | considered to match if 'REGEX' matches the raw URL of the |
| 77 | request. If 'FLAGS' contain the character `i`, 'REGEX' is |
| 78 | matched case-independently. See also URL UNQUOTING, below. |
| 79 | |
| 80 | *method* 'REGEX' 'FLAGS':: |
| 81 | |
| 82 | 'REGEX' must be an extended regular expression. The rule is |
| 83 | considered to match if 'REGEX' matches the HTTP method of the |
| 84 | request. If 'FLAGS' contain the character `i`, 'REGEX' is |
| 85 | matched case-independently. |
| 86 | |
| 87 | *header* 'HEADER' 'REGEX' 'FLAGS':: |
| 88 | |
| 89 | 'REGEX' must be an extended regular expression. The rule is |
| 90 | considered to match if 'REGEX' matches the named 'HEADER' in |
| 91 | the request. If the request does not contain the named |
| 92 | 'HEADER', the rule never matches. If 'FLAGS' contain the |
| 93 | character `i`, 'REGEX' is matched case-independently. |
| 94 | |
| 95 | *default*:: |
| 96 | |
| 97 | Matches if and only if no *match* stanza without a *default* |
| 98 | rule has matched. |
| 99 | |
| 100 | In addition to the rules, a *match* stanza must contain exactly one |
| 101 | follow-up line specifying the action to take if it matches. Currently, |
| 102 | only the *handler* action is recognized: |
| 103 | |
| 104 | *handler* 'HANDLER':: |
| 105 | |
| 106 | 'HANDLER' must be a named handler as declared by a *child* or |
| 107 | *fchild* stanza, to which the request is passed. |
| 108 | |
| 109 | Additionally, a *match* stanza may contain any of the following, |
| 110 | optional lines: |
| 111 | |
| 112 | *set* 'HEADER' 'VALUE':: |
| 113 | |
| 114 | If the *match* stanza as a whole matches, the named HTTP |
| 115 | 'HEADER' in the request is set to 'VALUE' before passing the |
| 116 | request on to the specified handler. A *match* stanza may |
| 117 | contain any number of *set* lines. |
| 118 | |
| 119 | *xset* 'HEADER' 'VALUE':: |
| 120 | |
| 121 | *xset* does exactly the same thing as *set*, except that |
| 122 | 'HEADER' is automatically prepended with the `X-Ash-` |
| 123 | prefix. The intention is only to make configuration files |
| 124 | look nicer in this very common case. |
| 125 | |
| 126 | *restpat* 'TEMPLATE':: |
| 127 | |
| 128 | If the *match* stanza as a whole matches, 'TEMPLATE' is |
| 129 | expanded and installed as the rest string of the request |
| 130 | before it is passed to the specified handler. In 'TEMPLATE', |
| 131 | the following parameters are recognized and expanded. At most |
| 132 | one *restpat* line may be given per *match* stanza. |
| 133 | |
| 134 | *$0* ... *$9*:: |
| 135 | |
| 136 | Exactly one of the *point*, *url*, *method* or *header* rules |
| 137 | specified in the *match* stanza must have the `s` character |
| 138 | among its 'FLAGS'. *$0* is replaced by the whole text that was |
| 139 | matched by the rule's 'REGEX', and any of *$1* to *$9* is |
| 140 | replaced by the corresponding parenthesized subgroup of |
| 141 | 'REGEX'. |
| 142 | |
| 143 | *$_*:: |
| 144 | |
| 145 | Replaced by the entire rest string, as it was originally. |
| 146 | |
| 147 | *$$*:: |
| 148 | |
| 149 | Replaced by a single *$*. |
| 150 | |
| 151 | *${*'HEADER'*}*:: |
| 152 | |
| 153 | Replaced by the value of the named 'HEADER' in the request, or |
| 154 | the empty string if the request contained no such header. |
| 155 | |
| 156 | If no *match* stanza matches, a 404 response is returned to the |
| 157 | client. |
| 158 | |
| 159 | URL UNQUOTING |
| 160 | ------------- |
| 161 | |
| 162 | If the 'FLAGS' of a *point* or *url* rule contain the character `q`, |
| 163 | then the rule's pattern will be matched against a copy of the input |
| 164 | string where URL percent-escapes have been decoded so that, for |
| 165 | example, the regular expression `^~` will match an input string that |
| 166 | begins with either `~`, `%7E` or `%7e`. |
| 167 | |
| 168 | Even if such percent-escapes were decoded, however, the original |
| 169 | version of the string will be used for any *restpat* expansion, |
| 170 | regardlessly of whether the escapes were unquoted inside or outside |
| 171 | the matched part of the string. |
| 172 | |
| 173 | SIGNALS |
| 174 | ------- |
| 175 | |
| 176 | SIGHUP:: |
| 177 | |
| 178 | Reread the given configuration file (but not the global |
| 179 | file). If any named handlers, as specified by *child* stanzas, |
| 180 | are currently running and have stanzas with matching names in |
| 181 | the new file, they are left running for those stanzas (even if |
| 182 | the *exec* line has changed). |
| 183 | |
| 184 | EXAMPLES |
| 185 | -------- |
| 186 | |
| 187 | The following configuration file serves files from the `/srv/www` |
| 188 | directory by default, and in addition recognizes standard `/~user/` |
| 189 | URLs as user directories and calls the *userplex*(1) program to serve |
| 190 | them. |
| 191 | |
| 192 | -------- |
| 193 | child root |
| 194 | exec sudo -u www-data dirplex /srv/www |
| 195 | child userdir |
| 196 | exec userplex -g users |
| 197 | match |
| 198 | default |
| 199 | handler root |
| 200 | match |
| 201 | point ^~ |
| 202 | handler userdir |
| 203 | -------- |
| 204 | |
| 205 | The following rules can be used to implement virtual hosts. The actual |
| 206 | handlers are left out of the example. Note that the dots in the |
| 207 | regular expressions need to be escaped with double backslashes, since |
| 208 | the configuration file reader consumes one level of quoting. |
| 209 | |
| 210 | -------- |
| 211 | # Match one exact domain name only. |
| 212 | match |
| 213 | header host ^www\\.foo\\.net$ i |
| 214 | handler site-foo |
| 215 | # Match any sub-domain of bar.com. |
| 216 | match |
| 217 | header host (^|\\.)bar\\.com$ i |
| 218 | handler site-bar |
| 219 | # Use the last level of the domain name to enter a subdirectory. |
| 220 | match |
| 221 | header host ^([^.]*)\\.multi\\.org$ is |
| 222 | restpat $1/$_ |
| 223 | handler site-multi |
| 224 | -------- |
| 225 | |
| 226 | AUTHOR |
| 227 | ------ |
| 228 | Fredrik Tolf <fredrik@dolda2000.com> |
| 229 | |
| 230 | SEE ALSO |
| 231 | -------- |
| 232 | *dirplex*(1), *ashd*(7), *regex*(7) |