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

Introduce annotation for rewrite rule #63

Closed
jmastr opened this issue Nov 4, 2016 · 11 comments
Closed

Introduce annotation for rewrite rule #63

jmastr opened this issue Nov 4, 2016 · 11 comments

Comments

@jmastr
Copy link

jmastr commented Nov 4, 2016

See #60

Instead of hard-coding the rewrite rule one could introduce a further annotation like in #61.

@pleshakov
Copy link
Contributor

I think we can add something like this:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: cafe-ingress
  annotations:
    nginx.org/rewrites: "serviceName=tea rewrite=/;serviceName=coffee-svc rewrite=/beans/"
spec:
  rules:
  - host: cafe.example.com
    http:
      paths:
      - path: /tea/
        backend:
          serviceName: tea-svc
          servicePort: 80
      - path: /coffee/
        backend:
          serviceName: coffee-svc
          servicePort: 80

Requests to the tea service are rewritten as follows:

  • /tea -> gets redirected to /tea/ first
  • /tea/ -> /
  • /tea/abc -> /abc

Requests to the coffee service are rewritten as follows:

  • /coffee -> gets redirected to /coffee/ first
  • /coffee/ -> /beans/
  • /coffee/abc -> /beans/abc

To accomplish that the following NGINX configuration can be used:

location /tea/ {
  proxy_pass http://tea-svc/;
}

location /coffee/ {
  proxy_pass http://coffee-svc/beans/;
}

See http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass for details.

However, rewrites don't guarantee that the application will work. Often applications return web pages with absolute links so that the rewriting of response bodies is also necessary.

@jmastr
Copy link
Author

jmastr commented Nov 7, 2016

However, rewrites don't guarantee that the application will work. Often applications return web pages with absolute links so that the rewriting of response bodies is also necessary.

I guess there is no way to rewrite the response body with our NGINX template, like:

nginx.org/rewrites: "serviceName=tea-svc rewriteRequest=/ rewriteResponse=..."

as well?

@jmastr
Copy link
Author

jmastr commented Nov 7, 2016

To accomplish that the following NGINX configuration can be used:

location /tea/ {
  proxy_pass http://tea-svc/;
}

location /coffee/ {
  proxy_pass http://coffee-svc/beans/;
}

I implemented this and it does not work for my use case. What I need is something like this:

location /tea {
  proxy_pass http://tea-svc;
}

location /coffee {
  rewrite ^/coffee/(.*) /$1 break;
  proxy_pass http://coffee-svc;
}

@pleshakov
Copy link
Contributor

Rewriting of the response body of a request is done with the sub_filter module.

Typically it requires many rewrite rules. For example,

sub_filter '<a href="http://127.0.0.1:8080/'  '<a href="https://$host/';
sub_filter '<img src="http://127.0.0.1:8080/' '<img src="https://$host/';
...

It would be very messy and complicated if we put such rules in an annotation.

For special cases like rewrites, I can suggest the following:

  1. Deploy another NGINX that will sit between the NGINX Ingress controller and the application. NGINX container can be added to the application pod specification. NGINX will be configured to do the necessary rewrites.
  2. Introduce conditional statements in the template that will handle special cases. For example,
location {{$location.Path}} {
  ...
  {{if eq $location.Path "/rabitmq/"}}
  # rewrite url 
  # rewrite ...
  proxy_pass http://{{$location.Upstream.Name}};
  # sub_filter rules to rewrite the response 
  # sub_filter ...
  {{else}}
  # handle default cases
  proxy_pass http://{{$location.Upstream.Name}};
  {{end}}
}{{end}}

This way you can customize the location block based on the location path, for example. More info about go templates is here https://golang.org/pkg/text/template/

Will any of those work for you?

@pleshakov
Copy link
Contributor

@jmastr
Not sure why this doesn't work.

For the following code snippet

location /coffee {
  rewrite ^/coffee/(.*) /$1 break;
  proxy_pass http://coffee-svc;
}

A request to /coffee won't be rewritten. the coffee-svc will get a request to /coffee as well.

@jmastr
Copy link
Author

jmastr commented Nov 7, 2016

@pleshakov

With this config:

        location /rabbitmq {
                proxy_http_version 1.1;

                proxy_connect_timeout 60s;
                proxy_read_timeout 60s;
                client_max_body_size 1m;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Port $server_port;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_pass http://default-cafe-ingress-cafe.example.com-rabbitmq-svc/rabbitmq;
        }

I get:

$ curl -k https://192.168.10.2:30443/rabbitmq/
Not found.

With:

        location /rabbitmq {
                proxy_http_version 1.1;

                proxy_connect_timeout 60s;
                proxy_read_timeout 60s;
                client_max_body_size 1m;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Port $server_port;
                proxy_set_header X-Forwarded-Proto $scheme;
                rewrite ^/rabbitmq/(.*) /$1 break;
                proxy_pass http://default-cafe-ingress-cafe.example.com-rabbitmq-svc;
        }

I get (what I want):

$ curl -k https://192.168.10.2:30443/rabbitmq/
<!doctype html>
<html>
  <head>
    <title>RabbitMQ Management</title>
    <script src="js/ejs.min.js" type="text/javascript"></script>
    <script src="js/jquery-1.6.4.min.js" type="text/javascript"></script>
    <script src="js/jquery.flot.min.js" type="text/javascript"></script>
    <script src="js/jquery.flot.time.min.js" type="text/javascript"></script>
    <script src="js/sammy.min.js" type="text/javascript"></script>
    <script src="js/json2.js" type="text/javascript"></script>
    <script src="js/base64.js" type="text/javascript"></script>
    <script src="js/global.js" type="text/javascript"></script>
    <script src="js/main.js" type="text/javascript"></script>
    <script src="js/prefs.js" type="text/javascript"></script>
    <script src="js/help.js" type="text/javascript"></script>
    <script src="js/formatters.js" type="text/javascript"></script>
    <script src="js/charts.js" type="text/javascript"></script>

    <link href="css/main.css" rel="stylesheet" type="text/css"/>
    <link href="favicon.ico" rel="shortcut icon" type="image/x-icon"/>

<!--[if lte IE 8]>
    <script src="js/excanvas.min.js" type="text/javascript"></script>
    <link href="css/evil.css" rel="stylesheet" type="text/css"/>
<![endif]-->
  </head>
  <body>
    <div id="outer"></div>
    <div id="debug"></div>
    <div id="scratch"></div>
  </body>
</html>

I just can state how it is...

@pleshakov
Copy link
Contributor

@jmastr
Could you try to change the location from /rabbitmq to /rabbitmq/? And also http://default-cafe-ingress-cafe.example.com-rabbitmq-svc/rabbitmq to http://default-cafe-ingress-cafe.example.com-rabbitmq-svc/rabbitmq/

location /rabbitmq/ {
                proxy_http_version 1.1;

                proxy_connect_timeout 60s;
                proxy_read_timeout 60s;
                client_max_body_size 1m;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Port $server_port;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_pass http://default-cafe-ingress-cafe.example.com-rabbitmq-svc/rabbitmq/;
        }

@jmastr
Copy link
Author

jmastr commented Nov 7, 2016

This:

        location /rabbitmq/ {
                proxy_http_version 1.1;

                proxy_connect_timeout 60s;
                proxy_read_timeout 60s;
                client_max_body_size 1m;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Port $server_port;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_pass http://default-cafe-ingress-cafe.example.com-rabbitmq-svc/rabbitmq/;
        }

gives me this:

$ curl -k https://192.168.10.2:30443/rabbitmq
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.11.4</center>
</body>
</html>

and this:

$ curl -k https://192.168.10.2:30443/rabbitmq/
Not found.

Btw. thank you very much for your support/help.

@pleshakov
Copy link
Contributor

@jmastr
My bad, proxy_pass must be proxy_pass http://default-cafe-ingress-cafe.example.com-rabbitmq-svc/;

$ curl -k https://192.168.10.2:30443/rabbitmq will redirect to https://192.168.10.2:30443/rabbitmq/

location /rabbitmq/ {
                ....
                proxy_pass http://default-cafe-ingress-cafe.example.com-rabbitmq-svc/;
        }

Thx! no problem!

@jmastr
Copy link
Author

jmastr commented Nov 7, 2016

Great! That works!

location /coffee/ {
        ...
        proxy_pass http://default-cafe-ingress-cafe.example.com-coffee-svc/;
}

works as well! Can I just add those two / to the ingess.tmpl?

@pleshakov
Copy link
Contributor

If it works for your applications, I assume so. But doesn't confirm to Ingress API if it is enabled by default though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants