6

我正在尝试使以下模式起作用。我需要在客户端代码中指定一个动态路径,以便能够切换到一些预定义的主机。我通过将它们的别名附加到 /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/

但是当测试正则表达式的结果时,我得到:

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

我希望和网址如下:

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

以导致:

http://foo.domain.nl/

...但这仍然行不通。我得到一个 404 返回。我错过了什么?

4

2 回答 2

7

我最终回到了第一种方法,因为为此向 url 添加查询参数并不方便。它使客户端逻辑不必要的复杂。

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

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
于 2013-08-27T12:15:01.290 回答
1

我走在正确的轨道上。

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

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

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

所以这导致:

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

它有效!:)

于 2013-08-27T10:42:54.050 回答