如果内容长度不超过2kb,为什么golang http ResponseWriter会自动添加内容长度

axr492tv  于 2023-01-15  发布在  Go
关注(0)|答案(2)|浏览(206)
func (handler Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    var content string
    ...
    w.Write([]byte(content))
}

如果len(content)〈= 2048,则在响应中自动添加content-length,如果超过2048,则没有content-length,添加Transfer-Encoding: chunked
我找不到2048年的时间。
我请求帮助找到源代码,在哪里确定2048.

c9x0cxw0

c9x0cxw01#

为了清楚起见,让我们看看http.ResponseWriter接口中此特性的文档:
[I]f所有写入数据的总大小小于几KB,并且没有Flush调用,则自动添加Content-Length报头。
首先,我们可以看到这个数字可能不是2048(2 KB),但在我们预期的“几KB”范围内;其次,我们可以看到这个行为与Flush方法有关,该方法记录在Flusher接口中:
Flush将所有缓冲数据发送到客户端。
Flusher接口由ResponseWriters实现,它允许HTTP处理程序将缓冲数据刷新到客户端。
默认的HTTP/1.x和HTTP/2 ResponseWriter实现支持Flusher,但ResponseWriter Package 器可能不支持。处理程序应始终在运行时测试此功能。
正如上面所说,您的ResponseWriter可能支持数据缓冲和刷新。这意味着当您将数据写入响应写入器时,它不会立即通过连接传输。相反,它首先被写入缓冲区。每次缓冲区太满而无法再写入时,以及当ServeHTTP方法返回时,整个缓冲区都将被传输。这确保了即使你做了很多微小的写入,数据也能有效地传输,并且所有数据最终都会被传输。您还可以选择使用Flush方法随时主动清空缓冲区。HTTP头必须在正文数据之前发送,但是在缓冲区第一次清空之前不需要发送它们。
把所有这些放在一起,你会发现如果写入的总量不超过缓冲区大小,并且我们从不调用Flush,那么在所有数据准备好之前不需要发送头,这时我们知道了内容长度;如果写入的总量超过缓冲区大小,那么在知道内容长度之前必须发送头。所以ResponseWriter不能自动确定它。
这是在net/http/server.go的源代码中实现的。具体来说,下面是缓冲区大小的声明,以及实现部分缓冲写入行为的chunkedWriter

// This should be >= 512 bytes for DetectContentType,
// but otherwise it's somewhat arbitrary.
const bufferBeforeChunkingSize = 2048

// chunkWriter writes to a response's conn buffer, and is the writer
// wrapped by the response.w buffered writer.
//
// chunkWriter also is responsible for finalizing the Header, including
// conditionally setting the Content-Type and setting a Content-Length
// in cases where the handler's final output is smaller than the buffer
// size. It also conditionally adds chunk headers, when in chunking mode.
//
// See the comment above (*response).Write for the entire write flow.
type chunkWriter struct {

Link to the source code for 1.19.5。请注意,源代码可能会随着Go语言的发布而发生变化。

dfddblmv

dfddblmv2#

该值定义如下:

// This should be >= 512 bytes for DetectContentType,
// but otherwise it's somewhat arbitrary.
const bufferBeforeChunkingSize = 2048

写的生命解释了发生了什么:
如果处理程序没有预先声明Content-Length,我们要么进入分块模式,要么,如果处理程序在分块缓冲区大小之前完成运行,我们计算Content-Length并在头中发送它。

相关问题