ASP.Net 具有不同根的核心反向代理

ASP.Net Core Reverse Proxy with different root

我在代理 ASP.NET 核心 MVC 应用程序时遇到问题。

我的应用程序在 localhost:5000 上的 Kestrel 上 运行,我的 Apache 2.4 反向代理在 localhost:80 上 运行。我想代理从 localhost:80/testlocalhost:5000

的所有请求

这是代理的 httpd.conf 部分:

...
<Location "/test">
   ProxyPass "http://localhost:5000"
   ProxyPassReverse "http://localhost:5000"
</Location>
...

代理有效,但所有 link 都已损坏。就像如果我有一个锚 link 到名为 HomeController 的控制器并执行 About,从代理返回的 link 是 localhost/Home/About 而不是 localhost/test/Home/About。主机正确,缺少上下文根 test

处理此问题的最佳做法是什么? ASP.NET Core 中是否配置了指定上下文根以便 TagHelpers 将其考虑在内?或者它是 Apache ProxyPass 中的一个配置来重写 links(真的不是这个的忠实粉丝)?

问题是 Web 应用程序不知道子路径 /test,因此在您的情况下,它只会像直接在根路径上调用一样响应。

ASP.NET Core 有一个 PathBase 的概念来解决这个问题。 PathBase 本质上是请求 URI 路径的一部分,将被视为路径的固定部分。每当框架内的组件生成 URL 时,它都会考虑当前的 PathBase 并确保将其作为前缀包含在所有生成的路径中。

默认情况下,PathBase 为空,具体如何设置 PathBase.

取决于你的反向代理的配置

UsePathBaseMiddleware

有内置的 UsePathBaseMiddleware 可用于为传入请求临时配置 PathBase。这个中间件的工作方式基本上是检查请求是否以可接受的路径前缀开头,如果是,则该前缀将从 Path 移动到 PathBase.

您可以使用 UsePathBaseExtensions.UsePathBase 扩展方法激活它。只需在 Startup 的 Configure 方法中首先调用该方法,并使用您要使用的基本路径:

public void Configure(IApplicationBuilder app)
{
    app.UsePathBase("/test");

    // all the other middlewares
    app.UseStaticFiles();
    app.UseMvc();
    // …
}

由于中间件只会在看到传入请求路径中的 /test 前缀时才调整 PathBase,因此您需要确保反向代理实际包含该前缀。因此,您必须调整 Apache 配置以包含该路径:

<Location "/test">
   ProxyPass "http://localhost:5000/test"
   ProxyPassReverse "http://localhost:5000/test"
</Location>

请注意,UsePathBaseMiddleware 不会阻止应用程序在没有 前缀的情况下工作。所以你实际上可以在有和没有基本路径的情况下使用它,它会正确适应。

自定义中间件

如果您不想调整您的反向代理配置以将路径包含在转发的请求中,那么您将无法使用 UsePathBaseMiddleware。相反,您必须在那里添加您自己的非常简单的中间件:

public void Configure(IApplicationBuilder app)
{
    app.Use((context, next) =>
    {
        context.Request.PathBase = "/test";
        return next();
    });

    // all the other middlewares
    app.UseStaticFiles();
    app.UseMvc();
    // …
}

这会将 /test 设置为传入请求的 常量 PathBase。所以实际传入的请求不必包含它,这意味着您可以保持反向代理配置不变(而不是转发 /test 路径)。然而,这也意味着与 UsePathBaseMiddleware 不同,其中 PathBase 是根据传入请求动态设置的,现在 all 对应用程序的请求将需要该路径,无论他们是否通过反向代理。

代理正在删除请求路径信息,因此您必须 re-introduce 通过执行以下操作来删除它:

app.Use((context, next) =>
{
  context.Request.PathBase = "/test";
  return next();
});

这与 UsePathBase 的做法不同,它将仍然存在的路径段从 Path 的开头移动到 PathBase 的结尾。

https://github.com/aspnet/HttpAbstractions/blob/49b447d6265f0de44304b1b887cbdd3227cb038d/src/Microsoft.AspNetCore.Http.Abstractions/Extensions/UsePathBaseMiddleware.cs#L54

对于 .net 核心你可以添加这个

app.UsePathBase(basePath);
app.UseRouting();