2015-02-26 12 views
5

Chúng tôi đang cố gắng triển khai nén gzip tùy chọn do người dùng xác định (trên màn hình cài đặt) trong ứng dụng khách của chúng tôi sử dụng HttpClient, vì vậy chúng tôi có thể ghi nhật ký và so sánh hiệu suất trên một số cuộc gọi khác nhau khoảng thời gian. Nỗ lực đầu tiên của chúng tôi là chỉ đơn giản là có điều kiện thêm tiêu đề như sau:HttpClient: Điều kiện thiết lập nén AcceptEncoding khi chạy

HttpRequestMessage request = new HttpRequestMessage(Method, Uri); 
if (AcceptGzipEncoding) 
{ 
    _client.DefaultRequestHeaders.AcceptEncoding.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("gzip")); 
} 

//Send to the server 
result = await _client.SendAsync(request); 

//Read the content of the result response from the server 
content = await result.Content.ReadAsStringAsync(); 

này tạo ra các yêu cầu chính xác, nhưng câu trả lời đã giải nén không được giải nén vào trở lại, dẫn đến một phản ứng bị cắt xén. Tôi thấy rằng chúng tôi phải bao gồm các HttpClientHandler khi xây dựng các HttpClient:

HttpClient _client = new HttpClient(new HttpClientHandler 
    { 
     AutomaticDecompression = DecompressionMethods.GZip 
    }); 

bài này hoạt động tốt, nhưng chúng tôi muốn thay đổi cho dù khách hàng sẽ gửi Accept-Encoding: gzip tiêu đề khi chạy, và không làm dường như là bất kỳ cách nào để truy cập hoặc thay đổi HttpClientHandler sau khi nó được chuyển đến hàm tạo HttpClient. Ngoài ra, việc thay đổi tiêu đề của đối tượng HttpRequestMessage không có bất kỳ ảnh hưởng nào đối với tiêu đề của yêu cầu nếu chúng được xác định bởi HttpClientHandler.

Có cách nào để thực hiện việc này mà không cần tạo lại HttpClient mỗi lần thay đổi này không?

Chỉnh sửa: Tôi cũng đã cố gắng để thay đổi một tham chiếu đến HttpClientHandler thay đổi AutomaticDecompression lúc chạy, nhưng đó là ném ngoại lệ này:

dụ này đã bắt đầu một hoặc nhiều yêu cầu. Chỉ có thể sửa đổi các thuộc tính trước khi gửi yêu cầu đầu tiên.

+0

Chỉ cần tò mò, bây giờ mà bạn đã nhìn thấy cách tiện dụng tự động giải nén là, tại sao * không * tái tạo cho khách hàng mỗi thời gian mà cài đặt thay đổi? Đó là chính xác những gì tôi muốn làm ở đây, trừ khi có một lý do rất tốt không. –

+0

@ToddMenier Đó là một câu hỏi rất hợp lệ. Đó là một cái gì đó chúng tôi đang xem xét, nhưng nó sẽ đòi hỏi một chút về cơ cấu lại tôi nghĩ, bởi vì cùng HttpClient được gắn vào một số lĩnh vực. Đó là một ứng dụng có kích thước vừa phải được kế thừa từ các nhà phát triển trước đó nên chúng tôi chỉ phải quản lý các thay đổi một cách cẩn thận. Chúng tôi sẽ xem xét nó trong tuần này.Cảm ơn các ý kiến ​​và giúp đỡ. – pcdev

Trả lời

1

Theo ý kiến ​​trên, tái tạo lại HttpClient thực sự là chỉ (mạnh mẽ) cách để làm điều này. Việc giải nén thủ công có thể đạt được nhưng có vẻ rất khó xác định/hiệu quả một cách đáng tin cậy liệu nội dung đã được mã hóa hay chưa, để xác định liệu có áp dụng giải mã hay không.

7

Bạn gần như ở đó với ví dụ đầu tiên, bạn chỉ cần tự làm lệch luồng. MS của GZipSteam sẽ giúp với điều này:

HttpRequestMessage request = new HttpRequestMessage(Method, Uri); 
if (AcceptGzipEncoding) 
{ 
    _client.DefaultRequestHeaders.AcceptEncoding.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("gzip")); 
} 

//Send to the server 
result = await _client.SendAsync(request); 

//Read the content of the result response from the server 
using (Stream stream = await result.Content.ReadAsStreamAsync()) 
using (Stream decompressed = new GZipStream(stream, CompressionMode.Decompress)) 
using (StreamReader reader = new StreamReader(decompressed)) 
{ 
    content = reader.ReadToEnd(); 
} 
+1

Hmm, nó chỉ ra rằng câu trả lời này hoạt động trừ khi máy chủ quyết định không (hoặc không được cấu hình) gzip phản hồi, sau đó nó rơi xuống. Rất tiếc, không có cách nào dễ dàng để có được tiêu đề "Mã hóa nội dung" từ đối tượng HttpResponseMessage [xem bài đăng này] (https://social.msdn.microsoft.com/Forums/windowsapps/en-US/cb7417b5-ca3e-44f6 -a272-9e2f8fc5d9b8/portable-httpclient-hides-contentlength-và-contentencoding-headers-với-gzip-encoding? diễn đàn = wpdevelop), do đó, có vẻ như tái tạo HttpClient thực sự là cách duy nhất để làm điều đó. Cảm ơn một lần nữa cho đầu vào của bạn. – pcdev

2

Nếu bạn muốn sử dụng cùng HttpClient và chỉ muốn bật tính năng nén cho một số yêu cầu, bạn không thể sử dụng giải nén tự động. Khi tính năng giải nén tự động được bật, khung cũng sẽ đặt lại tiêu đề Content-Encoding của phản hồi. Điều này có nghĩa là bạn không thể tìm hiểu xem phản hồi có thực sự được nén hay không. Nhân tiện, tiêu đề Content-Length của phản hồi khớp với kích thước của nội dung giải nén nếu bạn bật tính năng giải nén tự động.

Vì vậy, bạn cần phải giải nén nội dung theo cách thủ công. Các mẫu sau đây cho thấy một thực hiện cho nội dung gzip nén (cũng như thể hiện trong @ ToddMenier của response):

private async Task<string> ReadContentAsString(HttpResponseMessage response) 
{ 
    // Check whether response is compressed 
    if (response.Content.Headers.ContentEncoding.Any(x => x == "gzip")) 
    { 
     // Decompress manually 
     using (var s = await response.Content.ReadAsStreamAsync()) 
     { 
      using (var decompressed = new GZipStream(s, CompressionMode.Decompress)) 
      { 
       using (var rdr As New IO.StreamReader(decompressed)) 
       { 
        return await rdr.ReadToEndAsync(); 
       } 
      } 
     } 
    else 
     // Use standard implementation if not compressed 
     return await response.Content.ReadAsStringAsync(); 
} 
Các vấn đề liên quan