oxfordian
oxfordian

Reputation: 151

nginx dynamic proxy_pass based on url pa

I currently have the following proxy pass definition in my nginx config file :

location /pass/ {
    proxy_pass http://localhost:9999/pass/;
    proxy_redirect     off;
    proxy_set_header   Host $host;
}

This is working as expected - /pass requests are forwarded to the app running on port 9999.

Now, what I want to do is make the port forwarding part dynamic as follows :

location /pass/<input> {
    {a $port variable here that is evaluated via a script (php?)}
    proxy_pass http://localhost:$port/pass/;
    proxy_redirect     off;
    proxy_set_header   Host $host;
}

Requests to /pass/ABCD1234 should be forwarded to port 9898 and Requests to /pass/ABCD5678 should be forwarded to port 9797.

Note that the flow is dynamic - so, the mapping from ABCD1234 to 9898 should happen through some sort of scripting (PHP maybe?) and based on the output of the script (a port) the proxy_pass should forward the request to that port.

Please Help in this regard.

UPDATE :

Instead of getting the proxy_pass port from URI input, I would like to get this going with a cookie. So, here is the updated code block :

location /pass/ {
    add_header X-debug-message $host always;
    add_header X-debug-message $cookie_sdmport;
    set $proxyurl http://127.0.0.1:$cookie_theport/pass/;
    add_header X-debug-message $proxyurl;
    proxy_pass $proxyurl;
    proxy_redirect     off;
    proxy_set_header   Host $host;
}

With this code, there is looping 301 redirect back to the browser. The moment I switch back to static port, it works again! strange! The $proxyurl in the X-debug-message looks correct on the browser. So, wondering why proxy_pass is doing a 301!

UPDATE 2:

Finally got the forwarding working with following setup:

    set $targetIP 127.0.0.1;
    set $targetPort $cookie_passport;
    proxy_pass http://$targetIP:$targetPort$request_uri;

Not sure why the solution as posted in above keeps spinning with a 301 - I guess nginx does not like mixing dynamic and static parts in the proxy_pass param

Thank You.

Upvotes: 4

Views: 5695

Answers (1)

miknik
miknik

Reputation: 5941

You can do this using the auth_request module. It's not built by default though, you can find out if you have it by running the following:

nginx -V 2>&1 | grep -qF -- --with-http_auth_request_module && echo ":)" || echo ":("

If you see a smiley face then you are good to go.

location ~* /pass/(.*) { <- regex capture for your variable
    auth_request /auth;  <- location to process request
    auth_request_set $proxyurl http://localhost:$upstream_http_x_port/pass/; <- set $proxyurl using value returned in x-port header of your php script
    add_header x-my-variable $1; <- Pass variable from regex capture to auth location
    proxy_pass $proxyurl;
}

Then a location to handle the auth subrequests:

location /auth {
    internal; <- make location only accessible to internal requests from Nginx
    proxy_set_header x-my-variable $http_x_my_variable; <- pass variable to php
    proxy_pass_request_body off; <- No point sending body to php
    proxy_set_header Content-Length "";
    proxy_pass http://your-php-script/file.php;
}

This module is actually meant for access control, so if your php script returns response code 200 then client will be allowed access, if it returns 401 or 403 then access will be denied. Is you dont care about that then just set it to always return 200.

Do whatever evaluation you need and have your php return the port in the header defined earlier:

header('X-Port: 9999');

This now sets the variable for your proxy_pass directive port number and Nginx does the rest.

Upvotes: 6

Related Questions