18

我不明白为什么我们使用劫持,因为我可以直接在响应正文中写一些东西,有人可以解释一下吗?

func writeSome(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "write some thing")
}

与此相同:

func hijack(w http.ResponseWriter, r *http.Request) {
    hj, _ := w.(http.Hijacker)
    _, buf, _ := hj.Hijack()
    buf.WriteString("write some thing")
    buf.Flush()
}

我很困惑

4

2 回答 2

25

当您不想使用内置服务器的 HTTP 协议实现时,请使用 Hijack。这可能是因为您想要切换协议(例如切换到 WebSocket)或内置服务器妨碍了您。

上面的两个代码片段不会在线路上创建相同的输出。第一个片段的输出将包含一个响应标头:

HTTP/1.1 200 OK
Date: Wed, 26 Nov 2014 03:37:57 GMT
Content-Length: 16
Content-Type: text/plain; charset=utf-8

write some thing

第二个片段绕过内置的服务器代码并写入

write some thing

直接输出。

于 2014-11-26T03:39:28.900 回答
6

你可以看到一个库(martini),它介绍了hijackissue 45
(注意:我不推荐Martini,它不是惯用的,但这里提到它只是为了说明hijack

您的 responseWriter 类型是否可以实现 http.Hijack?
这将允许像这样的websockets库与 martini 一起使用。

该问题涉及以下 go-nuts thread,其中尝试嵌入接口http.ResponseWriter以记录写入的字节数和请求持续时间等统计信息。

后来有人指出了http库的一些其他有趣的特性,比如CloseNotifier接口,我意识到上面的代码可能不是一个好主意。
由于我嵌入了一个接口,我不能自动继承and*http.Response的实现。CloseNotifierFlusher

因此,如果您想接管ResponseWriter,以便:

  • 记录更多信息(状态,大小,...,在这里调用劫持可能是矫枉过正),
  • 实现另一个协议(如 websocket,它“ Upgrade”一个 HTTP 服务器连接,调用w.(http.Hijacker)

然后你可以考虑使用劫持。
但是,正如记录的那样,在调用 之后Hijack(),HTTP 服务器库不会对连接做任何其他事情。
管理和关闭连接成为调用者的责任。

如果不是,如this other question中所示,那么劫持就没意思了。

于 2014-11-22T08:47:21.410 回答