Skip to content

static_http#

The static_http namespace implemented in the header files under include/static_http contains an implementation of a static HTTP server. The term static here means that the files served by the HTTP server are not dynamic; they are fixed at compile time. The application for this feature is to embed a set of files (e.g., a web application) into the firmware for a device.

static_http stores files as gzip-compressed HTTP responses in a level-compressed search tree. The tool tools/mkfs.js can be used to generate filesystem images (which are C++ source files) for use with the static_http server.

The HTTP protocol parsing itself is implemented using one of three different libraries. The library used can be configured using the following defines:

  • AES70_STATIC_HTTP_USE_PICOHTTPPARSER enables usage of picohttpparser.
  • AES70_STATIC_HTTP_USE_LLHTTP enables usage of llhttp.
  • AES70_STATIC_HTTP_USE_HTTP_PARSER is deprecated and enables usage of http-parser.

The static_http library also supports WebSocket connections. This can be used to implement AES70 over WebSocket connections. The WebSocket support is described in more detail in the next section websocket.

Using the static HTTP server#

The API mirrors the pattern used for AES70 devices: you construct a server instance, then pass it to a port type that is used as the template argument to the platform’s TCP port (e.g. libuv::tcp::port or aes70::boost::tcp::port).

Server without WebSocket#

  1. Construct the server with your filesystem (and optional WebSocket port).
  2. Construct the TCP port with static_http::port<decltype(server)>, passing the server to the port constructor.
auto fs = static_http::filesystem::make_empty_filesystem();
static_http::server<decltype(fs)> http_server(fs);

libuv::tcp::port<static_http::port<decltype(http_server)>> http(
    0, "0.0.0.0", uv_default_loop(), http_server);

With Boost.Asio the pattern is the same; only the TCP port type changes:

static_http::server<decltype(fs)> http_server(fs);
aes70::boost::tcp::port<static_http::port<decltype(http_server)>> http(
    0, "0.0.0.0", io_context, http_server);

Server with WebSocket#

When the HTTP server is used together with a WebSocket port, pass both the filesystem and the WebSocket port to the server constructor, then pass the server to the HTTP TCP port:

auto fs = static_http::filesystem::make_empty_filesystem();
// ... create websocket port ws ...

static_http::server<decltype(fs), decltype(ws)> http_server(fs, ws);
libuv::tcp::port<static_http::port<decltype(http_server)>> http(
    http_port, "0.0.0.0", uv_default_loop(), http_server);

Migrating from the previous API#

If you are upgrading from an older version of libaes70, the way you bind the static HTTP server to a TCP port has changed.

Previous API: the TCP port was templated on the server type, and the port constructor received the server’s dependencies (e.g. filesystem and WebSocket port) directly:

// OLD: port is templated on the server, constructor gets (fs, ws)
libuv::tcp::port<static_http::server<decltype(fs), decltype(ws)>> http(
    0, "0.0.0.0", uv_default_loop(), fs, ws);

Current API: you must create a server object first, then pass that server to a TCP port that is templated on static_http::port<Server>:

// NEW: create server, then port templated on static_http::port<Server>
static_http::server<decltype(fs), decltype(ws)> http_server(fs, ws);
libuv::tcp::port<static_http::port<decltype(http_server)>> http(
    0, "0.0.0.0", uv_default_loop(), http_server);

This change was made so that the static HTTP server uses the same conceptual pattern as the AES70 device (device + aes70::port<Device>).