Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[nginx] Redirect with added trailing slash #646

Closed
himikof opened this issue Apr 25, 2017 · 9 comments
Closed

[nginx] Redirect with added trailing slash #646

himikof opened this issue Apr 25, 2017 · 9 comments
Labels
lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed.

Comments

@himikof
Copy link

himikof commented Apr 25, 2017

Nginx by default automatically adds HTTP redirect /foo -> /foo/ when using prefix match with trailing slash location /foo/ which is redirected to a backend (documented in the last paragraph here). This behavior is useful when serving a web application at http://example.com/foo/ and a user accesses http://example.com/foo. Unfortunately, this behavior is broken when using ingress.kubernetes.io/rewrite-target annotation, which turns location match into a non-prefix regex one.
I would argue that the behavior of adding a trailing slash by HTTP redirect on the base path of an web application exposed through an non-root Ingress (with or without a rewrite target) is very useful and should either work by default, or be enabled via some separate annotation.
I was unable to find a workaround in the latest version of Nginx ingress controller. Using /foo ingress path does not work as it breaks relative links inside the web application.
Also, if #619 would be fixed by unconditionally enabling regular expressions, even the currently working cases (without rewrite) will break.

@rutsky
Copy link

rutsky commented Apr 25, 2017

Related: kubernetes-retired/contrib#1884

As a workaround ingress.kubernetes.io/configuration-snippet can be used (based on this comment by @hartmut-co-uk):

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: app
  annotations:
    ingress.kubernetes.io/rewrite-target: /
    # adds 301 redirect with trailing slash
    ingress.kubernetes.io/configuration-snippet: |
      rewrite ^(/app)$ $1/ permanent;
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /app
        backend:
          serviceName: app
          servicePort: 80

This works with ingress.kubernetes.io/rewrite-target: / probably by accident, the configuration snippet is being added just before other rewrite rules:

# Parts of generated /etc/nginx/nginx.conf

        location ~* ^/app {
            set $proxy_upstream_name "default-routes-app-80";
            port_in_redirect off;

            # enforce ssl on server side
            if ($pass_access_scheme = http) {
                return 301 https://$host$request_uri;
            }

# ...

            rewrite ^(/app)$ $1/ permanent;
        rewrite /app/(.*) /$1 break;
        rewrite /app / break;
        proxy_pass http://default-routes-app-80;

        }

@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 Dec 23, 2017
@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 Jan 22, 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

@ProProgrammer
Copy link

Further to what @rutsky mentioned in his comment if you are using nginx ingress controller specifically and your annotations start with nginx as follows:

  name: ingress-tutorial
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/rewrite-target: "/"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      rewrite ^(/app)$ $1/ permanent;

Your annotation should start with nginx. and hence should read as nginx.ingress.kubernetes.io/configuration-snippet as opposed to ingress.kubernetes.io/configuration-snippet

@Glathrop
Copy link

Please keep in mind that while @ProProgrammer 's solution works 301 redirects are PERMANENT.

The unintended byproducts of forcing a trailing slash via 301 can be enough to get you fired.

It's likely safer to start with a 302 temporal redirect if you're just futzing around trying to get something operational.

Per the NGINX docs you can use the redirect param instead of the permanent param to provide a 302 instead of a 301 redirect.

  name: ingress-tutorial
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/rewrite-target: "/"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      rewrite ^(/app)$ $1/ redirect;

@nabeelio
Copy link

nabeelio commented Dec 5, 2018

I can't quite get that rewrite rule/block to work. It redirects me to the (internal) load balancer IP.

Is there another config to explicitly set the host? nginx doesn't work if I specify the host (there's an internal load balancer), I think the DNS name is getting dropped from the public load balancer.

@ahmadalli
Copy link

for anyone who's checking this issue, the annotation is now changed to nginx.ingress.kubernetes.io/configuration-snippet

@Vyom-Yadav
Copy link
Member

If you are wondering how rewrite ^(/app)$ $1/ permanent; works, give https://www.nginx.com/blog/creating-nginx-rewrite-rules/ a read.

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

No branches or pull requests

9 participants