带有map和regexp的动态proxy_pass

时间:2013-08-26 20:41:45

标签: regex configuration nginx

我正在尝试使用以下模式。我需要在客户端代码中指定一个动态路径才能切换到一些预定义的主机。我通过将它们的别名附加到/ fwd / url来映射这些主机。别名映射到nginx中的真实服务器,如下所示:

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

然后在服务器配置部分,我抓住任何以fwd开头的url并应用映射的别名值。别名之后的url的剩余部分也应该附加到url。

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;
}

如果我用以下方法测试:

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

我明白了:

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

但是当测试regexp的结果时,我得到了:

 $1: foo
 $2: something/else

总的来说,它似乎正在发挥作用。正则表达式似乎没问题,但是我无法将它连接成一个字符串?任何想法或是否有更容易/更好的方法来实现同样的目标?

[编辑]

通过使用名为forward的查询参数,我发现了一种可能更简单的方法。首先将查询参数映射到正确的主机:

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

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

}

然后使用要转发的路径中的参数:

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

我希望和url一样:

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

导致:

http://foo.domain.nl/

......但这仍然不起作用。我得到了404返回。我错过了什么?

2 个答案:

答案 0 :(得分:6)

我最终回到了第一种方法,因为为此将一个查询参数添加到网址是不方便的。它使客户端逻辑变得不必要复杂。

我找到了第一种方法的解决方案。位置声明中的正则表达式是错误的。您需要使用?来捕获变量名中的正则表达式?像这样:

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

然后$ fwd_alias将包含foo或bar之类的别名。 $ fwd_path包含之后的整个路径。

要传递包含可选查询参数的完整路径,请将proxy_pass指定为:

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

就是这样!

现在,包括第一个示例中的映射,并添加解析器,它归结为:

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;
}

请求具有以下路径:

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

映射到:

http://foo.domain.nl/something/else?with=query

答案 1 :(得分:1)

我走在正确的轨道上。

如果你想将proxy_pass与变量参数一起使用,你需要做两件事:

  1. 添加解析程序语句以解析主机名。据我所知,在启动时,nginx会查找配置中的所有域名并将它们映射到IP。由于我们使用的是变量主机名,因此在加载配置时nginx无法查找,我们需要指定DNS解析器。

  2. 在proxy_pass中使用变量时,需要为其添加http://。不知道为什么会这样。

  3. 所以这导致:

    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;
    }
    

    它有效! :)