HTTP Server

The class http.Server implements a basic server. The server handles receiving incoming HTTP connections, parsing them, and sending responses to them. To generate responses, it calls one of the abstract functions below. As such, to use the server, you need to create a class that inherits from http.Server and overrides the functions below. It is also possible to use http.RoutingServer to solve routing automatically.

The server is threaded, using Storm's user threads. A new thread is created for each client that connects to the server, and the created thread handles connections in parallell. Note, however, that user threads are scheduled cooperatively. As such, this model is not too dissimilar from webservers that utilize a few threads to handle requests in a multiplexed way.

The members that need to be overridden are the following:

The server also provides the following members that are relevant to be aware of:

Routing

The class http.RoutingServer extends http.Server and provides routing. That way, the server is usable without subclassing.

At a conceptual level, the routing server associates each path with a function that will be called whenever a client visits that particular path. Wildcards are supported. As such, if one path component is *, then any contents of that component will be considered a match. Note that wildcard components are always matched last.

Routes are added by calling the function add:

It is also possible to add a default handler that will be called whenever a more specific route does not exist. The default behavior of this handler is to provide a basic "page not found" message:

Example

Below is an example of using the HTTP library to create a simple server:

use core:net;
use core:io;
use http;
use core:lang;

private Str baseSite() {
    str {
        <!DOCTYPE html>
        <html>
        <body>
            <h1>Hello</h1>
            <p>Example page</p>
        </body>
        </html>
    };
}

private Str picturesSite() {
    str {
        <!DOCTYPE html>
        <html>
        <body>
            <h1>Pictures</h1>
            <p>Pictures page</p>
        </body>
        </html>
    };
}

void main() {
    RoutingServer server;

    // Sleep for 20 seconds, then call close to cause 'server.run' to return.
    spawn (() => { sleep(20 s); server.close; }).call();

    // Add a handler for the route /pictures/<anything>
    server.route(["pictures", "*"], (request) => Response(picturesSite));
    // Add a default handler.
    server.default((request) => Response(baseSite));

    // Run the server on port 1234.
    server.run(1234);
}