要求轉換包括要求路徑、查詢、HTTP 版本、方法和標頭。 在程式代碼中,這些是由 RequestTransformContext 物件表示,並由抽象類 RequestTransform 的實作處理。
注意事項:
- Proxy 要求方案(HTTP/https)、權限和路徑基底,從目的伺服器位址(
https://localhost:10001/Path/Base在上述範例中)提取,並不應以轉換形式修改。 - 主機標頭可以透過不依賴權威機制的轉換來覆寫,請參閱下面的RequestHeader。
- 建構 Proxy 要求時,不會使用要求的原始 PathBase 屬性,請參閱 X-Forwarded。
- 所有傳入的請求標頭預設會被複製到 Proxy 請求中,唯獨 Host 標頭除外(請參閱
Defaults預設值)。 預設情況下也會添加 X-Forwarded 標頭。 您可以使用下列轉換來設定這些行為。 您可以指定其他要求標頭,或藉由將標頭設定為空值來排除要求標頭。
下列是內建的轉換,這些轉換是通過其主要配置鍵識別的。 這些轉換會依照路由組態中指定的順序套用。
路徑前綴
修改新增前置詞值的要求路徑
| 鑰匙 | 價值 | 為必填項目 |
|---|---|---|
| 路徑前綴 | 開頭為 『/』 的路徑 | 是的 |
設定:
{ "PathPrefix": "/prefix" }
程式碼:
routeConfig = routeConfig.WithTransformPathPrefix(prefix: "/prefix");
transformBuilderContext.AddPathPrefix(prefix: "/prefix");
範例:
/request/path 變成 /prefix/request/path
這會在要求路徑前面加上指定的值。
移除前綴路徑
修改移除前置詞值的要求路徑
| 鑰匙 | 價值 | 為必填項目 |
|---|---|---|
| 移除前綴路徑 | 開頭為 『/』 的路徑 | 是的 |
設定:
{ "PathRemovePrefix": "/prefix" }
程式碼:
routeConfig = routeConfig.WithTransformPathRemovePrefix(prefix: "/prefix");
transformBuilderContext.AddPathRemovePrefix(prefix: "/prefix");
範例:
/prefix/request/path 變成 /request/path
/prefix2/request/path 未修改
這會從要求路徑中移除相符的前置詞。 比對是在路徑區段界限上建立的。/ 如果前置詞不相符,則不會進行任何變更。
PathSet
以指定的值取代要求路徑
| 鑰匙 | 價值 | 為必填項目 |
|---|---|---|
| PathSet | 開頭為 『/』 的路徑 | 是的 |
設定:
{ "PathSet": "/newpath" }
程式碼:
routeConfig = routeConfig.WithTransformPathSet(path: "/newpath");
transformBuilderContext.AddPathSet(path: "/newpath");
範例:
/request/path 變成 /newpath
這會使用指定的值來設定要求路徑。
路徑模式
使用模式範本取代要求路徑
| 鑰匙 | 價值 | 為必填項目 |
|---|---|---|
| 路徑模式 | 開頭為 『/』 的路徑範本 | 是的 |
設定:
{ "PathPattern": "/my/{plugin}/api/{**remainder}" }
程式碼:
routeConfig = routeConfig.WithTransformPathRouteValues(pattern: new PathString("/my/{plugin}/api/{**remainder}"));
transformBuilderContext.AddPathRouteValues(pattern: new PathString("/my/{plugin}/api/{**remainder}"));
這會使用指定的值來設定要求路徑,並將任何 {} 區段取代為相關聯的路由值。
{} 拿掉沒有相符路由值的區段。 最後 {} 的區段可以標示為 {**remainder} ,表示這是可能包含多個路徑區段的 catch-all 區段。 如需路由範本的詳細資訊,請參閱 ASP.NET Core 的 路由檔 。
範例:
| 步驟 | 價值 |
|---|---|
| 路由定義 | /api/{plugin}/stuff/{**remainder} |
| 請求路徑 | /api/v1/stuff/more/stuff |
| 插件值 | v1 |
| 餘數值 | more/stuff |
| 路徑模式 | /my/{plugin}/api/{**remainder} |
| 結果 | /my/v1/api/more/stuff |
查詢值參數
在要求查詢字串中新增或取代參數
| 鑰匙 | 價值 | 為必填項目 |
|---|---|---|
| 查詢值參數 | 查詢字串參數的名稱 | 是的 |
| 設定/追加 | 靜態值 | 是的 |
設定:
{
"QueryValueParameter": "foo",
"Append": "bar"
}
程式碼:
routeConfig = routeConfig.WithTransformQueryValue(queryKey: "foo", value: "bar", append: true);
transformBuilderContext.AddQueryValue(queryKey: "foo", value: "bar", append: true);
這會新增具有名稱 foo 的查詢字串參數,並將其設定為靜態值 bar。
範例:
| 步驟 | 價值 |
|---|---|
| 查詢 | ?a=b |
| 查詢值參數 | foo |
| 添附 | remainder |
| 結果 | ?a=b&foo=remainder |
查詢路由參數
從路由組態中取得值,以新增或取代查詢字串參數
| 鑰匙 | 價值 | 為必填項目 |
|---|---|---|
| 查詢路由參數 | 查詢字串參數的名稱 | 是的 |
| 設定/追加 | 路由值的名稱 | 是的 |
設定:
{
"QueryRouteParameter": "foo",
"Append": "remainder"
}
程式碼:
routeConfig = routeConfig.WithTransformQueryRouteValue(queryKey: "foo", routeValueKey: "remainder", append: true);
transformBuilderContext.AddQueryRouteValue(queryKey: "foo", routeValueKey: "remainder", append: true);
這會新增具有名稱 foo 的查詢字串參數,並將其設定為相關聯路由值的值。
範例:
| 步驟 | 價值 |
|---|---|
| 路由定義 | /api/{*remainder} |
| 請求路徑 | /api/more/stuff |
| 餘數值 | more/stuff |
| 查詢路由參數 | foo |
| 添附 | remainder |
| 結果 | ?foo=more/stuff |
QueryRemoveParameter
從要求查詢字串中移除指定的參數
| 鑰匙 | 價值 | 為必填項目 |
|---|---|---|
| QueryRemoveParameter | 查詢字串參數的名稱 | 是的 |
設定:
{ "QueryRemoveParameter": "foo" }
程式碼:
routeConfig = routeConfig.WithTransformQueryRemoveKey(queryKey: "foo");
transformBuilderContext.AddQueryRemoveKey(queryKey: "foo");
如果請求中存在,這將移除名為 foo 的查詢字串參數。
範例:
| 步驟 | 價值 |
|---|---|
| 請求路徑 | ?a=b&foo=c |
| QueryRemoveParameter | foo |
| 結果 | ?a=b |
HTTP 方法變更
變更要求中使用的 HTTP 方法
| 鑰匙 | 價值 | 為必填項目 |
|---|---|---|
| HTTP 方法變更 | 要取代的 HTTP 方法 | 是的 |
| 設定 | 新的 HTTP 方法 | 是的 |
設定:
{
"HttpMethodChange": "PUT",
"Set": "POST"
}
程式碼:
routeConfig = routeConfig.WithTransformHttpMethodChange(fromHttpMethod: HttpMethods.Put, toHttpMethod: HttpMethods.Post);
transformBuilderContext.AddHttpMethodChange(fromHttpMethod: HttpMethods.Put, toHttpMethod: HttpMethods.Post);
這會將 PUT 要求變更為 POST。
請求標頭複製
設定傳入要求標頭是否複製到輸出要求
| 鑰匙 | 價值 | 預設 | 為必填項目 |
|---|---|---|---|
| 請求標頭複製 | 真/假 | 是 | 是的 |
設定:
{ "RequestHeadersCopy": "false" }
程式碼:
routeConfig = routeConfig.WithTransformCopyRequestHeaders(copy: false);
transformBuilderContext.CopyRequestHeaders = false;
這個設定決定是否所有進入的請求標頭都會複製到代理請求中。 默認狀態下會啟用此設定,您可以藉由將轉換配置為false值來停用該設定。 即使停用此功能,參考特定標頭的轉換仍會執行。
RequestHeader原始主機
指定是否應將傳入請求的 Host 標頭複製到代理請求
| 鑰匙 | 價值 | 預設 | 為必填項目 |
|---|---|---|---|
| RequestHeader原始主機 | 真/假 | 假的 | 是的 |
設定:
{ "RequestHeaderOriginalHost": "true" }
routeConfig = routeConfig.WithTransformUseOriginalHostHeader(useOriginal: true);
transformBuilderContext.AddOriginalHost(true);
這會指定傳入要求主機標頭是否應該複製到代理要求。 此設定默認為停用狀態,但可通過配置轉換至 true 值來啟用。 直接參考 Host 標頭的轉換將會覆蓋此轉換。
請求標頭
新增或取代要求標頭
| 鑰匙 | 價值 | 為必填項目 |
|---|---|---|
| 請求標頭 | 標頭名稱 | 是的 |
| 設定/追加 | 標頭值 | 是的 |
設定:
{
"RequestHeader": "MyHeader",
"Set": "MyValue"
}
程式碼:
routeConfig = routeConfig.WithTransformRequestHeader(headerName: "MyHeader", value: "MyValue", append: false);
transformBuilderContext.AddRequestHeader(headerName: "MyHeader", value: "MyValue", append: false);
範例:
MyHeader: MyValue
這會設定或附加標頭名稱的數值。 Set 會取代任何現有的標頭。 Append 會新增具有指定值的額外標頭。 注意:不建議將 「設定為標頭值,而且可能會導致未定義的行為。
請求標頭路由值
從路由組態新增或取代標頭的值
| 鑰匙 | 價值 | 為必填項目 |
|---|---|---|
| 請求標頭 | 查詢字串參數的名稱 | 是的 |
| 設定/追加 | 路由值的名稱 | 是的 |
設定:
{
"RequestHeaderRouteValue": "MyHeader",
"Set": "MyRouteKey"
}
程式碼:
routeConfig = routeConfig.WithTransformRequestHeaderRouteValue(headerName: "MyHeader", routeValueKey: "key", append: false);
transformBuilderContext.AddRequestHeaderRouteValue(headerName: "MyHeader", routeValueKey: "key", append: false);
範例:
| 步驟 | 價值 |
|---|---|
| 路由定義 | /api/{*remainder} |
| 請求路徑 | /api/more/stuff |
| 餘數值 | more/stuff |
| 請求標頭從路由 | foo |
| 添附 | remainder |
| 結果 | foo: more/stuff |
這會設定或附加指定的標頭值,此值來自路由組態。 Set 會取代任何現有的標頭。 Append 會新增具有指定值的額外標頭。 注意:不建議將 「設定為標頭值,而且可能會導致未定義的行為。
移除請求標頭
拿掉要求標頭
| 鑰匙 | 價值 | 為必填項目 |
|---|---|---|
| 移除請求標頭 | 標頭名稱 | 是的 |
設定:
{
"RequestHeaderRemove": "MyHeader"
}
程式碼:
routeConfig = routeConfig.WithTransformRequestHeaderRemove(headerName: "MyHeader");
transformBuilderContext.AddRequestHeaderRemove(headerName: "MyHeader");
範例:
MyHeader: MyValue
AnotherHeader: AnotherValue
這會移除已命名的標頭。
允許的請求頭部
| 鑰匙 | 價值 | 為必填項目 |
|---|---|---|
| 允許的請求頭部 | 允許的標頭名稱清單,以分號分隔。 | 是的 |
設定:
{
"RequestHeadersAllowed": "Header1;header2"
}
程式碼:
routeConfig = routeConfig.WithTransformRequestHeadersAllowed("Header1", "header2");
transformBuilderContext.AddRequestHeadersAllowed("Header1", "header2");
YARP 預設會將大部分的要求標頭複製到 Proxy 要求(請參閱 RequestHeadersCopy)。 某些安全性模型只允許特定標頭被轉送。 此轉換會停用 RequestHeadersCopy,而且只會複製指定的標頭。 若未包含在允許清單中,修改或附加至現有標頭的其他轉換可能會受到影響。
請注意,有些標頭欄位 YARP 預設不會複製,因為它們是連線特定或與其他安全性相關的(例如,ConnectionAlt-Svc)。 將這些標頭名稱放在允許清單中將會略過該限制,但強烈建議您不要使用,因為它可能會對 Proxy 的功能造成負面影響,或造成安全性弱點。
範例:
Header1: value1
Header2: value2
AnotherHeader: AnotherValue
只有 header1 和 header2 會複製到 Proxy 要求。
X 轉寄
新增標頭,其中包含原始用戶端要求的相關信息
| 鑰匙 | 價值 | 預設 | 為必填項目 |
|---|---|---|---|
| X 轉寄 | 預設動作(Set、Append、Remove、Off)套用至下列所有 X-Forwarded-* | 設定 | 是的 |
| 為了 | 套用至此標頭的操作動作 | * 請參閱 X-Forwarded | 否 |
| 原型 | 套用至此標頭的操作動作 | * 請參閱 X-Forwarded | 否 |
| 主持人 | 套用至此標頭的操作動作 | * 請參閱 X-Forwarded | 否 |
| 前綴 | 套用至此標頭的操作動作 | * 請參閱 X-Forwarded | 否 |
| 標頭前綴 | 標頭名稱前綴 | “X-Forwarded-” | 否 |
動作 「Off」 會完全停用轉換。
設定:
{
"X-Forwarded": "Set",
"For": "Remove",
"Proto": "Append",
"Prefix": "Off",
"HeaderPrefix": "X-Forwarded-"
}
程式碼:
routeConfig = routeConfig.WithTransformXForwarded(
headerPrefix = "X-Forwarded-",
ForwardedTransformActions xDefault = ForwardedTransformActions.Set,
ForwardedTransformActions? xFor = null,
ForwardedTransformActions? xHost = null,
ForwardedTransformActions? xProto = null,
ForwardedTransformActions? xPrefix = null);
transformBuilderContext.AddXForwarded(ForwardedTransformActions.Set);
transformBuilderContext.AddXForwardedFor(headerName: "X-Forwarded-For", ForwardedTransformActions.Append);
transformBuilderContext.AddXForwardedHost(headerName: "X-Forwarded-Host", ForwardedTransformActions.Append);
transformBuilderContext.AddXForwardedProto(headerName: "X-Forwarded-Proto", ForwardedTransformActions.Off);
transformBuilderContext.AddXForwardedPrefix(headerName: "X-Forwarded-Prefix", ForwardedTransformActions.Remove);
範例:
X-Forwarded-For: 5.5.5.5
X-Forwarded-Proto: https
X-Forwarded-Host: IncomingHost:5000
X-Forwarded-Prefix: /path/base
停用預設標頭:
{ "X-Forwarded": "Off" }
transformBuilderContext.UseDefaultForwarders = false;
當 Proxy 連線到目的地伺服器時,連線與用戶端對 Proxy 建立的連接無關。 目的地伺服器可能需要原始連線資訊來進行安全性檢查,並正確產生連結和重新導向的絕對 URI。 若要啟用將用戶端連線的相關信息傳遞至目的地,可以新增一組額外的標頭。 在Forwarded標準創立以前,常見的解決方案是使用X-Forwarded-*標頭。 沒有正式制定 X-Forwarded-* 標題的標準,實作可能會有所不同,請檢查目的地伺服器是否提供支援。
即使路由設定中未指定,預設仍會啟用此轉換。
將 X-Forwarded 值設定為用逗號分隔的清單,其中包含您需要啟用的標頭。 預設會啟用所有的標頭選項。 您可以藉由指定 值 "Off"來停用所有 。
「Prefix」指定用於每個標頭的標頭名稱前綴詞。 使用預設X-Forwarded-前置詞時,產生的標頭會是X-Forwarded-For、 X-Forwarded-ProtoX-Forwarded-Host和 X-Forwarded-Prefix。
轉換動作會指定如何將每個標頭與相同名稱的現有標頭結合。 它可以是「Set」、「Append」、「Remove」或「Off」(完全停用轉換)。 穿越多個代理伺服器的請求可能會累積這些標頭的清單,而目的伺服器將需要評估這些清單以確定原始值。 如果操作為「Set」,且請求中無法取得相關參數的值(例如 RemoteIpAddress 為 null),仍會移除任何已存在的標頭,以防止偽裝。
{Prefix}For 標頭值取自 HttpContext.Connection.RemoteIpAddress 代表前一個呼叫端的 IP 位址。 不包含埠口。 IPv6 位址不包含 [] 方括號。
{Prefix}Proto 標頭值取自 HttpContext.Request.Scheme 指出先前呼叫端是否使用 HTTP 或 HTTPS。
{Prefix}Host 標頭值取自傳入要求的主機標頭。 這與上述指定的 RequestHeaderOriginalHost 無關。 Unicode/IDN 主機名稱會以 Punycode 進行編碼。
{Prefix}Prefix 標頭值取自 HttpContext.Request.PathBase。 產生 Proxy 要求時不會使用 PathBase 屬性,因此目的地伺服器需要原始值才能正確產生連結和導向。 值採用百分比編碼 URI 格式。
轉發
新增標頭,其中包含原始用戶端要求的相關信息
| 鑰匙 | 價值 | 預設 | 為必填項目 |
|---|---|---|---|
| 轉發 | 逗號分隔清單,包含下列任何值:for、by、proto、host | (無) | 是的 |
| ForFormat | Random/RandomAndPort/RandomAndRandomPort/Unknown/UnknownAndPort/UnknownAndRandomPort/ip/IpAndRandomPort | 隨機 | 否 |
| ByFormat | Random/RandomAndPort/RandomAndRandomPort/Unknown/UnknownAndPort/UnknownAndRandomPort/ip/IpAndRandomPort | 隨機 | 否 |
| 行動 | 要套用至此標題的動作(Set、Append、Remove、Off) | 設定 | 否 |
設定:
{
"Forwarded": "by,for,host,proto",
"ByFormat": "Random",
"ForFormat": "IpAndPort",
"Action": "Append"
},
程式碼:
routeConfig = routeConfig.WithTransformForwarded(useHost: true, useProto: true, forFormat: NodeFormat.IpAndPort, ByFormat: NodeFormat.Random, action: ForwardedTransformAction.Append);
transformBuilderContext.AddForwarded(useHost: true, useProto: true, forFormat: NodeFormat.IpAndPort, ByFormat: NodeFormat.Random, action: ForwardedTransformAction.Append);
範例:
Forwarded: proto=https;host="localhost:5001";for="[::1]:20173";by=_YQuN68tm6
標頭 Forwarded 是由 RFC 7239 所定義。 它整合了許多與非官方 X-Forwarded 標頭相同的功能,將資訊流向目的地伺服器,否則這些資訊在使用代理時會被遮蔽。
啟用此轉換將會停用預設 X 轉送轉換,因為它們會以另一種格式傳遞類似的資訊。 X 轉送轉換仍然可以明確啟用。
動作:這會指定轉換應該如何處理現有的轉送標頭。 它可以是「Set」、「Append」、「Remove」或「Off」(完全停用轉換)。 穿越多個代理伺服器的請求可能會累積這些標頭的清單,而目的伺服器將需要評估這些清單以確定原始值。
Proto:此值取自 HttpContext.Request.Scheme 指出先前呼叫端是否使用 HTTP 或 HTTPS。
主機:此值取自傳入要求的主機標頭。 這與上述指定的 RequestHeaderOriginalHost 無關。 Unicode/IDN 主機名稱會以 Punycode 進行編碼。
關於:這個值會識別之前的呼叫者。 IP 位址取自 HttpContext.Connection.RemoteIpAddress。 如需詳細資訊,請參閱下方的 ByFormat 和 ForFormat。
來源:這個值會識別代理伺服器接收請求的位置。 IP 位址取自 HttpContext.Connection.LocalIpAddress。 如需詳細資訊,請參閱下方的 ByFormat 和 ForFormat。
ByFormat 和 ForFormat:
RFC 允許 By 欄位和 For 欄位使用格式多樣。 它要求預設格式使用在此識別為 Random 的混淆識別碼。
| 格式 | 說明 | 範例 |
|---|---|---|
| 隨機 | 每次請求隨機生成的混淆識別碼。 這允許進行診斷追蹤情境,同時出於隱私考量限制唯一識別資訊的流通。 | by=_YQuN68tm6 |
| RandomAndPort | 隨機識別碼加上端口。 | by="_YQuN68tm6:80" |
| RandomAndRandomPort | 隨機標識元加上埠的另一個隨機標識碼。 | by="_YQuN68tm6:_jDw5Cf3tQ" |
| 未知 | 這可以在上述實體的身分識別未知時使用,但 Proxy 伺服器仍想要發出要求轉送的訊號。 | by=unknown |
| UnknownAndPort | 未知識別符加上端口(如果可用)。 | by="unknown:80" |
| 未知和隨機端口 | 未知識別碼加上埠的隨機標識碼。 | by="unknown:_jDw5Cf3tQ" |
| IP | IPv4 位址或 IPv6 位址,包括括弧。 | by="[::1]" |
| IpAndPort | IP 位址加上埠。 | by="[::1]:80" |
| IpAndRandomPort | 埠的IP位址加上隨機識別碼。 | by="[::1]:_jDw5Cf3tQ" |
ClientCert
將入站連線上使用的客戶端憑證作為標頭轉送至目的地
| 鑰匙 | 價值 | 為必填項目 |
|---|---|---|
| ClientCert | 標頭名稱 | 是的 |
設定:
{ "ClientCert": "X-Client-Cert" }
程式碼:
routeConfig = routeConfig.WithTransformClientCertHeader(headerName: "X-Client-Cert");
transformBuilderContext.AddClientCertHeader(headerName: "X-Client-Cert");
範例:
X-Client-Cert: SSdtIGEgY2VydGlmaWNhdGU...
由於輸入和輸出連線是獨立的,因此必須有一種方法,才能將任何輸入用戶端憑證傳遞至目的地伺服器。 這項轉換會將從HttpContext.Connection.ClientCertificate提取的用戶端憑證進行Base64編碼,並設定為指定標頭名稱的值。 目的地伺服器可能需要該憑證來驗證用戶端。 沒有定義此標頭的標準,因此實作可能有所不同,請檢查目的伺服器是否支援。
根據預設,伺服器會對傳入客戶端憑證執行最少的驗證。 憑證應該在 Proxy 或目的地中驗證,如需詳細資訊,請參閱 用戶端憑證驗證 檔。
只有在連線上已經有客戶端憑證時,才會套用此轉換。 請參閱 選擇性憑證文件,以便在需要時依每個路由向用戶端要求憑證。