假设服务器需要向客户端响应一些数据,并且数据来自本地磁盘上的文件.然后我们写,
n, err := io.Copy(w, f) // w is the ResponseWriter and f is the *os.File
Run Code Online (Sandbox Code Playgroud)
我在想什么就是io.Copy()首先从写一个标题,然后将数据复制f到w.
如果err不是nil(比方说unexpected EOF),客户端仍然会获得状态代码200,尽管响应正文包含错误.
也许本地磁盘坏了,或者客户端网络坏了.我们怎样才能确定
是否err是由服务器或客户机引起的?
io.Copy呼叫Write目标io.Writer.http.ResponseWriter有关该Write方法的文档指定了此行为:
// Write writes the data to the connection as part of an HTTP reply.
// If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK)
// before writing the data. If the Header does not contain a
// Content-Type line, Write adds a Content-Type set to the result of passing
// the initial 512 bytes of written data to DetectContentType.
Write([]byte) (int, error)
Run Code Online (Sandbox Code Playgroud)
这意味着它将首先调用WriteHeader:
// WriteHeader sends an HTTP response header with status code.
// If WriteHeader is not called explicitly, the first call to Write
// will trigger an implicit WriteHeader(http.StatusOK).
// Thus explicit calls to WriteHeader are mainly used to
// send error codes.
WriteHeader(int)
Run Code Online (Sandbox Code Playgroud)
所以,是的,如果您的HD在Write操作期间失败,那么您已经编写了一个200 OK响应,但是,如果您的响应指定了Content-Length客户端,当您的响应长度不匹配时,会知道某些内容是错误的.
在HTTP 1.1和分块传输编码的情况下,理论上您可以在HTTP预告片中的响应之后指定故障标头.遗憾的是,任何当前最常用的Web浏览器都不支持HTTP预告片.
@OneOfOne的贡献:io.Copy错误不会指定哪一端失败; 如果服务器或客户端.
因此,我们不能指出错误应该记录为4xx或5xx,对吧?
如果您正在记录HTTP状态标头,请记录您作为响应发送客户端的内容; 不应该是什么.