mirror of
https://github.com/oauth2-proxy/oauth2-proxy.git
synced 2025-01-10 04:18:14 +02:00
91 lines
3.2 KiB
Go
91 lines
3.2 KiB
Go
|
package upstream
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"html/template"
|
||
|
"net/http"
|
||
|
"net/url"
|
||
|
|
||
|
"github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options"
|
||
|
"github.com/oauth2-proxy/oauth2-proxy/pkg/logger"
|
||
|
)
|
||
|
|
||
|
// ProxyErrorHandler is a function that will be used to render error pages when
|
||
|
// HTTP proxies fail to connect to upstream servers.
|
||
|
type ProxyErrorHandler func(http.ResponseWriter, *http.Request, error)
|
||
|
|
||
|
// NewProxy creates a new multiUpstreamProxy that can serve requests directed to
|
||
|
// multiple upstreams.
|
||
|
func NewProxy(upstreams options.Upstreams, sigData *options.SignatureData, errorHandler ProxyErrorHandler) (http.Handler, error) {
|
||
|
m := &multiUpstreamProxy{
|
||
|
serveMux: http.NewServeMux(),
|
||
|
}
|
||
|
|
||
|
for _, upstream := range upstreams {
|
||
|
if upstream.Static {
|
||
|
m.registerStaticResponseHandler(upstream)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
u, err := url.Parse(upstream.URI)
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("error parsing URI for upstream %q: %w", upstream.ID, err)
|
||
|
}
|
||
|
switch u.Scheme {
|
||
|
case fileScheme:
|
||
|
m.registerFileServer(upstream, u)
|
||
|
case httpScheme, httpsScheme:
|
||
|
m.registerHTTPUpstreamProxy(upstream, u, sigData, errorHandler)
|
||
|
default:
|
||
|
return nil, fmt.Errorf("unknown scheme for upstream %q: %q", upstream.ID, u.Scheme)
|
||
|
}
|
||
|
}
|
||
|
return m, nil
|
||
|
}
|
||
|
|
||
|
// multiUpstreamProxy will serve requests directed to multiple upstream servers
|
||
|
// registered in the serverMux.
|
||
|
type multiUpstreamProxy struct {
|
||
|
serveMux *http.ServeMux
|
||
|
}
|
||
|
|
||
|
// ServerHTTP handles HTTP requests.
|
||
|
func (m *multiUpstreamProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||
|
m.serveMux.ServeHTTP(rw, req)
|
||
|
}
|
||
|
|
||
|
// registerStaticResponseHandler registers a static response handler with at the given path.
|
||
|
func (m *multiUpstreamProxy) registerStaticResponseHandler(upstream options.Upstream) {
|
||
|
m.serveMux.Handle(upstream.Path, newStaticResponseHandler(upstream.ID, upstream.StaticCode))
|
||
|
}
|
||
|
|
||
|
// registerFileServer registers a new fileServer based on the configuration given.
|
||
|
func (m *multiUpstreamProxy) registerFileServer(upstream options.Upstream, u *url.URL) {
|
||
|
logger.Printf("mapping path %q => file system %q", upstream.Path, u.Path)
|
||
|
m.serveMux.Handle(upstream.Path, newFileServer(upstream.ID, upstream.Path, u.Path))
|
||
|
}
|
||
|
|
||
|
// registerHTTPUpstreamProxy registers a new httpUpstreamProxy based on the configuration given.
|
||
|
func (m *multiUpstreamProxy) registerHTTPUpstreamProxy(upstream options.Upstream, u *url.URL, sigData *options.SignatureData, errorHandler ProxyErrorHandler) {
|
||
|
logger.Printf("mapping path %q => upstream %q", upstream.Path, upstream.URI)
|
||
|
m.serveMux.Handle(upstream.Path, newHTTPUpstreamProxy(upstream, u, sigData, errorHandler))
|
||
|
}
|
||
|
|
||
|
// NewProxyErrorHandler creates a ProxyErrorHandler using the template given.
|
||
|
func NewProxyErrorHandler(errorTemplate *template.Template, proxyPrefix string) ProxyErrorHandler {
|
||
|
return func(rw http.ResponseWriter, req *http.Request, proxyErr error) {
|
||
|
logger.Printf("Error proxying to upstream server: %v", proxyErr)
|
||
|
rw.WriteHeader(http.StatusBadGateway)
|
||
|
data := struct {
|
||
|
Title string
|
||
|
Message string
|
||
|
ProxyPrefix string
|
||
|
}{
|
||
|
Title: "Bad Gateway",
|
||
|
Message: "Error proxying to upstream server",
|
||
|
ProxyPrefix: proxyPrefix,
|
||
|
}
|
||
|
errorTemplate.Execute(rw, data)
|
||
|
}
|
||
|
}
|