何时在Golang中使用hijack?

22

我不明白为什么要使用劫持,因为我可以直接将一些内容写入响应体中,有人能解释一下吗?

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()
}

我很困惑

2个回答

29

当您不想使用内置服务器的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

直接输出到输出端口。


7
你可以查看一个介绍了 hijack 的库 (martini): Issue 45
(注:我不推荐使用不符合惯用法的 Martini,但只是在这里提到它来说明 hijack)。

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

那个问题涉及到以下go-nuts线程,其中有人试图嵌入接口http.ResponseWriter以记录诸如字节数和请求持续时间之类的统计信息。

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

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

  • 记录更多的信息(状态,大小等),调用劫持可能过于复杂
  • 实现另一个协议(比如websocket,它 " 升级" HTTP 服务器连接, 调用 w.(http.Hijacker)

然后您可以考虑使用劫持。
但是,正如文档所述,在调用Hijack()之后,HTTP服务器库将不会对连接执行任何其他操作。
这成为调用者管理和关闭连接的责任。

如果没有,就像在这个问题中说明的那样,那么劫持就不是有趣的了。


我不建议你使用Martini,因为它不符合Go的惯用法。 - qwertmax
@qwertmax 我知道了,并且我已经编辑了答案以使其更加清晰。你现在可以撤销你的踩了。 - VonC
@qwertmax 这很奇怪:你仍然没有撤销你的反对票。有什么遗漏吗? - VonC
“关于马蒂尼的想法”的链接现在链接到了bet365的垃圾邮件,有人有原始文章吗? - Felipe Valdes
@FelipeValdes 谢谢。我已经恢复了关于“我的Martini想法”的文章链接。 - VonC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接