2013-05-24 32 views
10

Tôi đã chơi xung quanh bằng cách sử dụng API Web (Máy chủ web) làm máy chủ proxy và đã gặp sự cố với cách proxy Web API xử lý phản hồi bằng "Chuyển mã hóa : chunked "tiêu đề.API Web dưới dạng Proxy và Mã hóa chuyển chunked

Khi bỏ qua proxy, tài nguyên từ xa gửi các tiêu đề phản ứng sau đây:

Cache-Control:no-cache 
Content-Encoding:gzip 
Content-Type:text/html 
Date:Fri, 24 May 2013 12:42:27 GMT 
Expires:-1 
Pragma:no-cache 
Server:Microsoft-IIS/8.0 
Transfer-Encoding:chunked 
Vary:Accept-Encoding 
X-AspNet-Version:4.0.30319 
X-Powered-By:ASP.NET 

Khi đi qua proxy dựa Web API của tôi, yêu cầu của tôi bị treo trừ khi tôi dứt khoát thiết lập lại tài sản TransferEncodingChunked vào tiêu đề đối phó với sai :

response.Headers.TransferEncodingChunked = false; 

tôi thừa nhận, tôi không hoàn toàn hiểu những gì tác động thiết lập thuộc tính TransferEncodingChunked có, nhưng có vẻ như xa lạ với tôi rằng để thực hiện công việc ủy ​​quyền như mong đợi, tôi cần phải đặt khách sạn này là false khi rõ ràng phản hồi đến có tiêu đề "Chuyển mã hóa: chunked". Tôi cũng lo ngại về tác dụng phụ để thiết lập rõ ràng tài sản này. Bất cứ ai có thể giúp tôi hiểu những gì đang xảy ra và tại sao thiết lập tài sản này là bắt buộc?

CẬP NHẬT: Vì vậy, tôi đã nghiên cứu thêm một chút về sự khác biệt trong phản hồi khi đi qua proxy so với không. Cho dù tôi đặt rõ ràng thuộc tính TransferEncodingChunked thành false, tiêu đề phản hồi khi đến thông qua proxy cũng giống như khi không thông qua proxy. Tuy nhiên, nội dung phản hồi là khác nhau. Dưới đây là một số mẫu (tôi đã tắt mã hóa gzip):

// With TransferEncodingChunked = false 
2d\r\n 
This was sent with transfer-encoding: chunked\r\n 
0\r\n 

// Without explicitly setting TransferEncodingChunked 
This was sent with transfer-encoding: chunked 

Rõ ràng, nội dung được gửi với TransferEncodingChọn được đặt thành sai được chuyển thực tế được mã hóa. Đây thực sự là câu trả lời chính xác vì nó được nhận từ tài nguyên được yêu cầu phía sau proxy. Điều gì tiếp tục là lạ là kịch bản thứ hai trong đó tôi không rõ ràng đặt TransferEncodingChunked trên phản hồi (nhưng nó nằm trong tiêu đề phản hồi nhận được từ dịch vụ proxy). Rõ ràng, trong trường hợp này, phản ứng KHÔNG thực sự được chuyển mã hóa bởi IIS, mặc dù thực tế là đáp ứng thực tế là. Lạ ... điều này đang bắt đầu cảm thấy như hành vi thiết kế (trong trường hợp đó, tôi rất muốn biết làm thế nào/tại sao) hoặc một lỗi trong IIS, ASP.Net, hoặc Web API.

Đây là một phiên bản đơn giản của mã Tôi đang chạy:

Proxy Web ứng dụng API:

// WebApiConfig.cs 
config.Routes.MapHttpRoute(
    name: "Proxy", 
    routeTemplate: "{*path}", 
    handler: HttpClientFactory.CreatePipeline(
     innerHandler: new HttpClientHandler(), // Routes the request to an external resource 
     handlers: new DelegatingHandler[] { new ProxyHandler() } 
    ), 
    defaults: new { path = RouteParameter.Optional }, 
    constraints: null 
); 

// ProxyHandler.cs 
public class ProxyHandler : DelegatingHandler 
{ 
    protected override async System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) 
    { 
     // Route the request to my web application 
     var uri = new Uri("http://localhost:49591" + request.RequestUri.PathAndQuery); 
     request.RequestUri = uri; 

     // For GET requests, somewhere upstream, Web API creates an empty stream for the request.Content property 
     // HttpClientHandler doesn't like this for GET requests, so set it back to null before sending along the request 
     if (request.Method == HttpMethod.Get) 
     { 
      request.Content = null; 
     } 

     var response = await base.SendAsync(request, cancellationToken); 

     // If I comment this out, any response that already has the Transfer-Encoding: chunked header will hang in the browser 
     response.Headers.TransferEncodingChunked = false; 

     return response; 
    } 
} 

Và điều khiển ứng dụng web của tôi mà tạo ra một "chửi rủa" phản ứng (cũng Web API):

public class ChunkedController : ApiController 
{ 
    public HttpResponseMessage Get() 
    { 
     var response = Request.CreateResponse(HttpStatusCode.OK); 

     var content = "This was sent with transfer-encoding: chunked"; 
     var bytes = System.Text.Encoding.ASCII.GetBytes(content); 
     var stream = new MemoryStream(bytes); 

     response.Content = new ChunkedStreamContent(stream); 

     return response; 
    } 
} 

public class ChunkedStreamContent : StreamContent 
{ 
    public ChunkedStreamContent(Stream stream) 
     : base(stream) { } 

    protected override bool TryComputeLength(out long length) 
    { 
     length = 0L; 
     return false; 
    } 
} 
+0

tiêu đề trông giống như thế nào trên yêu cầu gửi đi (proxy) khi nó bị treo? so sánh cái này với cái được bỏ qua. – wal

Trả lời

6

Từ quan điểm của HttpClient, việc sắp xếp nội dung thực chất là chi tiết của việc vận chuyển. Nội dung được cung cấp bởi response.Content luôn được de-chunked cho bạn bởi HttpClient.

Dường như có một lỗi trong API Web mà nó không chính xác (lại) nội dung khi được yêu cầu bởi response.Headers.TransferEncodingChunked tài sản khi chạy trên IIS. Vì vậy, vấn đề là proxy đang nói cho khách hàng, thông qua các tiêu đề, rằng nội dung được chunked khi trong thực tế nó không phải là. Tôi đã gửi lỗi ở đây: https://aspnetwebstack.codeplex.com/workitem/1124

Tôi nghĩ rằng giải pháp thay thế của bạn là tùy chọn tốt nhất hiện tại.

Cũng lưu ý rằng bạn có nhiều lớp ở đây có khả năng không được thiết kế/thử nghiệm cho các kịch bản proxy (và có thể không hỗ trợ nó).Về phía HttpClient, lưu ý rằng nó sẽ tự động giải nén và làm theo các chuyển hướng trừ khi bạn tắt hành vi đó. Ở mức tối thiểu, bạn sẽ muốn thiết lập hai thuộc tính sau đây: http://msdn.microsoft.com/en-us/library/system.net.http.httpclienthandler.allowautoredirect.aspx http://msdn.microsoft.com/en-us/library/system.net.http.httpclienthandler.automaticdecompression.aspx

Về phía WebAPI/IIS, bạn đã tìm thấy ít nhất một lỗi, và nó sẽ không được ngạc nhiên khi tìm thấy những người khác cũng . Chỉ cần được cảnh báo trước có thể có lỗi như thế này hiện đang viết một proxy bằng cách sử dụng các công nghệ này bên ngoài các trường hợp sử dụng thiết kế chính của họ.

+0

Cảm ơn bạn đã trả lời chi tiết và báo cáo lỗi. Cũng nhờ những lời cảnh cáo về cách tiếp cận của chúng tôi. Chúng tôi đã nhận thấy sự cố với thuộc tính AllowAutoRedirect. Đã không nghĩ về tài sản AutomaticDecompression và sẽ nhìn vào đó. Cảm ơn! –

Các vấn đề liên quan