在Go语言中,什么时候使用”hijack”?

huangapple go评论88阅读模式
英文:

when to use hijack in golang?

问题

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

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

我感到困惑。

英文:

I don't understand why we use hijack, since I can write something into response body directly, could anyone explain this?

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

it is same as this:

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

I am confused

答案1

得分: 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

写入输出。

英文:

Use Hijack when you don't want to use the built-in server's implementation of the HTTP protocol. This might be because you want to switch protocols (to WebSocket for example) or the built-in server is getting in your way.

The two snippets of code above do not create the same output on the wire. The output from the first snippet will include a response header:

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

The second snippet bypasses the built-in server code and writes

write some thing

directly to the output.

答案2

得分: 7

你可以看到一个名为martini的库引入了hijackissue 45
(注意:我不推荐使用Martini,它不符合惯用法,但这里只是为了说明hijack而提到它)

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

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

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

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

  • 记录更多信息(状态、大小等),调用hijack可能过于复杂,
  • 实现另一种协议(比如websocket,它会“Upgrade”一个HTTP服务器连接,调用w.(http.Hijacker)

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

如果不需要上述功能,就像这个问题中所示,那么hijack就不是很有趣。

英文:

You can see one library (martini) which introduced hijack: issue 45
(Note: I don't recommend Martini, which is not idiomatic, but it is mentioned here only to illustrate hijack)

> Would it be possible for your responseWriter type to implement http.Hijack?
This would allow libraries like this websockets one to work with martini.

That issue refers to the following go-nuts thread, where one tried to embed the interface http.ResponseWriter in order to record statistics like bytes written and request duration.

> Later on somebody pointed out some other interesting features of the http library, such as the CloseNotifier interface, and I realized the above code might not be such a good idea.
Since I'm embedding an interface, I can't automatically inherit *http.Response's implementations of CloseNotifier and Flusher.

So, if you want to take over the ResponseWriter in order to:

  • record more information (status, size, ..., calling hijack is probably overkill here),
  • implement another protocol (like websocket, which "Upgrade" an HTTP server connection, calling w.(http.Hijacker))

Then you can consider using hijack.
But, as documented, after a call to Hijack(), the HTTP server library will not do anything else with the connection.
It becomes the caller's responsibility to manage and close the connection.

If not, as illustrating in this other question, then hijack isn't interesting.

huangapple
  • 本文由 发表于 2014年11月22日 16:25:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/27075478.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定