git.iko.soy/typeable/oauth2-proxy
on master help sign in
Use ErrorPage to render proxy error page
commita63ed0225c39a893d9fc8fcddf672b7e5fde7711 authorJoel Speed <joel.speed@hotmail.co.uk> dateSat 6 Feb 2021, 22:17 (6 years ago) parentef457b1
6 files changed+51−45
oauthproxy.go+10−8 pkg/app/error_page.go+8 pkg/app/error_page_test.go+25−10 pkg/app/templates.go+2 pkg/upstream/proxy.go−22 pkg/upstream/proxy_test.go+6−5
oauthproxy.go+10−8
@@ -122,8 +122,15 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr
122122 if err != nil {
123123 return nil, fmt.Errorf("error loading templates: %v", err)
124124 }
125− proxyErrorHandler := upstream.NewProxyErrorHandler(templates.Lookup("error.html"), opts.ProxyPrefix)
126− upstreamProxy, err := upstream.NewProxy(opts.UpstreamServers, opts.GetSignatureData(), proxyErrorHandler)
125+
126+ errorPage := &app.ErrorPage{
127+ Template: templates.Lookup("error.html"),
128+ ProxyPrefix: opts.ProxyPrefix,
129+ Footer: opts.Templates.Footer,
130+ Version: VERSION,
131+ }
132+
133+ upstreamProxy, err := upstream.NewProxy(opts.UpstreamServers, opts.GetSignatureData(), errorPage.ProxyErrorHandler)
127134 if err != nil {
128135 return nil, fmt.Errorf("error initialising upstream proxy: %v", err)
129136 }
@@ -225,12 +232,7 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr
225232 sessionChain: sessionChain,
226233 headersChain: headersChain,
227234 preAuthChain: preAuthChain,
228− errorPage: &app.ErrorPage{
229− Template: templates.Lookup("error.html"),
230− ProxyPrefix: opts.ProxyPrefix,
231− Footer: opts.Templates.Footer,
232− Version: VERSION,
233− },
235+ errorPage: errorPage,
234236 }, nil
235237}
236238
pkg/app/error_page.go+8
@@ -54,3 +54,11 @@ func (e *ErrorPage) Render(rw http.ResponseWriter, status int, redirectURL strin
5454 http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
5555 }
5656}
57+
58+// ProxyErrorHandler is used by the upstream ReverseProxy to render error pages
59+// when there are issues with upstream servers.
60+// It is expected to always render a bad gateway error.
61+func (e *ErrorPage) ProxyErrorHandler(rw http.ResponseWriter, req *http.Request, proxyErr error) {
62+ logger.Errorf("Error proxying to upstream server: %v", proxyErr)
63+ e.Render(rw, http.StatusBadGateway, "", "Error proxying to upstream server")
64+}
pkg/app/error_page_test.go+25−10
@@ -1,6 +1,7 @@
11package app
22
33import (
4+ "errors"
45 "html/template"
56 "io/ioutil"
67 "net/http/httptest"
@@ -10,19 +11,22 @@ import (
1011)
1112
1213var _ = Describe("Error Page", func() {
14+ var errorPage *ErrorPage
15+
16+ BeforeEach(func() {
17+ tmpl, err := template.New("").Parse("{{.Title}} {{.Message}} {{.ProxyPrefix}} {{.StatusCode}} {{.Redirect}} {{.Footer}} {{.Version}}")
18+ Expect(err).ToNot(HaveOccurred())
19+
20+ errorPage = &ErrorPage{
21+ Template: tmpl,
22+ ProxyPrefix: "/prefix/",
23+ Footer: "Custom Footer Text",
24+ Version: "v0.0.0-test",
25+ }
26+ })
1327
1428 Context("Render", func() {
1529 It("Writes the template to the response writer", func() {
16− tmpl, err := template.New("").Parse("{{.Title}} {{.Message}} {{.ProxyPrefix}} {{.StatusCode}} {{.Redirect}} {{.Footer}} {{.Version}}")
17− Expect(err).ToNot(HaveOccurred())
18−
19− errorPage := &ErrorPage{
20− Template: tmpl,
21− ProxyPrefix: "/prefix/",
22− Footer: "Custom Footer Text",
23− Version: "v0.0.0-test",
24− }
25−
2630 recorder := httptest.NewRecorder()
2731 errorPage.Render(recorder, 403, "/redirect", "Access Denied")
2832
@@ -32,4 +36,15 @@ var _ = Describe("Error Page", func() {
3236 })
3337 })
3438
39+ Context("ProxyErrorHandler", func() {
40+ It("Writes a bad gateway error the response writer", func() {
41+ req := httptest.NewRequest("", "/bad-gateway", nil)
42+ recorder := httptest.NewRecorder()
43+ errorPage.ProxyErrorHandler(recorder, req, errors.New("some upstream error"))
44+
45+ body, err := ioutil.ReadAll(recorder.Result().Body)
46+ Expect(err).ToNot(HaveOccurred())
47+ Expect(string(body)).To(Equal("Bad Gateway Error proxying to upstream server /prefix/ 502 Custom Footer Text v0.0.0-test"))
48+ })
49+ })
3550})
pkg/app/templates.go+2
@@ -79,6 +79,7 @@ const (
7979 </div>
8080 {{ end }}
8181
82+ {{ if .Redirect }}
8283 <hr>
8384
8485 <div class="columns">
@@ -94,6 +95,7 @@ const (
9495 </form>
9596 </div>
9697 </div>
98+ {{ end }}
9799
98100 </div>
99101 </section>
pkg/upstream/proxy.go−22
@@ -2,7 +2,6 @@ package upstream
22
33import (
44 "fmt"
5− "html/template"
65 "net/http"
76 "net/url"
87
@@ -71,24 +70,3 @@ func (m *multiUpstreamProxy) registerHTTPUpstreamProxy(upstream options.Upstream
7170 logger.Printf("mapping path %q => upstream %q", upstream.Path, upstream.URI)
7271 m.serveMux.Handle(upstream.Path, newHTTPUpstreamProxy(upstream, u, sigData, errorHandler))
7372}
74−
75−// NewProxyErrorHandler creates a ProxyErrorHandler using the template given.
76−func NewProxyErrorHandler(errorTemplate *template.Template, proxyPrefix string) ProxyErrorHandler {
77− return func(rw http.ResponseWriter, req *http.Request, proxyErr error) {
78− logger.Errorf("Error proxying to upstream server: %v", proxyErr)
79− rw.WriteHeader(http.StatusBadGateway)
80− data := struct {
81− Title string
82− Message string
83− ProxyPrefix string
84− }{
85− Title: "Bad Gateway",
86− Message: "Error proxying to upstream server",
87− ProxyPrefix: proxyPrefix,
88− }
89− err := errorTemplate.Execute(rw, data)
90− if err != nil {
91− http.Error(rw, "Internal Server Error", http.StatusInternalServerError)
92− }
93− }
94−}
pkg/upstream/proxy_test.go+6−5
@@ -4,7 +4,6 @@ import (
44 "crypto"
55 "encoding/json"
66 "fmt"
7− "html/template"
87 "net/http"
98 "net/http/httptest"
109
@@ -20,9 +19,10 @@ var _ = Describe("Proxy Suite", func() {
2019 BeforeEach(func() {
2120 sigData := &options.SignatureData{Hash: crypto.SHA256, Key: "secret"}
2221
23− tmpl, err := template.New("").Parse("{{ .Title }}\n{{ .Message }}\n{{ .ProxyPrefix }}")
24− Expect(err).ToNot(HaveOccurred())
25− errorHandler := NewProxyErrorHandler(tmpl, "prefix")
22+ errorHandler := func(rw http.ResponseWriter, _ *http.Request, _ error) {
23+ rw.WriteHeader(502)
24+ rw.Write([]byte("Proxy Error"))
25+ }
2626
2727 ok := http.StatusOK
2828
@@ -56,6 +56,7 @@ var _ = Describe("Proxy Suite", func() {
5656 },
5757 }
5858
59+ var err error
5960 upstreamServer, err = NewProxy(upstreams, sigData, errorHandler)
6061 Expect(err).ToNot(HaveOccurred())
6162 })
@@ -143,7 +144,7 @@ var _ = Describe("Proxy Suite", func() {
143144 gapUpstream: {"bad-http-backend"},
144145 },
145146 // This tests the error handler
146− raw: "Bad Gateway\nError proxying to upstream server\nprefix",
147+ raw: "Proxy Error",
147148 },
148149 }),
149150 Entry("with a request to the to an unregistered path", &proxyTableInput{