Skip to content
This repository has been archived by the owner on Apr 17, 2019. It is now read-only.

[NGINIX Ingress Controller] Support for 301 redirects. #1884

Closed
MaikuMori opened this issue Oct 18, 2016 · 16 comments · Fixed by kubernetes/ingress-nginx#1184
Closed

[NGINIX Ingress Controller] Support for 301 redirects. #1884

MaikuMori opened this issue Oct 18, 2016 · 16 comments · Fixed by kubernetes/ingress-nginx#1184
Labels
lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed.

Comments

@MaikuMori
Copy link

Would be nice to be able to setup 301 redirects. As services come and go, certain things in the cluster get deprecated and require a redirect to a new location.

Two current solutions that I'm aware of now:

  • Use custom template, but this is overkill and makes upgrading controller harder/error prone;
  • Put another proxy in front of the ingress controller, also seems overkill, but maybe not a bad idea in longterm
  • Spin up container which only does redirection for configurable domains. (This is what I'll currently use until there is a better solution)

The general issue is to be able to add custom configuration sections in global and per ingress controller scope. Otherwise I feel the project will end up slowly implementing each NGINX config option as flag.

I am willing to contributing the redirect code.

@aledbf
Copy link
Contributor

aledbf commented Oct 18, 2016

@MaikuMori can you post an Ingress rules as example?

@MaikuMori
Copy link
Author

Could be done with some awkward Ingress rule like this:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test
  namespace: test
  annotations:
    ingress.kubernetes.io/301-to: "https://domain.com/path"
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: foo.bar.com

Other option is in the configmap using some sort of format:

301-redirects: "foo.bar.com:https://domain.com/path boo.bar.com:https://other.com/"

In this example split on and then on first:. I'm sure there is a better separator choice.

Personally I would like free-form config map entry like:

global-block: |
  some_other_custom_option set-to-value;
  server {
    listen 80;
    server_name foo.bar.com;
    return 301 $scheme://domain2.com$request_uri;
  }

Also such custom block set via annotations would be nice for adding custom options to server directives created by Ingress resource.

@aledbf what do you think?

@aledbf
Copy link
Contributor

aledbf commented Oct 19, 2016

@MaikuMori I think could be useful

That said there's a some issues some of the proposals:

Personally I would like free-form config map entry like:
global-block: |

that is not possible because it makes impossible the creation of a generic template (please check the current version to see the logic behind

301-redirects: "foo.bar.com:https://domain.com/path boo.bar.com:https://other.com/"

supporting "lists" inside the annotation is not an issue but you are mixing domains and paths that breaks all the logic behind the controller to generate the data for the template.
If the annotation to add redirects is added you can define multiples Ingress rules for the same FQDN and different paths and the redirect (in each rule) will be applied in the Ingress path. The downside of this is that you need multiple ingress

ingress.kubernetes.io/301-to: "https://domain.com/path"

WDYT of this (just to avoid numbers and provide clarity?):
ingress.kubernetes.io/permanent-redirect: "https://domain.com/path"
ingress.kubernetes.io/temporal-redirect: "https://domain.com/path"

@MaikuMori
Copy link
Author

MaikuMori commented Oct 20, 2016

that is not possible because it makes impossible the creation of a generic template (please > check the current version to see the logic behind

Technically NGINX supports multiple http blocks, but it's not exactly best practice and can break stuff. What about http-block which is inserted here nginx.tmpl#L365? Or did I completely misunderstood why it's not possible? If it's defined as template it could even take advantage of the template data. If it's inserted at the end, it can overwrite things. Personally I would prefer this over specifying custom template which is more error prone when it comes to controller updates. Obviously this would be advanced feature which allows people to shoot themselves in the leg.

you are mixing domains and paths that breaks all the logic behind the controller

I specifically added paths only to the destination. In my case I needed to redirect all traffic with specific Host header to another location.

But you're right, it's somewhat complex to define generic options because there are multiple use cases that people could have:

  • All traffic matching specific host to another host and preserve path.
  • All traffic matching specific host to another host with custom path (/ or /foo/bar)
  • All traffic matching specific host and path to another host and preserve path.
  • All traffic matching specific host and path to another host with custom path (/ or /foo/bar)
  • Even more custom rules which are currently supported using NGINX DSL.

WDYT of this (just to avoid numbers and provide clarity?):

Much better, the examples I gave were just to showcase different ideas. I still feel multiple Ingress rules are clumsy and overall too verbose.

@hartmut-pq
Copy link

+1

@hartmut-co-uk
Copy link

If anyone else may end up here - I found a pretty good way to solve one of my issues using ingress.kubernetes.io/configuration-snippet:

I've had issues with a setup using ingress.kubernetes.io/rewrite-target: / and /path != /path/

Basically my ingress worked for /path/ (rewrite target -> OK)
but not for /path -> no rewrite happened.. my underlying service received route /path which was not found...

Solution was to add a 2nd separate ingress resource with a custom rewrite:

    # adds 301 redirect with trailing slash
    ingress.kubernetes.io/configuration-snippet: | 
      rewrite ^([^.]*[^/])$ $1/ permanent;

@agustincastanio
Copy link

+1

2 similar comments
@SharpEdgeMarshall
Copy link

+1

@antoine-humbert
Copy link

+1

@mscottx88
Copy link

This helped to solve the issue at least with GET requests: /foo works and /foo/ works too but this cannot be said for POST requests.

Even with this rewrite rule, the POST request still requires the trailing slash.

@fejta-bot
Copy link

Issues go stale after 90d of inactivity.
Mark the issue as fresh with /remove-lifecycle stale.
Stale issues rot after an additional 30d of inactivity and eventually close.

Prevent issues from auto-closing with an /lifecycle frozen comment.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or @fejta.
/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Jan 25, 2018
@fejta-bot
Copy link

Stale issues rot after 30d of inactivity.
Mark the issue as fresh with /remove-lifecycle rotten.
Rotten issues close after an additional 30d of inactivity.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/lifecycle rotten
/remove-lifecycle stale

@k8s-ci-robot k8s-ci-robot added lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed. and removed lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. labels Feb 24, 2018
@fejta-bot
Copy link

Rotten issues close after 30d of inactivity.
Reopen the issue with /reopen.
Mark the issue as fresh with /remove-lifecycle rotten.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/close

@praseodym
Copy link

FYI, this is currently supported: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/annotations.md#permanent-redirect

@feluxe
Copy link

feluxe commented Apr 5, 2018

Could anyone please show me an example ingress for what @praseodym has posted. How would I redirect foo.mydomain.com to https://external-domain.com/foo with this?

@ProProgrammer
Copy link

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed.
Projects
None yet