koding / websocketproxy

WebSocket reverse proxy handler for Go
http://godoc.org/github.com/koding/websocketproxy
MIT License
427 stars 120 forks source link

Support regular http requests #1

Closed felixge closed 10 years ago

felixge commented 10 years ago

Hi,

would you be interested in a patch that adds support for proxying regular http requests as well? I'd just add a check for what type of request it is, and based on this dispatch to gorilla websocket or the httputil proxy.

Cheers, Felix

fatih commented 10 years ago

Hi Felix! this is really easy. As you know this package is just an http.Handler. That means create another http.Handler and dispatch websocket requests to koding/websocketproxy handler and the rest (http) to net/http/httputil/Reverseproxy package. An example would be (pseudo code):


p.websocketProxy = &websocketproxy.WebsocketProxy{
        Backend: p.backend,
        Upgrader: &websocket.Upgrader{
            ReadBufferSize:  4096,
            WriteBufferSize: 4096,
            CheckOrigin: func(r *http.Request) bool {
                // TODO: change this to publicdomain and also kites should add them to
                return true
            },
        },
    }

    p.httpProxy = &httputil.ReverseProxy{
        Director: p.director,
    }

func (p *Proxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
    if isWebsocket(req) {
        // we don't use https explicitly, ssl termination is done here
        req.URL.Scheme = "ws"
        p.websocketProxy.ServeHTTP(rw, req)
        return
    }

    p.httpProxy.ServeHTTP(rw, req)
}

// isWebsocket checks wether the incoming request is a part of websocket
// handshake
func isWebsocket(req *http.Request) bool {
    if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
        !strings.Contains(strings.ToLower(req.Header.Get("Connection")), "upgrade") {
        return false
    }
    return true
}

Having said that, this package is just a pure http.Handler for websocket proxy. It's meant to be pluggable. You can easily make a proxy that also supports http as described above. Thanks for report though :)

fatih commented 10 years ago

Here is an example for usage:

https://github.com/koding/kite/blob/master/reverseproxy/reverseproxy.go

felixge commented 10 years ago

@fatih wow, thanks for the fast and detailed response :smiley: . I already ended up using your proxy the way you described, I just wondered if it made sense to include this functionality directly into your pkg. IMO the idea behind websockets is that they're "just http" and any http proxy should also be able to proxy websocket requests. (It's too bad net/httputil doesn't support it)

fatih commented 10 years ago

You are right, but then I need to provide also a Director or Backend function which defines how to proxy incoming http requests. There are many other http proxies out there. But I could add an example that shows how to implement it with http.Reverseproxy. Let me think about it :)