Skip to content

Http Server

Spice
import "std/net/http-server";

HttpServer struct

A blocking HTTP/1.1 server, built on the plain TCP sockets of "std/net/socket".

Requests are served one at a time on the thread that drives the server: run keeps serving until stop is called, while handleNextRequest serves a single connection and hands control back, so the caller can weave the server into a loop of its own. Every connection is answered with Connection: close and closed afterwards.

Routing is exact-match on the path of the request target, so "/a" and "/a/" are different routes and the query string never takes part in the match. A path that is registered for some other method answers 405 instead of 404, and a HEAD request falls back to the GET route of the same path, with the body dropped again afterwards.

There is no TLS underneath, so the server speaks plain http only.

Note on handlers: a handler is stored in a Lambda (see "std/type/lambda"), which relocates the captures of the lambda onto the heap with a shallow copy. A handler may therefore capture plain values, but it must not capture a String, a container or anything else that owns memory, since only the owner itself would free it. Fixed content belongs into serve, and anything else into a global or into the request itself.

Fields

Name Type Description
port unsigned short Port the server listens on
serverIdent String Value of the Server field of every response
maxMessageSize unsigned long Upper bound on the size of a request
timeoutMillis unsigned long Per read/write timeout of a connection, 0 to block indefinitely

Constructors

ctor

Spice
public p HttpServer.ctor(unsigned short port = HTTP_PORT_FALLBACK)

Constructs a server for the given port. Nothing is bound yet - that happens in start.

Parameters

Name Type Description
port unsigned short Port to listen on (default: HTTP_PORT_FALLBACK)

dtor

Spice
public p HttpServer.dtor()

Closes the listening socket if the server is still up

Methods

route

Spice
public p HttpServer.route(HttpMethod method, string path, p(const HttpRequest&, HttpResponse&) handler)

Registers a handler for a method and path

Parameters

Name Type Description
method HttpMethod Method the route answers
path string Path the route answers, matched exactly
handler p(const HttpRequest&, HttpResponse&) Handler that fills in the response

get

Spice
public p HttpServer.get(string path, p(const HttpRequest&, HttpResponse&) handler)

Registers a GET handler for a path. HEAD requests for the same path are answered from it as well.

Parameters

Name Type Description
path string Path the route answers, matched exactly
handler p(const HttpRequest&, HttpResponse&) Handler that fills in the response

post

Spice
public p HttpServer.post(string path, p(const HttpRequest&, HttpResponse&) handler)

Registers a POST handler for a path

Parameters

Name Type Description
path string Path the route answers, matched exactly
handler p(const HttpRequest&, HttpResponse&) Handler that fills in the response

put

Spice
public p HttpServer.put(string path, p(const HttpRequest&, HttpResponse&) handler)

Registers a PUT handler for a path

Parameters

Name Type Description
path string Path the route answers, matched exactly
handler p(const HttpRequest&, HttpResponse&) Handler that fills in the response

patch

Spice
public p HttpServer.patch(string path, p(const HttpRequest&, HttpResponse&) handler)

Registers a PATCH handler for a path

Parameters

Name Type Description
path string Path the route answers, matched exactly
handler p(const HttpRequest&, HttpResponse&) Handler that fills in the response

delete

Spice
public p HttpServer.delete(string path, p(const HttpRequest&, HttpResponse&) handler)

Registers a DELETE handler for a path

Parameters

Name Type Description
path string Path the route answers, matched exactly
handler p(const HttpRequest&, HttpResponse&) Handler that fills in the response

serve

Spice
public p HttpServer.serve(string path, string content, string contentType = CONTENT_TYPE_HTML)

Registers a route that answers a path with a fixed piece of content

Parameters

Name Type Description
path string Path the route answers, matched exactly
content string Content to respond with
contentType string Media type of the content (default: CONTENT_TYPE_HTML)

serve

Spice
public p HttpServer.serve(string path, const String& content, string contentType = CONTENT_TYPE_HTML)

Registers a route that answers a path with a fixed piece of content

Parameters

Name Type Description
path string Path the route answers, matched exactly
content const String& Content to respond with
contentType string Media type of the content (default: CONTENT_TYPE_HTML)

setNotFoundHandler

Spice
public p HttpServer.setNotFoundHandler(p(const HttpRequest&, HttpResponse&) handler)

Registers the handler that answers requests no route matches. Without one, unmatched requests are answered with a plain 404.

Parameters

Name Type Description
handler p(const HttpRequest&, HttpResponse&) Handler that fills in the response

start

Spice
public f<Result<bool>> HttpServer.start(int connectionBacklog = DEFAULT_CONNECTION_BACKLOG)

Binds the configured port and starts listening on it

Parameters

Name Type Description
connectionBacklog int Maximum number of connections that may wait in the accept queue (default: DEFAULT_CONNECTION_BACKLOG)

Returns: Result<bool> — true once the server listens, or an error describing why it could not

handleNextRequest

Spice
public f<Result<bool>> HttpServer.handleNextRequest()

Accepts a single connection, answers the request on it and closes it again.

A request that cannot be parsed is answered with 400 rather than being dropped silently, so a confused client learns what happened.

Returns: Result<bool> — true if a request was served, or an error if the connection could not be accepted

run

Spice
public f<Result<bool>> HttpServer.run()

Serves connections until stop is called or a connection cannot be accepted.

The stop flag is checked between connections, so a stop from another thread takes effect once the connection that is currently being served is done.

Returns: Result<bool> — true if the loop ended through stop, or an error if a connection could not be accepted

stop

Spice
public p HttpServer.stop()

Asks a running run loop to end once the connection it is serving is done

isRunning

Spice
public f<bool> HttpServer.isRunning()

Checks whether a run loop is currently serving

Returns: bool

isListening

Spice
public f<bool> HttpServer.isListening()

Checks whether the server holds a listening socket

Returns: bool

close

Spice
public p HttpServer.close()

Closes the listening socket. The server can be started again afterwards.

Returns: Closing the socket was successful or not