Transfer-Encoding: gzip เทียบกับ Content-Encoding: gzip


102

สถานการณ์ปัจจุบันเป็นอย่างไรเมื่อต้องทำ

Transfer-Encoding: gzip

หรือก

Content-Encoding: gzip

เมื่อฉันต้องการที่จะช่วยให้ลูกค้าด้วยเช่นแบนด์วิดธ์ที่ จำกัด ในการส่งสัญญาณของพวกเขาเต็มใจที่จะยอมรับการตอบสนองที่ถูกบีบอัดและเซิร์ฟเวอร์มีสุดท้ายกล่าวหรือไม่ที่จะบีบอัด

อย่างหลังคือสิ่งที่เช่น mod_deflate ของ Apache และ IIS ทำถ้าคุณปล่อยให้มันดูแลการบีบอัด Transfer-Encoding: chunkedขึ้นอยู่กับขนาดของเนื้อหาที่ถูกบีบอัดก็จะทำเพิ่มเติม

นอกจากนี้ยังรวมถึง a Vary: Accept-Encodingซึ่งบอกใบ้ถึงปัญหาแล้ว Content-Encodingดูเหมือนว่าจะเป็นส่วนหนึ่งของเอนทิตีดังนั้นการเปลี่ยนContent-Encodingจำนวนเงินเป็นการเปลี่ยนแปลงของเอนทิตีกล่าวคือAccept-Encodingส่วนหัวที่แตกต่างกันเช่นแคชไม่สามารถใช้เอนทิตีที่เหมือนกันในเวอร์ชันแคช

มีคำตอบที่ชัดเจนเกี่ยวกับสิ่งนี้หรือไม่ที่ฉันพลาดไป (และไม่ได้ฝังอยู่ในข้อความในเธรดยาว ๆ ในกลุ่มข่าว apache บางกลุ่ม)

ความประทับใจในปัจจุบันของฉันคือ:

  • ในความเป็นจริงแล้วการโอนการเข้ารหัสเป็นวิธีที่ถูกต้องในการทำสิ่งที่ส่วนใหญ่ทำกับการเข้ารหัสเนื้อหาโดยการใช้เซิร์ฟเวอร์และไคลเอ็นต์ที่มีอยู่
  • การเข้ารหัสเนื้อหาเนื่องจากผลกระทบทางความหมายทำให้เกิดปัญหาสองสามประการ (เซิร์ฟเวอร์ควรทำอย่างไรETagเมื่อบีบอัดการตอบกลับอย่างโปร่งใส)
  • เหตุผลก็คือ chicken'n'egg: เบราว์เซอร์ไม่รองรับเนื่องจากเซิร์ฟเวอร์ไม่รองรับเนื่องจากเบราว์เซอร์ไม่รองรับ

ดังนั้นฉันคิดว่าวิธีที่ถูกต้องน่าจะเป็นTransfer-Encoding: gzip(หรือถ้าฉันรวมร่างเป็นก้อนมากขึ้นมันก็จะกลายเป็น Transfer-Encoding: gzip, chunked ) และไม่มีเหตุผลที่จะแตะต้องVaryหรือETagหรือส่วนหัวอื่นใดในกรณีนั้นเนื่องจากเป็นสิ่งที่มีระดับการขนส่ง

สำหรับตอนนี้ฉันไม่สนใจมากเกินไปเกี่ยวกับ 'hop-by-hop'-ness ของTransfer-Encodingสิ่งที่คนอื่นดูเหมือนจะกังวลเป็นอันดับแรกและสำคัญที่สุดเพราะพร็อกซีอาจคลายการบีบอัดและส่งต่อโดยไม่บีบอัดไปยังไคลเอนต์ อย่างไรก็ตามพร็อกซีอาจส่งต่อตามที่เป็นอยู่ (บีบอัด) ได้เช่นกันหากคำขอเดิมมีAccept-Encodingส่วนหัวที่เหมาะสมซึ่งในกรณีของเบราว์เซอร์ทั้งหมดที่ฉันรู้ว่าเป็นที่กำหนด

Btw ปัญหานี้เป็นอย่างน้อยในทศวรรษที่เก่าเห็นเช่น https://bugzilla.mozilla.org/show_bug.cgi?id=68517

คำชี้แจงใด ๆ เกี่ยวกับเรื่องนี้จะได้รับการชื่นชม ทั้งในแง่ของสิ่งที่ถือว่าเป็นไปตามมาตรฐานและสิ่งที่ถือว่าใช้ได้จริง ตัวอย่างเช่นไลบรารีไคลเอ็นต์ HTTP สนับสนุนเฉพาะ "การเข้ารหัสเนื้อหา" แบบโปร่งใสเท่านั้นที่จะเป็นข้อโต้แย้งในการปฏิบัติจริง


2
ที่เกี่ยวข้อง: stackapps.com/questions/916/…
Jo Liss

เพิ่งวิ่งเข้าไปในนี้ Curl บน PHP 5.3 ไม่เข้าใจTransfer-Encoding:gzipแม้ว่าบรรทัดคำสั่ง curl จะทำก็ตาม หากต้องการอยู่ในด้านที่ปลอดภัยให้ส่งทั้งสองอย่างเว้นแต่คุณจะรวมกลุ่มและ gzip เข้าด้วยกัน
Seva Alekseyev

1
@SevaAlekseyev การส่งทั้งสองจะผิดมาก - ลูกค้าอาจพยายามคลายการบีบอัดสองครั้ง
Joshua Wise

นี่เป็นสิ่งที่รบกวนฉันตลอดไปเช่นกัน ( คำถามที่ฉันถาม ) ... ต่อหนึ่งในคำตอบของคำถามที่ @JoLiss อ้างถึงมีตรรกะที่สมบูรณ์แบบสอดคล้องกันทางความหมายและเป็นไปตามมาตรฐานในการบีบอัดเนื้อหาคำขอ / การตอบสนอง ... และโดยพื้นฐานแล้ว ไม่มีไคลเอนต์ / เซิร์ฟเวอร์ใช้หรือสนับสนุน 🤦🏻‍
Dan Lenski

คำตอบ:


35

อ้างถึงRoy T. Fieldingหนึ่งในผู้เขียน RFC 2616:

การเปลี่ยนการเข้ารหัสเนื้อหาในทันทีในลักษณะที่ไม่สอดคล้องกัน (ไม่ว่าจะ "ไม่" หรือ "เสมอไป) ทำให้คำขอในภายหลังเกี่ยวกับเนื้อหานั้น (เช่น PUT หรือ GET ตามเงื่อนไข) ไม่สามารถจัดการได้อย่างถูกต้องแน่นอนว่าเหตุใดจึงต้องดำเนินการ การเข้ารหัสเนื้อหาแบบ on-the-fly เป็นความคิดที่โง่และทำไมฉันจึงเพิ่ม Transfer-Encoding ไปยัง HTTP เป็นวิธีที่เหมาะสมในการเข้ารหัสแบบ on-the-fly โดยไม่ต้องเปลี่ยนทรัพยากร

ที่มา: https://issues.apache.org/bugzilla/show_bug.cgi?id=39727#c31

กล่าวอีกนัยหนึ่ง: อย่าทำการเข้ารหัสเนื้อหาในทันทีให้ใช้ Transfer-Encoding แทน!

แก้ไข:นั่นคือถ้าคุณต้องการที่จะให้บริการเนื้อหา gzipped ให้กับลูกค้าที่เข้าใจเฉพาะเนื้อหาการเข้ารหัส ซึ่งน่าเสียดายที่ดูเหมือนจะเป็นส่วนใหญ่ แต่โปรดทราบว่าคุณออกจากขอบเขตของข้อมูลจำเพาะและอาจประสบปัญหาเช่นที่กล่าวถึงโดย Fielding เช่นเดียวกับอื่น ๆ เช่นเมื่อเกี่ยวข้องกับการแคชพร็อกซี


3
ดังนั้นถ้าฉันทำให้ถูกต้อง: 1. การเข้ารหัสเนื้อหาหมายถึงการเข้ารหัสเนื้อหาบนเซิร์ฟเวอร์ในบทคัดย่อกล่าวคือเนื้อหาจะแสดงในการเข้ารหัสที่ระบุโดยเซิร์ฟเวอร์อย่างสม่ำเสมอ 2. Transfer-encoding หมายถึงการเข้ารหัสที่เซิร์ฟเวอร์ตัดสินใจใช้เพื่อส่งมอบให้กับตัวแทนผู้ใช้ในอินสแตนซ์นี้เช่นในการตอบกลับนี้ แค่ทำให้แน่ใจว่าฉันไม่ได้ตีความคำตอบของคุณผิด
dot slash hack

32
@KemHeyndels เกี่ยวกับขวา อีกวิธีหนึ่ง: ตามข้อกำหนด Transfer-Encoding เป็นรายละเอียดชั้นการขนส่งที่บริสุทธิ์กล่าวคือพร็อกซีระดับกลางสามารถยกเลิกได้ฟรีเช่นการบีบอัด gzip ที่ระดับนั้นในขณะที่การเข้ารหัสเนื้อหาเป็นคุณสมบัติของชั้นธุรกิจซึ่งพร็อกซีจะไม่เป็น ได้รับอนุญาตให้เปลี่ยนแปลงนอกเหนือจากการแบ่งส่วนอื่น ๆ (ETags ฯลฯ ) อย่างไรก็ตามตามความเป็นจริงแล้ว TE ไม่ได้ใช้สำหรับการบีบอัดโดยปกติและเซิร์ฟเวอร์ / ไคลเอนต์จำนวนมากไม่สนับสนุนมันนอกกรอบในขณะที่CE ใช้วิธีที่ TE ตั้งใจจะใช้มากหรือน้อย : เป็นรายละเอียดเลเยอร์การขนส่ง .
Evgeniy Berezovsky

1
ดังนั้นเราจำเป็นต้องเพิกเฉยต่อคำแนะนำของ Roy T. Fielding?
dot slash hack

11
@KemHeyndels คุณมีหน้าที่ตามอุดมคติที่จะออกไปข้างนอกและก่อนอื่นให้เพิ่มการสนับสนุน TE สำหรับการใช้งานไคลเอ็นต์ / เซิร์ฟเวอร์ HTTP แบบโอเพนซอร์ส จากนั้นรับตัวคุณเองในทุก บริษัท ที่มีการใช้งาน HTTP แบบปิด (ฉันคิดว่านั่นคือ Microsoft เท่านั้น) และเพิ่มคุณสมบัติที่นั่นด้วย หลังจากนั้นความเป็นจริงและข้อมูลจำเพาะจะตรงกัน ;) (และ HTTP 2.0 จะได้รับการเผยแพร่ทำให้ปัญหานี้หายไป)
Evgeniy Berezovsky

10
การระบุว่าคุณรองรับ Transfer-Encoding ยังไม่ชัดเจนว่าคุณรองรับ gzip ผ่าน Transfer-Encoding ดังนั้นจึงไม่ได้ซื้ออะไรให้คุณ ตัวบ่งชี้ที่จะทำวิธีอื่น ๆ : ลูกค้าใด ๆ ที่สามารถทำ gzip ผ่าน TE: gzipTransfer-การเข้ารหัสจะช่วยให้รู้เซิร์ฟเวอร์โดยการตั้งค่า จากนั้นเซิร์ฟเวอร์ของคุณควรไปที่เส้นทาง Transfer-Encoding ถ้าลูกค้าบอกAccept-Encoding: gzipคุณต้องทำContent-Encodingอย่างนั้น หากไคลเอนต์ไม่ระบุในคำขอเซิร์ฟเวอร์จะต้องไม่ gzip เลย
Evgeniy Berezovsky

28

การใช้งานที่ถูกต้องตามที่กำหนดไว้ใน RFC 2616 และนำไปใช้จริงในไวลด์คือสำหรับไคลเอ็นต์ในการส่งAccept-Encodingส่วนหัวของคำขอ (ไคลเอ็นต์อาจระบุการเข้ารหัสหลายรายการ) จากนั้นเซิร์ฟเวอร์อาจเข้ารหัสการตอบสนองตามการเข้ารหัสที่ไคลเอ็นต์รองรับ (หากข้อมูลไฟล์ไม่ได้ถูกเก็บไว้ในการเข้ารหัสนั้น) ระบุในContent-Encodingส่วนหัวของการตอบกลับว่ากำลังใช้การเข้ารหัสใด ลูกค้าก็จะสามารถอ่านข้อมูลออกจากซ็อกเก็ตขึ้นอยู่กับTransfer-Encoding(เช่นchunked) แล้วถอดรหัสได้ขึ้นอยู่กับContent-Encoding(เช่น: gzip)

ดังนั้นในกรณีของคุณไคลเอนต์จะส่งAccept-Encoding: gzipส่วนหัวของคำขอจากนั้นเซิร์ฟเวอร์อาจตัดสินใจบีบอัด (หากยังไม่มี) และส่งส่วนหัวการตอบกลับContent-Encoding: gzipและเป็นทางเลือกTransfer-Encoding: chunked

และใช่Transfer-Encodingส่วนหัวสามารถใช้ในคำขอได้ แต่สำหรับ HTTP 1.1 เท่านั้นซึ่งกำหนดให้การใช้งานไคลเอ็นต์และเซิร์ฟเวอร์รองรับการchunkedเข้ารหัสทั้งสองทิศทาง

ETagระบุข้อมูลทรัพยากรบนเซิร์ฟเวอร์โดยไม่ซ้ำกันไม่ใช่ข้อมูลที่กำลังส่งจริงๆ หากรีซอร์ส URL ที่ระบุเปลี่ยนETagค่าหมายความว่าข้อมูลฝั่งเซิร์ฟเวอร์สำหรับรีซอร์สนั้นมีการเปลี่ยนแปลง


14
การเข้ารหัสเนื้อหาเป็นลักษณะเฉพาะของเอนทิตีที่ระบุโดย Request-URIกล่าวอีกนัยหนึ่งคือความแตกต่างContent-Encodingต้องการความแตกต่างETagนี่คือ btw ข้อบกพร่องของ mod_deflate ที่ฉันอ้างถึงในคำตอบของฉันนั้นเกี่ยวกับอะไร ทำให้ฉันสงสัยว่าทำไมรายละเอียดระดับแอปพลิเคชันนี้จึงอยู่ในมาตรฐาน HTTP ตั้งแต่แรก Transfer-Encodingอย่างไรก็ตามเมื่อใช้การตั้งค่าระดับการขนส่งไม่จำเป็นต้องเปลี่ยนไฟล์ETag. ยกเว้นไม่มีใครใช้ Transfer-Enc
Evgeniy Berezovsky

2
การเข้ารหัสเนื้อหาไม่ได้มีไว้สำหรับการเข้ารหัสแบบ "ทันที" RFC 2616 กล่าวว่า "การเข้ารหัสการถ่ายโอน ... แตกต่างจากการเข้ารหัสเนื้อหาตรงที่การเข้ารหัสการถ่ายโอนเป็นคุณสมบัติของข้อความไม่ใช่ของเอนทิตี" ( tools.ietf.org/html/rfc2616#section-14.41 ) และ "การเข้ารหัสเนื้อหาเป็นลักษณะเฉพาะของเอนทิตีที่ระบุโดย Request-URI โดยปกติเอนทิตี - บอดี้จะถูกจัดเก็บด้วยการเข้ารหัสนี้" ( tools.ietf.org/html/rfc2616#section-14.11 ) ดังนั้นฉันจึงลงคะแนน
Robert

สิ่งที่ผมอธิบายคือสิ่งที่เป็น " การใช้งานจริงในป่า " โดยไม่คำนึงถึงVSContent-Encoding Transfer-Encodingใช่ gzip ควรเป็นคุณสมบัติของการถ่ายโอนทรัพยากรหากดำเนินการได้ทันที ในทางกลับกันหากรีซอร์สถูกบีบอัดไว้บนเซิร์ฟเวอร์ทรัพยากรนั้นควรเป็นคุณสมบัติของเนื้อหาของรีซอร์สแทนหากส่งตามที่เป็นอยู่ แต่สิ่งที่ควรจะเป็นและสิ่งที่เป็นจริงไม่ใช่สิ่งเดียวกันเสมอไป
Remy Lebeau
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.