2014-09-25 1 views
4

Предположим, что мы имеем функцию обработки в запрос HTTP, что-то вроде:Будет ли буфер реагирования HTTP ResponseWriter в Go?

func handler(w http.ResponseWriter, r *http.Request) { 
    w.Write([]byte("first piece of data")) 
    // do something 
    w.Write([]byte("second piece of data")) 
} 

Я задаюсь вопросом, что если первый вызов w.Write() промывается клиенту или нет?

Если он покраснел, мы на самом деле реагируем на клиентов дважды, это странно, потому что, как мы можем определить Content-Length перед вторым звонком написать?

Если он не покраснел (скажем, что данные буферизуются локально), то что, если мы напишем огромное количество данных при первом вызове? (будет ли переполнение стека?)

Любые объяснения будут оценены! :)

ответ

5

Мне интересно, если первый вызов w.Write() будет очищен клиентом или нет?

net/http По умолчанию ResonseWriter имеет (в настоящее время 4KB) большой выходной буфер над net.Conn он записывает в. Кроме того, ОС обычно буферизует запись в сокет. Поэтому в большинстве случаев происходит некоторая буферизация.

Если он покраснел, мы на самом деле реагируем на клиентов дважды, это странно, потому что, как мы можем определить Content-Length до второго вызова для записи?

Хорошо, есть HTTP 1.1, который позволяет постоянные соединения. Такие ответы обычно не включают заголовок . Кроме того, есть трейлеры HTTP.

Если ваш клиент не поддерживает HTTP 1.1 и постоянные соединения, у них будет некоторый тайм-аут чтения, в течение этого времени вы можете писать в соединение столько раз, сколько захотите; это один ответ.

Это больше связано с природой сокетов TCP и реализаций HTTP, чем Go.

Если он не покраснел (скажем, данные буферизуются локально), то что, если мы напишем огромное количество данных при первом вызове? (Будет что переполнение стека?)

Нет, выделения буфера в стеке не имеет смысла – тело буфера будет жить в куче. Если вы нажмете ограничение на производительность для каждого процесса, ваше приложение будет паниковать «вне памяти».

Смотрите также:

Редактировать, чтобы ответить на ваш вопрос в комментариях:

Chunked Transfer Encoding является частью спецификации HTTP 1.1 и не поддерживаются в HTTP 1,0.

Редактировать, чтобы уточнить:

Пока общее время она принимает вас, чтобы написать обе части вашего ответа не превышает вашего клиента прочитать тайм-аут, и вы не указали Content-Length заголовок просто написать свой ответа, а затем закройте соединение. Все в порядке, а не «хаки».

+0

HTTP-трейлеры поддерживаются обоими версиями Go 'net/http' Server и Client. И нет, клиент без тайм-аута чтения не продержался бы дня в дикой природе. Стратегия буферизации вывода сервера HTTP имеет абсолютное значение, которое не имеет ничего общего с HTTP и да, буферы ОС записывают в сокеты, которые в случае HTTP являются сокетами TCP. Вы слишком стараетесь, чтобы набросать ответы других народов. – thwd

+2

[Да, они делают] (https://golang.org/src/pkg/net/http/transfer.go#L32), я буду игнорировать ваши комментарии с этого момента. – thwd

+1

[Пожалуйста, прекратите комментировать.] (Https://golang.org/src/pkg/net/http/response.go#L253) – thwd