Skip to content

Multi-platform http server - #646

Merged
KenVanHoeylandt merged 6 commits into
mainfrom
multi-platform-server-support
Sep 6, 2026
Merged

Multi-platform http server#646
KenVanHoeylandt merged 6 commits into
mainfrom
multi-platform-server-support

Conversation

@KenVanHoeylandt

@KenVanHoeylandt KenVanHoeylandt commented Sep 6, 2026

Copy link
Copy Markdown
Contributor
  • Add server support to http-module
  • Ensure DevelopmentService works on all platforms (including posix)
  • Ensure the built-in web server with dashboard works on all platforms (inluding posix). It still has some issues with certain featuers, but the basics work.

@coderabbitai

coderabbitai Bot commented Sep 6, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The change adds a platform-neutral HTTP server module with routing, request parsing, response APIs, lifecycle control, chunked transfer, and integration tests. Development and web server services migrate from ESP-IDF HTTP APIs to the new server API. Related services and apps now compile and register across platforms. Web server settings use portable IP lookup and platform-specific default ports. File execution uses app_execute directly.

Merge Risk: 🟠 High · up to c675b

The portable HTTP services are not ready to merge: exposed management routes can trigger unintended actions, malformed uploads can exhaust storage, and uploaded dashboard content can execute in the server origin. Several cross-platform lifecycle and response behaviors also remain incorrect.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.06% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 124 functions across 20 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: adding a multi-platform HTTP server. It is concise and relevant to the pull request objectives.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch multi-platform-server-support

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🧹 Nitpick comments (3)
Modules/http-module/source/server.cpp (1)

226-229: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Terminate a chunked response that the handler left open.

The fallback covers only the case where the handler sent nothing. If a handler calls http_server_request_send_chunk_start and then returns without calling http_server_request_send_chunk_end, response_sent is already true, so no terminator is sent. The client receives a chunked body with no final "0\r\n\r\n" and reports a truncated response.

Close the chunked stream here when it is still open.

♻️ Proposed change
     if (!request.response_sent) {
         LOG_W(TAG, "Handler for %s did not send a response", matched->uri);
         http_server_request_send_error(&request, 500, "Handler did not send a response");
+    } else if (request.chunked) {
+        LOG_W(TAG, "Handler for %s left a chunked response open", matched->uri);
+        http_server_request_send_chunk_end(&request);
     }
Modules/http-module/tests/source/server_test.cpp (1)

27-28: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Correct the file and function names in this comment.

The comment names server_posix.cpp and recv_retry(). The implementation lives in Modules/http-module/source/server.cpp, and the function is receive_retry().

♻️ Proposed change
-    // The FreeRTOS POSIX port's tick signal can interrupt a blocking syscall on this thread, so
-    // every blocking call below retries on EINTR (matches server_posix.cpp's own recv_retry()).
+    // The FreeRTOS POSIX port's tick signal can interrupt a blocking syscall on this thread, so
+    // every blocking call below retries on EINTR (matches server.cpp's own receive_retry()).
Tactility/Source/service/webserver/WebServerService.cpp (1)

1725-1729: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Skip the 2-second delay on non-ESP platforms.

Line 1724 blocks the request task for 2 seconds so the response can flush before esp_restart(). On non-ESP platforms no restart follows, so the delay only stalls the HTTP server task and delays the reply to the client. Move vTaskDelay inside the ESP_PLATFORM branch.

♻️ Proposed change
-    // Reboot after a short delay to allow response to be sent
-    vTaskDelay(pdMS_TO_TICKS(2000));
 `#ifdef` ESP_PLATFORM
+    // Reboot after a short delay to allow response to be sent
+    vTaskDelay(pdMS_TO_TICKS(2000));
     esp_restart();
 `#else`
     LOG_W(TAG, "Reboot is not supported on this platform");
 `#endif`

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: a15ce6b3-38a0-4e4b-ba64-b6bca864ae86

📥 Commits

Reviewing files that changed from the base of the PR and between a0b2ee7 and 78337bd.

📒 Files selected for processing (24)
  • Modules/http-module/include/http/server.h
  • Modules/http-module/include/http/types.h
  • Modules/http-module/source/module.cpp
  • Modules/http-module/source/server.cpp
  • Modules/http-module/source/types.cpp
  • Modules/http-module/tests/source/server_test.cpp
  • Tactility/Include/Tactility/network/HttpServer.h
  • Tactility/Include/Tactility/network/HttpServerReq.h
  • Tactility/Include/Tactility/network/HttpdReq.h
  • Tactility/Include/Tactility/settings/WebServerSettings.h
  • Tactility/Private/Tactility/service/development/DevelopmentService.h
  • Tactility/Private/Tactility/service/development/DevelopmentSettings.h
  • Tactility/Private/Tactility/service/webserver/WebServerService.h
  • Tactility/Source/Tactility.cpp
  • Tactility/Source/app/development/Development.cpp
  • Tactility/Source/app/files/View.cpp
  • Tactility/Source/app/terminal/Terminal.cpp
  • Tactility/Source/app/webserversettings/WebServerSettings.cpp
  • Tactility/Source/network/HttpServer.cpp
  • Tactility/Source/network/HttpServerReq.cpp
  • Tactility/Source/network/HttpdReq.cpp
  • Tactility/Source/service/development/DevelopmentService.cpp
  • Tactility/Source/service/development/DevelopmentSettings.cpp
  • Tactility/Source/service/webserver/WebServerService.cpp
💤 Files with no reviewable changes (5)
  • Tactility/Source/service/development/DevelopmentSettings.cpp
  • Tactility/Source/network/HttpServer.cpp
  • Tactility/Include/Tactility/network/HttpServer.h
  • Tactility/Source/network/HttpdReq.cpp
  • Tactility/Private/Tactility/service/development/DevelopmentSettings.h

Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review.

Comment thread Modules/http-module/source/server.cpp
Comment thread Modules/http-module/source/server.cpp
Comment thread Modules/http-module/source/server.cpp
Comment thread Modules/http-module/source/server.cpp
Comment thread Modules/http-module/source/server.cpp
Comment thread Tactility/Source/app/files/View.cpp Outdated
Comment thread Tactility/Source/network/HttpServerReq.cpp
Comment thread Tactility/Source/network/HttpServerReq.cpp Outdated
Comment thread Tactility/Source/service/development/DevelopmentService.cpp
Comment thread Tactility/Source/service/development/DevelopmentService.cpp

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
Modules/http-module/source/server.cpp (1)

451-451: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Apply a body-progress deadline.

Line 451 starts a new five-second wait for every body read. A client can keep /app/install in receiveFile by sending one byte before each timeout. The listener task then remains in handle_connection, so it cannot accept other clients and http_server_stop waits for the handler to finish.

Carry a body deadline into HttpServerRequest, or enforce a minimum body throughput and a maximum body duration.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 1c950c29-6178-4755-bb2f-a5553a8b7cb0

📥 Commits

Reviewing files that changed from the base of the PR and between e8a35dc and 1928cfa.

📒 Files selected for processing (6)
  • Modules/http-module/source/server.cpp
  • Modules/http-module/tests/source/server_test.cpp
  • Tactility/Include/Tactility/network/HttpServerReq.h
  • Tactility/Source/network/HttpServerReq.cpp
  • Tactility/Source/network/Url.cpp
  • Tactility/Source/service/development/DevelopmentService.cpp
🚧 Files skipped from review as they are similar to previous changes (3)
  • Modules/http-module/tests/source/server_test.cpp
  • Tactility/Include/Tactility/network/HttpServerReq.h
  • Tactility/Source/network/HttpServerReq.cpp

Included review availability: Your plan provides up to 4 included reviews per hour; 2 remain after this review.

Comment thread Modules/http-module/source/server.cpp
Comment thread Modules/http-module/source/server.cpp Outdated
Comment thread Tactility/Source/service/development/DevelopmentService.cpp

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
Tactility/Source/service/webserver/WebServerService.cpp (4)

520-524: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Stop AP mode on every HTTP server startup failure.

If startApMode() succeeds but allocation or startup fails, this branch frees the HTTP server and returns without calling stopApMode(). stopServer() cannot clean up later because httpServer is null and returns at Line 543. Stop AP mode before returning from this failure path.

Proposed fix
     if (httpServer == nullptr || http_server_start(httpServer) != ERROR_NONE) {
         LOG_E(TAG, "Failed to start HTTP server on port %u", (unsigned)settings.webServerPort);
         http_server_free(httpServer);
         httpServer = nullptr;
+        stopApMode();
         return false;
     }

1002-1002: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use boundary-aware URI matching in all dispatchers.

These strncmp checks accept arbitrary suffixes. For example, /admin/reboot-now triggers reboot and /api/apps/run-now invokes the app-run handler instead of returning 404. Replace the prefix checks with the existing uriMatches helper.

Also applies to: 1015-1015, 1027-1034, 1052-1056, 1074-1074


1723-1726: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not report a reboot on non-ESP platforms.

The handler sends Rebooting... and blocks for two seconds before the non-ESP branch only logs that reboot is unsupported. Non-ESP clients receive a misleading success response. Send an unsupported-operation error on non-ESP platforms, and keep the delay and restart logic inside the ESP branch.


1790-1792: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Implement the default.html fallback.

This branch only logs that default.html should be served. It does not update requestedPath or dataPath, so the request still checks the missing dashboard.html path and returns 404.

Proposed fix
     if (requestedPath == "/dashboard.html" && !file::isFile(dataPath.c_str())) {
         LOG_I(TAG, "dashboard.html not found, serving default.html");
+        requestedPath = "/default.html";
+        dataPath = std::string(file::MOUNT_POINT_SYSTEM) + "/app/WebServer" + requestedPath;
     }

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 88bca0cd-09fc-462d-861f-b0bb2f0ef341

📥 Commits

Reviewing files that changed from the base of the PR and between 1928cfa and 7ecbc83.

📒 Files selected for processing (1)
  • Tactility/Source/service/webserver/WebServerService.cpp

Included review availability: Your plan provides up to 4 included reviews per hour; 1 remains after this review.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
Tactility/Source/service/webserver/WebServerService.cpp (4)

1003-1003: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Require exact or segment-boundary route checks.

strncmp accepts any URI that starts with the route. For example, /admin/reboot-now can invoke reboot, and /api/apps/run-extra?id=... can invoke app_start. Use an exact-path check for leaf endpoints. Allow only \0 or ? after the route.

Also applies to: 1016-1016, 1028-1035, 1053-1057, 1075-1076


1728-1734: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Return an unsupported response on non-ESP platforms.

The handler sends "Rebooting..." and waits two seconds before the non-ESP branch logs that reboot is unsupported. Non-ESP clients receive a successful-looking response even though no reboot occurs.

Move the response and delay inside #ifdef ESP_PLATFORM. Return HTTP 501 on non-ESP platforms.


1432-1433: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Denial of Service (CWE-400): Uncontrolled Resource Consumption

Reachability: External · Exploitability: Moderate

Delete the temporary file when trailing multipart validation fails.

receiveFile creates file_path before readAndDiscardOrSendError runs. This branch returns without deleting it, allowing repeated truncated uploads to fill the temporary filesystem.

Proposed cleanup
     if (!network::readAndDiscardOrSendError(request, boundary_and_newlines_after_file)) {
+        file::deleteFile(file_path);
         return ERROR_UNDEFINED;
     }

923-924: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

XSS (CWE-79): Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

Reachability: External · Exploitability: Moderate

Do not serve user-writable files as active web content.

handleFsUpload writes client-supplied content below /sdcard, including /sdcard/tactility/webserver. handleAssets serves that directory and maps .html, .js, and .svg files to active MIME types. A client can upload content that executes in the dashboard origin when web-server authentication is disabled.

Store uploads outside the served directory, allow only inert formats, or serve user files from an isolated origin with download disposition.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 09f87cf8-8a3d-4899-a58f-28e511d3a9c1

📥 Commits

Reviewing files that changed from the base of the PR and between 7ecbc83 and c675b69.

📒 Files selected for processing (2)
  • Modules/http-module/source/server.cpp
  • Tactility/Source/service/webserver/WebServerService.cpp
🚧 Files skipped from review as they are similar to previous changes (1)
  • Modules/http-module/source/server.cpp

Included review availability: Your plan provides up to 4 included reviews per hour; 1 remains after this review.

@KenVanHoeylandt
KenVanHoeylandt merged commit 1b16184 into main Sep 6, 2026
64 checks passed
@KenVanHoeylandt
KenVanHoeylandt deleted the multi-platform-server-support branch September 6, 2026 12:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant