4

I have an NGINX server that acts as reverse proxy to a bunch of backend IIS servers. I would like to pass each incoming HTTPS request to a certain backend (upstream) server, depending on the URI specified, WHILE keeping the same URL in the address bar (to keep the backend servername or address invisible to users)

E.g.
address bar request looks like:
https://test.blahblah.com/url_a
actually goes to -->
https://upstreamserver_a/url_a
but in the address bar still looks like:
https://test.blahblah.com/url_a

Here is my nginx.conf so far:

    ## Upstreamserver_A backend for test.blahblah.com
    upstream upstreamserver_a {
            server 10.10.1.12:80; #upstreamserver_a.blahblah.com
    }

    map_hash_bucket_size 128;
    map_hash_max_size 2048;


    # URI to Server Map
    map $1 $upstream_host {
            default         whatever;
            url_a       upstreamserver_a;
    }


    ## OUR HTTP SERVER AT PORT 80
    server  {
            listen      80;
            server_name test.blahblah.com;
            index       index.html;
            root        /usr/share/nginx/html;

            ## redirect http to https ##
            proxy_redirect http:// https://;
    }


    server  {
            listen      443 ssl;
            server_name test.blahblah.com;
            #root        /usr/share/nginx/html;
        ### ssl config - customize as per your setup ###
            ssl_certificate      ssl/blahblah.com/blahblah.pem;
            ssl_certificate_key  ssl/blahblah.com/blahblah.key;
            ssl_protocols        SSLv3 TLSv1 TLSv1.1 TLSv1.2;
            ssl_ciphers RC4:HIGH:!aNULL:!MD5;
            ssl_prefer_server_ciphers on;
            keepalive_timeout    70;
            ssl_session_cache    shared:SSL:10m;
           ssl_session_timeout  10m;


        ## PROXY backend
            location ~ ^/(.*)$ {
                    rewrite ^/([^/]+)$ https://test.blahblah.com/webapps        /Application.html?firm=$1#login break;

                    proxy_pass http://$upstream_host$uri;
            }
     }

Of course, once I can get one server working, then I will add multiple upstream servers, eg upstreamserver_b, upstreamserver_c, etc.
I dont need help with the SSL part, just the mapping and/or variable reference.
I've proven that the SSL works by substituting this line:
proxy_pass http://$upstream_host$uri;
with
proxy_pass http://upstreamserver_a;
which works. AKA, It redirects to upstreamserver_a, while keeping the URL disguised under the url 'test.blahblah.com'.

Any help would be so much appreciated!
I have found many examples with answers that are very close to what I need, but Ive been too stupid to mold them to my particular need!

user202985
  • 43
  • 1
  • 1
  • 3

2 Answers2

2

you need to describe your URI pattern in regular expression and use it in your location to capture the parts of it that you can use in the rewrite or proxy_pass target. e.g.:

location ~ ^/url_(.).*$ {
  #this will capture your /url_a or /url_b URI's 
  #and will store the "a" or "b" into $1 variable
  #which you can use to proxy the request to a specific server
  proxy_pass http://$1.$upstreams$uri;
  #the above will result in a.<upstreams>/url_a for your example.
  #don't forget the resolver configuration for domain names.
}

hope it helps

  • Thanks Michael! This helps, I think this means Im on the right track. But I have one qualm - my urls dont have a pattern like youre suggesting. Ie. they dont all start with the prefix "url_". Thats why im using a mapping to correlate specific URIs with specific upstream servers. – user202985 Dec 19 '13 at 19:41
  • @user202985 well, you need to have a pattern, without pattern you are stuck with static mappings that you can do just with locations alone – Michael Tabolsky Dec 19 '13 at 20:12
  • Thanks again for the response, much appreciated. Thats really too bad....Apache has a major leg up in this scenario then, as Ive got this working on Apache - which apparently has much more versatile mapping capabilities. Im becoming more and more bitter about NGINX...what with the terrible official documentation and inaccurate wiki... But anyways thanks again, Ill mark your answer as correct. – user202985 Dec 19 '13 at 22:11
  • @MichaelTabolsky hi can you answer this.. i ended up at this question with google but it doesn't seem to be it http://serverfault.com/questions/678521/nginx-how-to-set-host-header-to-the-server-chosen-load-balancing – Muhammad Umer Mar 26 '15 at 18:06
1

Depending on what exactly is it that you want, there are a few directives that come to mind:

E.g., if you basically just want to have nginx proxy everything to your various upstream servers that aren't fully aware of their internet names, and have a mapping between internal and external names, then something like this should do it:

map $host $host_upstream_mapped {
    hostnames;

    test.example.su  test_iis.internal:8070;
    example.com  bleeding_edge.internal:9999;

    default  localhost:8080;
}
server {
    listen [::]:80;
    location / {
        proxy_pass http://$host_upstream_mapped$request_uri;
    }
}

P.S. Note that it's important to use $request_uri in this context (and not just $uri, because otherwise you'll be leaving $args behind), or, alternatively, if you're using rewrite directives as well, then $uri$is_args$args is also a good option (note that the two are not equivalent).

cnst
  • 12,948
  • 7
  • 51
  • 75