git.iko.soy/typeable/oauth2-proxy
on request-rules help sign in
90 lines 3.2 kB history raw
1package upstream
3import (
4 "fmt"
5 "html/template"
6 "net/http"
7 "net/url"
9 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options"
10 "github.com/oauth2-proxy/oauth2-proxy/pkg/logger"
13// ProxyErrorHandler is a function that will be used to render error pages when
14// HTTP proxies fail to connect to upstream servers.
15type ProxyErrorHandler func(http.ResponseWriter, *http.Request, error)
17// NewProxy creates a new multiUpstreamProxy that can serve requests directed to
18// multiple upstreams.
19func NewProxy(upstreams options.Upstreams, sigData *options.SignatureData, errorHandler ProxyErrorHandler) (http.Handler, error) {
20 m := &multiUpstreamProxy{
21 serveMux: http.NewServeMux(),
22 }
24 for _, upstream := range upstreams {
25 if upstream.Static {
26 m.registerStaticResponseHandler(upstream)
27 continue
28 }
30 u, err := url.Parse(upstream.URI)
31 if err != nil {
32 return nil, fmt.Errorf("error parsing URI for upstream %q: %w", upstream.ID, err)
33 }
34 switch u.Scheme {
35 case fileScheme:
36 m.registerFileServer(upstream, u)
37 case httpScheme, httpsScheme:
38 m.registerHTTPUpstreamProxy(upstream, u, sigData, errorHandler)
39 default:
40 return nil, fmt.Errorf("unknown scheme for upstream %q: %q", upstream.ID, u.Scheme)
41 }
42 }
43 return m, nil
46// multiUpstreamProxy will serve requests directed to multiple upstream servers
47// registered in the serverMux.
48type multiUpstreamProxy struct {
49 serveMux *http.ServeMux
52// ServerHTTP handles HTTP requests.
53func (m *multiUpstreamProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
54 m.serveMux.ServeHTTP(rw, req)
57// registerStaticResponseHandler registers a static response handler with at the given path.
58func (m *multiUpstreamProxy) registerStaticResponseHandler(upstream options.Upstream) {
59 m.serveMux.Handle(upstream.Path, newStaticResponseHandler(upstream.ID, upstream.StaticCode))
62// registerFileServer registers a new fileServer based on the configuration given.
63func (m *multiUpstreamProxy) registerFileServer(upstream options.Upstream, u *url.URL) {
64 logger.Printf("mapping path %q => file system %q", upstream.Path, u.Path)
65 m.serveMux.Handle(upstream.Path, newFileServer(upstream.ID, upstream.Path, u.Path))
68// registerHTTPUpstreamProxy registers a new httpUpstreamProxy based on the configuration given.
69func (m *multiUpstreamProxy) registerHTTPUpstreamProxy(upstream options.Upstream, u *url.URL, sigData *options.SignatureData, errorHandler ProxyErrorHandler) {
70 logger.Printf("mapping path %q => upstream %q", upstream.Path, upstream.URI)
71 m.serveMux.Handle(upstream.Path, newHTTPUpstreamProxy(upstream, u, sigData, errorHandler))
74// NewProxyErrorHandler creates a ProxyErrorHandler using the template given.
75func NewProxyErrorHandler(errorTemplate *template.Template, proxyPrefix string) ProxyErrorHandler {
76 return func(rw http.ResponseWriter, req *http.Request, proxyErr error) {
77 logger.Printf("Error proxying to upstream server: %v", proxyErr)
78 rw.WriteHeader(http.StatusBadGateway)
79 data := struct {
80 Title string
81 Message string
82 ProxyPrefix string
83 }{
84 Title: "Bad Gateway",
85 Message: "Error proxying to upstream server",
86 ProxyPrefix: proxyPrefix,
87 }
88 errorTemplate.Execute(rw, data)
89 }