Regex match slash in Path

Imagine a frontend application that changed the prefix of urls many times in the past month. For backward compability reasons, I need to keep supporting them. To give an example:

GET /as/products
GET /v1/as/products
GET /v1/app/products
GET /app/products => recent version and the one I want to maintain going forward

All these combinations point to the same resource on the backend. Say now we want to redirect this endpoint to a different service. I expect a regex like this to work:

      rule: Path(`/{(v1/)?((as)|(app))}/products`)

Note: I can't do PathPrefix(/v1/as/, /v1/app/, /as/, /app/) because I need to slowly migrate endpoints, one by one.

here is a docker-compose.yml with a similar scenario:

version: '3'

    image: traefik:v2.6
    command: --api.insecure=true --providers.docker
      - "80:80"
      - "8080:8080"
      - /var/run/docker.sock:/var/run/docker.sock
    image: traefik/whoami
      - "traefik.http.routers.whoami.rule=Path(`/{(v1/)?((as)|(app))}/products`)"

Testing this I get the following results:

curl http://localhost/app/products => OK
curl http://localhost/as/products => OK
curl http://localhost/v1/app/products => FAIL
curl http://localhost/v1/as/products => FAIL

So it seems the regex does not match /. Any suggestion about how to solve this problem?

Hello @LuanJames,

There are specificities when using regexps in routers' matcher.
According to Routers - Traefik :

!!! important "Regexp Syntax"

    `HostRegexp`, `PathPrefix`, and `Path` accept an expression with zero or more groups enclosed by curly braces, which are called named regexps.
    Named regexps, of the form `{name:regexp}`, are the only expressions considered for regexp matching.
    The regexp name (`name` in the above example) is an arbitrary value, that exists only for historical reasons.

    Any `regexp` supported by [Go's regexp package]( may be used.

So your configuration should look something like:

    image: traefik/whoami
      - "traefik.http.routers.whoami.rule=Path(`/{path:(v1/)?((as)|(app))}/products`)"

Hope it helps :slight_smile:

1 Like