svelteesp32 1.9.2 → 1.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -175,7 +175,7 @@ const char * etag_assets_index_Soe6cpLA_css = "d4f23bc45ef67890ab12...";
175
175
  void initSvelteStaticFiles(PsychicHttpServer * server) {
176
176
  server->on("/assets/index-KwubEIf-.js", HTTP_GET, [](PsychicRequest * request) {
177
177
  if (request->hasHeader("If-None-Match") &&
178
- request->header("If-None-Match") == String(etag_assets_index_KwubEIf__js)) {
178
+ request->header("If-None-Match").equals(etag_assets_index_KwubEIf__js)) {
179
179
  PsychicResponse response304(request);
180
180
  response304.setCode(304);
181
181
  return response304.send();
@@ -192,7 +192,7 @@ void initSvelteStaticFiles(PsychicHttpServer * server) {
192
192
 
193
193
  server->on("/assets/index-Soe6cpLA.css", HTTP_GET, [](PsychicRequest * request) {
194
194
  if (request->hasHeader("If-None-Match") &&
195
- request->header("If-None-Match") == String(etag_assets_index_Soe6cpLA_css)) {
195
+ request->header("If-None-Match").equals(etag_assets_index_Soe6cpLA_css)) {
196
196
  PsychicResponse response304(request);
197
197
  response304.setCode(304);
198
198
  return response304.send();
@@ -242,6 +242,8 @@ Since microcontroller data traffic is moderately expensive, it is an individual
242
242
 
243
243
  The use of ETag is **not enabled by default**, this can be achieved with the `--etag=true` switch.
244
244
 
245
+ All four engines (psychic, psychic2, async, espidf) fully support ETag validation with HTTP 304 Not Modified responses, reducing bandwidth usage when clients have valid cached content.
246
+
245
247
  > This setting has three states: yes, no, and compiler mode is available. In compiler mode, you can disable/enable ETag by setting the `SVELTEESP32_ENABLE_ETAG` c++ compiler directive. For example, if using platformio, just type `-D SVELTEESP32_ENABLE_ETAG`.
246
248
 
247
249
  ### Cache-control
package/dist/cppCode.js CHANGED
@@ -126,7 +126,7 @@ void {{methodName}}(PsychicHttpServer * server) {
126
126
 
127
127
  {{#switch ../etag}}
128
128
  {{#case "true"}}
129
- if (request->hasHeader("If-None-Match") && request->header("If-None-Match") == String(etag_{{this.dataname}})) {
129
+ if (request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag_{{this.dataname}})) {
130
130
  PsychicResponse response304(request);
131
131
  response304.setCode(304);
132
132
  return response304.send();
@@ -134,12 +134,12 @@ void {{methodName}}(PsychicHttpServer * server) {
134
134
  {{/case}}
135
135
  {{#case "compiler"}}
136
136
  #ifdef {{../definePrefix}}_ENABLE_ETAG
137
- if (request->hasHeader("If-None-Match") && request->header("If-None-Match") == String(etag_{{this.dataname}})) {
137
+ if (request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag_{{this.dataname}})) {
138
138
  PsychicResponse response304(request);
139
139
  response304.setCode(304);
140
140
  return response304.send();
141
141
  }
142
- #endif
142
+ #endif
143
143
  {{/case}}
144
144
  {{/switch}}
145
145
 
@@ -235,18 +235,18 @@ void {{methodName}}(PsychicHttpServer * server) {
235
235
 
236
236
  {{#switch ../etag}}
237
237
  {{#case "true"}}
238
- if (request->hasHeader("If-None-Match") && request->header("If-None-Match") == String(etag_{{this.dataname}})) {
238
+ if (request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag_{{this.dataname}})) {
239
239
  response->setCode(304);
240
240
  return response->send();
241
241
  }
242
242
  {{/case}}
243
243
  {{#case "compiler"}}
244
244
  #ifdef {{../definePrefix}}_ENABLE_ETAG
245
- if (request->hasHeader("If-None-Match") && request->header("If-None-Match") == String(etag_{{this.dataname}})) {
245
+ if (request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag_{{this.dataname}})) {
246
246
  response->setCode(304);
247
247
  return response->send();
248
248
  }
249
- #endif
249
+ #endif
250
250
  {{/case}}
251
251
  {{/switch}}
252
252
 
@@ -336,22 +336,24 @@ void {{methodName}}(AsyncWebServer * server) {
336
336
  {{#each sources}}
337
337
  //
338
338
  // {{this.filename}}
339
- ArRequestHandlerFunction func_{{this.dataname}} = [](AsyncWebServerRequest * request) {
339
+ server->on("/{{this.filename}}", HTTP_GET, [](AsyncWebServerRequest * request) {
340
340
 
341
341
  {{#switch ../etag}}
342
342
  {{#case "true"}}
343
- if (request->hasHeader("If-None-Match") && request->getHeader("If-None-Match")->value() == String(etag_{{this.dataname}})) {
343
+ const AsyncWebHeader* h = request->getHeader("If-None-Match");
344
+ if (h && h->value().equals(etag_{{this.dataname}})) {
344
345
  request->send(304);
345
346
  return;
346
347
  }
347
348
  {{/case}}
348
349
  {{#case "compiler"}}
349
350
  #ifdef {{../definePrefix}}_ENABLE_ETAG
350
- if (request->hasHeader("If-None-Match") && request->getHeader("If-None-Match")->value() == String(etag_{{this.dataname}})) {
351
+ const AsyncWebHeader* h = request->getHeader("If-None-Match");
352
+ if (h && h->value().equals(etag_{{this.dataname}})) {
351
353
  request->send(304);
352
354
  return;
353
355
  }
354
- #endif
356
+ #endif
355
357
  {{/case}}
356
358
  {{/switch}}
357
359
 
@@ -373,7 +375,7 @@ void {{methodName}}(AsyncWebServer * server) {
373
375
  {{/if}}
374
376
  #else
375
377
  AsyncWebServerResponse *response = request->beginResponse(200, "{{this.mime}}", data_{{this.dataname}}, {{this.length}});
376
- #endif
378
+ #endif
377
379
  {{/case}}
378
380
  {{/switch}}
379
381
 
@@ -396,15 +398,81 @@ void {{methodName}}(AsyncWebServer * server) {
396
398
  response->addHeader("Cache-Control", "no-cache");
397
399
  {{/../cacheTime}}
398
400
  response->addHeader("ETag", etag_{{this.dataname}});
399
- #endif
401
+ #endif
400
402
  {{/case}}
401
403
  {{/switch}}
402
404
 
403
405
  request->send(response);
404
- };
405
- server->on("/{{this.filename}}", HTTP_GET, func_{{this.dataname}});
406
+ });
406
407
  {{#if this.isDefault}}
407
- server->on("/", HTTP_GET, func_{{this.dataname}});
408
+ server->on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
409
+
410
+ {{#switch ../etag}}
411
+ {{#case "true"}}
412
+ const AsyncWebHeader* h = request->getHeader("If-None-Match");
413
+ if (h && h->value().equals(etag_{{this.dataname}})) {
414
+ request->send(304);
415
+ return;
416
+ }
417
+ {{/case}}
418
+ {{#case "compiler"}}
419
+ #ifdef {{../definePrefix}}_ENABLE_ETAG
420
+ const AsyncWebHeader* h = request->getHeader("If-None-Match");
421
+ if (h && h->value().equals(etag_{{this.dataname}})) {
422
+ request->send(304);
423
+ return;
424
+ }
425
+ #endif
426
+ {{/case}}
427
+ {{/switch}}
428
+
429
+ {{#switch ../gzip}}
430
+ {{#case "true"}}
431
+ AsyncWebServerResponse *response = request->beginResponse(200, "{{this.mime}}", datagzip_{{this.dataname}}, {{this.lengthGzip}});
432
+ {{#if this.isGzip}}
433
+ response->addHeader("Content-Encoding", "gzip");
434
+ {{/if}}
435
+ {{/case}}
436
+ {{#case "false"}}
437
+ AsyncWebServerResponse *response = request->beginResponse(200, "{{this.mime}}", data_{{this.dataname}}, {{this.length}});
438
+ {{/case}}
439
+ {{#case "compiler"}}
440
+ #ifdef {{../definePrefix}}_ENABLE_GZIP
441
+ AsyncWebServerResponse *response = request->beginResponse(200, "{{this.mime}}", datagzip_{{this.dataname}}, {{this.lengthGzip}});
442
+ {{#if this.isGzip}}
443
+ response->addHeader("Content-Encoding", "gzip");
444
+ {{/if}}
445
+ #else
446
+ AsyncWebServerResponse *response = request->beginResponse(200, "{{this.mime}}", data_{{this.dataname}}, {{this.length}});
447
+ #endif
448
+ {{/case}}
449
+ {{/switch}}
450
+
451
+ {{#switch ../etag}}
452
+ {{#case "true"}}
453
+ {{#../cacheTime}}
454
+ response->addHeader("Cache-Control", "max-age={{value}}");
455
+ {{/../cacheTime}}
456
+ {{^../cacheTime}}
457
+ response->addHeader("Cache-Control", "no-cache");
458
+ {{/../cacheTime}}
459
+ response->addHeader("ETag", etag_{{this.dataname}});
460
+ {{/case}}
461
+ {{#case "compiler"}}
462
+ #ifdef {{../definePrefix}}_ENABLE_ETAG
463
+ {{#../cacheTime}}
464
+ response->addHeader("Cache-Control", "max-age={{value}}");
465
+ {{/../cacheTime}}
466
+ {{^../cacheTime}}
467
+ response->addHeader("Cache-Control", "no-cache");
468
+ {{/../cacheTime}}
469
+ response->addHeader("ETag", etag_{{this.dataname}});
470
+ #endif
471
+ {{/case}}
472
+ {{/switch}}
473
+
474
+ request->send(response);
475
+ });
408
476
  {{/if}}
409
477
 
410
478
  {{/each}}
@@ -1 +1 @@
1
- export declare const espidfTemplate = "\n//engine: espidf\n//cmdline: {{{commandLine}}}\n{{#if created }}\n//created: {{now}}\n{{/if}}\n//\n\n{{#switch etag}}\n{{#case \"true\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n#warning {{definePrefix}}_ENABLE_ETAG has no effect because it is permanently switched ON\n#endif\n{{/case}}\n{{#case \"false\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n#warning {{definePrefix}}_ENABLE_ETAG has no effect because it is permanently switched OFF\n#endif\n{{/case}}\n{{/switch}}\n\n{{#switch gzip}}\n{{#case \"true\"}}\n#ifdef {{definePrefix}}_ENABLE_GZIP\n#warning {{definePrefix}}_ENABLE_GZIP has no effect because it is permanently switched ON\n#endif\n{{/case}}\n{{#case \"false\"}}\n#ifdef {{definePrefix}}_ENABLE_GZIP\n#warning {{definePrefix}}_ENABLE_GZIP has no effect because it is permanently switched OFF\n#endif\n{{/case}}\n{{/switch}}\n\n//\n{{#if version }}\n#define {{definePrefix}}_VERSION \"{{version}}\"\n{{/if}}\n#define {{definePrefix}}_COUNT {{fileCount}}\n#define {{definePrefix}}_SIZE {{fileSize}}\n#define {{definePrefix}}_SIZE_GZIP {{fileGzipSize}}\n\n//\n{{#each sources}}\n#define {{../definePrefix}}_FILE_{{this.datanameUpperCase}}\n{{/each}}\n\n//\n{{#each filesByExtension}}\n#define {{../definePrefix}}_{{this.extension}}_FILES {{this.count}}\n{{/each}}\n\n#include <stdint.h>\n#include <esp_err.h>\n#include <esp_http_server.h>\n\n//\n{{#switch gzip}}\n{{#case \"true\"}}\n {{#each sources}}\nconst char datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };\n {{/each}}\n{{/case}}\n{{#case \"false\"}}\n {{#each sources}}\nconst char data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };\n {{/each}}\n{{/case}}\n{{#case \"compiler\"}}\n#ifdef {{definePrefix}}_ENABLE_GZIP\n {{#each sources}}\nconst char datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };\n {{/each}}\n#else\n {{#each sources}}\nconst char data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };\n {{/each}}\n#endif \n{{/case}}\n{{/switch}}\n\n//\n{{#switch etag}}\n{{#case \"true\"}}\n {{#each sources}}\nconst char * etag_{{this.dataname}} = \"{{this.md5}}\";\n {{/each}}\n{{/case}}\n{{#case \"false\"}}\n{{/case}}\n{{#case \"compiler\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n {{#each sources}}\nconst char * etag_{{this.dataname}} = \"{{this.md5}}\";\n {{/each}}\n#endif \n{{/case}}\n{{/switch}}\n\n{{#each sources}}\n\nstatic esp_err_t file_handler_{{this.datanameUpperCase}} (httpd_req_t *req)\n{\n httpd_resp_set_type(req, \"{{this.mime}}\");\n{{#switch ../gzip}}\n{{#case \"true\"}}\n{{#if this.isGzip}}\n httpd_resp_set_hdr(req, \"Content-Encoding\", \"gzip\");\n{{/if}}\n{{/case}}\n{{#case \"compiler\"}}\n {{#if this.isGzip}}\n #ifdef {{../definePrefix}}_ENABLE_GZIP\n httpd_resp_set_hdr(req, \"Content-Encoding\", \"gzip\");\n #endif \n {{/if}}\n{{/case}}\n{{/switch}}\n\n{{#switch ../etag}}\n{{#case \"true\"}}\n{{#../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"max-age={{value}}\");\n{{/../cacheTime}}\n{{^../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"no-cache\");\n{{/../cacheTime}}\n httpd_resp_set_hdr(req, \"ETag\", etag_{{this.dataname}});\n{{/case}}\n{{#case \"compiler\"}}\n #ifdef {{../definePrefix}}_ENABLE_ETAG\n{{#../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"max-age={{value}}\");\n{{/../cacheTime}}\n{{^../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"no-cache\");\n{{/../cacheTime}}\n httpd_resp_set_hdr(req, \"ETag\", etag_{{this.dataname}});\n #endif \n{{/case}}\n{{/switch}}\n\n{{#switch ../gzip}}\n{{#case \"true\"}}\n httpd_resp_send(req, datagzip_{{this.dataname}}, {{this.lengthGzip}});\n{{/case}}\n{{#case \"false\"}}\n httpd_resp_send(req, data_{{this.dataname}}, {{this.length}});\n{{/case}}\n{{#case \"compiler\"}}\n #ifdef {{../definePrefix}}_ENABLE_GZIP\n httpd_resp_send(req, datagzip_{{this.dataname}}, {{this.lengthGzip}});\n #else\n httpd_resp_send(req, data_{{this.dataname}}, {{this.length}});\n #endif \n{{/case}}\n{{/switch}}\n return ESP_OK;\n}\n\n{{#if this.isDefault}}\nstatic const httpd_uri_t route_def_{{this.datanameUpperCase}} = {\n .uri = \"/\",\n .method = HTTP_GET,\n .handler = file_handler_{{this.datanameUpperCase}},\n};\n{{/if}}\n\nstatic const httpd_uri_t route_{{this.datanameUpperCase}} = {\n .uri = \"/{{this.filename}}\",\n .method = HTTP_GET,\n .handler = file_handler_{{this.datanameUpperCase}},\n};\n\n{{/each}}\n\n\n\nstatic inline void {{methodName}}(httpd_handle_t server) {\n{{#each sources}}\n{{#if this.isDefault}}\n httpd_register_uri_handler(server, &route_def_{{this.datanameUpperCase}});\n{{/if}}\n httpd_register_uri_handler(server, &route_{{this.datanameUpperCase}});\n{{/each}}\n\n}";
1
+ export declare const espidfTemplate = "\n//engine: espidf\n//cmdline: {{{commandLine}}}\n{{#if created }}\n//created: {{now}}\n{{/if}}\n//\n\n{{#switch etag}}\n{{#case \"true\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n#warning {{definePrefix}}_ENABLE_ETAG has no effect because it is permanently switched ON\n#endif\n{{/case}}\n{{#case \"false\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n#warning {{definePrefix}}_ENABLE_ETAG has no effect because it is permanently switched OFF\n#endif\n{{/case}}\n{{/switch}}\n\n{{#switch gzip}}\n{{#case \"true\"}}\n#ifdef {{definePrefix}}_ENABLE_GZIP\n#warning {{definePrefix}}_ENABLE_GZIP has no effect because it is permanently switched ON\n#endif\n{{/case}}\n{{#case \"false\"}}\n#ifdef {{definePrefix}}_ENABLE_GZIP\n#warning {{definePrefix}}_ENABLE_GZIP has no effect because it is permanently switched OFF\n#endif\n{{/case}}\n{{/switch}}\n\n//\n{{#if version }}\n#define {{definePrefix}}_VERSION \"{{version}}\"\n{{/if}}\n#define {{definePrefix}}_COUNT {{fileCount}}\n#define {{definePrefix}}_SIZE {{fileSize}}\n#define {{definePrefix}}_SIZE_GZIP {{fileGzipSize}}\n\n//\n{{#each sources}}\n#define {{../definePrefix}}_FILE_{{this.datanameUpperCase}}\n{{/each}}\n\n//\n{{#each filesByExtension}}\n#define {{../definePrefix}}_{{this.extension}}_FILES {{this.count}}\n{{/each}}\n\n#include <stdint.h>\n#include <string.h>\n#include <stdlib.h>\n#include <esp_err.h>\n#include <esp_http_server.h>\n\n//\n{{#switch gzip}}\n{{#case \"true\"}}\n {{#each sources}}\nconst char datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };\n {{/each}}\n{{/case}}\n{{#case \"false\"}}\n {{#each sources}}\nconst char data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };\n {{/each}}\n{{/case}}\n{{#case \"compiler\"}}\n#ifdef {{definePrefix}}_ENABLE_GZIP\n {{#each sources}}\nconst char datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };\n {{/each}}\n#else\n {{#each sources}}\nconst char data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };\n {{/each}}\n#endif \n{{/case}}\n{{/switch}}\n\n//\n{{#switch etag}}\n{{#case \"true\"}}\n {{#each sources}}\nconst char * etag_{{this.dataname}} = \"{{this.md5}}\";\n {{/each}}\n{{/case}}\n{{#case \"false\"}}\n{{/case}}\n{{#case \"compiler\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n {{#each sources}}\nconst char * etag_{{this.dataname}} = \"{{this.md5}}\";\n {{/each}}\n#endif \n{{/case}}\n{{/switch}}\n\n{{#each sources}}\n\nstatic esp_err_t file_handler_{{this.datanameUpperCase}} (httpd_req_t *req)\n{\n{{#switch ../etag}}\n{{#case \"true\"}}\n size_t hdr_len = httpd_req_get_hdr_value_len(req, \"If-None-Match\");\n if (hdr_len > 0) {\n char* hdr_value = malloc(hdr_len + 1);\n if (httpd_req_get_hdr_value_str(req, \"If-None-Match\", hdr_value, hdr_len + 1) == ESP_OK) {\n if (strcmp(hdr_value, etag_{{this.dataname}}) == 0) {\n free(hdr_value);\n httpd_resp_set_status(req, \"304 Not Modified\");\n httpd_resp_send(req, NULL, 0);\n return ESP_OK;\n }\n }\n free(hdr_value);\n }\n{{/case}}\n{{#case \"compiler\"}}\n #ifdef {{../definePrefix}}_ENABLE_ETAG\n size_t hdr_len = httpd_req_get_hdr_value_len(req, \"If-None-Match\");\n if (hdr_len > 0) {\n char* hdr_value = malloc(hdr_len + 1);\n if (httpd_req_get_hdr_value_str(req, \"If-None-Match\", hdr_value, hdr_len + 1) == ESP_OK) {\n if (strcmp(hdr_value, etag_{{this.dataname}}) == 0) {\n free(hdr_value);\n httpd_resp_set_status(req, \"304 Not Modified\");\n httpd_resp_send(req, NULL, 0);\n return ESP_OK;\n }\n }\n free(hdr_value);\n }\n #endif\n{{/case}}\n{{/switch}}\n httpd_resp_set_type(req, \"{{this.mime}}\");\n{{#switch ../gzip}}\n{{#case \"true\"}}\n{{#if this.isGzip}}\n httpd_resp_set_hdr(req, \"Content-Encoding\", \"gzip\");\n{{/if}}\n{{/case}}\n{{#case \"compiler\"}}\n {{#if this.isGzip}}\n #ifdef {{../definePrefix}}_ENABLE_GZIP\n httpd_resp_set_hdr(req, \"Content-Encoding\", \"gzip\");\n #endif \n {{/if}}\n{{/case}}\n{{/switch}}\n\n{{#switch ../etag}}\n{{#case \"true\"}}\n{{#../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"max-age={{value}}\");\n{{/../cacheTime}}\n{{^../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"no-cache\");\n{{/../cacheTime}}\n httpd_resp_set_hdr(req, \"ETag\", etag_{{this.dataname}});\n{{/case}}\n{{#case \"compiler\"}}\n #ifdef {{../definePrefix}}_ENABLE_ETAG\n{{#../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"max-age={{value}}\");\n{{/../cacheTime}}\n{{^../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"no-cache\");\n{{/../cacheTime}}\n httpd_resp_set_hdr(req, \"ETag\", etag_{{this.dataname}});\n #endif \n{{/case}}\n{{/switch}}\n\n{{#switch ../gzip}}\n{{#case \"true\"}}\n httpd_resp_send(req, datagzip_{{this.dataname}}, {{this.lengthGzip}});\n{{/case}}\n{{#case \"false\"}}\n httpd_resp_send(req, data_{{this.dataname}}, {{this.length}});\n{{/case}}\n{{#case \"compiler\"}}\n #ifdef {{../definePrefix}}_ENABLE_GZIP\n httpd_resp_send(req, datagzip_{{this.dataname}}, {{this.lengthGzip}});\n #else\n httpd_resp_send(req, data_{{this.dataname}}, {{this.length}});\n #endif \n{{/case}}\n{{/switch}}\n return ESP_OK;\n}\n\n{{#if this.isDefault}}\nstatic const httpd_uri_t route_def_{{this.datanameUpperCase}} = {\n .uri = \"/\",\n .method = HTTP_GET,\n .handler = file_handler_{{this.datanameUpperCase}},\n};\n{{/if}}\n\nstatic const httpd_uri_t route_{{this.datanameUpperCase}} = {\n .uri = \"/{{this.filename}}\",\n .method = HTTP_GET,\n .handler = file_handler_{{this.datanameUpperCase}},\n};\n\n{{/each}}\n\n\n\nstatic inline void {{methodName}}(httpd_handle_t server) {\n{{#each sources}}\n{{#if this.isDefault}}\n httpd_register_uri_handler(server, &route_def_{{this.datanameUpperCase}});\n{{/if}}\n httpd_register_uri_handler(server, &route_{{this.datanameUpperCase}});\n{{/each}}\n\n}";
@@ -54,6 +54,8 @@ exports.espidfTemplate = `
54
54
  {{/each}}
55
55
 
56
56
  #include <stdint.h>
57
+ #include <string.h>
58
+ #include <stdlib.h>
57
59
  #include <esp_err.h>
58
60
  #include <esp_http_server.h>
59
61
 
@@ -104,6 +106,40 @@ const char * etag_{{this.dataname}} = "{{this.md5}}";
104
106
 
105
107
  static esp_err_t file_handler_{{this.datanameUpperCase}} (httpd_req_t *req)
106
108
  {
109
+ {{#switch ../etag}}
110
+ {{#case "true"}}
111
+ size_t hdr_len = httpd_req_get_hdr_value_len(req, "If-None-Match");
112
+ if (hdr_len > 0) {
113
+ char* hdr_value = malloc(hdr_len + 1);
114
+ if (httpd_req_get_hdr_value_str(req, "If-None-Match", hdr_value, hdr_len + 1) == ESP_OK) {
115
+ if (strcmp(hdr_value, etag_{{this.dataname}}) == 0) {
116
+ free(hdr_value);
117
+ httpd_resp_set_status(req, "304 Not Modified");
118
+ httpd_resp_send(req, NULL, 0);
119
+ return ESP_OK;
120
+ }
121
+ }
122
+ free(hdr_value);
123
+ }
124
+ {{/case}}
125
+ {{#case "compiler"}}
126
+ #ifdef {{../definePrefix}}_ENABLE_ETAG
127
+ size_t hdr_len = httpd_req_get_hdr_value_len(req, "If-None-Match");
128
+ if (hdr_len > 0) {
129
+ char* hdr_value = malloc(hdr_len + 1);
130
+ if (httpd_req_get_hdr_value_str(req, "If-None-Match", hdr_value, hdr_len + 1) == ESP_OK) {
131
+ if (strcmp(hdr_value, etag_{{this.dataname}}) == 0) {
132
+ free(hdr_value);
133
+ httpd_resp_set_status(req, "304 Not Modified");
134
+ httpd_resp_send(req, NULL, 0);
135
+ return ESP_OK;
136
+ }
137
+ }
138
+ free(hdr_value);
139
+ }
140
+ #endif
141
+ {{/case}}
142
+ {{/switch}}
107
143
  httpd_resp_set_type(req, "{{this.mime}}");
108
144
  {{#switch ../gzip}}
109
145
  {{#case "true"}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelteesp32",
3
- "version": "1.9.2",
3
+ "version": "1.9.4",
4
4
  "description": "Convert Svelte (or any frontend) JS application to serve it from ESP32 webserver (PsychicHttp)",
5
5
  "author": "BCsabaEngine",
6
6
  "license": "ISC",
@@ -33,14 +33,15 @@
33
33
  "dev:psychic2": "nodemon src/index.ts -- -e psychic2 -s ./demo/svelte/dist -o ./demo/esp32/include/svelteesp32.h --etag=false --gzip=false --version=v$npm_package_version",
34
34
  "test:esp32": "./package.script && ~/.platformio/penv/bin/pio run -d ./demo/esp32",
35
35
  "test:esp32idf": "./package.script && ~/.platformio/penv/bin/pio run -d ./demo/esp32idf",
36
- "test:all": "npm run test:esp32 && npm run test:esp32idf",
36
+ "test:all": "node --run test:esp32 && node --run test:esp32idf",
37
37
  "clean": "tsc --build --clean",
38
38
  "build": "tsc --build --clean && tsc --build --force",
39
39
  "format:check": "prettier --check .",
40
- "format:fix": "prettier --write .",
40
+ "format:fix": "prettier --write . | grep -v 'unchanged' | sed G",
41
41
  "lint:check": "eslint .",
42
42
  "lint:fix": "eslint --fix .",
43
- "fix": "npm run format:fix && npm run lint:fix && npm run format:fix",
43
+ "fix": "node --run format:fix && node --run lint:fix && node --run format:fix",
44
+ "all": "node --run fix && node --run build",
44
45
  "npm:reinstall": "rm -rf ./node_modules && rm -f ./package-lock.json && npm i && npm i"
45
46
  },
46
47
  "keywords": [
@@ -57,21 +58,21 @@
57
58
  ],
58
59
  "devDependencies": {
59
60
  "@types/mime-types": "^3.0.1",
60
- "@types/node": "^24.8.1",
61
- "@typescript-eslint/eslint-plugin": "^8.46.1",
62
- "@typescript-eslint/parser": "^8.46.1",
63
- "eslint": "^9.38.0",
61
+ "@types/node": "^24.10.1",
62
+ "@typescript-eslint/eslint-plugin": "^8.47.0",
63
+ "@typescript-eslint/parser": "^8.47.0",
64
+ "eslint": "^9.39.1",
64
65
  "eslint-config-prettier": "^10.1.8",
65
66
  "eslint-plugin-simple-import-sort": "^12.1.1",
66
- "eslint-plugin-unicorn": "^61.0.2",
67
- "nodemon": "^3.1.10",
67
+ "eslint-plugin-unicorn": "^62.0.0",
68
+ "nodemon": "^3.1.11",
68
69
  "prettier": "^3.6.2",
69
70
  "ts-node": "^10.9.2",
70
71
  "tsx": "^4.20.6",
71
72
  "typescript": "^5.9.3"
72
73
  },
73
74
  "dependencies": {
74
- "glob": "^11.0.3",
75
+ "glob": "^12.0.0",
75
76
  "handlebars": "^4.7.8",
76
77
  "mime-types": "^3.0.1",
77
78
  "ts-command-line-args": "^2.5.1"