Chuyển mã hóa: gzip so với Mã hóa nội dung: gzip


98

Tình trạng hiện tại của công việc là gì khi nói đến việc có nên làm

Transfer-Encoding: gzip

hoặc một

Content-Encoding: gzip

khi tôi muốn cho phép các máy khách có băng thông hạn chế, ví dụ như báo hiệu họ sẵn sàng chấp nhận phản hồi đã nénmáy chủ có quyền quyết định cuối cùng có nén hay không .

Sau đó là những gì ví dụ như mod_deflate và IIS của Apache làm, nếu bạn để nó chăm sóc nén. Tùy thuộc vào kích thước của nội dung được nén, nó sẽ thực hiện bổ sung Transfer-Encoding: chunked.

Nó cũng sẽ bao gồm một Vary: Accept-Encoding, đã gợi ý về vấn đề. Content-Encodingdường như là một phần của thực thể, vì vậy việc thay đổi Content-Encodingsố lượng đối với một sự thay đổi của thực thể, tức là một Accept-Encodingtiêu đề khác có nghĩa là bộ đệm ẩn không thể sử dụng phiên bản đã lưu trong bộ đệm của thực thể giống hệt.

Có câu trả lời chắc chắn nào về điều này mà tôi đã bỏ qua (và điều đó không bị chôn vùi trong một tin nhắn trong một chuỗi dài trong một nhóm tin apache nào đó) không?

Ấn tượng hiện tại của tôi là:

  • Chuyển-Mã hoá thực tế sẽ là cách phù hợp để thực hiện những gì chủ yếu được thực hiện với Mã hoá Nội dung bằng các ứng dụng máy chủ và máy khách hiện có
  • Mã hóa nội dung, vì hàm ý ngữ nghĩa của nó, mang một số vấn đề (máy chủ nên làm gì ETagkhi nó nén phản hồi một cách minh bạch?)
  • Lý do là Chicken'n'egg: Trình duyệt không hỗ trợ nó vì máy chủ không hỗ trợ vì trình duyệt không

Vì vậy, tôi giả định cách đúng sẽ là một Transfer-Encoding: gzip(hoặc, nếu tôi bổ sung thêm phần cơ thể, nó sẽ trở thành Transfer-Encoding: gzip, chunked ). Và không có lý do gì để chạm vào Varyhoặc ETagbất kỳ tiêu đề nào khác trong trường hợp đó vì nó là một thứ cấp độ vận chuyển.

Hiện tại, tôi không quan tâm quá nhiều đến 'hop-by-hop'-ness Transfer-Encoding, điều mà những người khác dường như quan tâm đầu tiên và quan trọng nhất, bởi vì proxy có thể giải nén và chuyển tiếp không nén đến máy khách. Tuy nhiên, proxy cũng có thể chuyển tiếp nó như hiện tại (được nén), nếu yêu cầu ban đầu có Accept-Encodingtiêu đề phù hợp , trong trường hợp tất cả các trình duyệt mà tôi biết đều là tiêu đề nhất định.

Btw, vấn đề này đã tồn tại ít nhất một thập kỷ, hãy xem ví dụ: https://bugzilla.mozilla.org/show_bug.cgi?id=68517 .

Bất kỳ làm rõ về điều này sẽ được đánh giá cao. Cả về những gì được coi là tuân thủ tiêu chuẩn và những gì được coi là thực tế. Ví dụ: các thư viện máy khách HTTP chỉ hỗ trợ "Mã hóa nội dung" minh bạch sẽ là một đối số chống lại tính thực tế.



Chỉ cần chạy vào điều này. Curl trên PHP 5.3 không hiểu Transfer-Encoding:gzip, mặc dù dòng lệnh curl có. Để an toàn, hãy gửi cả hai, trừ khi bạn đang kết hợp chunked và gzip.
Seva Alekseyev

1
@SevaAlekseyev gửi cả hai sẽ rất sai - khách hàng có thể cố gắng để giải nén hai lần
Joshua khôn ngoan

Đây cũng là điều khiến tôi nhớ mãi không quên ( câu hỏi tôi đã hỏi )… mỗi một trong những câu trả lời cho câu hỏi mà @JoLiss đã trích dẫn, có một cách hoàn toàn hợp lý, mạch lạc về mặt ngữ nghĩa và tuân thủ các tiêu chuẩn để nén các nội dung yêu cầu / phản hồi… và về cơ bản không có máy khách / máy chủ nào sử dụng hoặc hỗ trợ nó. 🤦🏻‍
Dan Lenski

Câu trả lời:


35

Trích dẫn Roy T. Fielding , một trong những tác giả của RFC 2616:

việc thay đổi mã hóa nội dung nhanh chóng theo cách không nhất quán (không phải "không bao giờ" cũng không phải "luôn luôn) khiến các yêu cầu sau này liên quan đến nội dung đó (ví dụ: PUT hoặc GET có điều kiện) không thể được xử lý chính xác. Tất nhiên, đây là lý do tại sao thực hiện mã hóa nội dung nhanh chóng là một ý tưởng ngu ngốc và tại sao tôi lại thêm Mã hóa truyền vào HTTP như một cách thích hợp để thực hiện mã hóa nhanh mà không thay đổi tài nguyên.

Nguồn: https://issues.apache.org/bugzilla/show_bug.cgi?id=39727#c31

Nói cách khác: Đừng làm on-the-fly Content-Encoding, sử dụng Transfer-Encoding thay!

Chỉnh sửa: Nghĩa là, trừ khi bạn muốn cung cấp nội dung được nén cho các khách hàng chỉ hiểu Mã hóa nội dung . Mà, thật không may, dường như là hầu hết trong số họ. Nhưng hãy lưu ý rằng bạn rời khỏi lĩnh vực của thông số kỹ thuật và có thể gặp phải các vấn đề như vấn đề được đề cập bởi Fielding cũng như những người khác, ví dụ như khi proxy bộ nhớ đệm có liên quan.


3
Vì vậy, nếu tôi hiểu đúng: 1. Mã hóa nội dung đề cập đến mã hóa nội dung trên máy chủ trong phần tóm tắt, tức là nội dung sẽ được máy chủ phân phối nhất quán trong mã hóa được chỉ định. 2. Chuyển mã hóa đề cập đến mã hóa mà máy chủ quyết định sử dụng để cung cấp nó cho tác nhân người dùng trong trường hợp này, tức là trong phản hồi này. Chỉ cần đảm bảo rằng tôi không hiểu sai câu trả lời của bạn.
dot slash hack vào

30
@KemHeyndels Về quyền. Nói cách khác: Theo thông số kỹ thuật, Transfer-Encoding là một tinh khiết lớp truyền tải chi tiết , tức là một proxy trung gian là miễn phí để lùi lại ví dụ gzip nén ở mức độ đó, trong khi Content-Encoding là một lớp kinh doanh bất động sản , trong đó một proxy sẽ không được được phép thay đổi, ngoài các phân nhánh khác (ETags, v.v.). Tuy nhiên, theo thực tế , TE thường không được sử dụng để nén và nhiều máy chủ / máy khách thậm chí không hỗ trợ nó ngay lập tức, trong khi CE được sử dụng ít nhiều theo cách TE dự định được sử dụng : như một chi tiết lớp truyền tải .
Eugene Beresovsky

1
Vì vậy, chúng ta buộc phải bỏ qua lời khuyên của Roy T. Fielding?
dot slash hack vào

11
@KemHeyndels Theo chủ nghĩa lý tưởng, bạn có nghĩa vụ phải ra ngoài và đầu tiên thêm hỗ trợ TE vào tất cả các triển khai máy khách / máy chủ HTTP mã nguồn mở. Sau đó, hãy tự nhận mình làm việc tại mọi công ty có triển khai HTTP mã nguồn đóng (dù sao tôi nghĩ đó chỉ là Microsoft) và thêm cả tính năng vào đó. Sau đó, thực tế và thông số kỹ thuật sẽ trùng khớp. ;) (Và HTTP 2.0 sẽ được phát hành, dù sao thì vấn đề cũng sẽ biến mất)
Eugene Beresovsky

10
Việc chỉ ra rằng bạn hỗ trợ Mã hóa chuyển giao vẫn không thể hiện rõ rằng bạn hỗ trợ gzip qua Mã hóa chuyển giao, vì vậy điều đó không mang lại lợi ích gì cho bạn. Chỉ báo được thực hiện theo cách khác : Bất kỳ máy khách nào có thể thực hiện gzip thông qua Chuyển mã hóa sẽ cho máy chủ biết bằng cách cài đặt TE: gzip. Và sau đó máy chủ của bạn sẽ đi theo lộ trình Mã hóa Truyền. Nếu khách hàng chỉ nói Accept-Encoding: gzip, bạn phải làm Content-Encodingtheo cách đó. Nếu máy khách không chỉ định trong yêu cầu của nó, máy chủ hoàn toàn không được gzip.
Eugene Beresovsky

27

Cách sử dụng chính xác , như được định nghĩa trong RFC 2616 và thực sự được triển khai trong tự nhiên, là để máy khách gửi Accept-Encodingtiêu đề yêu cầu (máy khách có thể chỉ định nhiều mã hóa). Sau đó, máy chủ có thể và chỉ sau đó, mã hóa phản hồi theo các mã hóa được hỗ trợ của máy khách (nếu dữ liệu tệp chưa được lưu trữ trong mã hóa đó), chỉ ra trong Content-Encodingtiêu đề phản hồi mã hóa nào đang được sử dụng. Sau đó máy khách có thể đọc dữ liệu ra khỏi socket dựa trên Transfer-Encoding(tức là, chunked) và sau đó giải mã nó dựa trên Content-Encoding(tức là gzip:).

Vì vậy, trong trường hợp của bạn, máy khách sẽ gửi một Accept-Encoding: gziptiêu đề yêu cầu và sau đó máy chủ có thể quyết định nén (nếu chưa có) và gửi một tiêu đề phản hồi Content-Encoding: gzipvà tùy chọn Transfer-Encoding: chunked.

Và có, Transfer-Encodingtiêu đề có thể được sử dụng trong các yêu cầu, nhưng chỉ cho HTTP 1.1, yêu cầu rằng cả triển khai máy khách và máy chủ đều hỗ trợ chunkedmã hóa theo cả hai hướng.

ETagxác định duy nhất dữ liệu tài nguyên trên máy chủ, không phải dữ liệu thực sự đang được truyền. Nếu một tài nguyên URL nhất định thay đổi ETaggiá trị của nó , điều đó có nghĩa là dữ liệu phía máy chủ cho tài nguyên đó đã thay đổi.


14
mã hóa nội dung là một đặc điểm của thực thể được xác định bởi URI Yêu cầu Nói cách khác: Khác nhau Content-Encodingyêu cầu khác nhauETag Đây là btw lỗi mod_deflate mà tôi đề cập đến trong câu trả lời của mình. Khiến tôi tự hỏi tại sao chi tiết cấp ứng dụng này lại nằm trong tiêu chuẩn HTTP ngay từ đầu. Transfer-EncodingTuy nhiên, khi sử dụng cài đặt mức vận chuyển, không cần phải thay đổi ETag. Ngoại trừ không ai đã triển khai Transfer-Enc.
Eugene Beresovsky

2
Mã hóa nội dung không dành cho mã hóa "đang bay". RFC 2616 cho biết "Mã hóa truyền ... khác với mã hóa nội dung ở chỗ mã hóa truyền là thuộc tính của thông báo, không phải của thực thể." ( Tools.ietf.org/html/rfc2616#section-14.41 ) và "Mã hóa nội dung là một đặc điểm của thực thể được xác định bởi URI yêu cầu. Thông thường, phần thân thực thể được lưu trữ bằng mã hóa này" ( tools.ietf.org/html/rfc2616#section-14.11 ). Vì vậy, tôi bỏ phiếu xuống.
Robert

Những gì tôi mô tả là những gì là " thực sự thực hiện trong môi trường tự nhiên ", bất kể Content-Encodingvs Transfer-Encoding. Đúng, gzip phải là một thuộc tính của việc chuyển tài nguyên, nếu được thực hiện một cách nhanh chóng. Mặt khác, nếu tài nguyên được lưu trữ nén trên máy chủ, thay vào đó nó phải là một thuộc tính của nội dung tài nguyên, nếu được gửi nguyên trạng. Nhưng những gì nên có và những gì thực sự không phải lúc nào cũng giống nhau.
Remy Lebeau
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.