From 572a716140874d12ccc827564dce40364b40a9f5 Mon Sep 17 00:00:00 2001 From: MDLeom <2809763-curben@users.noreply.gitlab.com> Date: Thu, 12 Nov 2020 06:53:41 +0000 Subject: [PATCH] post: 'Serving pre-compressed files in Caddy 2' --- source/_posts/caddy2-pre-compressed.md | 244 +++++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 source/_posts/caddy2-pre-compressed.md diff --git a/source/_posts/caddy2-pre-compressed.md b/source/_posts/caddy2-pre-compressed.md new file mode 100644 index 0000000..27a9a92 --- /dev/null +++ b/source/_posts/caddy2-pre-compressed.md @@ -0,0 +1,244 @@ +--- +title: Serving pre-compressed files in Caddy 2 +excerpt: gzip and brotli files +date: 2020-11-12 +tags: +- caddy +--- + +Caddy v0.9.4+ and v1.0.0+ support pre-compressed gzip and brotli files automatically. However, this feature is [not yet](https://github.com/caddyserver/caddy/issues/2665) implemented in v2 and requires manual configuration. Examples available at the Caddy forum are incomplete, it's either gzip or brotli. The config provided in this guide supports _both_, prioritising brotli if supported by the requesting web browser (and there are .br files), otherwise fallback to gzip. + +## Default usage + +This configuration supports URL normalisation; when a URL has a trailing slash `http://localhost:8080/about/`, Caddy will serve `http://localhost:8080/about/index.html` using _internal/transparent_ redirect (without 301/302 redirect). If you need to internal redirect `http://localhost:8080/bio` to `http://localhost:8080/bio.html`, refer to the [next section](#Pretty-URLs). + +``` plain Caddyfile +http://localhost:8080 { + bind 127.0.0.1 ::1 + + root * /home/user/www + file_server + + @brotli { + header Accept-Encoding *br* + file { + try_files {path}.br {path}/index.html.br + } + } + handle @brotli { + header Content-Encoding br + rewrite {http.matchers.file.relative} + } + + @gzip { + header Accept-Encoding *gzip* + file { + try_files {path}.gz {path}/index.html.gz + } + } + handle @gzip { + header Content-Encoding gzip + rewrite {http.matchers.file.relative} + } + + @html { + file + path *.html */ + } + header @html Content-Type text/html + + @css { + file + path *.css + } + header @css Content-Type text/css + + @js { + file + path *.js + } + header @js Content-Type text/javascript + + @svg { + file + path *.svg + } + header @svg Content-Type image/svg+xml + + @xml { + file + path *.xml + } + header @xml Content-Type application/xmlr + } + + @json { + file + path *.json + } + header @json Content-Type application/json +} +``` + +### Content-Type + +``` +@svg { + file + path *.svg +} +header @svg Content-Type image/svg+xml +``` + +`Content-Type` response header needs to be specified as a workaround, otherwise Caddy responses with `application/gzip`. + +### URL normalisation + +``` +@html { + file + path *.html */ +} +``` + +`*/` is to match path with a trailing slash `/path/` since that is (transparently) redirects to `/path/index.html`. + +### Dummy files + +``` +root * /home/user/www +``` + +I prepared a set of dummy files with most common file extensions ([download](https://gitlab.com/curben/blog/-/raw/site/20201112/dummy.zip)). This enables you to test whether Caddy serves the correct file. `.gz` and `.br` files are _not_ compressed files, they are text files so that you can easily identify the file being served. + +Unzip the dummy.zip and specify the folder in the `root` directive. Following are some sample tests after you start Caddy: + +``` +$ curl -i http://localhost:8080/foo.svg -H 'Accept-Encoding: gzip' + +# /foo.svg.gz should be served +HTTP/1.1 200 OK +Content-Encoding: gzip +Content-Type: image/svg+xml + +svg gz +``` + +``` +$ curl -i http://localhost:8080/foo.svg -H 'Accept-Encoding: gzip,br' + +# /foo.svg.br should be served +HTTP/1.1 200 OK +Content-Encoding: br +Content-Type: image/svg+xml + +svg br +``` + +``` +$ curl -i http://localhost:8080/foo.svg + +# /foo.svg should be served +HTTP/1.1 200 OK +Content-Type: image/svg+xml + +svg +``` + +## Pretty URLs + +This configuration supports transparently redirect a URL without trailing slash and file extension, e.g. `http://localhost:8080/bio` to `http://localhost:8080/bio.html`. If you request "bio.html", Caddy still still serve it as usual, without any redirect. This feature is similar to [Netlify's](https://docs.netlify.com/routing/redirects/redirect-options/#trailing-slash). + +``` plain Caddyfile +http://localhost:8080 { + bind 127.0.0.1 ::1 + + root * /home/user/www + file_server + try_files {path}.html + + @brotli { + header Accept-Encoding *br* + file { + try_files {path}.br {path}/index.html.br {path}.html.br + } + } + handle @brotli { + header { + Content-Encoding br + Content-Type text/html + } + rewrite {http.matchers.file.relative} + } + + @gzip { + header Accept-Encoding *gzip* + file { + try_files {path}.gz {path}/index.html.gz {path}.html.gz + } + } + handle @gzip { + header { + Content-Encoding gzip + Content-Type text/html + } + rewrite {http.matchers.file.relative} + } + + @html { + file + path *.html */ + } + header @html { + Content-Type text/html + defer + } + + @css { + file + path *.css + } + header @css { + Content-Type text/css + defer + } + + @js { + file + path *.js + } + header @js { + Content-Type text/javascript + defer + } + + @svg { + file + path *.svg + } + header @svg { + Content-Type image/svg+xml + defer + } + + @xml { + file + path *.xml + } + header @xml { + Content-Type application/xml + defer + } + + @json { + file + path *.json + } + header @json { + Content-Type application/json + defer + } +} +``` + +Derived from [[1]](https://caddy.community/t/how-to-serve-pre-compressed-files-with-caddy-v2/8760), [[2]](https://caddy.community/t/how-to-serve-gzipped-files-automatically-in-caddy-v2/7311), [[3]](https://caddy.community/t/why-caddy-2-is-not-able-to-serve-static-brotli-files/7653).