为什么找不到反向代理后面的这些 Swagger 端点?

Why are these Swagger endpoints behind a reverse-proxy not found?

我有少量 ASP.NET 核心服务,所有 运行 都在 Docker 中(通过 Docker Compose)。所有服务当前都使用前缀路由(它们自己的服务名称)。它们都在 Docker Compose 中设置为使用它们自己的服务名称作为它们的主机名(服务容器之间的连接正常)。

/api-docs端点由Swashbuckle提供;我们也在这里设置前缀路由。

app.UseSwagger(options =>
{
    options.RouteTemplate = "scheduler/api-docs/{documentName}/swagger.json";
});

app.UseSwaggerUI(options =>
{
    options.RoutePrefix = "scheduler/api-docs";
    options.SwaggerEndpoint("/scheduler/api-docs/v1/swagger.json", "Scheduler API v1");
});

我正在尝试在容器网络中配置 Nginx 反向代理,这样我就可以去...

http://localhost/<service-name>/api-docs

它会在容器网络内部重定向到...

http://<service-name>:5000/<service-name>/api-docs

所以,这是我提出的 Nginx 配置...基本上,匹配请求 URI 的第一部分,它应该是服务名称,并代理到与 Nginx 名称相同的主机 应该自动添加$request_uri

server {
    listen 80;

    location ~* ^/(?<target>.+)/ {
        proxy_pass http://$target:5000;
        proxy_redirect off;
        resolver 127.0.0.11;
    }
}

这是我得到的 /scheduler/healthcheck 端点。一切顺利!

api-gateway_1               | 172.19.0.1 - - [27/Mar/2018:17:50:24 +0000] "GET /scheduler/healthcheck HTTP/1.1" 200 491 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" "-"

但是,当我尝试转到 /scheduler/api-docs 时,我遇到了问题。我们到达服务容器,Swashbuckle 执行从 /scheduler/api-docs/scheduler/api-docs/.

的 301 重定向
api-gateway_1               | 172.19.0.1 - - [27/Mar/2018:17:51:18 +0000] "GET /scheduler/api-docs HTTP/1.1" 301 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" "-"

然后,事情变糟了...我们 "lose" 路线的 /scheduler 部分!

api-gateway_1               | 172.19.0.1 - - [27/Mar/2018:17:51:18 +0000] "GET /scheduler/api-docs/ HTTP/1.1" 502 576 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" "-"
api-gateway_1               | 2018/03/27 17:51:18 [error] 5#5: *2 connect() failed (111: Connection refused) while connecting to upstream, client: 172.19.0.1, server: , request: "GET /scheduler/api-docs/ HTTP/1.1", upstream: "http://172.19.0.5:80/api-docs:5000", host: "localhost:4000"

为什么 Swashbuckle 重定向通过 Nginx 将请求发回,我认为这将由本地服务处理,为什么 Nginx 会从该请求中剥离必要的路由前缀?

我如何让它运行?!


我试图重建 "whole" URI,只是为了看看会发生什么...

-   proxy_pass http://$target:5000;
+   proxy_pass http://$target:5000$request_uri;

而且 甚至 更糟!

api-gateway_1               | 172.19.0.1 - - [27/Mar/2018:18:03:48 +0000] "GET /scheduler/api-docs HTTP/1.1" 301 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" "-"
api-gateway_1               | 172.19.0.1 - - [27/Mar/2018:18:03:48 +0000] "GET /scheduler/api-docs/ HTTP/1.1" 502 576 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" "-"
api-gateway_1               | 2018/03/27 18:03:48 [error] 5#5: *2 connect() failed (111: Connection refused) while connecting to upstream, client: 172.19.0.1, server: , request: "GET /scheduler/api-docs/ HTTP/1.1", upstream: "http://172.19.0.5:80/api-docs:5000/scheduler/api-docs/", host: "localhost:4000"

仅供参考,如果我直接访问网站(通过 Docker 等发布端口后),在我的浏览器中一切正常)

咳咳...问题是 "greedy" 正则表达式。根据定义,正则表达式捕获组 .+ 将消耗 所有内容 直到 last forward-slash.

您应该使用 "lazy" 正则表达式捕获组 .+? 来捕获两个 forward-slash 之间的单个 URI 段,而不是 所有内容 last forward-slash!