Заголовок Content-Length HTTP его наличие и отсутствие
Подскажите пожалуйста, вот есть заголовок Content-length в HTTP ответе от сервера. Но, как я понял этот заголовок не является обязательным. И вот интересная такая ситуация, вот пример ответа от сервера без заголовка Content-length:
HTTP/1.0 408 Request Time-out Cache-Control: no-cache Connection: close Content-Type: text/html 408 Request Time-out
Your browser didn't send a complete request in time.
То есть предположим: -я выделил буфер ровно под весь размер Http-заголовков -прочитал их в буфер -теперь мне нужно прочитать сам HTML: я вызываю функцию чтения WSARecv(из Winsock) еще раз и дочитываю сообщение от до Тут понятно. А теперь предположим, пришел точно такой же ответ от сервера, НО без HTML тела, и я опять повторяю все действия и опять вызываю WSARecv, но так как после HTTP-заголовков более ничего нет и не предвидится, то теоретически WSARecv зависнет на бесконечное время в ожидании приема. И вот тут уже не понятно, как такие ситуации отрабатывать ? Отбивать по таймауту просто ? Или есть более правильные способы ?
Http Web Request. Content Length Свойство
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Возвращает или задает заголовок HTTP Content-length .
public: virtual property long ContentLength < long get(); void set(long value); >;
public override long ContentLength
member this.ContentLength : int64 with get, set
Public Overrides Property ContentLength As Long
Значение свойства
Количество байтов данных, отправляемых в интернет-ресурс. Значение по умолчанию, равное –1, показывает, что свойство не установлено и отсутствуют данные запроса, предназначенные для отправки.
Исключения
Новое значение ContentLength меньше 0.
Примеры
В следующем примере кода свойству ContentLength присваивается длина публикуемой строки.
// Set the 'Method' property of the 'Webrequest' to 'POST'. myHttpWebRequest->Method = "POST"; Console::WriteLine( "\nPlease enter the data to be posted to the (http://www.contoso.com/codesnippets/next.asp) Uri :" ); // Create a new String* Object* to POST data to the Url. String^ inputData = Console::ReadLine(); String^ postData = String::Concat( "firstone= ", inputData ); ASCIIEncoding^ encoding = gcnew ASCIIEncoding; array^ byte1 = encoding->GetBytes( postData ); // Set the content type of the data being posted. myHttpWebRequest->ContentType = "application/x-www-form-urlencoded"; // Set the content length of the String* being posted. myHttpWebRequest->ContentLength = byte1->Length; Stream^ newStream = myHttpWebRequest->GetRequestStream(); newStream->Write( byte1, 0, byte1->Length ); Console::WriteLine( "The value of 'ContentLength' property after sending the data is ", myHttpWebRequest->ContentLength ); // Close the Stream Object*. newStream->Close();
// Set the 'Method' property of the 'Webrequest' to 'POST'. myHttpWebRequest.Method = "POST"; Console.WriteLine ("\nPlease enter the data to be posted to the (http://www.contoso.com/codesnippets/next.asp) Uri :"); // Create a new string object to POST data to the Url. string inputData = Console.ReadLine (); string postData = "firstone=" + inputData; ASCIIEncoding encoding = new ASCIIEncoding (); byte[] byte1 = encoding.GetBytes (postData); // Set the content type of the data being posted. myHttpWebRequest.ContentType = "application/x-www-form-urlencoded"; // Set the content length of the string being posted. myHttpWebRequest.ContentLength = byte1.Length; Stream newStream = myHttpWebRequest.GetRequestStream (); newStream.Write (byte1, 0, byte1.Length); Console.WriteLine ("The value of 'ContentLength' property after sending the data is ", myHttpWebRequest.ContentLength); // Close the Stream object. newStream.Close ();
' Set the 'Method' property of the 'Webrequest' to 'POST'. myHttpWebRequest.Method = "POST" Console.WriteLine(ControlChars.Cr + "Please enter the data to be posted to the (http://www.contoso.com/codesnippets/next.asp) Uri :") ' Create a new string object to POST data to the Url. Dim inputData As String = Console.ReadLine() Dim postData As String = "firstone" + ChrW(61) + inputData Dim encoding As New ASCIIEncoding() Dim byte1 As Byte() = encoding.GetBytes(postData) ' Set the content type of the data being posted. myHttpWebRequest.ContentType = "application/x-www-form-urlencoded" ' Set the content length of the string being posted. myHttpWebRequest.ContentLength = byte1.Length Dim newStream As Stream = myHttpWebRequest.GetRequestStream() newStream.Write(byte1, 0, byte1.Length) Console.WriteLine("The value of 'ContentLength' property after sending the data is ", myHttpWebRequest.ContentLength) newStream.Close()
Комментарии
Свойство ContentLength содержит значение для отправки в качестве заголовка Content-length HTTP с запросом.
Любое значение, отличное от -1 в свойстве ContentLength , указывает, что запрос передает данные и что в свойстве Method разрешено задавать только методы, которые передают данные.
После того как свойству ContentLength присвоено значение, это число байтов должно быть записано в поток запросов, возвращаемый путем вызова GetRequestStream метода или методов BeginGetRequestStream и EndGetRequestStream .
Значение данного свойства содержится в WebHeaderCollection. Если задана коллекция WebHeaderCollection, значение свойства утрачивается.
Как рассчитывается значение заголовка Content-Length?
Я никогда об этом не задумывался, но сегодня вдруг задался вопросом, а что именно обозначает Content-Length? Исключительно размер тела запроса или оно показывает размер всего запроса, т. е. служебные заголовки + тело?
P. S. В документации написано, что это размер тела запроса, но не сказано, относятся ли служебные заголовки к телу!
- Вопрос задан более двух лет назад
- 1779 просмотров
2 комментария
Простой 2 комментария

Ярослав Иванов @space2pacman
Заголовки относятся к заголовкам. Длинна контента это только тело.

Content-Length бывает 0, при этом очевидно что если бы в него входили заголовки, то такого бы быть не могло.
Решения вопроса 1

Какой вопрос — такой и ответ
Content-length показывает размер Body.
Т.е. он вполне может быть нулевого размера даже при наличии кучи заголовков и статуса.
Для таких простых вопросов всегда есть гугл и докментация
https://developer.mozilla.org/en-US/docs/Web/HTTP/.
Ответ зашит в самом названии — «Content length»
В документации написано, что это размер тела запроса, но не сказано, относятся ли служебные заголовки к телу!
Как вычислить поле Content-Length заголовка POST запроса?
Сабж. Как это делается? Это длина в символах отправляемого json массива или что? Пишу парсер на питоне, пытаюсь выцепить AJAX запрос, а просто так он не работает. Посмотрел все отсылаемые заголовки, выставляю так же, но все равно ошибка 400. URL правильный, но вот не знаю как вычислить Content-Length

Qwentor ★★★★★
19.05.16 13:09:44 MSK

Это длина в символах отправляемого json массива или что?
Это длина тела запроса в байтах.
i-rinat ★★★★★
( 19.05.16 13:10:41 MSK )
А разве в таких случаях не проще юзать curl, который все это посчитает сам и умеет еще много чего другого?
xtraeft ★★☆☆
( 19.05.16 13:15:09 MSK )

>>> s = "Привет, Qwentor" >>> len(s) 15 >>> len(s.encode('utf-8')) 21
Как сказано выше, это Content-Length — длинна строки в байтах, при этом стоит учитывать, что в питоне ваше тело сообщения, будучи строкой, кодируется в юникоде.
И, если мне не изменяет память, все заголовки должны заканчиваться именно \r\n , не уверен, правда, та же ли ошибка будет в случае неправильных переводов строк, но стоит проверить.
evilface ★★
( 19.05.16 16:42:04 MSK )

Если Вы правильно сформулировали вопрос, то оно вам не надо. AJAX-у не надо лезть в HTTP-заголовки, это всё делает браузер. На стороне сервера, это тоже не очень надо, т.к. POST обычно обрабатывается как поток. Но если таки надо, то для CGI скриптов и программ, заголовок доступен в переменных окружения среды. Не знаю, как на Pithon-е, в массиве C это называется CONTENT_LENGTH, в sh/Bash подстановка $CONTENT_LENGTH.