組態 或透過 程式代碼 中指定的 Proxy 路由必須至少包含路徑或主機名稱,才能對照。 除了這些,路由也可以指定請求中必須存在的一個或多個標頭。
優先權
預設路由比對優先順序為
- 路徑
- 方法
- 主機
- 標題
- 查詢參數
指明方法且不包括標頭的路由會優先於指明標頭且不包括方法的路由進行比對。 可以透過在路由上設定 Order 屬性來覆蓋此設置(在 組態屬性中查看範例)。
配置
標頭資訊是在代理路由的 Match 區段中指定。
如果在路由上指定多個標頭規則,則所有標頭規則都必須符合要採用的路由。 OR 邏輯必須在標頭規則內實作,或實作為個別路由。
設定:
"Routes": {
"route1" : {
"ClusterId": "cluster1",
"Match": {
"Path": "{**catch-all}",
"Headers": [
{
"Name": "header1",
"Values": [ "value1" ],
"Mode": "ExactHeader"
}
]
}
},
"route2" : {
"ClusterId": "cluster1",
"Match": {
"Path": "{**catch-all}",
"Headers": [
{
"Name": "header2",
"Values": [ "1prefix", "2prefix" ],
"Mode": "HeaderPrefix"
}
]
}
},
"route3" : {
"ClusterId": "cluster1",
"Match": {
"Path": "{**catch-all}",
"Headers": [
{
"Name": "header3",
"Mode": "Exists"
}
]
}
},
"route4" : {
"ClusterId": "cluster1",
"Match": {
"Path": "{**catch-all}",
"Headers": [
{
"Name": "header4",
"Values": [ "value1", "value2" ],
"Mode": "ExactHeader"
},
{
"Name": "header5",
"Mode": "Exists"
}
]
}
},
"route5" : {
"ClusterId": "cluster1",
"Match": {
"Path": "{**catch-all}",
"Headers": [
{
"Name": "header5",
"Values": [ "value1", "value2" ],
"Mode": "Contains"
},
{
"Name": "header6",
"Mode": "Exists"
}
]
}
},
"route6" : {
"ClusterId": "cluster1",
"Match": {
"Path": "{**catch-all}",
"Headers": [
{
"Name": "header6",
"Values": [ "value1", "value2" ],
"Mode": "NotContains"
},
{
"Name": "header7",
"Mode": "Exists"
}
]
}
},
"route7" : {
"ClusterId": "cluster1",
"Match": {
"Path": "{**catch-all}",
"Headers": [
{
"Name": "header7",
"Mode": "NotExists"
}
]
}
}
}
程式碼:
var routes = new[]
{
new RouteConfig()
{
RouteId = "route1",
ClusterId = "cluster1",
Match = new RouteMatch
{
Path = "{**catch-all}",
Headers = new[]
{
new RouteHeader()
{
Name = "Header1",
Values = new[] { "value1" },
Mode = HeaderMatchMode.ExactHeader
}
}
}
},
new RouteConfig()
{
RouteId = "route2",
ClusterId = "cluster1",
Match = new RouteMatch
{
Path = "{**catch-all}",
Headers = new[]
{
new RouteHeader()
{
Name = "Header2",
Values = new[] { "1prefix", "2prefix" },
Mode = HeaderMatchMode.HeaderPrefix
}
}
}
},
new RouteConfig()
{
RouteId = "route3",
ClusterId = "cluster1",
Match = new RouteMatch
{
Path = "{**catch-all}",
Headers = new[]
{
new RouteHeader()
{
Name = "Header3",
Mode = HeaderMatchMode.Exists
}
}
}
},
new RouteConfig()
{
RouteId = "route4",
ClusterId = "cluster1",
Match = new RouteMatch
{
Path = "{**catch-all}",
Headers = new[]
{
new RouteHeader()
{
Name = "Header4",
Values = new[] { "value1", "value2" },
Mode = HeaderMatchMode.ExactHeader
},
new RouteHeader()
{
Name = "Header5",
Mode = HeaderMatchMode.Exists
}
}
}
},
new RouteConfig()
{
RouteId = "route5",
ClusterId = "cluster1",
Match = new RouteMatch
{
Path = "{**catch-all}",
Headers = new[]
{
new RouteHeader()
{
Name = "Header5",
Values = new[] { "value1", "value2" },
Mode = HeaderMatchMode.Contains
}
}
}
},
new RouteConfig()
{
RouteId = "route6",
ClusterId = "cluster1",
Match = new RouteMatch
{
Path = "{**catch-all}",
Headers = new[]
{
new RouteHeader()
{
Name = "Header6",
Values = new[] { "value1", "value2" },
Mode = HeaderMatchMode.NotContains
}
}
}
},
new RouteConfig()
{
RouteId = "route7",
ClusterId = "cluster1",
Match = new RouteMatch
{
Path = "{**catch-all}",
Headers = new[]
{
new RouteHeader()
{
Name = "Header7",
Mode = HeaderMatchMode.NotExists
}
}
}
}
};
合同
RouteHeader 定義代碼契約,並從 config 映射。
名字
要檢查請求中的標頭名稱。 需要非空白值。 此欄位根據 HTTP RFC 將不區分大小寫。
價值觀
要搜尋的可能值清單。 標頭必須根據指定的 Mode 至少匹配其中一個值('NotContains' 除外)。 除非將 Mode 設定為 Exists 或 NotExists,否則至少需要一個值。
模式
HeaderMatchMode 指定如何將值與請求標頭進行匹配。 預設值為 ExactHeader。
- ExactHeader - 具有指定名稱的任何標頭必須完全相符,但受限於
IsCaseSensitive的值。 如果標頭包含多個值(以,或;分隔),則會在比對之前進行分割。 在比對之前,值中的一對引號也會被移除。 - HeaderPrefix - 具有指定名稱的任何標頭必須以其前綴比對,受
IsCaseSensitive的值限制。 如果標頭包含多個值(以,或;分隔),則會在比對之前進行分割。 在比對之前,值中的一對引號也會被移除。 - Exists - 標頭必須存在且包含任何非空白值。 如果有多個具有相同名稱的標頭,規則也會相符。
- Contains - 具有指定名稱的任何標頭都必須包含任何相符值,受限於
IsCaseSensitive的值。 - 不包含 - 具有指定名稱的標頭中沒有一個可以包含任何相符值,這一情況受限於
IsCaseSensitive的值。
是否區分大小寫
表示值比對是否應該以區分大小寫或不區分大小寫的方式執行。 預設值為 false,對大小寫不敏感。
例子
這些範例會使用上述指定的組態。
案例 1 - 完全相符標題
具有下列標題的請求將與 route1 匹配。
Header1: Value1
如果標頭包含多個值,則會個別比對每一個值。 下列要求將會符合。
Header1: Value1, Value2
如果多個值被分割在具有相同名稱的多個標頭中,同樣情況成立。
Header1: Value1
Header1: Value2
在比對之前,可能會從值中移除一組括住的引號。 下列要求將會相符。
Header1: "Value1"
多組引號將 無法 匹配。
Header1: ""Value1""
情境 2 - 多個值
Route2 定義了多個值,以在標頭中搜尋 #“1prefix”、“2prefix”),任何值都可以接受。 它也會將 Mode 指定為 HeaderPrefix,因此可以接受以這些值開頭的任何標頭。
下列任何標頭都會匹配 route2。
Header2: 1prefix
Header2: 2prefix
Header2: 1prefix-extra
Header2: 2prefix-extra
如果標頭包含多個值,則會個別比對每一個值。 下列要求將會相符。
Header2: foo, 1prefix, 2prefix
如果多個值被分割在具有相同名稱的多個標頭中,同樣情況成立。
Header2: 1prefix
Header2: 2prefix
比對之前,可能會從值中移除單一括住引號。 下列要求將會相符。
Header2: "2prefix"
多對引號將 不 相符。
Header2: ""2prefix""
案例 3 - 存在
Route3 只需要標頭「Header3」存在並擁有任何非空值。
以下是符合 route3 的範例。
Header3: value
空白標頭將無法匹配。
Header3:
此模式支援具有多個值的標頭,以及具有相同名稱的多個標頭,因為它不會查看標頭內容。 下列內容將會符合。
Header3: value1, value2
Header3: value1
Header3: value2
Header3:
Header3:
案例 4 - 多個標頭
Route4 需要 header4 和 header5,每個項目必須根據其指定的 Mode相符。 以下標頭將符合 route4:
Header4: value1
Header5: AnyValue
Header4: value2
Header5: AnyValue
這些 不會 匹配 route4,因為它們缺少其中一個必要標頭:
Header4: value2
Header5: AnyValue
案例 5 - NotExists
Route7 要求標頭 「Header7」 不得存在
下列標頭會匹配 route7:
NotHeader7: AnyValue
下列標頭 不會 符合 route7,因為標頭 “Header7” 存在。
Header7: AnyValue
Header7: