YARP — Transform (biến đổi) Request và Response
Giới thiệu
Khi proxy (ủy quyền) một request, thường cần sửa đổi một số phần của request hoặc response để phù hợp với yêu cầu của máy chủ đích, hoặc để chuyển tiếp thêm thông tin như địa chỉ IP gốc của client. Quá trình này được thực hiện thông qua Transforms (các biến đổi). Các loại transform được định nghĩa toàn cục cho ứng dụng, sau đó mỗi route cung cấp tham số để bật và cấu hình các transform đó. Các đối tượng request gốc không bị sửa đổi bởi transform — chỉ có proxy request mới bị thay đổi.
Transform cho body của request và response không được YARP cung cấp sẵn, nhưng bạn có thể viết middleware để thực hiện điều này.
Mặc định
Các transform sau được bật mặc định cho tất cả các route. Chúng có thể được cấu hình hoặc tắt như được mô tả ở phần sau trong tài liệu này.
- Host — Bỏ qua header Host của request đến. Proxy request sẽ mặc định dùng tên host được chỉ định trong địa chỉ máy chủ đích. Xem
RequestHeaderOriginalHostbên dưới. - X-Forwarded-For — Đặt địa chỉ IP của client vào header X-Forwarded-For. Xem
X-Forwardedbên dưới. - X-Forwarded-Proto — Đặt scheme gốc của request (http/https) vào header X-Forwarded-Proto. Xem
X-Forwardedbên dưới. - X-Forwarded-Host — Đặt Host gốc của request vào header X-Forwarded-Host. Xem
X-Forwardedbên dưới. - X-Forwarded-Prefix — Đặt PathBase gốc của request (nếu có) vào header X-Forwarded-Prefix. Xem
X-Forwardedbên dưới.
Ví dụ, request đến http://IncomingHost:5000/path:
GET /path HTTP/1.1 Host: IncomingHost:5000 Accept: */* header1: foo
sẽ được transform và proxy tới máy chủ đích https://DestinationHost:6000/ như sau khi dùng các giá trị mặc định:
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
Phân loại Transform
Transform được chia thành một số loại: Request, Response, và Response Trailers (xem trang transforms-response). Request trailers không được hỗ trợ vì HttpClient bên dưới không hỗ trợ chúng.
Nếu bộ transform tích hợp sẵn không đủ, có thể thêm transform tùy chỉnh thông qua extensibility (khả năng mở rộng).
Thêm Transform
Transform có thể được thêm vào route thông qua cấu hình hoặc bằng code.
Từ cấu hình (Configuration)
Transform có thể được cấu hình trên RouteConfig.Transforms và liên kết từ phần Routes của file cấu hình. Chúng có thể được sửa đổi và tải lại mà không cần khởi động lại proxy. Một transform được cấu hình bằng một hoặc nhiều cặp chuỗi key-value.
Dưới đây là ví dụ về các transform phổ biến:
{
"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"
}
}
}
}
}
}Tất cả các mục cấu hình được xử lý không phân biệt chữ hoa/thường, mặc dù máy chủ đích có thể xử lý các giá trị kết quả theo cách phân biệt hoặc không phân biệt (ví dụ như path).
Nhà phát triển muốn tích hợp transform tùy chỉnh của mình với phần Transforms của cấu hình có thể làm điều đó bằng ITransformFactory được mô tả bên dưới.
Từ Code
Transform có thể được thêm vào route bằng code bằng cách gọi phương thức AddTransforms.
AddTransforms có thể được gọi sau AddReverseProxy để cung cấp một callback để cấu hình transform. Callback này được gọi mỗi khi một route được xây dựng hoặc xây dựng lại, và cho phép nhà phát triển kiểm tra thông tin RouteConfig và thêm transform có điều kiện cho route đó.
Callback AddTransforms cung cấp một TransformBuilderContext nơi các transform có thể được thêm hoặc cấu hình. Hầu hết các transform cung cấp các extension method cho TransformBuilderContext để dễ dàng thêm hơn.
TransformBuilderContext cũng bao gồm một IServiceProvider để truy cập bất kỳ service nào cần thiết.
services.AddReverseProxy()
.LoadFromConfig(_configuration.GetSection("ReverseProxy"))
.AddTransforms(builderContext =>
{
// Thêm vào tất cả các route.
builderContext.AddPathPrefix("/prefix");
// Thêm transform có điều kiện cho các route yêu cầu xác thực.
if (!string.IsNullOrEmpty(builderContext.Route.AuthorizationPolicy))
{
builderContext.AddRequestTransform(async transformContext =>
{
transformContext.ProxyRequest.Headers.Add("CustomHeader", "CustomValue");
});
}
});Để kiểm soát nâng cao hơn, xem ITransformProvider được mô tả bên dưới.