I've come up with an attempted solution. It's not finished yet (no tests and I haven't published to CPAN), because I was hoping to get some feedback if anyone has time before I move further in case it's not a great solution :)
I created a role that uses the before method modifiers on serve_asset <https://metacpan.org/pod/Mojolicious::Static#serve_asset> and is_fresh <https://metacpan.org/pod/Mojolicious::Static#is_fresh>. In the serve_asset before, I check if serving a compressed asset is appropriate (the asset is a Mojo::Asset::File, the compressed asset exists for the file, the client accepts that type of encoding), and then serve if while adding the necessary headers (content_encoding, etc). If none of those conditions are met, the uncompressed asset will be served. The is_fresh before method is used only if a compressed asset exists to set the last modified time of the compressed asset to the last modified time of the uncompressed asset, and also to modify the etag to contain the encoding at the end. I would really appreciate any feedback or recommendations :) Here's a link to the github repo, which has a README with documentation: https://github.com/srchulo/Mojolicious-Static-Role-Compressed On Monday, April 1, 2019 at 11:38:55 PM UTC-5, Adam Hopkins wrote: > > Hi all, > > I wanted to get some feedback on how to approach serving compressed static > assets. I have my static assets along with pre-compressed versions of the > assets via gzip and brotli. I’d like to serve static assets first by the > brotli compressed asset if it exists, then gzip if it exists (preferrably > the smallest first, but that should be the brotli asset if it exists), then > the regular asset if there is neither. > > I had mentioned this in the #mojo IRC channel, and kraih and batman had > recommended maybe this would make sense as a part of > Mojolicious::Plugin::AssetPack > <https://metacpan.org/pod/Mojolicious::Plugin::AssetPack>. However, now I > already have the assets compressed, so I’m not sure that this would make > sense. > > A suggestion was made that a before_dispatch > <https://mojolicious.org/perldoc/Mojolicious#before_dispatch> hook could > maybe look at Accept-Encoding and modify the request if gzip or br was > accepted and the file existed. I have a few concerns with this after > thinking about it. One is that this won’t work for static files that are > served via reply->static > <https://metacpan.org/pod/Mojolicious::Plugin::DefaultHelpers#reply-%3Estatic>, > > or serve in Mojolicious::Static > <https://metacpan.org/pod/Mojolicious::Static#serve>. Another concern is > that the Last-Modified time for asset.css.gzip isn’t guaranteed to be the > same as asset.css, and I feel like asset.css’s Last-Modified time is what > should be used. Another is that ETags are suppose to be content coding > aware: > > https://tools.ietf.org/html/rfc7232#section-2.3.3 > > And since Mojolicous::Static > <https://metacpan.org/pod/Mojolicious::Static> calls md5_sum > <https://metacpan.org/pod/Mojo::Util#md5_sum> on the files Last-Modified > time, it’s not guaranteed that the different content-codings will have > different ETags. > > After thinking about all of this, it seems like what would need to be done > is create a Mojolicious::Static > <https://metacpan.org/pod/Mojolicious::Static> class or a subclass. I > believe maybe just serve in Mojolicious::Static > <https://metacpan.org/pod/Mojolicious::Static#serve> would need to be > overridden. However, I definitely prefer to avoid this approach as changes > in Mojolicious::Static <https://metacpan.org/pod/Mojolicious::Static> or > what methods Mojolicious <https://metacpan.org/pod/Mojolicious> expects > the object in static <https://metacpan.org/pod/Mojolicious#static> to > handle could cause it to break. Also, there's a lot of HTTP/RFC login in > serve, and I'd prefer not to mess with that. > > Is there a good way to solve this with a plugin? Or am I correct in > assuming that this would need to happen at some level in the object in > static <https://metacpan.org/pod/Mojolicious#static>? > > -- You received this message because you are subscribed to the Google Groups "Mojolicious" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at https://groups.google.com/group/mojolicious. For more options, visit https://groups.google.com/d/optout.
