full-stack-ex / tiny-template-engine-arduino

Hello ${0}! A line-by-line Arduino/ESP template engine for large input data with a very small memory footprint
MIT License
1 stars 1 forks source link

Empty lines cause problems #1

Closed Bytekeeper closed 5 years ago

Bytekeeper commented 5 years ago

Thanks for the library!

I found a small problem. Given the following string:

static PGM_P test PROGMEM = R"==(shown

not shown
)==";

nextLine only seems to read "shown".

Using this string:

static PGM_P test2 PROGMEM = R"==(shown
also shown
)==";

nextLine returns both.

This is the code I used for testing in both cases:

    server.setContentLength(CONTENT_LENGTH_UNKNOWN);
    server.send(200, "text/html", String());
    TinyTemplateEngineMemoryReader reader(test);
    TinyTemplateEngine engine(reader);
    while (const char* line = engine.nextLine()) {
      server.sendContent(line);
    }
full-stack-ex commented 5 years ago

Somehow, I have not received any notifications, just discovered your message. Got it, thank you.

full-stack-ex commented 5 years ago

Well, it looks like the engine processes the R-string correctly. Here's the Serial output from the library example, with your content:

...
not shown
shown

not shown
shown
...

The issues seems to be in the way the web server handles empty strings. Since content length is not passed in the header, the server is looking for an empty string as a content terminator. (Frankly, I would use something like a NULL pointer instead.)

So, could you please try this in your environment?

server.setContentLength(CONTENT_LENGTH_UNKNOWN);
server.send(200, "text/html", String());
TinyTemplateEngineMemoryReader reader(test);
TinyTemplateEngine engine(reader);
while (const char* line = engine.nextLine()) {
  // MODIFIED to avoid sending empty lines. Assuming an extra space is harmless in this case
  server.sendContent(*line ? line : " ");
}
// ADDED: end of stream for the server
server.sendContent("");

If that works, the next step might be adding an option to preserve line ends in engine.nextLine().

full-stack-ex commented 5 years ago

New version pushed with an option to keep line ends, like this:

server.setContentLength(CONTENT_LENGTH_UNKNOWN);
server.send(200, "text/html", String());
TinyTemplateEngineMemoryReader reader(test);

// NEW FUNCTION:
reader.keepLineEnds(true);  // Include trailing "\n" in the output

TinyTemplateEngine engine(reader);
while (const char* line = engine.nextLine()) {
  server.sendContent(line);
}

// This is necessary: end of stream for the server
server.sendContent("");

The Arduino Library Manager is supposed to pick up this push soon.

Thank you for your discovery!

full-stack-ex commented 5 years ago

It has been updated by the Arduino Library Manager. Available in Arduino IDE.

full-stack-ex commented 5 years ago

Closing this issue.

Bytekeeper commented 5 years ago

Thanks! I'll update.