🟥 HTTP parser and server
SaneCppHttp.h is a library implementing a hand-written http 1.1 parser, and server.
Dependencies

Features
- HTTP 1.1 Parser
- HTTP 1.1 Server
Status
🟥 Draft
In current state the library is able to host simple static website but it cannot be used for any internet facing application.
Additionally its API will be changing heavily as it's undergoing major re-design to make it fully allocation free and extend it to support more of the HTTP 1.1 standard.
Description
The HTTP parser is an incremental parser, that will emit events as soon as a valid element has been successfully parsed. This allows handling incomplete responses without needing holding it entirely in memory.
The HTTP server is for now just a basic implementations and it's missing many important features. It's however capable of serving files through http while staying inside a few user provided fixed buffers, without allocating any kind of dynamic memory.
The HTTP client has been for now moved to the tests as it needs significant re-work to become useful.
Videos
This is the list of videos that have been recorded showing some of the internal thoughts that have been going into this library:
Blog
Some relevant blog posts are:
HttpAsyncServer
Async Http Server.
This class handles a fully asynchronous http server staying inside 5 fixed memory regions passed during init.
Usage:
- See also
- SC::HttpAsyncFileServer, SC::HttpConnectionsPool
constexpr int MAX_CONNECTIONS = 3;
constexpr int REQUEST_SLICES = 2;
constexpr int REQUEST_SIZE = 1 * 1024;
constexpr int HEADER_SIZE = 8 * 1024;
using HttpConnectionType = HttpAsyncConnection<REQUEST_SLICES, REQUEST_SLICES, HEADER_SIZE, REQUEST_SIZE>;
HttpConnectionType connections[MAX_CONNECTIONS];
HttpAsyncServer httpServer;
SC_TEST_EXPECT(httpServer.init(Span<HttpConnectionType>(connections)));
struct ServerContext
{
int numRequests;
} serverContext = {0};
httpServer.onRequest = [this, &serverContext](HttpConnection& client)
{
HttpRequest& request = client.request;
HttpResponse& response = client.response;
if (request.getParser().method != HttpParser::Method::HttpGET)
{
return;
}
if (request.getURL() != "/index.html" and request.getURL() != "/")
{
return;
}
serverContext.numRequests++;
SC_TEST_EXPECT(response.addHeader(
"Date",
"Mon, 27 Aug 2023 16:37:00 GMT"));
SC_TEST_EXPECT(response.addHeader(
"Last-Modified",
"Wed, 27 Aug 2023 16:37:00 GMT"));
const char sampleHtml[] = "<html>\r\n"
"<body bgcolor=\"#000000\" text=\"#ffffff\">\r\n"
"<h1>This is a title {}!</h1>\r\n"
"We must start from somewhere\r\n"
"</body>\r\n"
"</html>\r\n";
String content;
SC_TEST_EXPECT(StringBuilder::format(content, sampleHtml, serverContext.numRequests));
SmallString<16> contentLength;
SC_TEST_EXPECT(StringBuilder::format(contentLength,
"{}", content.view().sizeInBytes()));
SC_TEST_EXPECT(response.addHeader(
"Content-Length", contentLength.view()));
};
HttpAsyncFileServer
Http file server statically serves files from a directory.
This class registers the onRequest callback provided by HttpAsyncServer to serves files from a given directory.
constexpr int MAX_CONNECTIONS = 16;
constexpr int REQUEST_SLICES = 2;
constexpr int REQUEST_SIZE = 1 * 1024;
constexpr int HEADER_SIZE = 8 * 1024;
constexpr int NUM_FS_THREADS = 4;
using HttpConnectionType = HttpAsyncConnection<REQUEST_SLICES, REQUEST_SLICES, HEADER_SIZE, REQUEST_SIZE>;
HttpConnectionType connections[MAX_CONNECTIONS];
HttpAsyncFileServer::StreamQueue<REQUEST_SLICES> streams[MAX_CONNECTIONS];
HttpAsyncServer httpServer;
HttpAsyncFileServer fileServer;
ThreadPool threadPool;
if (eventLoop.needsThreadPoolForFileOperations())
{
}
SC_TEST_EXPECT(httpServer.init(Span<HttpConnectionType>(connections)));
SC_TEST_EXPECT(fileServer.init(threadPool, eventLoop, webServerFolder));
httpServer.onRequest = [&](HttpConnection& connection)
{
SC_ASSERT_RELEASE(fileServer.serveFile(streams[connection.getConnectionID().getIndex()], connection)); };
Examples
Roadmap
🟨 MVP
- Implement Stream based client and agent for socket re-use and connection persistence
- Support mostly used HTTP verbs / methods
- HTTP 1.1 Chunked Encoding
🟩 Usable Features:
🟦 Complete Features:
- HTTPS
- Support all HTTP verbs / methods
💡 Unplanned Features:
Statistics
| Type | Lines Of Code | Comments | Sum |
| Headers | 282 | 216 | 498 |
| Sources | 1530 | 283 | 1813 |
| Sum | 1812 | 499 | 2311 |