Server provides a basic implementation of an HTTP server. The
recommended usage of this server is for internal use, tasks like a
mock server for tests, a private service for IPC, etc. It is not
recommended to be exposed to untrusted clients as it may be vulnerable
to denial of service attacks or other exploits.
To begin, create a server using [ctor
server.new]. Add
at least one handler by calling
[method
server.add_handler] or
[method
server.add_early_handler]; the handler will be
called to process any requests underneath the path you pass. (If you
want all requests to go to the same handler, just pass "/" (or
Nothing) for the path.)
When a new connection is accepted (or a new request is started on an
existing persistent connection), the
Server will emit
signalserver[requestStarted] and then begin
processing the request as described below, but note that once the
message is assigned a status-code, then callbacks after that point
will be skipped. Note also that it is not defined when the callbacks
happen relative to various [class
serverMessage]
signals.
Once the headers have been read,
Server will check if there is
a [class
authDomain]
(qv) covering the
Request-URI; if so, and if the message does not contain suitable
authorization, then the [class
authDomain] will set a
status of
StatusUnauthorized on the message.
After checking for authorization,
Server will look for "early"
handlers (added with [method
server.add_early_handler])
matching the Request-URI. If one is found, it will be run; in
particular, this can be used to connect to signals to do a streaming
read of the request body.
(At this point, if the request headers contain
Expect:
100-continue, and a status code has been set, then
Server
will skip the remaining steps and return the response. If the request
headers contain
Expect: 100-continue and no status code has
been set,
Server will return a
StatusContinue status
before continuing.)
The server will then read in the response body (if present). At this
point, if there are no handlers at all defined for the Request-URI,
then the server will return
StatusNotFound to the client.
Otherwise (assuming no previous step assigned a status to the message)
any "normal" handlers (added with
[method
server.add_handler]) for the message's
Request-URI will be run.
Then, if the path has a WebSocket handler registered (and has not yet
been assigned a status),
Server will attempt to validate the
WebSocket handshake, filling in the response and setting a status of
StatusSwitchingProtocols or
StatusBadRequest
accordingly.
If the message still has no status code at this point (and has not
been paused with [method
serverMessage.pause]), then it
will be given a status of
StatusInternalServerError (because at
least one handler ran, but returned without assigning a status).
Finally, the server will emit
signalserver[requestFinished] (or
signalserver[requestAborted] if an I/O error
occurred before handling was completed).
If you want to handle the special "*" URI (eg, "OPTIONS *"), you must
explicitly register a handler for "*"; the default handler will not be
used for that case.
If you want to process https connections in addition to (or instead
of) http connections, you can set the
[property
server:tls-certificate] property.
Once the server is set up, make one or more calls to
[method
server.listen],
[method
server.listen_local], or
[method
server.listen_all] to tell it where to listen
for connections. (All ports on a
Server use the same handlers;
if you need to handle some ports differently, such as returning
different data for http and https, you'll need to create multiple
SoupServers, or else check the passed-in URI in the handler
function.).
Server will begin processing connections as soon as you return
to (or start) the main loop for the current thread-default
MainContext.