3. Walk-through

The server and support headers are included:

#include <vws/server.h>

#include "vwsx.h"

The handler answers every request with the same body. It receives the server, the connection id, the parsed vws_http_msg (unused here), and the worker context, and returns a bool:

static bool process(vws_svr* s, vws_cid_t cid, vws_http_msg* msg, void* ctx)
{
    (void)msg;
    (void)ctx;

    const char* body     = "Hello world";
    size_t      body_len = strlen(body);

    char response[256];
    int  n = snprintf(response, sizeof(response),
                      "HTTP/1.1 200 OK\r\n"
                      "Content-Type: text/plain\r\n"
                      "Content-Length: %zu\r\n"
                      "\r\n"
                      "%s",
                      body_len, body);

The full HTTP response — status line, headers, and body — is formatted into a local buffer. The Content-Length is computed from body_len rather than hardcoded, so the header always matches the payload. The formatted bytes are then copied onto the heap and handed to a response object, which is sent:

char* data = (char*)vws.malloc((size_t)n);
memcpy(data, response, (size_t)n);

vws_svr_data* reply = vws_svr_data_own((vws_tcp_svr*)s, cid,
                                       (ucstr)data, (size_t)n);
vws_tcp_svr_send(reply);

return true;

vws_svr_data_own() takes ownership of the heap copy and binds the reply to the request's connection id; vws_tcp_svr_send() queues it for the networking thread. The handler casts the server to (vws_tcp_svr*) to use these base-layer calls, and returns true to tell the framework the request was handled.

Setup mirrors the WebSocket server but installs the HTTP handler:

vws_svr* server = vws_svr_new(10, 0, 0);

if (server == NULL)
{
    vwsx_die("vws_svr_new() failed");
}

server->process_http = process;

Because the HTTP and WebSocket handlers live on the same vws_svr, one server can serve both: setting process_http as well as a process_ws lets the framework route each request to the right handler. The run and stop go through the base type, exactly as in the WebSocket server:

vwsx_serve_stop_on_signal((vws_tcp_svr*)server);

vws_tcp_svr_run((vws_tcp_svr*)server, HOST, PORT);

vws_svr_free(server);