Skip to content
This repository was archived by the owner on Jan 29, 2023. It is now read-only.
This repository was archived by the owner on Jan 29, 2023. It is now read-only.

Sending GZIP HTML ~ 120kb+ (suggested enhancement) #3

Closed
@aaron-neal

Description

@aaron-neal

Before I start out, would just like to say thanks for this library it has helped me very quickly port a lot of work from the ESP to the STM32 platform where I can keep both systems fairly in sync!

I also do not know if this is a generic enhancment for both this repo and the non STM32 repo, that's up to you.

I have a HTML build process using GULP which Inlines, uglifies, minifies all of my HTML, CSS and JS . The output file is a single header file that puts the entire thing into PROGMEM.

#define index_html_gz_len 129855

const char PROGMEM index_html_gz[] = {
    0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,....

In both the ESP32 / 8266 the following is used to send this as the index:

server.on(String(F("/index.html")).c_str(), HTTP_GET, [](AsyncWebServerRequest *request){
        if(authenticate(request)){
            return request->requestAuthentication();
        }
        
         //webPage setup
        char lastModified[50]; // Variable to hold the last modification datetime of website
        sprintf_P(lastModified, PSTR("%s %s GMT"), __DATE__, __TIME__); // Populate the last modification date based on build datetime
    
        if (request->header(F("If-Modified-Since")).equals(lastModified)) {
            request->send(304);
        } else {
            // Dump the byte array in PROGMEM with a 200 HTTP code (OK)
            AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), index_html_gz, index_html_gz_len);
            // Tell the browswer the contemnt is Gzipped
            response->addHeader(F("Content-Encoding"), F("gzip"));
            // And set the last-modified datetime so we can check if we need to send it again next time or not
            response->addHeader(F("Last-Modified"), lastModified);
            request->send(response);
        }
        WiFi.scanNetworks(true); //they might request wifi networks at some point
    });

Unforunately, this did not work with this library using the send_P command as I expected, the headers were send but no content. I have finally come up with a solution, I doubt that it is optimal, but for me it is working.

void EthernetWebServer::sendContent_P(PGM_P content, size_t size) 
{
  const char * footer = "\r\n";
  
  if (_chunked) 
  {
    char * chunkSize = (char *) malloc(11);
    
    if (chunkSize) 
    {
      sprintf(chunkSize, "%x%s", size, footer);
      _currentClient.write(chunkSize, strlen(chunkSize));
      free(chunkSize);
    }
  }

  uint16_t bufSize = 4096;
  uint8_t buffer[bufSize];
  uint16_t count = size / bufSize;
  uint16_t remainder = size % bufSize;
  uint16_t i = 0;

  for (i = 0; i < count; i++) {
    /* code */
    memcpy_P(buffer, &content[i*bufSize], bufSize);
    _currentClient.write(buffer, bufSize);
  }
  
  memcpy_P(buffer, &content[i*bufSize], remainder);
  _currentClient.write(buffer, remainder);
  
  if (_chunked) 
  {
    _currentClient.write(footer, 2);
  }
}

If there is a better way of doing this I would love to know, but for now I can carry on with my development, happy to offer a PR for something to work from if needed?

Now I can have my fully bootstrapped web interface that I use with my ESP devices. 👍

image

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions