下游主机的 Ocelot 占位符

Ocelot placeholder for downstream host

我在 .NET Core 3.1 使用 Ocelot 有一个 API 网关 运行。一切正常,如预期。

现在我正在尝试在中间件过程中替换下游主机。

这是我的 configuration.json:

{
  "Routes": [
    {
      "DownstreamPathTemplate": "/api/product/getProduct",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": "44300"
        }
      ],
      "UpstreamPathTemplate": "/getProduct"
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "https://localhost:62012/"
  }
}

我想在运行时更改 DownstreamHostAndPorts 中的 Host,因为此时从 jwt 中获取声明 我将知道用户所属的租户知道在哪里发送请求。

说得更清楚一点,网关的请求来自 http://localhost:62012/api/getProduct,

然后我从进行此调用的请求中的 jwt 中获取租户,然后将请求重定向到相关的 api,就像这样

http://tenant1.com/api/product/getProduct 要么 http://tenant2.com/api/product/getProduct

您需要创建自定义中间件并将其注入到 Authentication 中间件之后。最好的扩展点是 PreAuthorisationMiddleware。假设您有一项服务可以通过用户声明解析租户 uri,如下所示:

public interface ITenantHostResolver
{
    Task<Uri> Resolve(ClaimsPrincipal claimsPrincipal);
}

在您的 Startup class 中注入将覆盖下游设置的中间件:

public void Configure(IApplicationBuilder app)
{

    var conf = new OcelotPipelineConfiguration
    {
        PreAuthorisationMiddleware = async (httpContext, next) =>
        {
            if(!httpContext.Request.Path.Equals("/api/product/getProduct"))
            {
                await _next.Invoke(httpContext);

                return;
            }

            var claimsPrincipal = httpContext.User;

            var tenantHostResolver = httpContext.RequestServices.GetRequiredService<ITenantHostResolver>();

            var tenantHostAndPort = await tenantHostResolver.Resolve(claimsPrincipal);

            var downstreamRequest = httpContext.Items.DownstreamRequest();

            downstreamRequest.Host = tenantHostAndPort.Host;

            downstreamRequest.Port = tenantHostAndPort.Port;

            downstreamRequest.Scheme = tenantHostAndPort.Scheme;

            await next.Invoke();
        }
    };

    app.UseCustomOcelot(conf).Wait();
}