简体   繁体   English

如何将 wss 反向代理实现为 gin 路由?

[英]How do I implement a wss reverse proxy as a gin route?

I just recently started coding in go and thus I am not so skilled yet.我最近才开始在 go 中编码,因此我还不是很熟练。

I have a use case where I want to implement a reverse proxy as a gin route.我有一个用例,我想将反向代理实现为 gin 路由。 So my route looks like this:所以我的路线是这样的:

server.router.POST("/console", server.proxyConsoleUrl)

And my handler function something like this:我的处理程序 function 是这样的:

func (server *Server) proxyConsoleUrl(ctx *gin.Context) {
    director := func(req *http.Request) {
        r := ctx.Request
        // This is not working, scheme wss is not supported
        req.URL.Scheme = "wss"
        req.URL.Host = "192.168.******:8006"
        // The path which gets proxied should be overriden
        req.URL.RawPath = "/api2/json/nodes/something/qemu/123/vncwebsocket?port=5900&vncticket=something"
        req.Header["my-header"] = []string{r.Header.Get("my-header")}
        // Golang camelcases headers
        delete(req.Header, "My-Header")
        // This header has to be added to every request which gets proxied
        req.Header["Authorization"] = []string{"MYCUSTOMHEADER"}
    }
    proxy := &httputil.ReverseProxy{Director: director, Transport: &http.Transport{
        Proxy: http.ProxyFromEnvironment,
        Dial: (&net.Dialer{
            Timeout:   30 * time.Second,
            KeepAlive: 30 * time.Second,
        }).Dial,
        TLSHandshakeTimeout: 10 * time.Second,
        TLSClientConfig:     &tls.Config{InsecureSkipVerify: true},
    }}
    proxy.ServeHTTP(ctx.Writer, ctx.Request)
}

So my first problem is, that httputil.ReverseProxy doesn't support web socket as far as I know and noticed when running my code:所以我的第一个问题是,据我所知并在运行我的代码时注意到,httputil.ReverseProxy 不支持 web 套接字:

httputil: unsupported protocol scheme "wss"

The Second problem is, that I want to override the backend url as well as add custom headers which are added by the proxy.第二个问题是,我想覆盖后端 url 以及添加代理添加的自定义标头。

Maybe someone has an idea hot to implement this, if it's even possible.如果可能的话,也许有人有一个热门的想法来实现这一点。 -Thanks in advance -提前致谢

WebSocket support was added to httputil.ReverseProxy in Go version 1.12. WebSocket 支持已添加到 Go 版本 1.12 中的 httputil.ReverseProxy。

Use the result of url.Parse("https://192.168.******:8006/api2/json/nodes/something/qemu/123/vncwebsocket?port=5900&vncticket=something") to set the target URL.使用url.Parse("https://192.168.******:8006/api2/json/nodes/something/qemu/123/vncwebsocket?port=5900&vncticket=something")的结果设置目标 ZE6B391A8D2C4D458073DZB38A . This fixes the following issues:这解决了以下问题:

  • The WebSocket protocol uses "http" or "https" on the wire, not "wss". WebSocket 协议在线上使用“http”或“https”,而不是“wss”。
  • RawPath is ignored when RawPath is a not a valid escaping of Path.当 RawPath 不是 Path 的有效 escaping 时,忽略 RawPath。 See EscapedPath for the details.有关详细信息,请参阅转义路径 Because the RawPath in the question includes a query string, it will never be a valid escaping of Path.因为问题中的 RawPath 包含查询字符串,所以它永远不会是 Path 的有效 escaping。 The client's path is alway used as is.客户端的路径始终按原样使用。 Ditto for the client's query string.客户端的查询字符串同上。

Create the proxy once and reuse it.创建一次代理并重用它。 The important point is to create an reuse a single transport per the Transport documentation.重要的一点是根据传输文档创建重用单个传输。 Reusing the proxy accomplishes that goal.重用代理可以实现该目标。

func createProxy() *httputil.ReverseProxy {
    target, _ := url.Parse("https://192.168.******:8006/api2/json/nodes/something/qemu/123/vncwebsocket?port=5900&vncticket=something")
    director := func(req *http.Request) {
        req.URL = target
        req.Header["my-header"] = []string{req.Header.Get("my-header")}
        delete(req.Header, "My-Header")
        req.Header["Authorization"] = []string{"MYCUSTOMHEADER"}
    }
    return &httputil.ReverseProxy{Director: director, Transport: &http.Transport{
        Proxy: http.ProxyFromEnvironment,
        Dial: (&net.Dialer{
            Timeout:   30 * time.Second,
            KeepAlive: 30 * time.Second,
        }).Dial,
        TLSHandshakeTimeout: 10 * time.Second,
        TLSClientConfig:     &tls.Config{InsecureSkipVerify: true},
    }}
}

var proxy = createProxy()

func (server *Server) proxyConsoleUrl(ctx *gin.Context) {
    proxy.ServeHTTP(ctx.Writer, ctx.Request)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 nginx 作为与 Golang 一起的反向代理? - How do I use nginx as a reverse proxy alongside Golang? Golang gin Gonic Web 框架代理路由到另一个后端 - Golang gin gonic web framework proxy route to another backend 如何在gin-gonic/gin中间件中实现高效的IP白名单 - How to implement efficient IP whitelist in gin-gonic/gin middleware golang中如何实现反向代理支持nginx渐进式下载? - How to implement reverse proxy in golang to support nginx progressive download? 如何从 Go Gin 上下文中找到请求方法? - How do I find the request method from Go Gin context? 如何在 Gin 的上下文中获取匹配的路由? - How to get matched route in context in Gin? 如何进行反向代理? - How to make reverse proxy? Gin 反向代理测试因接口转换失败:*httptest.ResponseRecorder is not http.CloseNotifier:缺少方法 CloseNotify - Gin reverse proxy tests failing for interface conversion: *httptest.ResponseRecorder is not http.CloseNotifier: missing method CloseNotify 在端口8000和443上将nginx配置为反向代理,以便在8000上运行的webapp。如何禁用与端口8000的连接? - Configured nginx as reverse proxy on ports 80 and 443 for webapp running on 8000. How do I disable connections to port 8000? 如何在中间定义一个ID为go-gin的路线 - How to define a go-gin route with an id in the middle
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM