jkent / frogfs

Fast Read-Only General-purpose File System (ESP-IDF and ESP8266_RTOS_SDK compatible)
https://frogfs.readthedocs.io
Mozilla Public License 2.0
25 stars 32 forks source link

Add brotli transform to compress the files using brotli algorithm #62

Closed X-Ryl669 closed 1 month ago

X-Ryl669 commented 1 month ago

Purpose

With new code, frogfs is much better tooled for embedded storage of a website. On the web, the best supported compression algorithm is brotli. All browsers support it (96.93% support in caniuse), and it provides a strong compression advantage (for example, gzip encoded JS file will take 660 bytes while brotli will only use 440 bytes)

So this PR mainly add brotli as a transformation filter, like gzip and deflate used to do it.

It doesn't add any code in the microcontroller for decompressing the brotli's data, it's only used as a preprocessing step to reduce the filesystem size. The microcontroller will simply send the data as-is when requested.

Fixes

While testing this PR, I've found few subtle bugs that I corrected.

Transform order wasn't respected

Let's say you had this in your YAML file:

[...]
filters:
  '*': 
    - gzip

  '*.css':
    - uglifycss
    - gzip

In the current code, the later filter on CSS files will apply uglifycss on a gzipped input. That because, when the xforms dict is created in apply_rules, it first find the '*' filter, thus a gzip is transform is created. Then it finds the '*.css' filter, and create the uglifycss transform (it later find the gzip filter again, but since it already exists, it only replace it, not changing the order in the dictionary). You end up with a dict containing gzip, uglifycss in that order.

I've solved that simply by ranking the filters. A filter with a higher rank will overwrite the xforms dict thus preventing bad transforms order in the dictionary. A lower rank filter will be ignored if an higher rank filter was processed before it. I think it's the most logical solution, since you don't want to mix the actions of filters with higher specializations.

no transform crashed the processing

In the current code, if you have a no something filter, the ent["transform"] will contain a False argument (as a way to prevent processing this action). Yet, the actual code doing the processing was only expecting a dict, crashing the processing. Now, the processing handles the case carefully by bypassing the processing as expected.

Fixing spell error