YARP 请求和响应转换

介绍

代理请求时,通常修改请求或响应的各个部分,以适应目标服务器的要求或流出其他数据,例如客户端的原始 IP 地址。 此过程通过Transforms实现。 为应用程序全局定义转换类型,然后各个路由提供参数以启用和配置这些转换。 原始请求对象不会由这些转换修改,只修改代理请求。

请求和响应正文转换不是由 YARP 提供的,但你可以编写中间件来执行此作。

默认值

默认情况下为所有路由启用以下转换。 可以配置或禁用它们,如本文档稍后所示。

  • Host - 禁止传入请求的 Host 标头。 代理请求默认为目标服务器地址中指定的主机名。 请参阅 RequestHeaderOriginalHost 下文。
  • X-Forwarded-For - 将客户端的 IP 地址设置为 X-Forwarded-For 标头。 请参阅 X-Forwarded 下文。
  • X-Forwarded-Proto - 将请求的原始方案 (http/https) 设置为 X-Forwarded-Proto 标头。 请参阅 X-Forwarded 下文。
  • X-Forwarded-Host - 将请求的原始 Host 标头设置为 X-Forwarded-Host 标头。 请参阅 X-Forwarded 下文。
  • X-Forwarded-Prefix - 将请求的原始 PathBase 标头(如果有)设置为 X-Forwarded-Prefix 标头。 请参阅 X-Forwarded 下文。

例如,传入 http://IncomingHost:5000/path 的以下请求:

GET /path HTTP/1.1
Host: IncomingHost:5000
Accept: */*
header1: foo

将转换并代理到目标服务器 https://DestinationHost:6000/ ,如下所示,使用以下默认值:

GET /path HTTP/1.1
Host: DestinationHost:6000
Accept: */*
header1: foo
X-Forwarded-For: 5.5.5.5
X-Forwarded-Proto: http
X-Forwarded-Host: IncomingHost:5000

转换类别

转换分为以下几个类别:请求响应响应尾部。 不支持请求尾部,因为它们不受基础 HttpClient 支持。

如果内置转换集不足,则可以通过 扩展性添加自定义转换。

添加转换

可以通过配置或编程方式将变换添加到路由中。

通过配置添加

可以在 RouteConfig.Transforms 中配置转换,并可从配置文件的 Routes 部分中绑定这些转换。 可以在不重新启动代理的情况下修改和重新加载这些设置。 使用一个或多个键值配对字符串来配置转换。

下面是常见转换的示例:

{
  "ReverseProxy": {
    "Routes": {
      "route1" : {
        "ClusterId": "cluster1",
        "Match": {
          "Hosts": [ "localhost" ]
        },
        "Transforms": [
          { "PathPrefix": "/apis" },
          {
            "RequestHeader": "header1",
            "Append": "bar"
          },
          {
            "ResponseHeader": "header2",
            "Append": "bar",
            "When": "Always"
          },
          { "ClientCert": "X-Client-Cert" },
          { "RequestHeadersCopy": "true" },
          { "RequestHeaderOriginalHost": "true" },
          {
            "X-Forwarded": "Append",
            "HeaderPrefix": "X-Forwarded-"
          }
        ]
      },
      "route2" : {
        "ClusterId": "cluster1",
        "Match": {
          "Path": "/api/{plugin}/stuff/{**remainder}"
        },
        "Transforms": [
          { "PathPattern": "/foo/{plugin}/bar/{**remainder}" },
          {
            "QueryValueParameter": "q",
            "Append": "plugin"
          }
        ]
      }
    },
    "Clusters": {
      "cluster1": {
        "Destinations": {
          "cluster1/destination1": {
            "Address": "https://localhost:10001/Path/Base"
          }
        }
      }
    }
  }
}

所有配置条目都被视为不区分大小写,但目标服务器可能会将生成的值视为区分大小写或不区分大小写(如路径)。

本文档稍后将介绍这些转换的详细信息。

希望将自定义转换与 Transforms 配置部分集成的开发人员可以使用下面描述的 ITransformFactory

通过代码添加

可以通过调用 AddTransforms 方法以编程方式将转换添加到路由中。

AddTransforms 可以在 AddReverseProxy 之后调用,以提供用于配置转换的回调。 每次生成或重新生成路由时都会调用此回调,并允许开发人员检查 RouteConfig 信息并有条件地为其添加转换。

AddTransforms 回调提供一个 TransformBuilderContext,用于添加或配置转换。 大多数转换都提供 TransformBuilderContext 扩展方法,使其更易于添加。 以下是记录在下面的扩展及其各自的转换说明。

TransformBuilderContext 还包括一个用于访问任何所需服务的 IServiceProvider

services.AddReverseProxy()
    .LoadFromConfig(_configuration.GetSection("ReverseProxy"))
    .AddTransforms(builderContext =>
    {
        // Added to all routes.
        builderContext.AddPathPrefix("/prefix");

        // Conditionally add a transform for routes that require auth.
        if (!string.IsNullOrEmpty(builderContext.Route.AuthorizationPolicy))
        {
            builderContext.AddRequestTransform(async transformContext =>
            {
                transformContext.ProxyRequest.Headers.Add("CustomHeader", "CustomValue");
            });
        }
    });

有关更高级的控制,请参阅 ITransformProvider 下文。