WebSocket反向代理中无法使用的响应主体

时间:2018-11-04 00:29:20

标签: http go websocket

Go的httputil.ReverseProxy不适用于WebSocket流量。 here对此问题进行了详细说明。看起来该修复程序/功能可能已在Go 1.12中发布(请参阅“将其添加到Go1.12里程碑中” here)。

由于修复/功能尚未发布,因此我试图编写自己的反向代理来解决该问题,直到发布为止。在服务器上,我编写了一个简单的gorilla/websocket处理程序,该处理程序将升级连接,然后等待来自客户端的消息。

在我的反向代理服务器上,我根据Go 1.12更改提交here,特别是在reverseproxy.go中的添加,编写了一个反向代理处理程序。在相关部分,这是我的反向代理处理程序的核心:

outreq := r.WithContext(ctx)
if r.ContentLength == 0 {
    outreq.Body = nil
}
p.director(outreq)
outreq.Header = copyHeaders(browserHeaders)
setForwardHeader(r.RemoteAddr, outreq)
log.Infof("outreq URL is %+v", outreq.URL)

transport := http.DefaultTransport
res, err := transport.RoundTrip(outreq)
if err != nil {
    log.Errorf("RoundTrip(outreq) failed: %s", err)
}
log.Infof("Server response was %+v", res)

if res.StatusCode != http.StatusSwitchingProtocols {
    log.Errorf("Did not receive HTTP status 101 switchingn protocols: %d\n", res.StatusCode)
    return
}
if !hasUpgradeHeaders(res.Header) {
    log.Error("request does not contain upgrade headers")
    return
}
backConn, ok := res.Body.(io.ReadWriteCloser)
if !ok {
    log.Errorf("internal error: 101 switching protocols response with non-writable body: %v (%T)", res.Body, res.Body)
    return
}

当我尝试通过浏览器连接WebSocket时,我得到的是最后一个if语句。类型为io.ReadWriteCloser的响应正文的类型声明失败。当我记录响应时,我看到以下内容:

Server response was &{Status:101 Switching Protocols StatusCode:101 Proto:HTTP/1.1 
ProtoMajor:1 ProtoMinor:1 Header:map[Upgrade:[websocket] Connection:[Upgrade]
Sec-Websocket-Accept:[B1fWETPTtNo0bAHFWkFn2lAm9iw=]] Body:{} ContentLength:0 
TransferEncoding:[] Close:false Uncompressed:false 
Trailer:map[] Request:0xc000112100 TLS:<nil>}

错误日志输出是这样的:

ERRO[0012] internal error: 101 switching protocols response with non-writable body: {} (http.noBody)

为什么我在响应正文中得到http.noBody而不是实现io.ReadWriteCloser接口的东西?如何解决该问题,以便可以继续进行hijack连接并促进浏览器与服务器之间的通信?

更新

我认为我找到了“为什么”问题的答案。 Go的最新版本在net / http包中的transport.go中的persistConn的readLoop函数中不包含以下行:

if resp.isProtocolSwitch() {
    resp.Body = newReadWriteCloserBody(pc.br, pc.conn)
}

Source

与当前的here比较。

有任何解决方法的想法吗?

0 个答案:

没有答案