Я знаю, что HTTP-клиент может отправить следующий запрос по TCP-соединению, даже если он не получил ответов на свои предыдущие запросы - это называется конвейерной обработкой HTTP.
Однако допустимо ли для HTTP-сервера начать передачу ответа до того, как запрос был получен полностью? Есть ли RFC, регулирующий такое поведение?
Например. представьте себе службу, которая получает некоторые данные через HTTP POST, выполняет какое-то преобразование и отвечает преобразованными данными. Если преобразование может быть выполнено в потоковом режиме, то сервер может начать создание тела ответа, даже если тело запроса является неполным.
Я был бы удивлен, если бы стандарты явно описывали и благословляли такую операцию (потому что это исчезающе (редко, вы можете быть уверены, что полученный вами частичный запрос содержит достаточно информации, чтобы начать давать ответ), но я ожидаю, что в большинстве случаев это сработает. Любые данные, которые вы отправляете в ответ, почти наверняка не будут прочитаны клиентом до тех пор, пока он не завершит отправку запроса, поэтому они будут сидеть в буфере чтения, пока клиент не начнет читать, после чего он подумает: "черт возьми это было быстро!" и начни весело жевать. Он не поймет, что данные УЖЕ ВНУТРИ ЗДАНИЯ ...
Я уверен, что есть какая-то странная реализация HTTP-клиента, которая делает странные вещи со своим циклом отправки, так что, если он обнаруживает, что сокет доступен для чтения до того, как завершит запись запроса, он испугается, но единственный способ найти это - попробовать это и посмотреть, что сломается. То есть в основном то, как все делается в HTTP-мире - и как создаются новые стандартные модели поведения (кто-то делает что-то безумное, что становится достаточно популярным, чтобы все остальные должны были адаптироваться, поэтому рабочая группа IETF говорит: «Хорошо, мы Тогда сделаю это поведение стандартом ").
Я добавлю к ответу @wombie, что это было бы довольно опасно.
Когда HTTP-агент (например, обратный прокси-сервер или балансировщик нагрузки, действующий между браузером и конечным сервером) получает ответ, он обычно предполагает, что запрос был полностью отправлен и что следующий запрос может быть отправлен обратно.
Большинство обратных прокси-агентов не будут использовать конвейеры при передаче запросов на конечный сервер. Это означает, что даже если браузер пытается создать конвейер п запрашивает связь между обратным прокси-сервером и серверной частью обычно n индивидуальных запросов и ответов, ожидая каждого ответа перед отправкой следующего запроса (можно использовать соединение для поддержания активности, но обычно без конвейерной обработки).
Такое поведение значительно снижает риск контрабанды HTTP с атаками HTTP-запросов или ответов.
Отправка ответа до получения всего тела облегчит нападение контрабанды.
Для большей ясности представьте, что вы отправляете единый запрос, со странным синтаксисом и большим телом. Это содержимое тела выглядит как другой запрос с телом. И тело этого запроса в теле - это еще один третий запрос. Но это всего лишь один запрос с телом.
Обратный прокси-сервер имеет ошибка странного синтаксиса и не видит тело первого запроса. Для прокси это конвейер из 2 запросов. Таким образом, он отправляет этот первый запрос без тела серверной части.
Внутренний сервер нет ошибок в странном синтаксисе, так что это в ожидании тела. Но он посылает ранний ответ... у нас начнутся проблемы. Если бы вы дождались полного тела перед отправкой ответа, атаки на этом бы остановились.
У обратного есть ответ, поэтому он думает, что может перейти к следующему запросу, и отправляет псевдо-второй запрос (который содержит тело со скрытым третьим запросом) в бэкэнд.
Бэкэнд думает, что это просто тело первого запроса, и что-то делает с ним, или нет. Но для бэкэнда это не запрос. Скажем, это тело имеет размер 20 КБ, а серверная часть ожидает тела размером 10 КБ. Последние 10 КБ - это еще один запрос для бэкэнда, запрос, скрытый в теле, и этот запрос будет рассматриваться как еще один с новым ответом.
Прокси-сервер получит ответ на скрытый третий запрос и будет считать, что это ответ на второй запрос.
Вы можете использовать это для заражения кеша. Раннего ответа недостаточно для создания атаки (здесь также необходим странный синтаксис запроса, при котором прокси и серверная часть будут по-разному воспринимать размер тела), но это упрощает использование уязвимостей. И, конечно же, такое поведение можно встретить в дикой природе.