feat: global error handler with template rendering
Some checks are pending
Cadoles/bouncer/pipeline/pr-develop Build started...

This commit is contained in:
2024-09-27 10:09:25 +02:00
parent 590505e17a
commit d4c28b80d7
11 changed files with 109 additions and 63 deletions

View File

@ -1,9 +1,11 @@
package proxy
import (
"bytes"
"context"
"fmt"
"html/template"
"io"
"log"
"net"
"net/http"
@ -23,7 +25,6 @@ import (
"forge.cadoles.com/cadoles/bouncer/internal/store"
"github.com/Masterminds/sprig/v3"
"github.com/getsentry/sentry-go"
sentryhttp "github.com/getsentry/sentry-go/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
@ -112,6 +113,7 @@ func (s *Server) run(parentCtx context.Context, addrs chan net.Addr, errs chan e
s.directorCacheTTL,
),
),
director.WithHandleErrorFunc(s.handleError),
)
if s.serverConfig.HTTP.UseRealIP {
@ -217,27 +219,24 @@ func (s *Server) createReverseProxy(ctx context.Context, target *url.URL) *httpu
httpTransport.DialContext = dialer.DialContext
reverseProxy.Transport = httpTransport
reverseProxy.ErrorHandler = s.handleError
reverseProxy.ErrorHandler = s.handleProxyError
return reverseProxy
}
func (s *Server) handleDefault(w http.ResponseWriter, r *http.Request) {
err := errors.Errorf("no proxy target found")
logger.Error(r.Context(), "proxy error", logger.CapturedE(err))
sentry.CaptureException(err)
s.renderErrorPage(w, r, err, http.StatusBadGateway, http.StatusText(http.StatusBadGateway))
s.handleError(w, r, http.StatusBadGateway, errors.Errorf("no proxy target found"))
}
func (s *Server) handleError(w http.ResponseWriter, r *http.Request, err error) {
func (s *Server) handleError(w http.ResponseWriter, r *http.Request, status int, err error) {
err = errors.WithStack(err)
logger.Error(r.Context(), err.Error(), logger.CapturedE(err))
logger.Error(r.Context(), "proxy error", logger.CapturedE(err))
sentry.CaptureException(err)
s.renderErrorPage(w, r, err, status, http.StatusText(status))
}
s.renderErrorPage(w, r, err, http.StatusBadGateway, http.StatusText(http.StatusBadGateway))
func (s *Server) handleProxyError(w http.ResponseWriter, r *http.Request, err error) {
s.handleError(w, r, http.StatusBadGateway, err)
}
func (s *Server) renderErrorPage(w http.ResponseWriter, r *http.Request, err error, statusCode int, status string) {
@ -288,12 +287,18 @@ func (s *Server) renderPage(w http.ResponseWriter, r *http.Request, page string,
return
}
if err := blockTmpl.Execute(w, templateData); err != nil {
var buf bytes.Buffer
if err := blockTmpl.Execute(&buf, templateData); err != nil {
logger.Error(ctx, "could not render proxy page", logger.CapturedE(errors.WithStack(err)))
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
if _, err := io.Copy(w, &buf); err != nil {
logger.Error(ctx, "could not write page", logger.CapturedE(errors.WithStack(err)))
}
}
func NewServer(funcs ...OptionFunc) *Server {