Bundle xterm.js libraries as embedded static files

Embed xterm.js 5.5.0, addon-fit 0.10.0, and addon-web-links 0.11.0
(minified JS and CSS) into the server binary, served at /js/*.
This removes the dependency on CDN and makes the web terminal
page fully self-contained, like the dashboard.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
This commit is contained in:
Alexey Milovidov
2026-03-21 14:28:05 +01:00
co-authored by Claude Opus 4.6
parent 1d5c996a8f
commit ab7bc27ae3
7 changed files with 78 additions and 15 deletions
+38 -11
View File
@@ -30,6 +30,22 @@ constexpr unsigned char resource_lz_string_js[] =
{
#embed "../../programs/server/js/lz-string.js"
};
constexpr unsigned char resource_xterm_js[] =
{
#embed "../../programs/server/js/xterm.min.js"
};
constexpr unsigned char resource_xterm_css[] =
{
#embed "../../programs/server/js/xterm.min.css"
};
constexpr unsigned char resource_addon_fit_js[] =
{
#embed "../../programs/server/js/addon-fit.min.js"
};
constexpr unsigned char resource_addon_web_links_js[] =
{
#embed "../../programs/server/js/addon-web-links.min.js"
};
constexpr unsigned char resource_binary_html[] =
{
#embed "../../programs/server/binary.html"
@@ -98,19 +114,30 @@ void MergesWebUIRequestHandler::handleRequest(HTTPServerRequest & request, HTTPS
void JavaScriptWebUIRequestHandler::handleRequest(HTTPServerRequest & request, HTTPServerResponse & response, const ProfileEvents::Event &)
{
if (request.getURI() == "/js/uplot.js")
struct Resource { const char * path; const unsigned char * data; size_t size; const char * content_type; };
const Resource resources[] = {
{"/js/uplot.js", resource_uplot_js, std::size(resource_uplot_js), nullptr},
{"/js/lz-string.js", resource_lz_string_js, std::size(resource_lz_string_js), nullptr},
{"/js/xterm.min.js", resource_xterm_js, std::size(resource_xterm_js), nullptr},
{"/js/xterm.min.css", resource_xterm_css, std::size(resource_xterm_css), "text/css; charset=UTF-8"},
{"/js/addon-fit.min.js", resource_addon_fit_js, std::size(resource_addon_fit_js), nullptr},
{"/js/addon-web-links.min.js", resource_addon_web_links_js, std::size(resource_addon_web_links_js), nullptr},
};
for (const auto & resource : resources)
{
handle(request, response, {reinterpret_cast<const char *>(resource_uplot_js), std::size(resource_uplot_js)}, http_response_headers_override);
}
else if (request.getURI() == "/js/lz-string.js")
{
handle(request, response, {reinterpret_cast<const char *>(resource_lz_string_js), std::size(resource_lz_string_js)}, http_response_headers_override);
}
else
{
response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_NOT_FOUND);
*response.send() << "Not found.\n";
if (request.getURI() == resource.path)
{
auto headers = http_response_headers_override;
if (resource.content_type)
headers["Content-Type"] = resource.content_type;
handle(request, response, {reinterpret_cast<const char *>(resource.data), resource.size}, headers);
return;
}
}
response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_NOT_FOUND);
*response.send() << "Not found.\n";
}
void JemallocWebUIRequestHandler::handleRequest(HTTPServerRequest & request, HTTPServerResponse & response, const ProfileEvents::Event &)