FIXED / How to add the missing trailing slash? (RedirectRegex + stripprefixregex) no need for ReplacePathRegex

Hi,

In the screenshot above, portainer is stucked in this weird state without the /. At the moment, I need to add it manually. Per example mydomain.club/portainer/

EDIT: it's not limited to portainer

As I'm migrating from V1 to V2, I can't find the right way to write the middleware(s) in Traefik V2 that will automatically add the missing /.

In V1 here is how it worked:

      ## Working configs from traefik:v1.7
      ## fixed https://github.com/containous/traefik/issues/563#issuecomment-421360934
      - "traefik.frontend.redirect.regex=^(.*)/portainer$$"
      - "traefik.frontend.redirect.replacement=$$1/portainer/"
      - "traefik.frontend.rule=PathPrefix:/portainer;ReplacePathRegex: ^/portainer/(.*) /$$1"

In v2 without the redirectregex (working)

This works with portainer. But I will need to manually add a / at the end.

version: "3.3"
services:
  portainer:
    image: portainer/portainer
    ...
    labels:
      #### core configs
      - "traefik.enable=true"
      - "traefik.http.routers.portainer.rule=Host(`mydomain.club`) && PathPrefix(`/portainer`)"
      - "traefik.http.services.portainer.loadbalancer.server.port=9000"
      #### set TLS (https)
      - "traefik.http.routers.portainer.entrypoints=websecure"
      - "traefik.http.routers.portainer.tls=true"
      - "traefik.http.routers.portainer.tls.certresolver=leresolver"
      #### use these middlewares (rules like our-auth,our-retry,our-ratelimit are defined within traefik's labels)
      - "traefik.http.routers.portainer.middlewares=our-auth,our-retry,our-ratelimit,our-header,portainer-strip"
        #___ specific middleware rule for this service
      - "traefik.http.middlewares.portainer-strip.stripprefix.prefixes=/portainer"

In v2 with redirectregex + replacepathregex

Not working yet ... draft in progress.

    labels:
      #### core configs
      - "traefik.enable=true"
      - "traefik.http.routers.portainer.rule=Host(`mydomain.club`) && PathPrefix(`/portainer`)"
      - "traefik.http.services.portainer.loadbalancer.server.port=9000"
      #### set TLS (https)
      - "traefik.http.routers.portainer.entrypoints=websecure"
      - "traefik.http.routers.portainer.tls=true"
      - "traefik.http.routers.portainer.tls.certresolver=leresolver"
      #### use these middlewares (rules like our-auth,our-retry,our-ratelimit are defined within traefik's labels)
      - "traefik.http.routers.portainer.middlewares=our-auth,our-retry,our-ratelimit,our-header,portainer-strip,portainer-trailingslash"
        #___ specific middleware rule for this service
      - "traefik.http.middlewares.portainer-strip.stripprefix.prefixes=/portainer"
        #___ add missing '/' at the end i.e. mydomain.club/portainer/
      - "traefik.http.middlewares.portainer-trailingslash.replacepathregex.regex=^/portainer(.*)"
      - "traefik.http.middlewares.portainer-trailingslash.replacepathregex.replacement=/portainer/$$1"

Thanks in advance!

2 Likes

Here are two examples that are working under Traefik V1.7

Here are an interesting findings:

1)

Testing a web server like Nginx. Using the default homepage it loads. (no trailings slash)

2)

Using my HTML code, only index.html seems to load. All CSS and images are ignore. (no trailings slash)

3)

Good. My content loads normally when I type the URL using a trailing slash.

4)

When traefik loads it's own dashboard, it manage to add the trailing slash and life is good.

my compose.yml

version: "3.3"

services:

  nginx:
    image: nginx:1.17-alpine
    container_name: nginx
    hostname: nginx
    restart: unless-stopped
    volumes:
      - /mnt/webapps/green:/usr/share/nginx/html

    labels:
      #### core configs
      - "traefik.enable=true"
      - "traefik.http.routers.nginx.rule=Host(`devkiwi.club`) && PathPrefix(`/nginx`)"
      - "traefik.http.services.nginx.loadbalancer.server.port=80"
      #### set TLS (https)
      - "traefik.http.routers.nginx.entrypoints=websecure"
      - "traefik.http.routers.nginx.tls=true"
      - "traefik.http.routers.nginx.tls.certresolver=leresolver"
      #### use these middlewares (rules like our-auth,our-retry,our-ratelimit are defined within traefik's labels)
      - "traefik.http.routers.nginx.middlewares=our-retry,our-ratelimit,our-header,nginx-strip"
        #___ specific middleware rule for this service
      - "traefik.http.middlewares.nginx-strip.stripprefix.prefixes=/nginx"

Still not working at the moment. But we are getting closer. Following on this suggestion to use replacepathregex

This is how I think I should configure the replacepathregex:

      - "traefik.http.middlewares.nginx-pathregex.replacepathregex.regex=^/nginx(.*)"
      - "traefik.http.middlewares.nginx-pathregex.replacepathregex.replacement=/nginx/$$1"

compose-nginx.yml

version: "3.3"

services:

  nginx:
    image: nginx:1.17-alpine
    container_name: nginx
    hostname: nginx
    restart: unless-stopped
    volumes:
      - /mnt/webapps/green:/usr/share/nginx/html

    labels:
      #### core configs
      - "traefik.enable=true"
      # - "traefik.http.routers.caddy.service=nginx" # swarm
      - "traefik.http.routers.nginx.rule=Host(`mydomain.club`) && PathPrefix(`/nginx`)"
      - "traefik.http.services.nginx.loadbalancer.server.port=80"
      #### set TLS (https)
      - "traefik.http.routers.nginx.entrypoints=websecure"
      - "traefik.http.routers.nginx.tls=true"
      - "traefik.http.routers.nginx.tls.certresolver=leresolver"
      #### use these middlewares (rules like our-auth,our-retry,our-ratelimit are defined within traefik's labels)
      - "traefik.http.routers.nginx.middlewares=our-retry,our-ratelimit,our-header,nginx-strip,nginx-pathregex"
        #___ specific middleware rule for this service
      - "traefik.http.middlewares.nginx-strip.stripprefix.prefixes=/nginx"
        #___ add missing trailing slash
      - "traefik.http.middlewares.nginx-pathregex.replacepathregex.regex=^/nginx(.*)"
      - "traefik.http.middlewares.nginx-pathregex.replacepathregex.replacement=/nginx/$$1"

      #### https://twitter.com/askpascalandy

traefik's dashboard

here is the solution!! Full credit to @trajano <== :cowboy_hat_face: :nerd_face: :sunglasses:

To conclude this is how it looks like now:

compose nginx

    labels:
      ...
      #### core configs
      - "traefik.enable=true"
      # - "traefik.http.routers.caddy.service=nginx" # swarm
      - "traefik.http.routers.nginx.rule=Host(`devkiwi.club`) && PathPrefix(`/nginx`)"
      - "traefik.http.services.nginx.loadbalancer.server.port=80"
      #### set TLS (https)
      - "traefik.http.routers.nginx.entrypoints=websecure"
      - "traefik.http.routers.nginx.tls=true"
      - "traefik.http.routers.nginx.tls.certresolver=leresolver"
      #### use these middlewares (rules like our-auth,our-retry,our-ratelimit are defined within traefik's labels)
      - "traefik.http.routers.nginx.middlewares=our-retry,our-ratelimit,our-header,our-slash"

compose traefik

The redirectregex and stripprefixregex are working together with the chain.middlewares :slight_smile:

    labels:
      ...
        #___ add missing trailing slash
      - "traefik.http.middlewares.our-slash.chain.middlewares=strip-prefix-1,strip-prefix-2"
      - "traefik.http.middlewares.strip-prefix-1.redirectregex.regex=^(https?://[^/]+/[a-z0-9_]+)$$"
      - "traefik.http.middlewares.strip-prefix-1.redirectregex.replacement=$${1}/"
      - "traefik.http.middlewares.strip-prefix-1.redirectregex.permanent=true"
      - "traefik.http.middlewares.strip-prefix-2.stripprefixregex.regex=/[a-z0-9_]+"
2 Likes