HTTP 仕様によると、技術的に Content-Length ヘッダーを指定する必要はありません。RFC 2616 14.13から:
アプリケーションは、セクション 4.4 のルールで禁止されていない限り、このフィールドを使用してメッセージ本文の転送長を示す必要があります。
ただし、これはほとんどのサーバーにとって非常に標準的な要件であり、Content-Length
ヘッダーが欠落しているか正しく指定されていない場合、通常はエラー応答を返します。すべての意図と目的において、この場合のSHOULDはMUSTと同等です。
Content-Length
問題は (特にキープアライブ接続の場合)、要求メッセージがヘッダーなしで実際にいつ終了するかをサーバーが認識できないことです。リクエスト エンティティ ボディをストリーミングする場合のもう 1 つのオプションは、Transfer-Encoding: chunked
ヘッダーを送信し、エンティティ ボディのチャンクを一度に 1 つずつ手動で送信することです。
Content-Length
要約すると、メッセージと共にエンティティ本体を送信したいが、ヘッダーを送信したくない場合、唯一の現実的なオプションは、チャンクされた HTTP メッセージを送信することです。これは基本的に、そのエンティティ本体をストリーミングしたいが、その長さが事前にわからない場合に必要です。
ストリーミング用に HTTP エンティティ本体をチャンク エンコードする方法 ...
Transfer-Encoding: chunked
RFC2616 Sec3.6.1で定められた制約に従って、HTTP メッセージのエンティティ ボディをエンコードしていることを意味します。このエンコード形式は、リクエストまたはレスポンスのいずれかに適用できます (どちらも HTTP メッセージです)。この形式は、エンティティ本体のサイズや、エンティティ本体がどうなるかを正確に知る前に、HTTP メッセージの送信をすぐに開始できるため、非常に便利です。実際、これはまさに PHP が透過的に行うことでecho
あり、header('Content-Length: 42')
.
チャンク エンコーディングの詳細については説明しませんが (HTTP 仕様はそのためのものです)、リクエスト エンティティ ボディをストリーミングしたい場合は、次のようにする必要があります。
<?php
$sock = fsockopen($host,80,$errno, $error);
$readStream = fopen('/some/file/path.txt', 'r+');
fwrite($sock, "POST /somePath HTTP/1.1\r\n" .
"Host: www.somehost.com\r\n" .
"Transfer-Encoding: chunked\r\n\r\n");
while (!feof($readStream)) {
$chunkData = fread($readStream, $chunkSize);
$chunkLength = strlen($chunkData);
$chunkData = dechex($chunkLength) . "\r\n$chunkData\r\n";
fwrite($sock, $chunkData);
}
fwrite($sock, "0\r\n\r\n");