Django - serve static assets with cache expire not working

1. Not working: serve static assets with an efficient cache policy

I have setup a Django website with Caddy(2.7.6). All works fine. But when I run my website through the pagespeed test, one of the things it recommends is “serve static assets with an efficient cache policy”, however I have this added to my Caddy conf file. So I don’t know why it’s not working.

3. Caddy version: 2.7.5

4. How I installed and ran Caddy:

I installed Caddy from repo copr:copr.fedorainfracloud.org:group_caddy:caddy on a RHEL like system. Release 1.el9. Installed with dnf after adding COPR repo.

a. System environment:

Alma Linux 9. I started Caddy via systemd.

b. Command:

So sudo systemctl start caddy & sudo systemctl enable caddy.

c. Service/unit/compose file:

Systemd.

d. My complete Caddy config:

www.example.com {
        log {
          output file /var/log/caddy/example.access.log
          level INFO
        }

        encode zstd gzip

        handle_path /static/* {
          root * /var/www/example.com/static
          file_server
        }

        handle {
          reverse_proxy localhost:3000
        }

        @cachedFiles {
          file
          path *.ico *.css *.js *.gif *.jpg *.jpeg *.png *.svg *.woff *.woff2 *.webp *.ttf *.avif
        }
        header @cachedFiles Cache-Control "public, max-age=604800, must-revalidate"
        # header @static Cache-Control max-age=31536000

        #route {
        #       header           Cache-Control max-age=3600
        #        header /static/* Cache-Control max-age=31536000
        #}
}

On my Caddyfile I just have import *.caddy and then the above config is on example.caddy.

The @cachedFiles block should cache the static assets. I also tried commenting out the @cachedFiles block and trying the route block below. But the pagespeed always tells me I need to set expire headers.

Am I putting it in the wrong place or am I doing anything wrong?

Is this meant to apply to files in /static?

If so, I think the problem is that this is outside your handle_path /static/*, so the file matcher is using the current request path before being stripped of the /static prefix, and root is not set in the current request context.

Move this inside of your handle_path and it should work, it’ll run after root and after the path is stripped, so the file matcher should correctly map to files on disk.

Yes that did the job. Thanks a lot for your help.