假设我们有一个处理 HTTP 请求的函数,类似于:
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() 的第一次调用是否刷新到客户端?
如果它被刷新,那么我们实际上响应了客户端两次,这很奇怪,因为我们如何在第二次调用 write 之前确定 Content-Length
?
如果不刷新(比如数据在本地缓冲),那么如果我们在第一次调用时写入大量数据怎么办? (那个堆栈会溢出吗?)
任何解释将不胜感激! :)
最佳答案
I'm wondering that if the first call to w.Write() is flushed to client or not?
net/http
的默认 ResonseWriter
在它写入的 net.Conn
上有一个(当前为 4KB)大输出缓冲区。此外,操作系统通常会缓冲对套接字的写入。所以在大多数情况下,会发生某种缓冲。
If it is flushed, then we actually responses to clients twice, this is strange because how can we determine Content-Length before the second call to write?
好吧,HTTP 1.1 允许持久连接。此类响应通常不包含 Content-Length
header 。此外,还有 HTTP 预告片。
如果您的客户端不支持 HTTP 1.1 和持久连接,它们将有某种读取超时,在此期间您可以根据需要多次写入连接;这是一个回应。
与 Go 相比,这与 TCP 套接字和 HTTP 实现的性质有关。
If it is not flushed (say the data is buffered locally), then what if we write a huge amount of data at the first call? (will that stack overflow?)
不,在堆栈上分配缓冲区没有意义——缓冲区的主体将存在于堆上。如果您达到每个进程的内存限制,您的应用程序将出现“内存不足”的 panic 。
另见:
编辑以在评论中回答您的问题:
Chunked Transfer Encoding是 HTTP 1.1 规范的一部分,在 HTTP 1.0 中不受支持。
编辑澄清:
只要您编写响应的两个部分所花费的总时间不超过客户端的读取超时,并且您不指定 Content-Length
header ,您只需编写您的响应,然后关闭连接。这完全没问题,不是“hacky”。
关于http - HTTP ResponseWriter 的 write 函数会在 Go 中缓冲吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26033853/