How to match files for cache-control in a handler

1. The problem I’m having:

I am trying to set a cache-control header based on a file type in a path. I tried this:

But putting this within the handler didn’t work and of course this is a reverse_proxy so it needs to be header_down. If I use this, it works but of course for all files which is not what I want.

@nocache {
        file *.txt
}

handle {
                reverse_proxy https://192.168.73.49:8080 {
                        transport http {
                                dial_timeout 30s # Experimental
                                tls_insecure_skip_verify

                        }
	header_down cache-control no-store
                }
        }

The path in question is https://tester1.camdenacres.stream/static/status.txt

Things I have tried:

@nocache {
        file 
        path *.txt
}

handle {
                reverse_proxy https://192.168.73.49:8080 {
                        transport http {
                                dial_timeout 30s # Experimental
                                tls_insecure_skip_verify

                        }
	header_down @nocache cache-control no-store
                }
        }
handle {
                reverse_proxy https://192.168.73.49:8080 {
                        transport http {
                                dial_timeout 30s # Experimental
                                tls_insecure_skip_verify

                        }
	header_down @nocache cache-control no-store
                }
@nocache {
        file *.txt
}
        }

Several other permutations.

2. Error messages and/or full log output:

N/A - This is a config issue.

3. Caddy version:

v2.6.4 h1:2hwYqiRwk1tf3VruhMpLcYTg+11fCdr8S3jhNAdnPy8=

4. How I installed and ran Caddy:

Docker compose

version: "3.6"
services:
  Caddy:
    container_name: "Caddy"
    hostname: "Caddy"
    image: "caddy:latest"
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
    networks:
      - "Docker1"
    ports:
      - "443:443/tcp"
      - "80:80/tcp"
    restart: "unless-stopped"
    volumes:
      - "/opt/caddy/html:/var/caddy/html:ro"
      - "/opt/caddy:/etc/caddy:ro"

networks:
  Docker1:
    external: true
    name: "Docker1"

a. System environment:

Debian 11.7 running Docker 23.0.1

b. Command:

See docker-compose aobve

c. Service/unit/compose file:

See above

d. My complete Caddy config:

https://tester1.camdenacres.stream {

        handle_path /errors* {
                root * /var/caddy/html
                file_server
        }

	@nocache {
	        file *.txt
	}
        
	handle {
                reverse_proxy https://192.168.73.49:8080 {
                        transport http {
                                dial_timeout 30s # Experimental
                                tls_insecure_skip_verify

                        }
	header_down @nocache cache-control no-store
                }
        }

        handle_errors {
                @502 `{err.status_code} == 502`
 		handle @502 {
                        root * /var/caddy/html
                        rewrite * /502.html
                        file_server
                }
        }
}

5. Links to relevant resources:

Use the header directive, not the header_down option of reverse_proxy.

The directive supports matchers, the proxy option does not.

Also, you’re looking for the path matcher, not file. The file matcher looks for a file existing on disk, but Caddy doesn’t have access to files in your setup since it’s proxying to a remote server.

I had a response and I think I see the issue as I misunderstood what you meant.

@nocache {
        path *.txt
}
        
        handle {
                reverse_proxy https://192.168.73.49:8080 {
                        transport http {
                                dial_timeout 30s # Experimental
                                tls_insecure_skip_verify
                        }
                }
                        header @nocache cache-control no-store
        }

This seems to work betterish - but I have two cache-control headers now. So at least I know the match is working but I would expect the other cache-control to have been replaced with no-store. Example:

curl -I https://tester1.camdenacres.stream/static/status.txt
HTTP/2 200 
accept-ranges: bytes
alt-svc: h3=":443"; ma=2592000
cache-control: no-store
cache-control: public, max-age=2678400 
content-type: text/plain
date: Tue, 16 May 2023 01:24:58 GMT
etag: "175f769c838c22ab-271"
last-modified: Tue, 16 May 2023 00:00:01 GMT
server: Caddy
server: Python/3.10 aiohttp/3.8.4
content-length: 625

Note "cache-control: public, max-age=2678400 ".

EDIT: I tried

header @nocache cache-control public* no-store

and that seemingly didn’t match the exisiting header.

What you can do is use the defer option of the header directive to make sure it operates after the proxy, so it will overwrite it instead of letting the proxy add its own afterwards.

@nocache path *.txt
header @nocache {
	Cache-Control no-store
	defer
}
1 Like

Brilliant, that worked perfectly. Thank you!

FWIW I’m thinking of adding a shortcut for that case because I’m a bit annoyed by the longer syntax :sweat_smile:

1 Like

LGTM! Ship it. :slight_smile:

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.