1
0
mirror of https://github.com/oauth2-proxy/oauth2-proxy.git synced 2025-06-15 00:15:00 +02:00

Merge websocket proxy feature from openshift/oauth-proxy. Original author: Hiram Chirino <hiram@hiramchirino.com>

This commit is contained in:
Adam Szalkowski
2019-03-08 09:15:21 +01:00
parent 21c9d38ada
commit c7193b4085
7 changed files with 145 additions and 26 deletions

View File

@ -17,6 +17,7 @@ import (
"github.com/mbland/hmacauth"
"github.com/pusher/oauth2_proxy/cookie"
"github.com/pusher/oauth2_proxy/providers"
"github.com/yhat/wsutil"
)
const (
@ -95,9 +96,10 @@ type OAuthProxy struct {
// UpstreamProxy represents an upstream server to proxy to
type UpstreamProxy struct {
upstream string
handler http.Handler
auth hmacauth.HmacAuth
upstream string
handler http.Handler
wsHandler http.Handler
auth hmacauth.HmacAuth
}
// ServeHTTP proxies requests to the upstream provider while signing the
@ -108,7 +110,12 @@ func (u *UpstreamProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
r.Header.Set("GAP-Auth", w.Header().Get("GAP-Auth"))
u.auth.SignRequest(r)
}
u.handler.ServeHTTP(w, r)
if u.wsHandler != nil && r.Header.Get("Connection") == "Upgrade" && r.Header.Get("Upgrade") == "websocket" {
u.wsHandler.ServeHTTP(w, r)
} else {
u.handler.ServeHTTP(w, r)
}
}
// NewReverseProxy creates a new reverse proxy for proxying requests to upstream
@ -145,6 +152,26 @@ func NewFileServer(path string, filesystemPath string) (proxy http.Handler) {
return http.StripPrefix(path, http.FileServer(http.Dir(filesystemPath)))
}
// NewWebSocketOrRestReverseProxy creates a reverse proxy for REST or websocket based on url
func NewWebSocketOrRestReverseProxy(u *url.URL, opts *Options, auth hmacauth.HmacAuth) (restProxy http.Handler) {
u.Path = ""
proxy := NewReverseProxy(u, opts.FlushInterval)
if !opts.PassHostHeader {
setProxyUpstreamHostHeader(proxy, u)
} else {
setProxyDirector(proxy)
}
// this should give us a wss:// scheme if the url is https:// based.
var wsProxy *wsutil.ReverseProxy
if opts.ProxyWebSockets {
wsScheme := "ws" + strings.TrimPrefix(u.Scheme, "http")
wsURL := &url.URL{Scheme: wsScheme, Host: u.Host}
wsProxy = wsutil.NewSingleHostReverseProxy(wsURL)
}
return &UpstreamProxy{u.Host, proxy, wsProxy, auth}
}
// NewOAuthProxy creates a new instance of OOuthProxy from the options provided
func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy {
serveMux := http.NewServeMux()
@ -157,23 +184,17 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy {
path := u.Path
switch u.Scheme {
case httpScheme, httpsScheme:
u.Path = ""
log.Printf("mapping path %q => upstream %q", path, u)
proxy := NewReverseProxy(u, opts.FlushInterval)
if !opts.PassHostHeader {
setProxyUpstreamHostHeader(proxy, u)
} else {
setProxyDirector(proxy)
}
serveMux.Handle(path,
&UpstreamProxy{u.Host, proxy, auth})
proxy := NewWebSocketOrRestReverseProxy(u, opts, auth)
serveMux.Handle(path, proxy)
case "file":
if u.Fragment != "" {
path = u.Fragment
}
log.Printf("mapping path %q => file system %q", path, u.Path)
proxy := NewFileServer(path, u.Path)
serveMux.Handle(path, &UpstreamProxy{path, proxy, nil})
serveMux.Handle(path, &UpstreamProxy{path, proxy, nil, nil})
default:
panic(fmt.Sprintf("unknown upstream protocol %s", u.Scheme))
}