こんにちは。
先日、仕事でハマったのでContent-LengthとTransfer-Encodingについて調べてみました。

Content-LengthとTransfer-Encodingとは

Content-Length と Transfer-Encoding は、HTTP プロトコルで使用されるヘッダーで、サーバーがクライアントにデータを送信する際の情報を提供します。

Content-Length

Content-Lengthは、レスポンスやリクエストのボディのサイズをバイト単位で指定します。
このContent-Lengthを使用することで、クライアントやサーバーは受信するデータの長さを事前に知ることができ、データの終わりを検知することができます。

例:
Content-Length: 256

この場合は、メッセージボディが 256 バイトであることを示しています。

Transfer-Encoding

Transfer-Encodingは、データ転送の方法を指定します。一般的に使われる値は chunked (チャンク転送)です。
チャンク転送を使用することで、Content-Lengthを指定せずにデータを分割して送信することが可能となります。
サーバーが一度にデータ全体のサイズを計算できない場合など、Content-Length の代わりに使用されます。チャンク転送を使うと、データはチャンクと呼ばれるデータの塊に分けられて送信されます。
これにより、クライアント側はデータをリアルタイムで処理することが可能になります。

例:
Transfer-Encoding: chunked

この場合、クライアントは各チャンクのサイズを読み取ってデータを受信し、ゼロバイトのチャンクを検知したタイミングでメッセージの終了を判定します。
※この記事では詳しくは書きませんが、この仕様を悪用する攻撃手法としてHTTP Request Smuggling(スマグリング)がある。

まとめ

Content-Length はデータの長さをバイト単位で指定するヘッダーで、送信データのサイズが事前にわかっている場合に使います。一方、Transfer-Encoding はデータ転送の方法を示し、特に chunked を使うとデータを分割して送信できるため、サイズが事前にわからない場合に使われます。
凄く基本的な内容になりますが、調べてみたらチャンク転送の仕様など普段はあまり気にしないところでの学びがありました。
特にチャンク転送は画面と内部のAPIで全く別のフレームワークを使用していたりするとパースに失敗することがあったりするので、押さえておいて損はない知識だと思います。