1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
5 * @file CustomConfig.ino
6 * @brief Demonstrates overriding every compile-time sizing constant.
8 * All buffer and pool dimensions are set via build flags in platformio.ini.
9 * The values below cut memory use roughly in half compared to the defaults,
10 * which is useful for sensor nodes or builds that share the ESP32 heap with
13 * Add these to your platformio.ini [env] block to use this profile:
17 * -DMAX_CONNS=2 ; simultaneous TCP connections (default 4)
18 * -DRX_BUF_SIZE=512 ; ring-buffer bytes / connection (default 1024)
19 * -DCONN_TIMEOUT_MS=3000 ; idle timeout in ms (default 5000)
20 * -DMAX_HEADERS=4 ; headers stored per request (default 8)
21 * -DMAX_PATH_LEN=48 ; URL path bytes incl. leading / (default 64)
22 * -DMAX_KEY_LEN=16 ; header field-name bytes (default 24)
23 * -DMAX_VAL_LEN=32 ; header field-value bytes (default 48)
24 * -DMAX_QUERY_LEN=64 ; raw query-string bytes (default 128)
25 * -DMAX_QUERY_PARAMS=4 ; parsed query parameters (default 8)
26 * -DQUERY_KEY_LEN=16 ; query parameter key bytes (default 24)
27 * -DQUERY_VAL_LEN=24 ; query parameter value bytes (default 48)
28 * -DBODY_BUF_SIZE=128 ; request body bytes (default 256)
29 * -DMAX_ROUTES=8 ; registered route handlers (default 16)
32 * Example curl commands:
33 * curl http://<ip>/config
34 * curl http://<ip>/echo -X POST -d "hello"
35 * curl "http://<ip>/search?q=esp32&sort=date"
38#include "DeterministicESPAsyncWebServer.h"
39#include "network_drivers/physical.h"
42static const char *SSID = "YOUR_SSID";
43static const char *PASSWORD = "YOUR_PASSWORD";
48// Returns every active sizing constant as JSON so you can verify your
49// build flags took effect without needing a debugger.
50void handle_config(uint8_t slot_id, HttpReq *req)
53 snprintf(body, sizeof(body),
57 "\"CONN_TIMEOUT_MS\":%u,"
59 "\"MAX_PATH_LEN\":%u,"
62 "\"MAX_QUERY_LEN\":%u,"
63 "\"MAX_QUERY_PARAMS\":%u,"
64 "\"QUERY_KEY_LEN\":%u,"
65 "\"QUERY_VAL_LEN\":%u,"
66 "\"BODY_BUF_SIZE\":%u,"
69 (unsigned)MAX_CONNS, (unsigned)RX_BUF_SIZE, (unsigned)CONN_TIMEOUT_MS, (unsigned)MAX_HEADERS,
70 (unsigned)MAX_PATH_LEN, (unsigned)MAX_KEY_LEN, (unsigned)MAX_VAL_LEN, (unsigned)MAX_QUERY_LEN,
71 (unsigned)MAX_QUERY_PARAMS, (unsigned)QUERY_KEY_LEN, (unsigned)QUERY_VAL_LEN, (unsigned)BODY_BUF_SIZE,
72 (unsigned)MAX_ROUTES);
74 server.send(slot_id, 200, "application/json", body);
78// Echoes the request body back. With -DBODY_BUF_SIZE=128, bodies longer
79// than 128 bytes trigger an automatic 413 before this handler is called.
80void handle_echo(uint8_t slot_id, HttpReq *req)
82 server.send(slot_id, 200, "text/plain", (const char *)req->body);
86// Reads up to MAX_QUERY_PARAMS query parameters and echoes them back.
87// With -DMAX_QUERY_PARAMS=4, a fifth parameter is parsed but silently
88// dropped — this handler shows exactly what was retained.
89void handle_search(uint8_t slot_id, HttpReq *req)
91 char body[256] = "params: ";
92 for (uint8_t i = 0; i < req->query_count; i++)
95 strncat(body, ", ", sizeof(body) - strlen(body) - 1);
96 strncat(body, req->query_params[i].key, sizeof(body) - strlen(body) - 1);
97 strncat(body, "=", sizeof(body) - strlen(body) - 1);
98 strncat(body, req->query_params[i].val, sizeof(body) - strlen(body) - 1);
100 server.send(slot_id, 200, "text/plain", body);
105 Serial.begin(115200);
107 // Print the active config so you can confirm build flags without curl
108 Serial.println("\n--- Active DetWebServer config ---");
109 Serial.printf(" MAX_CONNS = %u\n", (unsigned)MAX_CONNS);
110 Serial.printf(" RX_BUF_SIZE = %u\n", (unsigned)RX_BUF_SIZE);
111 Serial.printf(" CONN_TIMEOUT_MS = %u\n", (unsigned)CONN_TIMEOUT_MS);
112 Serial.printf(" MAX_HEADERS = %u\n", (unsigned)MAX_HEADERS);
113 Serial.printf(" MAX_PATH_LEN = %u\n", (unsigned)MAX_PATH_LEN);
114 Serial.printf(" MAX_KEY_LEN = %u\n", (unsigned)MAX_KEY_LEN);
115 Serial.printf(" MAX_VAL_LEN = %u\n", (unsigned)MAX_VAL_LEN);
116 Serial.printf(" MAX_QUERY_LEN = %u\n", (unsigned)MAX_QUERY_LEN);
117 Serial.printf(" MAX_QUERY_PARAMS= %u\n", (unsigned)MAX_QUERY_PARAMS);
118 Serial.printf(" QUERY_KEY_LEN = %u\n", (unsigned)QUERY_KEY_LEN);
119 Serial.printf(" QUERY_VAL_LEN = %u\n", (unsigned)QUERY_VAL_LEN);
120 Serial.printf(" BODY_BUF_SIZE = %u\n", (unsigned)BODY_BUF_SIZE);
121 Serial.printf(" MAX_ROUTES = %u\n", (unsigned)MAX_ROUTES);
122 Serial.println("----------------------------------");
124 init_wifi_physical(SSID, PASSWORD);
125 Serial.print("Connecting to WiFi");
126 while (!wifi_ready())
131 Serial.print("\nIP: ");
132 Serial.println(WiFi.localIP());
134 server.on("/config", HTTP_GET, handle_config);
135 server.on("/echo", HTTP_POST, handle_echo);
136 server.on("/search", HTTP_GET, handle_search);
138 // Pass a runtime config to override CONN_TIMEOUT_MS without a rebuild
139 WebServerConfig cfg = {.conn_timeout_ms = CONN_TIMEOUT_MS};
140 int32_t result = server.begin(80, &cfg);
143 Serial.printf("begin() failed — need %d more heap bytes\n", -result);
146 Serial.println("Server started on port 80");