"module not registered: http.matchers.status" when trying to intercept responses

1. Caddy version (caddy version):

2.4.0

2. How I run Caddy:

a. System environment:

Docker using the 2.4.0-alpine tag

b. Command:

docker-compose up

No command given in docker-compose.yml

c. Service/unit/compose file:

services:
  proxy:
    image: caddy:2.4.0-alpine
    restart: always
    ports:
      - 80:80
      - 443:443
    volumes:
      - caddy_data:/data
      - caddy_config:/config
      - ./Caddyfile:/etc/caddy/Caddyfile
    logging:
      driver: syslog
      options:
        tag: caddy

d. My complete Caddyfile or JSON config:

mysite.com {
  log
  encode gzip
  reverse_proxy {
    to minio:9000
    header_down -Server
    header_down -Content-Security-Policy
    header_down -X-Amz-Request-Id
  }

  header {
    Permissions-Policy interest-cohort=()
  }

  @noslash {
    not expression {path}.endsWith("/")
    path_regexp ^[a-z\-/]*$
  }

  @with_query {
    not expression {query}.size() == 0
  }

  handle @noslash {
    redir @with_query {path}/?{query} permanent
    redir {path}/ permanent
  }

  handle {
    @document expression {path}.endsWith("/")
    route @document {
      rewrite {path}index.html
    }
    rewrite * /bucket{path}
  }

  @notfound status 404
  handle_response @notfound {
    rewrite /bucket/404.html
    reverse_proxy minio:9000
  }
}

3. The problem I’m having:

Following the documentation here: reverse_proxy (Caddyfile directive) — Caddy Documentation I’m trying to use the handle_response directive to display custom 404 pages when serving static sites managed by a MinIO storage.

When I add the additional notfound matcher and the handle_response directive, Caddy fails to start up.

4. Error messages and/or full log output:

May 14 09:45:27 caddy[549]: {"level":"info","ts":1620978327.6110585,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
May 14 09:45:27 caddy[549]: run: adapting config using caddyfile: getting matcher module 'status': module not registered: http.matchers.status

Is the status matcher not part of the official builds? In case it requires a custom build, how would this work and should this be mentioned in the reverse_proxy documenation?

In your current Caddyfile, this section is outside the reverse_proxy directive block:

The status matcher and the handle_response directive are part of the reverse_proxy namespace. Currently you have the reverse_proxy at the top of your Caddyfile, then handle_response at the bottom of the Caddyfile containing outside of the reverse_proxy directive. Put the matcher and the handle_response inside the the reverse_proxy directive at the top.

1 Like

Thanks for the pointer @Mohammed90 - this makes sense.

I don’t know what I am doing wrong, but I get another error after changing the config like this:

May 14 11:54:28 caddy[549]: run: adapting config using caddyfile: parsing caddyfile tokens for 'reverse_proxy': /etc/caddy/Caddyfile:88 - Error during parsing: parsing caddyfile tokens for 'rewrite': /etc/caddy/Caddyfile:86 - Error during parsing: Wrong argument count or unexpected line ending after 'rewrite'

Config now looks like this:

mysite.com {
  log
  encode gzip
  reverse_proxy {
    to minio:9000
    header_down -Server
    header_down -Content-Security-Policy
    header_down -X-Amz-Request-Id

    @notfound status 404
    handle_response @notfound {
      rewrite /bucket/404.html
      reverse_proxy minio:9000
    }
  }

  header {
    Permissions-Policy interest-cohort=()
  }

  @noslash {
    not expression {path}.endsWith("/")
    path_regexp ^[a-z\-/]*$
  }

  @with_query {
    not expression {query}.size() == 0
  }

  handle @noslash {
    redir @with_query {path}/?{query} permanent
    redir {path}/ permanent
  }

  handle {
    @document expression {path}.endsWith("/")
    route @document {
      rewrite {path}index.html
    }
    rewrite * /bucket{path}
  }
}

There is no spurious whitespace or any exotic line breaks in effect here.

Oh, I see it. This:

Should be:

rewrite * /bucket/404.html
2 Likes

Ah nice, that works, thank you very much.

Is this a different situation than in the docs which use

reverse_proxy localhost:8080 {
	@error status 500 503
	handle_response @error {
		root    * /path/to/error/pages
		rewrite   /{http.reverse_proxy.status_code}.html
		file_server
	}
}

or is the * missing there as well?

1 Like

It’s an idiosyncrasy of the parser. See because the argument starts with a forward slash /, the parser assumes it’s a matcher, which leads it to believe the second argument is missing. In such cases, it’s best being explicit by including the wildcard matcher *.

I’ll fix the docs :slightly_smiling_face:

3 Likes

My bad for the mistake in the docs :man_facepalming:

Thanks @Mohammed90 for cleaning up after me :grin:

2 Likes

Thanks again for the explanation and helping me getting this fixed so quickly.

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