概要
ESP32のArduino用Httpサーバーといえばコアに内蔵しているHttpServerか、非同期型のESPAsyncWebServerライブラリを利用するのが一般的です。しかしながらESP-IDFには非同期型で高機能なesp_http_serverがありますので、そちらを利用するHttpServerライブラリを作ってみました。
作成物

上記のライブラリです。Arduino標準HttpServerは同時アクセスに弱いのと、設計が古いのであまりおすすめしません。ESPAsyncWebServerも設計自体はいいのですが、RP2040などに対応範囲が増えており、導入も少し面倒な感じです。
esp_http_serverはESP32専用でばりばりチューニングがされていますので非常におすすめです。そこに今風のArduino APIで利用できるクラスにしたのがEspHttpServerとなります。
ページの動的生成
server.on("/", HTTP_GET, [](EspHttpServer::Request &req, EspHttpServer::Response &res)
{
(void)req;
res.sendText(200, "text/plain", "EspHttpServer ready!"); });
onでPathを指定することでページを生成可能です。
チャンクに分割しての送信
server.on("/stream", HTTP_GET, [](EspHttpServer::Request &req, EspHttpServer::Response &res)
{
(void)req;
res.beginChunked(200, "application/json");
res.sendChunk("[\n");
res.sendChunk(" {\"index\":0},\n");
res.sendChunk(" {\"index\":1}\n");
res.sendChunk("]\n");
res.endChunked(); });
大きなページなど省メモリにしたいときにはチャンクに分割して送信することも可能です。
テンプレート埋め込み
<!doctype html>
<html>
<head>
<title>{{name}} demo</title>
</head>
<body>
<h1>{{{name}}}</h1>
<p>Version: {{version}}</p>
</body>
</html>
こんな感じでテンプレートを埋め込むこともできます。
server.on("/template", HTTP_GET, [](EspHttpServer::Request &req, EspHttpServer::Response &res)
{
(void)req;
// en: Inject runtime variables into the HTML template.
// ja: 実行時変数をテンプレートへ埋め込む。
res.setTemplateHandler([](const String& key, Print& out) -> bool {
if (key == "name") {
out.print("<b>ESP32</b>");
return true;
}
if (key == "version") {
out.print("0.0.1");
return true;
}
return false;
});
setTemplateHandlerで埋め込み用コールバックを設定していて置換されます。
FSに静的ページ埋め込み
server.serveStatic("/www", LittleFS, "/wwwroot",
[](const EspHttpServer::StaticInfo &info, EspHttpServer::Request &req, EspHttpServer::Response &res)
{
(void)req;
if (!info.exists)
{
// en: Basic SPA fallback example.
// ja: SPA 用のフォールバック例。
res.sendFile(LittleFS, "/wwwroot/index.html");
return;
}
res.sendStatic();
});
FSにあらかじめファイルを保存しておき、そこを直接配信することが可能です。
ソースコード埋め込み

上記のVSCODEの拡張機能を利用するとassetフォルダに入れたファイルを自動的に.hに変換してくれる機能があります。そこで不要な改行やスペースを減らしたminifyや、ZIP圧縮を自動的にしてくれる機能があります。
上記のサンプルのようにFSを配信する感じでassetから配信が可能です。オリジナルのhtmlなどはプロジェクトの中に入れておいて、埋め込むデータだけminifyされる形となります。
PlainBindを利用してテンプレート埋め込み

上記のJavaScriptライブラリと組み合わせてのテンプレート機能もあります。通常の埋め込みテンプレートは{{name}}などのように通常のHtmlを汚してしまいます。
<h1 data-bind="title"></h1>
上記のようにdata-から始まる項目を埋め込んでいて、そこのデータをsetHeadInjectionという機能を利用して<head>の中に埋め込んでいます。
String head;
head.reserve(json.length() + 160);
head += "<script id=\"plainbind-data\" type=\"application/json\">";
head += json;
head += "</script>";
res.setHeadInjection(head);
こんな感じで埋め込みようのデータを利用して<head>に埋め込む処理をしているので、JavaScriptライブラリ側がデータを解釈して文字の差し替えや表示、非表示を変更しています。Html的にはきれいなのとローカルの場合には同じフォルダにデータをおいておけば描画テストがかんたんにできる構造となっています。ESP32ではなくブラウザ側でレンダリングをして、さらにデザイナーさんともデータ埋め込みの済みで動作確認が終わったHtmlテンプレートをお願いできるかもみたいな構造です。

詳しくは上記の例をみてください。
まとめ
今風のHtmlレンダリングライブラリっぽい構成にしてみました。クッキーやセッションの処理、GetやPathなどの分解などにももちろん対応しています。
普通に利用するだけでも標準のHttpServerよりも安定するのでおすすめです。

コメント