traefik: Wrong HTTPS redirect when also using AddPrefix

Do you want to request a feature or report a bug?

Bug

What did you do?

I’m using traefik as a kubernetes ingress controller. I have configured HTTPS redirect as follows in the TOML config file:

[entryPoints]
  [entryPoints.http]
  address = ":80"
  [entryPoints.http.redirect]
    regex = "^http://(.*)"
    replacement = "https://$1"
  [entryPoints.https]
  address = ":443"
  [entryPoints.https.tls]

I have also configured an ingress like this:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test
  annotations:
    kubernetes.io/tls-acme: "true"
    kubernetes.io/ingress.class: "traefik"
    traefik.frontend.rule.type: "AddPrefix"
spec:
  tls:
  - hosts:
    - demo.example.com
    secretName: tls
  rules:
  - host: demo.example.com
    http:
      paths:
      - path: /path
        backend:
          serviceName: myservice
          servicePort: 80

What did you expect to see?

When accessing http://demo.example.com, I wanted it to redirect to https://demo.example.com.

What did you see instead?

When accessing http://demo.example.com, I wanted it to redirect to https://demo.example.com/path.

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

Version:      v1.3.7
Codename:     raclette
Go version:   go1.8.3
Built:        2017-08-25_08:56:06PM
OS/Arch:      linux/amd64

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

defaultEntryPoints = ["http","https"]
[entryPoints]
  [entryPoints.http]
  address = ":80"
  [entryPoints.http.redirect]
    regex = "^http://(.*)"
    replacement = "https://$1"
  [entryPoints.https]
  address = ":443"
  [entryPoints.https.tls]
[acme]
email = "certmaster@example.com"
storage = "/acme/acme.json"
entryPoint = "https"
onDemand = false
OnHostRule = true
acmelogging = true
caServer = "https://acme-v01.api.letsencrypt.org/directory"
acmeLogging = true

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 3
  • Comments: 21 (6 by maintainers)

Most upvoted comments

@timoreimann thank you, I was thinking that exactly. I’ll do some debuggin tonight to see if the same issue happens without kubernetes.

I have finally understood the problem. Traefik has two kinds of middlewares: 1) entryPoint middlewares, and 2) frontend middlewares. EntryPoint middlewares are implemented as Negroni middlewares, while frontend middlewares are implemented as http.Handler interface that wrap around one after another, and finally wrap the Negroni handler. This can be seen in the server.wireFrontendBackend

The effect of this is that, in spite of the load order of the negroni middlewares, frontend middlewares are always executed before. Thus, the URL that the middleware.Rewrite receives has already been modified.

I did a test to create a temporary handler that suppports order of execution (having pre and post handlers), but the result is that the Request never gets forwarded to the actual backend. I am not sure if this is the expected behavior.

IMHO, the most intuitive behavior would be to have the entryPoint middlewares executed first, and have the frontend middlewares modifiy the internal forwarded route, without the client noticing it.

I think there are two ways of fixing this issue:

  1. We could have the rewrite handler reverse ingeneering any rewrites made on the Request URL, so it acts on the original requested url. This needs the least code refactoring, athought it doesn’t feel like a good solution

  2. We could rewrite the frontend middlewares in order to act as regular Negroni middlewares, and then comply with the loading order logic. I’m not really sure if this is possible because I don’t fully understand how the requests are forwarded to the backend.

@ldez do you have any input about this?

Quick update. I have been able to reproduce the problem with a basic file provider. The bug seems to be that the Rewrite middleware is being applied after the AddPath middleware. I’m trying to switch the order and see if that works (and doesn’t break anything).

Any ideas are welcome 😃

Yes, I have already saw that. I have some experience in Go and would like to contribute to this project. Could you point me to a good starting point to investigate this?