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)
 | |
| 	}
 | |
| }
 |