1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
|
<!--
# VIP @lib/vip/html.l
# 26oct23 Software Lab. Alexander Burger
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>The 'httpGate' Proxy Server</title>
<link rel="stylesheet" href="doc.css" type="text/css">
</head>
<body>
<a href="mailto:mattias@inogu.se">mattias@inogu.se</a>
<h1>The 'httpGate' Proxy Server</h1>
<p style="text-align: right">(c) Software Lab. Mattias Sundblad
<p>This document describes the <code>httpGate</code> utility which is included
in the PicoLisp distribution.
<p>For basic information about the PicoLisp system please look at the <a
href="ref.html">PicoLisp Reference</a> and the <a href="tut.html">PicoLisp
Tutorial</a>.
<p><ul>
<li><a href="#purpose">Purpose</a>
<li><a href="#basic">Basic functionality</a>
<li><a href="#building">Building httpGate</a>
<li><a href="#running">Running httpGate</a>
<li><a href="#config">Configuring httpGate</a>
<ul>
<li><a href="#names">The "names" config file</a>
<li><a href="#balanced">Balanced "names" file</a>
<li><a href="#voidfile">The "void" file</a>
<li><a href="#reload">Reloading the configuration</a>
</ul>
<li><a href="#keepalive">Keep-alive and retirement</a>
</ul>
<p><hr>
<h2><a id="purpose">Purpose</a></h2>
<p><code>httpGate</code> is a central element of the PicoLisp application server
architecture. Its purpose is to perform the following tasks:
<p><ul>
<li>Provide a single application entry port (e.g. 80 or 443).
<li>Allow PicoLisp applications to run as non-root.
<li>Start application servers on demand.
<li>Handle HTTPS/SSL communication.
</ul>
<h2><a id="basic">Basic functionality</a></h2>
<p>A HTTP request to port 80, respectively 443, of the form
<pre>
http[s]://server.org/12345/path/file
</pre>
<p>is forwarded to a server on localhost listening on port 12345, to ask for the
resource "path/file".
<p>If httpGate was started with a config file, and that file contains an entry
for "app", then also the following request is accepted:
<pre>
http[s]://server.org/app/path/file
</pre>
<p>In that case, the "app" server process is started automatically (if it is not
already running) listening on port 12345, and the request is forwarded as above.
<p>Only GET and POST requests will be forwarded, and only to ports >= 1024.
The main httpGate process then forks two child processes, one for each
direction. These child processes terminate automatically if the connection is
idle for more than 7 minutes.
<h2><a id="running">Running httpGate</a></h2>
<p>The simplest way to run httpGate is to start it with an explicit port
argument:
<pre>
bin/httpGate 80 8080
bin/httpGate 443 8080 pem/www.domain.key,pem/domain.crt
</pre>
<p>When started in this way, httpGate forwards requests from port 80 and 443
respectively to a PicoLisp application on port 8080. This form has a drawback
though, since it only allows for a single application to be handled. Usually,
there are many PicoLisp applications running on the same machine, and we need
httpGate to forward requests to all of them.
<p>To handle several applications, start httpGate with a "names" config file:
<pre>
bin/httpGate 80 names
bin/httpGate 443 names pem/www.domain.key,pem/domain.crt
</pre>
<p>httpGate needs to be started as root, but application servers should run
under normal user accounts. The easiest way to start httpGate automatically is
to add lines like the ones above to '/etc/rc.local'.
<h2><a id="config">Configuring httpGate</a></h2>
<h3><a id="names">The "names" config file</a></h3>
<p>The "names" config file contains one line per application server. Each line
holds six whitespace separated tokens, for example:
<pre>
app 12345 tom /home/tom log/app ./pil app/main.l lib/app.l -main -go -wait
</pre>
<p><ol>
<li>"app" is the name of the application, and the key to this line.
<li>"12345" is the port where this server should listen at.
<li>"tom" is the user under whose ID the server should run.
<li>"/home/tom" is the working directory where the server should start.
<li>"log/app" is a log file to redirect stdout/stderr to.
<li>The rest of the line "./pil app/main.l ..." is the command to start the application.
</ol>
<p>Empty lines, and lines starting with a "#", are ignored. If the key in a
config file record is the special name "@", then it denotes the default
application for this machine. URLs without name will be forwarded to that port.
If the key contains a slash followed by a string (e.g. "app/foo") then this
string is inserted in front of URLs.
<p>Optional tokens (e.g. log files) or empty arguments to the commands must be
written as single caret (^) characters to denote empty strings. Double or single
quotes are not parsed.
<p>If the port is zero, then a single additional token is expected which should
denote an URL to redirect the request to:
<pre>
app 0 https://domain/foo/bar
</pre>
This will cause httpGate to respnd with "302 Found" and "Location:
https://domain/foo/bar".
<h3><a id="balanced">Balanced names file</a></h3>
<p>If the config file contains many (hundreds or thousands) entries, then it is
recommended to sort it with the 'balance' utility. This may greatly accelerate
name (key) lookup at runtime. For that, put the above config lines into a file
"config". The tool 'balance' can be built - together with httpGate - with
<pre>
(cd src; make tools gate)
</pre>
<p>The following command will create a balanced "names" file:
<pre>
cat config | bin/balance -sort > names
</pre>
<h3><a id="voidfile">The "void" file</a></h3>
<p>If the local application server cannot be connected on the requested port
(typically because a session timed out), and a file with the name "void" exists
in the current working directory (token 4 in the config line), then the contents
of that file (normally HTML) are sent as response to the client.
<h3><a id="reload">Reloading the configuration</a></h3>
<p>When the config file is modified, it can be reloaded by sending SIGHUP to all
running top-level httpGate processes:
<pre>
$ sudo pkill -HUP -P1 httpGate
</pre>
<p>Another possibility is to restart httpGate(s). This is not a problem, and can
be done also while the server is in production.
<p>Just kill the top level httpGate parent process. This is not harmful, because
existing user sessions are handled by pairs of child processes, which continue
to run (until they terminate normally) even if their parent is stopped. Note
that this is different from PicoLisp DB applications, where the parent should
*never* be hard-stopped (eg. with 'kill -9 <pid>') while child processes
are running ('kill <pid>' is OK though, because the parent takes care of
stopping the children).
<p>An example for stopping and restarting a running httpGate is:
<pre>
(let L
# Build list of all httpGate parents (i.e. on 80 and 443)
(make
(in '("sudo" "pgrep" "-P1" "httpGate")
(while (read)
(link @) ) ) )
# Stop them
(for P L
(call "sudo" "kill" P) )
# Wait until all are gone
(while (find '((P) (kill P 0)) L)
(wait 200) )
# Start new
(call "sudo" "bin/httpGate" 80 "names")
(call "sudo" "bin/httpGate" 443 "names" "pem/...") )
</pre>
<h2><a id="keepalive">Keep-alive and retirement</a></h2>
<p>Applications should call
<pre>
(retire 20)
</pre>
<p>before they call 'server'. This causes the parent server process to terminate
automatically 20 minutes after the last child process (user session) terminated.
It will be started by httpGate again on demand. User sessions in turn terminate
automatically after 5 minutes (if nobody logged in) or 1 hour (if a user is
logged in), unless JavaScript is enabled in the client browser and the
application calls
<pre>
(<ping> 7)
</pre>
<p>in its main 'action' function. In that case, the user session will not
terminate until the user closes the last window or tab to this application.
</body>
</html>
|