Skip to content

Add Cache Control Header #999

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
sticilface opened this issue Nov 11, 2015 · 19 comments
Closed

Add Cache Control Header #999

sticilface opened this issue Nov 11, 2015 · 19 comments

Comments

@sticilface
Copy link
Contributor

Regarding ESP8266WebServer:

When serving files from SPIFFS, have the option to add Cache Control Header. Having this option makes for example serving static javascript files much much better as the ESP does not have to continually serve up unchanged files.

    HTTP.sendHeader("Cache-Control"," max-age=xyz"); 

proposed implementation

  void serveStatic(const char* uri, fs::FS& fs, const char* path, uint32_t max-age);

Any thoughts for or against such an addition? I'm willing to / attempt to implement it.

@luc-github
Copy link
Contributor

will this take in account : Cache-Control: no-cache ? which is little bit different than Cache-Control: max-age=0

@sticilface
Copy link
Contributor Author

i propose a default max-age = 0, and then just leave it out if it is not set, i.e. current behaviour. So the change does not break existing sketches.

 void serveStatic(const char* uri, fs::FS& fs, const char* path, uint32_t max-age = 0)
if (max-age != 0) HTTP.sendHeader("Cache-Control"," max-age=xyz"); 

@luc-github
Copy link
Contributor

why ignoring max-age = 0 ?
something more flexible which cover all case/need:

void serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_header)     
if (strlen(cache_header) != 0) HTTP.sendHeader("Cache-Control",cache_header); 

@sticilface
Copy link
Contributor Author

How about , if i made it a int32_t then -1 = no-cache, 0 = max-age=0, >1 as expected?

@sticilface
Copy link
Contributor Author

maybe add in -2 to just leave it out, and set default value to -2?

@luc-github
Copy link
Contributor

start to be complex - also this does not take in account other command or cumulative command like :
Cache-Control: max-age=3600, must-revalidate
https://www.mnot.net/cache_docs/#CACHE-CONTROL
but you may want to set this as limitation:

@sticilface
Copy link
Contributor Author

ah, i see. yes i like ur idea. would it be acceptable to use a nullptr as default ?

void serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_header = nullptr)     
if (cache_header) HTTP.sendHeader("Cache-Control",cache_header); 

or is this frowned on?

@igrr
Copy link
Member

igrr commented Nov 11, 2015

Just make sure you don't store cache_header as const char* because user can pass you a pointer which is a temporary. Store it as a String and then check if (!cache_header.length()) // send default.

@luc-github
Copy link
Contributor

Yes my bad, should use String not const char *
sendHeader(const String& name, const String& value, bool first)

@sticilface
Copy link
Contributor Author

This was why I was originally thinking of using int32_t, as it is conceptually simpler for me, and doesn't eat more ram up. If you think this would be a good addition I will work on it later and submit a PR?

@me-no-dev
Copy link
Collaborator

While you are working on the static server, why not add the option to use gzipped content? I saw it was missing from the source but was working on other things and did not want to bother mixing merges. Gzipped files are much. much smaller and permit larger web apps to be stored on the flash. Not to mention the option to store some nice content even on a 512K board.
There is example code in the FSServer example.

@sticilface
Copy link
Contributor Author

I will take a look at that too.
I'm using jquerymobile, and with caching it works really very well, so i agree.

@sticilface
Copy link
Contributor Author

I've added a Gzipped handling. What would you guys prefer.. to serve a non-compressed over a compressed file, or vice versa. just thinking for debugging it might make it easier that it only serves a gz if it can't find an exact match? That way you can edit a non compressed file get it working, without having to delete an old gx version. I'm open either way. what do you think?

Also you set everything up as a the content type you want to send. ie.. you point to an htm, js file in spiffs which sets the content type correctly, then put the .gz file in there and it finds it, and sets the content encoding to gzip. If you point the handle to a .gz file , you will download it.

sound ok?

@igrr
Copy link
Member

igrr commented Nov 11, 2015

This logic sounds fine to me.

On Wed, Nov 11, 2015, 23:17 sticilface [email protected] wrote:

I've added a Gzipped handling. What would you guys prefer.. to serve a
non-compressed over a compressed file, or vice versa. just thinking for
debugging it might make it easier that it only serves a gz if it can't find
an exact match? That way you can edit a non compressed file get it working,
without having to delete an old gx version. I'm open either way. what do
you think?

Also you set everything up as a the content type you want to send. ie..
you point to an htm, js file in spiffs which sets the content type
correctly, then put the .gz file in there and it finds it, and sets the
content encoding to gzip. If you point the handle to a .gz file , you will
download it.

sound ok?


Reply to this email directly or view it on GitHub
#999 (comment).

@hallard
Copy link
Contributor

hallard commented Nov 27, 2015

@sticilface
I'm using SPIFFS to serve files and I need also caching, how did you enabled jquery caching ?
just compress .js file and set it to .js.gz is enought ?

@sticilface
Copy link
Contributor Author

The cache control header is added to any servestatic handlers. for example to serve your whole SPIFFS

server.serveStatic("/", SPIFFS, "/", "max-age=86400"); 

The web server will send any file with a .gz, when the non-compressed is requested, setting the correct content-type and content-encoding headers. eg.. client request is for file abc.txt if there is an abc.txt.gz file then it will serve that. However, if there is an uncompressed file abc.txt it will serve that in preference to the compressed one.

hope that helps

@hallard
Copy link
Contributor

hallard commented Nov 27, 2015

@sticilface
got it thanks,
so if I want to cache only my bootstrap files (gz or not) located in /js /css /font and no cache on all other files this is working ?

server.on("/", handleRoot);
  server.on("/json", sendJSON);
  server.on("/tinfo.json", tinfoJSONTable);
  server.on("/system.json", sysJSONTable);
  server.on("/config.json", confJSONTable);
  server.on("/spiffs.json", spiffsJSONTable);
  server.on("/wifiscan.json", wifiScanJSON);
  server.on("/factory_reset", handleFactoryReset);
  server.on("/reset", handleReset);
  server.onNotFound(handleNotFound);

  // serves all SPIFFS with 24hr max-age control
  server.serveStatic("/font", SPIFFS, "/font","max-age=86400"); 
  server.serveStatic("/js",   SPIFFS, "/js"  ,"max-age=86400"); 
  server.serveStatic("/css",  SPIFFS, "/css" ,"max-age=86400"); 
  server.begin();

  Debugln(F("HTTP server started"));

@sticilface
Copy link
Contributor Author

looks good to me.

@hallard
Copy link
Contributor

hallard commented Nov 27, 2015

great, thanks ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants