Simple path matching

1. The problem I’m having:

I’m trying to match URLs containing “profile” with a specific pattern:
/some-id/profile/some-other-url-part/and-another

This is a simple Caddyfile I am using:

:2015

@profile {
    path */profile/*
}

handle @profile {
  respond "Hello, profile!"
}

respond "Hello, world!"

Expected behavior: Match paths with exactly one segment before “profile” and any number after.

Current behavior:

  • localhost:2015/a/profile/s returns “Hello, profile!” (correct)
  • localhost:2015/a/profile/s/d returns “Hello, world!” (incorrect)
  • Previous matcher */profile/* was too permissive, matching multiple segments before “profile”

2. Error messages and/or full log output:

N/A

3. Caddy version:

2.8.4 on alpine

4. How I installed and ran Caddy:

Installed locally via homebrew and also tested in Docker

a. System environment:

macOS 15.1.1

b. Command:

caddy run --config Caddyfile

c. Service/unit/compose file:

N/A

d. My complete Caddy config:

:2015

@profile {
    path /*/profile/*
}

handle @profile {
  respond "Hello, profile!"
}

respond "Hello, world!"

5. Links to relevant resources:

You should use path_regexp for this case. The path matcher does fast prefix and fast suffix matching, it doesn’t stop at path segments.

Might a {path.*} placeholder be useful here for precision and speed?

There’s no base matcher for it, so you’d need to test it with CEL. It would look like:

@profile `{path.1} == "profile"`
respond @profile "Hello, profile!"

respond "Hello, world!"

Not quite the same logically as /*/profile/* though; it matches on /foo/profile as well as /foo/profile/bar.

But it does match exactly your specified example behaviour; exactly one segment, then another segment “profile”, then any number of segments (including zero) afterwards.