英文:
check whether http connection is hijacked in go server
问题
我正在使用Go语言编写一个HTTP服务器,使用以下模式来处理API输出:
func handler(w http.ResponseWriter, r *http.Request) {
defer reply(w, r, L)() // L是一个Logger
// 做一些事情...
}
func reply(w http.ResponseWriter, r *http.Request, log Logger) func() {
cid := []byte{0, 0, 0, 0}
if log != nil {
rand.Read(cid)
log.Debug("[%x] %s %s", cid, r.Method, r.URL.String())
}
entry := time.Now()
return func() {
if log != nil {
defer log.Debug("[%x] elapsed %d millis", cid, time.Since(entry).Milliseconds())
}
_, err := w.Write(nil)
if err == http.ErrHijacked {
return // API是一个WEBSOCKET入口点,不做任何操作
}
// 处理普通HTTP API的通用输出逻辑...
}
}
我这样做的原因是,我在标准库中找到了这样的注释:
// ErrHijacked是在ResponseWriter.Write调用时返回的,
// 当底层连接使用Hijacker接口被劫持时。在被劫持的连接上进行零字节写入将返回ErrHijacked而没有其他副作用。
ErrHijacked = errors.New("http: connection has been hijacked")
然而,在Write()方法之后,我找到了这样的注释:
// Write将数据作为HTTP回复的一部分写入连接。
//
// 如果尚未调用WriteHeader,Write在写入数据之前调用WriteHeader(http.StatusOK)。
// 如果Header不包含Content-Type行,Write会将Content-Type设置为将前512个字节的写入数据传递给...
Write([]byte) (int, error)
我的问题是:
1)使用我的代码来安全地检测HTTP连接是否被劫持是否可以?我只想检查连接是否被劫持,而不希望它为我添加标头!
2)由于ResponseWriter
是一个接口,我无法通过源代码找出标准库是如何实现该方法的。一般来说,我如何深入到标准库(或任何开源代码)中,以找出接口的实现方式?
英文:
I am writing an HTTP server in Go, which uses the following pattern to handle API output:
func handler(w http.ResponsWriter, r *http.Request) {
defer reply(w, r, L)() //L is a Logger
//do things...
}
func reply(w http.ResponseWriter, r *http.Request, log Logger) func() {
cid := []byte{0, 0, 0, 0}
if log != nil {
rand.Read(cid)
log.Debug("[%x] %s %s", cid, r.Method, r.URL.String())
}
entry := time.Now()
return func() {
if log != nil {
defer log.Debug("[%x] elapsed %d millis", cid, time.Since(entry).Milliseconds())
}
_, err := w.Write(nil)
if err == http.ErrHijacked {
return //API is a WEBSOCKET entry point, do nothing
}
//handle common output logic for normal HTTP APIs...
}
}
The reason I do this, is that I found this comment in the standard library:
// ErrHijacked is returned by ResponseWriter.Write calls when
// the underlying connection has been hijacked using the
// Hijacker interface. A zero-byte write on a hijacked
// connection will return ErrHijacked without any other side
// effects.
ErrHijacked = errors.New("http: connection has been hijacked")
However following the Write() method, I got this comment:
// 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
// ...
Write([]byte) (int, error)
My questions are:
-
Is it OK to use my code to safely detect if a HTTP connection is hijacked? I only want to check the connection is hijacked or not, but do NOT want it to add headers for me!
-
Since the
ResponseWriter
is an interface, I cannot click through the source code to find out how the standard library implements that method. In general, how can I drill down to the standard library (or any open source code) to find out the implementation of an interface?
答案1
得分: 1
感谢Cerise,我找到了标准response.Writer的源代码:
func (w *response) write(lenData int, dataB []byte, dataS string) (n int, err error) {
if w.conn.hijacked() {
if lenData > 0 {
caller := relevantCaller()
w.conn.server.logf("http: response.Write on hijacked connection from %s (%s:%d)", caller.Function, path.Base(caller.File), caller.Line)
}
return 0, ErrHijacked
}
... ....
所以,正如文档中所说,没有副作用。
英文:
Thanks to Cerise, I found the source code of the standard response.Writer:
func (w *response) write(lenData int, dataB []byte, dataS string) (n int, err error) {
if w.conn.hijacked() {
if lenData > 0 {
caller := relevantCaller()
w.conn.server.logf("http: response.Write on hijacked connection from %s (%s:%d)", caller.Function, path.Base(caller.File), caller.Line)
}
return 0, ErrHijacked
}
... ....
So, as said in the document, there is NO side effect.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论