Logo Pico-Framework A web-first embedded framework for C++
Loading...
Searching...
No Matches
HttpServer Class Reference

HTTP Server that listens for incoming connections and dispatches requests. More...

#include <HttpServer.h>

+ Collaboration diagram for HttpServer:

Public Member Functions

 HttpServer (int port, Router &router)
 Construct a new HttpServer instance.
 
void enableTLS (const std::string &certPem, const std::string &keyPem)
 Enable TLS/HTTPS support with certificate and private key.
 
bool isTLSEnabled () const
 Check if TLS is enabled for this server.
 
bool start ()
 Start the HTTP server as a FreeRTOS task.
 
bool initNetwork ()
 Initialize the network stack (wait for DHCP or static IP).
 
void run ()
 Main server loop: initializes, binds, and begins accepting connections.
 
TcpinitListener ()
 Create, bind, and listen on the server.
 
void handleClient (Tcp *conn)
 Accept a client connection and handle it directly (not task-based).
 
void startHandlingClient (Tcp *conn)
 Spawn a task to handle the client connection.
 
HttpRequest receiveRequest (Tcp *conn, char *method, char *path, std::string &body, size_t &contentLength, std::unordered_map< std::string, std::string > &headers)
 Receive an HTTP request and parse key components.
 
RoutergetRouter ()
 Return the router associated with the server.
 

Static Public Member Functions

static void startServerTask (void *pvParameters)
 Launch the HTTP server task (used by FreeRTOS).
 
static void handleClientTask (void *pvParameters)
 Handle client logic inside a FreeRTOS task.
 

Private Attributes

int port
 Accept client connections in a blocking loop and spawn handlers.
 
Routerrouter
 Reference to router for dispatching requests.
 
Tcp listener
 
bool tlsEnabled = false
 
std::string serverCert
 
std::string serverKey
 

Static Private Attributes

static constexpr int BUFFER_SIZE = 1460
 
static constexpr int BOUNDARY_MAX_LEN = 128
 
static StackType_t xStack [HTTP_STACK_SIZE]
 Stack for static FreeRTOS task.
 
static StaticTask_t xTaskBuffer
 Task control block buffer.
 

Detailed Description

Definition at line 28 of file HttpServer.h.

Constructor & Destructor Documentation

◆ HttpServer()

HttpServer::HttpServer ( int  port,
Router router 
)

Construct a new HttpServer instance.

Parameters
portPort number to listen on.
routerReference to the Router for handling requests.
Parameters
portPort number to listen on.
routerReference to the Router for handling requests.

Definition at line 78 of file HttpServer.cpp.

80{
81}
int port
Accept client connections in a blocking loop and spawn handlers.
Definition HttpServer.h:124
Router & router
Reference to router for dispatching requests.
Definition HttpServer.h:125

Member Function Documentation

◆ enableTLS()

void HttpServer::enableTLS ( const std::string &  certPem,
const std::string &  keyPem 
)

Enable TLS/HTTPS support with certificate and private key.

Parameters
certPemServer certificate in PEM format
keyPemPrivate key in PEM format
Note
Must be called before start() to take effect
Parameters
certPemServer certificate in PEM format
keyPemPrivate key in PEM format
Note
Must be called before start() to take effect

Definition at line 84 of file HttpServer.cpp.

85{
86 serverCert = certPem;
87 serverKey = keyPem;
88 tlsEnabled = true;
89 printf("[HttpServer] TLS enabled for HTTPS support\n");
90}
bool tlsEnabled
Definition HttpServer.h:130
std::string serverCert
Definition HttpServer.h:131
std::string serverKey
Definition HttpServer.h:132

References serverCert, serverKey, and tlsEnabled.

◆ getRouter()

Router & HttpServer::getRouter ( )
inline
Returns
Router reference.

Definition at line 110 of file HttpServer.h.

110{ return router; }

References router.

◆ handleClient()

void HttpServer::handleClient ( Tcp conn)

Accept a client connection and handle it directly (not task-based).

Tcp* TCP connection instance

Tcp* TCP connection instance

Definition at line 245 of file HttpServer.cpp.

246{
247 int64_t start = to_ms_since_boot(get_absolute_time());
248 int64_t lastActivity = start;
249 const int64_t idleTimeoutMs = HTTP_IDLE_TIMEOUT; // idle timeout - kill connection if no data received
250
251
253 if (req.getMethod().empty())
254 {
255 TRACE("[HttpServer] Empty HTTP method — client either closed connection or it is Safari trying to reuse closed socket\n");
256 return;
257 }
258 TRACE("HttpRequest received: %s, %s\n", req.getMethod().c_str(), req.getPath().c_str());
259 TRACE("HttpRequest content length: %s\n", req.getContentLength());
260 TRACE("HttpRequest content type: %s\n", req.getContentType());
261 TRACE("HttpRequest boundary: %s\n", req.getBoundary());
262 TRACE("HttpRequest is multipart: %s\n", (req.isMultipart() ? "true" : "false"));
263 TRACE("HttpRequest header count: %d\n", req.getHeaders().size());
264 TRACE("HttpRequest url: %s\n", req.getUri().c_str());
265 TRACE("HttpRequest path: %s\n", req.getPath().c_str());
266 TRACE("HttpRequest query: %s\n", req.getQuery().c_str());
267
268 for (const auto& param : req.getQueryParams())
269 {
270 TRACE("HttpRequest query parameter %s : %s\n", param.first.c_str(), param.second.c_str());
271 }
272
273 for (const auto& param : req.getFormParams())
274 {
275 TRACE("HttpRequest form parameter %s : %s\n", param.first.c_str(), param.second.c_str());
276 }
277
278 for (const auto& cookie : req.getCookies())
279 {
280 TRACE("HttpRequest cookie %s : %s\n", cookie.first.c_str(), cookie.second.c_str());
281 }
282
283 if (req.getContentLength() > 0)
284 {
285 TRACE("HttpRequest body length: %d\n", req.getBody().length());
286 TRACE("HttpRequest start of body index: %d\n", req.getHeaderEnd());
287 }
288
289 TRACE("HttpRequest headers:\n");
290 for (const auto& headr : req.getHeaders())
291 {
292 TRACE("%s : %s\n", headr.first.c_str(), headr.second.c_str());
293 }
294
295 TRACE("HttpRequest body: %s\n", req.getBody().c_str());
296
297 QUIET_PRINTF("[HttpServer] Client request received: %s, path: %s\n", req.getMethod().c_str(), req.getPath().c_str());
298
299 HttpResponse res(conn);
300 TRACE("HttpResponse created\n");
301 res.setHeader("Connection", "close"); // Close the connection
302
303 bool ok = router.handleRequest(req, res);
304 TRACE("HttpRequest handled: %s\n", ok ? "true" : "false");
305
306 if (!ok)
307 {
308 JsonResponse::sendError(res, 404, "NOT_FOUND", "route: " + std::string(req.getUri()));
309 }
310
311 lastActivity = to_ms_since_boot(get_absolute_time());
312
313 if (req.getHeader("Connection") == "close")
314 {
315 TRACE("[HttpServer] Client requested Connection: close, closing connection\n");
316 return;
317 }
318
319 if (to_ms_since_boot(get_absolute_time()) - lastActivity > idleTimeoutMs)
320 {
321 printf("[HttpServer] Idle timeout reached, closing connection\n");
322 return;
323 }
324
325 conn->close();
326 int64_t end = to_ms_since_boot(get_absolute_time());
327 TRACE("[HttpServer] Client handled in %lld ms\n", end - start);
328}
#define TRACE(...)
Default trace (INFO level).
Definition DebugTrace.h:187
Forward declaration for potential routing needs.
Definition HttpRequest.h:32
const std::string & getBody() const
Get the request body (copy).
const std::map< std::string, std::string > & getHeaders() const
Get all request headers.
const std::string & getMethod() const
Get the HTTP method.
static HttpRequest receive(Tcp *tcp)
Receive and parse an HTTP request from a socket.
size_t getHeaderEnd()
Get the header end offset (used for body parsing).
const std::string & getPath() const
Get the parsed request path (without query string).
const std::string getContentType() const
Get the raw Content-Type string.
const std::string & getQuery() const
Get the parsed query string from the URL.
int getContentLength() const
Get the Content-Length header as integer.
const std::string getBoundary() const
Get the boundary string (for multipart/form-data).
bool isMultipart() const
Check whether the request is multipart/form-data.
std::string getHeader(const std::string &field) const
Get a specific header field (case-insensitive).
const std::string & getUri() const
Get the original URL from the request line.
Represents an HTTP response object.
bool start()
Start the HTTP server as a FreeRTOS task.
bool handleRequest(HttpRequest &req, HttpResponse &res)
Handle an incoming HTTP request.
Definition Router.cpp:228
int close()
Close the connection and free resources.
Definition Tcp.cpp:443
#define QUIET_PRINTF(...)
#define HTTP_IDLE_TIMEOUT
Timeout for idle HTTP connections in milliseconds.
void sendError(HttpResponse &res, int statusCode, const std::string &code, const std::string &message)

References Tcp::close(), HttpRequest::getBody(), HttpRequest::getBoundary(), HttpRequest::getContentLength(), HttpRequest::getContentType(), HttpRequest::getCookies(), HttpRequest::getFormParams(), HttpRequest::getHeader(), HttpRequest::getHeaderEnd(), HttpRequest::getHeaders(), HttpRequest::getMethod(), HttpRequest::getPath(), HttpRequest::getQuery(), HttpRequest::getQueryParams(), HttpRequest::getUri(), Router::handleRequest(), HTTP_IDLE_TIMEOUT, HttpRequest::isMultipart(), QUIET_PRINTF, HttpRequest::receive(), router, JsonResponse::sendError(), HttpResponse::setHeader(), start(), and TRACE.

Referenced by startHandlingClient().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ handleClientTask()

static void HttpServer::handleClientTask ( void *  pvParameters)
static
Parameters
pvParametersPointer to TaskParams (including Tcp*)

Referenced by startHandlingClient().

+ Here is the caller graph for this function:

◆ initListener()

Tcp * HttpServer::initListener ( )
Returns
Tcp* TCP connection instance

Definition at line 192 of file HttpServer.cpp.

193{
194 // Configure TLS if enabled
195 if (tlsEnabled) {
196 printf("[HttpServer] Configuring TLS server with certificate and key\n");
198 }
199
201 return nullptr;
202 }
203
204 printf("[HttpServer] Server listening on port %d (%s)\n",
205 port, tlsEnabled ? "HTTPS" : "HTTP");
206
207 // Once server is listening
209 AppContext::get<EventManager>()->postEvent(e); // tell others that we are up
210 return &listener;
211}
static constexpr std::uintptr_t getTypeKey()
Definition AppContext.h:91
void setServerTlsConfig(const std::string &certPem, const std::string &keyPem)
Set the certificate and key to use for server-side TLS (PEM format).
bool bindAndListen(int port)
Bind and listen on a port for incoming connections (for server use).
Definition Tcp.cpp:542
Represents a framework event, optionally carrying payload data.
Definition Event.h:24

References Tcp::bindAndListen(), AppContext::getTypeKey(), HttpServerStarted, listener, port, serverCert, serverKey, Tcp::setServerTlsConfig(), and tlsEnabled.

Referenced by run().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ initNetwork()

bool HttpServer::initNetwork ( )

Initialize the network stack (wait for DHCP or static IP).

Returns
true if successful.
Returns
true if successful.

Definition at line 170 of file HttpServer.cpp.

171{
172 struct netif *netif;
173
174 //TRACE("Waiting for DHCP lease...\n");
175
176 while (true)
177 {
178 netif = netif_list;
179 if (netif && netif->ip_addr.addr != 0)
180 {
181 break;
182 }
183 vTaskDelay(pdMS_TO_TICKS(10));
184 }
185
186 //TRACE("Assigned IP Address: %s\n", ip4addr_ntoa(&netif->ip_addr));
187 return true;
188}

Referenced by run().

+ Here is the caller graph for this function:

◆ isTLSEnabled()

bool HttpServer::isTLSEnabled ( ) const

Check if TLS is enabled for this server.

Returns
true if TLS is configured and enabled
Returns
true if TLS is configured and enabled

Definition at line 93 of file HttpServer.cpp.

94{
95 return tlsEnabled;
96}

References tlsEnabled.

◆ receiveRequest()

HttpRequest HttpServer::receiveRequest ( Tcp conn,
char *  method,
char *  path,
std::string &  body,
size_t &  contentLength,
std::unordered_map< std::string, std::string > &  headers 
)
Parameters
Tcp*TCP connection instance
methodOutput buffer for method.
pathOutput buffer for path.
bodyOutput body content.
contentLengthOutput content length.
headersOutput map of parsed headers.
Returns
Parsed HttpRequest object.

◆ run()

void HttpServer::run ( )

Main server loop: initializes, binds, and begins accepting connections.

Definition at line 118 of file HttpServer.cpp.

119{
120
121 printf("[HttpServer] Starting %s Server on port %d\n",
122 tlsEnabled ? "HTTPS" : "HTTP", port);
123
124 if (!initNetwork())
125 {
126 return;
127 }
128
130 if (!listener)
131 {
132 printf("[HttpServer] Failed to initialize listener\n");
133 return;
134 }
135
137
138 // Optional: store listener as a class member if needed later
139 while (true)
140 {
141 TRACE("[HttpServer] Waiting for client connection...\n");
142 Tcp* conn = listener->accept();
143 if (conn)
144 {
145 QUIET_PRINTF("\n===== HTTP CLIENT ACCEPTED ====\n");
146 QUIET_PRINTF("[HttpServer] Accepted client connection\n");
148 vTaskDelay(pdMS_TO_TICKS(10));
149
150 QUIET_PRINTF("[HttpServer] Client connection handled\n");
151 QUIET_PRINTF("===============================\n\n");
152 #if !defined(HTTP_SERVER_USE_TASK_PER_CLIENT)
153 delete conn;
154 #endif
155 }
156 else
157 {
158 warning("[HttpServer] Failed to accept client connection\n");
159 vTaskDelay(pdMS_TO_TICKS(10)); // Wait before retrying
160 }
161
162 }
163
164 // Note: we never reach here in this model
165 delete listener;
166}
bool initNetwork()
Initialize the network stack (wait for DHCP or static IP).
Tcp * initListener()
Create, bind, and listen on the server.
void startHandlingClient(Tcp *conn)
Spawn a task to handle the client connection.
General-purpose TCP socket wrapper with optional TLS support via mbedTLS (altcp).
Definition Tcp.h:39
Tcp * accept()
Accept a new incoming connection (for server use).
Definition Tcp.cpp:491
void warning(const std::string &msg)
Definition utility.cpp:215

References Tcp::accept(), AppContext::getTypeKey(), HttpServerStarted, initListener(), initNetwork(), listener, port, QUIET_PRINTF, startHandlingClient(), tlsEnabled, TRACE, and warning().

Referenced by startServerTask().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ start()

bool HttpServer::start ( )

Start the HTTP server as a FreeRTOS task.

Returns
true if task created successfully.
Returns
true if task created successfully.

Definition at line 99 of file HttpServer.cpp.

100{
102 return xTaskCreateStatic(startServerTask, "HttpServer", HTTP_STACK_SIZE, this, 5, xStack, &xTaskBuffer);
103}
SemaphoreHandle_t clientSemaphore
static constexpr int MAX_CONCURRENT_CLIENTS
#define HTTP_STACK_SIZE
Definition HttpServer.h:23
static void startServerTask(void *pvParameters)
Launch the HTTP server task (used by FreeRTOS).
static StackType_t xStack[HTTP_STACK_SIZE]
Stack for static FreeRTOS task.
Definition HttpServer.h:136
static StaticTask_t xTaskBuffer
Task control block buffer.
Definition HttpServer.h:137

References clientSemaphore, HTTP_STACK_SIZE, MAX_CONCURRENT_CLIENTS, startServerTask(), xStack, and xTaskBuffer.

Referenced by handleClient(), and App::onEvent().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ startHandlingClient()

void HttpServer::startHandlingClient ( Tcp conn)
Parameters
Tcp*TCP connection instance.

Definition at line 213 of file HttpServer.cpp.

214{
215#ifdef HTTP_SERVER_USE_TASK_PER_CLIENT
216 if (xSemaphoreTake(clientSemaphore, pdMS_TO_TICKS(100)) == pdPASS)
217 {
218 TaskParams *params = new TaskParams{this, conn};
219
220 if (xTaskCreate(handleClientTask, "HttpClient", 4096, params, 4, NULL) == pdPASS)
221 {
222 TRACE("Client task created successfully");
223 }
224 else
225 {
226 TRACE("Failed to create client task");
227 conn->close();
228 delete params;
229 xSemaphoreGive(clientSemaphore);
230 }
231 }
232 else
233 {
234 TRACE("Max concurrent clients reached, closing connection");
235 conn->close();
236 // Optional: return a "503 Service Unavailable" if desired
237 }
238#else
239 handleClient(conn);
240
241#endif
242}
void handleClient(Tcp *conn)
Accept a client connection and handle it directly (not task-based).
static void handleClientTask(void *pvParameters)
Handle client logic inside a FreeRTOS task.
Parameters passed to the per-client handler task.

References clientSemaphore, Tcp::close(), handleClient(), handleClientTask(), and TRACE.

Referenced by run().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ startServerTask()

void HttpServer::startServerTask ( void *  pvParameters)
static

Launch the HTTP server task (used by FreeRTOS).

Parameters
pvParametersPointer to HttpServer instance.
Parameters
pvParametersPointer to HttpServer instance.

Definition at line 106 of file HttpServer.cpp.

107{
108 HttpServer *server = static_cast<HttpServer *>(pvParameters);
109 server->run();
110 vTaskDelete(NULL);
111}
HTTP Server that listens for incoming connections and dispatches requests.
Definition HttpServer.h:29
void run()
Main server loop: initializes, binds, and begins accepting connections.

References run().

Referenced by start().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ BOUNDARY_MAX_LEN

constexpr int HttpServer::BOUNDARY_MAX_LEN = 128
staticconstexprprivate

Definition at line 134 of file HttpServer.h.

◆ BUFFER_SIZE

constexpr int HttpServer::BUFFER_SIZE = 1460
staticconstexprprivate

Definition at line 133 of file HttpServer.h.

◆ listener

Tcp HttpServer::listener
private

Definition at line 127 of file HttpServer.h.

Referenced by initListener(), and run().

◆ port

int HttpServer::port
private

Port number to listen on.

Definition at line 124 of file HttpServer.h.

Referenced by initListener(), and run().

◆ router

Router& HttpServer::router
private

Definition at line 125 of file HttpServer.h.

Referenced by getRouter(), and handleClient().

◆ serverCert

std::string HttpServer::serverCert
private

Definition at line 131 of file HttpServer.h.

Referenced by enableTLS(), and initListener().

◆ serverKey

std::string HttpServer::serverKey
private

Definition at line 132 of file HttpServer.h.

Referenced by enableTLS(), and initListener().

◆ tlsEnabled

bool HttpServer::tlsEnabled = false
private

Definition at line 130 of file HttpServer.h.

Referenced by enableTLS(), initListener(), isTLSEnabled(), and run().

◆ xStack

StackType_t HttpServer::xStack
staticprivate

Definition at line 136 of file HttpServer.h.

Referenced by start().

◆ xTaskBuffer

StaticTask_t HttpServer::xTaskBuffer
staticprivate

Definition at line 137 of file HttpServer.h.

Referenced by start().


The documentation for this class was generated from the following files: