Docker label `forceslash=true` doesn't seem to work

Here below a description of my problem:

What did you do?

In chrome browser I entered https://<my public IP address>/node-red

What did you expect to see?

After entering my traefik basic authentication credentials (I don't need to enter them always - they seem to be cached) I should see my node-red editor home screen.

Note that it is working fine when I enter the same url with a / at the end (= https://<my public IP address>/node-red )

As forceslash is set to true, i would expect to get exactly the same behaviour when entering the URL with or without a / at the end.

What did you see instead?

blank screen.

Output of traefik version: (What version of Traefik are you using?)

Version: 2.1.3
Codename: cantal
Go version: go1.13.6
Built: 2020-01-21T17:30:29Z
OS/Arch: linux/amd64

What is your environment & configuration (arguments, toml, provider, platform, ...)?

Here below the relevant part of my docker-compose file (note that I have masked some fields like LAN_HOSTNAME, PUBLIC_HOSTNAME)

  traefik:
    image: traefik
    container_name: "traefik"
    command:
      - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      #- "--entrypoints.nodered.address=:1880"
      #- "--entrypoints.grafana.address=:3000"
      - "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
      #  # - "--certificatesresolvers.mytlschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.mytlschallenge.acme.email=jXXXXXXXX@gmail.com"
      - "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
    ports:
      # The HTTP port
      - "80:80"
      - "443:443"
      #- "1880:1880"
      #- "3000:3000"
      # The Web UI (enabled by --api.insecure=true)
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./letsencrypt:/letsencrypt"
  node-red:
    build: node-red
    privileged: true
    volumes:
       - 'node-red-data:/data'
    #ports:
    #   - "1880:1880"
    depends_on:
        - mqtt
    restart: always
    environment:
      - TZ=Europe/Brussels
    labels:
      - "traefik.enable=true"
    # HTTP (LAN) connection
      - "traefik.http.routers.nodered_lan.rule=Host(`LAN_HOSTNAME`) && PathPrefix(`/node-red`)"
      - "traefik.http.routers.nodered_lan.entrypoints=web"
    # HTTPS (WAN) connection
      - "traefik.http.routers.nodered_wan.rule=Host(`PUBLIC_HOSTNAME`) && PathPrefix(`/node-red`)"
      - "traefik.http.routers.nodered_wan.entrypoints=websecure"
      - "traefik.http.routers.nodered_wan.tls.certresolver=mytlschallenge"
    # middlewares
      - "traefik.http.routers.nodered_lan.middlewares=nodered_auth,strip_node_red_prefix"
      - "traefik.http.routers.nodered_wan.middlewares=nodered_auth,strip_node_red_prefix"
      # To create user:password pair, it's possible to use this command:
      # echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g
      - "traefik.http.middlewares.nodered_auth.basicauth.users=jan:$$aHASHED_PASSWORDpup/"
      - "traefik.http.middlewares.strip_node_red_prefix.stripprefix.prefixes=/node-red"
      - "traefik.http.middlewares.strip_node_red_prefix.stripprefix.forceslash=true"

Many thanks in advance for all support with this issue
Jan.

Before raising this forum topic I have created a github issue for this : https://github.com/containous/traefik/issues/6254

This github is closed with following comment: I don't reproduce, could you go to the community forum to get more help.

So for me it is still an issue.
Any support would be welcome.

Hello,

the stripPrefix middleware only modify the path of the request to node-red (/node-red -> /), and I can guarantee that the forceSlash works as expected (the / is added).

The problem is the way that the node-red UI manage the path on the assets. Those elements are evaluate in the browser not during the calls.

The browser calls:
http://lan.localhost/vendor/jquery/css/base/jquery-ui.min.css

instead of:
http://lan.localhost/node-red/vendor/jquery/css/base/jquery-ui.min.css

so the way to achieve what you want:

version: "3.7"

services:

  traefik:
    image: traefik:v2.1.3
    command:
      - --log.level=DEBUG
      - --api.insecure=true
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
    ports:
      - 80:80
      - 443:443
      # The Web UI (enabled by --api.insecure=true)
      - 8080:8080
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro

  node-red:
    image: nodered/node-red:1.0.3-2
    labels:
      traefik.enable: true

      # HTTP (LAN) connection
      traefik.http.routers.nodered_lan.rule: Host(`lan.localhost`) && PathPrefix(`/node-red`)
      traefik.http.routers.nodered_lan.entrypoints: web
      traefik.http.routers.nodered_lan.middlewares: nodered_redirect,nodered_auth,strip_node_red_prefix

      # HTTPS (WAN) connection
      traefik.http.routers.nodered_wan.rule: Host(`wan.localhost`) && PathPrefix(`/node-red`)
      traefik.http.routers.nodered_wan.entrypoints: websecure
      traefik.http.routers.nodered_wan.middlewares: nodered_redirect,nodered_auth,strip_node_red_prefix
      traefik.http.routers.nodered_wan.tls: true

      # middlewares
      traefik.http.middlewares.nodered_auth.basicauth.users: user:$$apr1$$q8eZFHjF$$Fvmkk//V6Btlaf2i/ju5n/ # user/password
      traefik.http.middlewares.strip_node_red_prefix.stripprefix.prefixes: /node-red
      traefik.http.middlewares.nodered_redirect.redirectregex.regex: ^(https?)://([^/]+)/node-red$$
      traefik.http.middlewares.nodered_redirect.redirectregex.replacement: $${1}://$${2}/node-red/
Bonus: WAN HTTP to HTTPS redirection
version: "3.7"

services:

  traefik:
    image: traefik:v2.1.3
    command:
      - --log.level=INFO
      - --api.insecure=true
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
    ports:
      - 80:80
      - 443:443
      # The Web UI (enabled by --api.insecure=true)
      - 8080:8080
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    labels:
      traefik.enable: true

      # (WAN) redirect to HTTPS
      traefik.http.routers.wan_redirect_https.rule: Host(`wan.localhost`)
      traefik.http.routers.wan_redirect_https.entrypoints: web
      traefik.http.routers.wan_redirect_https.middlewares: redirect_https

      traefik.http.middlewares.redirect_https.redirectScheme.scheme: https

  node-red:
    image: nodered/node-red:1.0.3-2
    labels:
      traefik.enable: true

      # HTTP (LAN) connection
      traefik.http.routers.nodered_lan.rule: Host(`lan.localhost`) && PathPrefix(`/node-red`)
      traefik.http.routers.nodered_lan.entrypoints: web
      traefik.http.routers.nodered_lan.middlewares: nodered_redirect,nodered_auth,strip_node_red_prefix

      # HTTPS (WAN) connection
      traefik.http.routers.nodered_wan.rule: Host(`wan.localhost`) && PathPrefix(`/node-red`)
      traefik.http.routers.nodered_wan.entrypoints: websecure
      traefik.http.routers.nodered_wan.middlewares: nodered_redirect,nodered_auth,strip_node_red_prefix
      traefik.http.routers.nodered_wan.tls: true

      # middlewares
      traefik.http.middlewares.nodered_auth.basicauth.users: user:$$apr1$$q8eZFHjF$$Fvmkk//V6Btlaf2i/ju5n/ # user/password
      traefik.http.middlewares.strip_node_red_prefix.stripprefix.prefixes: /node-red
      traefik.http.middlewares.nodered_redirect.redirectregex.regex: ^(https?)://([^/]+)/node-red$$
      traefik.http.middlewares.nodered_redirect.redirectregex.replacement: $${1}://$${2}/node-red/

2 Likes

Thanks a lot it works !!