6

I'm trying to get the following pattern to work. I need to specify a dynamic path in my client side code to be able to switch to a few predefined hosts. I map these hosts by appending their alias to a /fwd/ url. The alias is mapped to the real server in nginx like this:

map $uri $repoUrl {
    default             invalid;
    ~^/fwd/foo/.*        http://foo.domain.nl/;
    ~^/fwd/bar/.*        http://bar.domain.nl/;
  }

Then in the server config part I catch any url starting with fwd and apply the mapped alias value. The remaining part of the url, after the alias should be appended to the url as well.

location /fwd/(\w+)/(.*)$ {
  add_header X-FwdHost "$repoUrl$2";
  add_header Access-Control-Allow-Origin "*";
  proxy_pass         "$repoUrl$2";
  proxy_redirect off;
  access_log on;
}

If I test this with:

curl -i http://localhost:8080/fwd/foo/something/else

I get:

X-FwdHost: http://foo.domain.nl/

But when test the results from the regexp I get:

 $1: foo
 $2: something/else

So overall it seems to be working. The regex appears to be ok, but I can't get it to concatenate into one string? Any ideas or is there an easier/better way to accomplish the same?

[EDIT]

I found a possibly much easier way to do this, by using a query parameter named forward. First map the query parameter to a the right host:

map $arg_forward $repo_forward {
default           http://invalid_repo_forward/;

foo              http://foo.domain.nl/;
bar              http://bar.domain.nl/;

}

Then use the parameter in the path to be forwarded:

location /fwd/ {
  add_header X-FwdHost $repo_forward;
  add_header Access-Control-Allow-Origin "*";
  proxy_pass         $repo_forward;
  proxy_redirect off;
  access_log on;
}

I would expect and url like:

http://localhost:8080/fwd/?forward=foo

To result in:

http://foo.domain.nl/

...but still this doesn't work. I get a 404 returned. What am I missing?

0

2 Answers 2

7

I eventually went back to the first approach, because it's not convenient to add a query parameter to a url for this. It makes the client logic unnecessary complex.

I found the solution to my first approach. The regex in the location statement was wrong. You need to capture the regex in variable names by using ? like this:

location ~ ^/fwd/(?<fwd_alias>\w+)/(?<fwd_path>.*)$

Then $fwd_alias will contain the alias like foo or bar. $fwd_path with contain the whole path after that.

To pass on the full path including optional query parameters you specify the proxy_pass as:

proxy_pass http://$repo_url$fwd_path$is_args$args;

That's it!

So now, including the mapping in the first example, and adding the resolver, it comes down to:

location ~ ^/fwd/(?<fwd_alias>\w+)/(?<fwd_path>.*)$ {
  resolver 8.8.8.8;
  add_header Access-Control-Allow-Origin "*";
  proxy_pass http://$repo_url$fwd_path$is_args$args;
  proxy_redirect off;
  access_log on;
}

And a request with the following path:

http://localhost:8080/fwd/foo/something/else?with=query 

maps to:

http://foo.domain.nl/something/else?with=query
Sign up to request clarification or add additional context in comments.

1 Comment

Any chance you can post a "full" copy of the solution please. I'm following this (as far as I can) but still getting 404's. Alstublieft.
1

I was on the right track.

If you want to use proxy_pass with a variable argument you need to do two things:

  1. Add a resolver statement to resolve the hostnames. As I understand it, on startup nginx looks up all domain names in the config and maps them to IPs. Since we're using a variable hostname nginx can't look it up when loading the config and we need to specify the DNS resolver.

  2. When using a variable in proxy_pass you need to add http:// to it. Not sure why that is.

So this results in:

location /fwd/ {
  resolver 8.8.8.8;
  add_header X-FwdHost $repo_forward;
  add_header Access-Control-Allow-Origin "*";
  proxy_pass http://$repo_forward;
  proxy_redirect off;
  access_log on;
}

And it works! :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.