Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
SC::HttpAsyncServer Struct Reference

Async Http Server. More...

#include <HttpAsyncServer.h>

Public Member Functions

template<typename T , typename = typename TypeTraits::EnableIf<TypeTraits::IsBaseOf<HttpAsyncConnectionBase, T>::value>::type>
Result init (Span< T > clients)
 Initializes the async server with all needed memory buffers.
 
template<typename T , typename = typename TypeTraits::EnableIf<TypeTraits::IsBaseOf<HttpAsyncConnectionBase, T>::value>::type>
Result resize (Span< T > clients)
 
Result close ()
 Closes the server, removing references to the memory buffers passed during init.
 
Result start (AsyncEventLoop &loop, StringSpan address, uint16_t port)
 Starts the http server on the given AsyncEventLoop, address and port.
 
Result stop ()
 Stops http server asynchronously pushing cancel and close requests to the event loop.
 
bool isStarted () const
 Returns true if the server has been started.
 
const HttpConnectionsPoolgetConnections () const
 

Public Attributes

Function< void(HttpConnection &)> onRequest
 Called after enough data from a newly connected client has arrived, causing all headers to be parsed.
 

Detailed Description

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; // Max number of concurrent http connections
constexpr int REQUEST_SLICES = 2; // Number of slices of the request buffer for each connection
constexpr int REQUEST_SIZE = 1 * 1024; // How many bytes are allocated to stream data for each connection
constexpr int HEADER_SIZE = 8 * 1024; // How many bytes are dedicated to hold request and response headers
// The size of the header and request memory, and length of read/write queues are fixed here, but user can
// set any arbitrary size for such queues doing the same being done in HttpAsyncConnection constructor.
using HttpConnectionType = HttpAsyncConnection<REQUEST_SLICES, REQUEST_SLICES, HEADER_SIZE, REQUEST_SIZE>;
// 1. Memory to hold all http connections (single array for simplicity).
// WebServerExample (SCExample) shows how to leverage virtual memory, to handle dynamic number of clients
HttpConnectionType connections[MAX_CONNECTIONS];
// Initialize and start the http server
HttpAsyncServer httpServer;
SC_TEST_EXPECT(httpServer.init(Span<HttpConnectionType>(connections)));
SC_TEST_EXPECT(httpServer.start(eventLoop, "127.0.0.1", 6152));
struct ServerContext
{
int numRequests;
} serverContext = {0};
// Handle the request and answer accordingly
httpServer.onRequest = [this, &serverContext](HttpConnection& client)
{
HttpRequest& request = client.request;
HttpResponse& response = client.response;
if (request.getParser().method != HttpParser::Method::HttpGET)
{
SC_TEST_EXPECT(response.startResponse(405));
SC_TEST_EXPECT(response.sendHeaders());
SC_TEST_EXPECT(response.end());
return;
}
if (request.getURL() != "/index.html" and request.getURL() != "/")
{
SC_TEST_EXPECT(response.startResponse(404));
SC_TEST_EXPECT(response.sendHeaders());
SC_TEST_EXPECT(response.end());
return;
}
serverContext.numRequests++;
SC_TEST_EXPECT(response.startResponse(200));
SC_TEST_EXPECT(response.addHeader("Connection", "Closed"));
SC_TEST_EXPECT(response.addHeader("Content-Type", "text/html"));
SC_TEST_EXPECT(response.addHeader("Server", "SC"));
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";
// Create a "user provided" dynamically allocated string, to show this is possible
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()));
SC_TEST_EXPECT(response.sendHeaders());
// Note that the system takes ownership of the dynamically allocated user provided string
// through type erasure and it will invoke its destructor after th write operation will finish,
// freeing user memory as expected.
// This write operation succeeds because EXTRA_SLICES allocates one more slot buffer exactly
// to hold this user provided buffer, that is not part of the "re-usable" buffers created
// at the beginning of this sample.
SC_TEST_EXPECT(response.getWritableStream().write(move(content)));
SC_TEST_EXPECT(response.end());
};

Member Function Documentation

◆ close()

Result SC::HttpAsyncServer::close ( )

Closes the server, removing references to the memory buffers passed during init.

Note
This call will wait until all async operations will be finished before returning

◆ init()

template<typename T , typename = typename TypeTraits::EnableIf<TypeTraits::IsBaseOf<HttpAsyncConnectionBase, T>::value>::type>
Result SC::HttpAsyncServer::init ( Span< T > clients)
inline

Initializes the async server with all needed memory buffers.

◆ isStarted()

bool SC::HttpAsyncServer::isStarted ( ) const
inlinenodiscard

Returns true if the server has been started.

◆ start()

Result SC::HttpAsyncServer::start ( AsyncEventLoop & loop,
StringSpan address,
uint16_t port )

Starts the http server on the given AsyncEventLoop, address and port.

Parameters
loopThe event loop to be used, where to add the listening socket
addressThe address of local interface where to listen to
portThe local port where to start listening to
Returns
Valid Result if http listening has been started successfully

◆ stop()

Result SC::HttpAsyncServer::stop ( )

Stops http server asynchronously pushing cancel and close requests to the event loop.

Warning
Consider calling HttpAsyncServer::close before reclaiming memory used by this class

Member Data Documentation

◆ onRequest

Function<void(HttpConnection&)> SC::HttpAsyncServer::onRequest

Called after enough data from a newly connected client has arrived, causing all headers to be parsed.


The documentation for this struct was generated from the following file: