英文:
https and websocket handler with different deadlines
问题
我有一个玩具代理服务器,它在一个端口上接受连接。我设置了一些读/写操作的截止时间,以避免由于无法正确关闭的糟糕客户端而产生太多空闲连接。
问题是,我想为那些面向WebSockets(特别是wss)的连接设置更长的截止时间。对于普通的HTTP请求,我可以看到101 Switching Protocols
的响应,但是对于HTTPS/WSS来说就比较棘手,因为我主要是从源连接到目标连接进行io.CopyBuffer
,并且在初始代理连接中看不到任何与"websocket相关"的内容,以区分HTTPS和WSS并应用适当的截止时间。
我在这个向wss://
演示服务器发出的请求中包含了一个调试屏幕。
有什么想法吗?
英文:
I have a toy proxy server that accepts connections on a port. I set some deadlines for read/write operations to avoid having too many idle connections from bad clients that fail to close properly.
The problem is that I would like to set a higher deadline for connections that are towards websockets (wss
in particular). For plain http requests I can see the 101 Switching Protocols
response but https/wss is trickier since I mostly do a io.CopyBuffer
from src connection to dst connection and I don't see anything "websocket related" in the initial proxy connection in order to differentiate between https and wss and apply the proper deadline.
I've included a debug screen to such a request towards a wss://
demo server.
Any ideas?
答案1
得分: 1
从加密数据中仅凭外观无法可靠地区分“正常”的HTTP流量和Websockets。
可以尝试通过观察流量模式来进行一些启发式分析,例如传输数据的方向、在何时传输多少数据以及数据之间的空闲时间。这些启发式分析可以基于以下假设:HTTP是一种请求-响应协议,通常是短暂的请求后紧随着较大的响应,而Websockets可以显示任意的流量模式。
但是,任意的流量模式也意味着Websockets也可能以请求-响应的方式使用(包括请求+响应)。此外,在某些用例中,HTTP的使用模式主要由较大的请求后跟着小的响应。因此,根据应用程序的类型,这些启发式分析可能会成功,也可能会失败。
英文:
One cannot reliably distinguish between "normal" HTTP traffic and Websockets just from looking at the encrypted data.
One can try to do some heuristics by looking at traffic patterns, i.e. in which direction how many data are transferred in which time and with which idle times between data. Such heuristics can be based on the assumption that HTTP is a request + response protocol with typically small requests shortly followed by larger responses, while Websockets can show arbitrary traffic patterns.
But arbitrary traffic patterns also means that Websockets might be used in a request + response way too. (including request + response though). Also, in some use cases the usage pattern for HTTP consists of mostly larger requests followed by small responses. Thus depending on the kind of application such heuristics might be successful or they might fail.
答案2
得分: -1
定义全局服务器超时时间是一个很好的实践,以确保资源不会永久锁定。这个超时时间应该不小于所有处理程序中最长的超时时间。
DefaultServer = &http.Server{
Handler: http.TimeoutHandler(handler, wssTimeout, timeoutResponse),
...
}
在处理HTTP和WSS请求的处理程序中,我们需要动态设置超时时间。
func (proxy *ProxyHttpServer) handleHttps(w http.ResponseWriter, r *http.Request) {
// 如果客户端连接关闭,请求被取消(使用HTTP/2),或者上面创建的服务器超时,请求上下文将被取消。
// 所有下层代码都应该尊重该上下文。
ctx := r.Context()
timeout := httpTimeout
if itIsWSS(r) {
timeout = wssTimeout
}
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
// 所有下面的代码都应该使用ctx而不是context.Background()/TODO()
}
以上是要翻译的内容。
英文:
It is always a good practice to define global Server timeout to make sure that resources are not locked forever. That timeout should be not smaller that longest timeout in all handlers.
DefaultServer = &http.Server{
Handler: http.TimeoutHandler(handler, wssTimeout, timeoutResponse),
...
}
In handler that processes http and wss requests, we need to set timeout dynamically.
func (proxy *ProxyHttpServer) handleHttps(w http.ResponseWriter, r *http.Request) {
// Request Context is going to be cancelled if client's connection closes, the request is canceled (with HTTP/2), Server we created above time outed.
// all code down the stack should respect that ctx.
ctx := r.Context()
timeoit := httpTimeout
if itIsWSS(r) {
timeout = wssTimeout
}
ctx, cancel = cWithTimeout(ctx, timeout)
defer cancel()
// all code below to use ctx instead of context.Backgound()/TODO()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论