feat: templatized proxy error page
All checks were successful
Cadoles/bouncer/pipeline/head This commit looks good
All checks were successful
Cadoles/bouncer/pipeline/head This commit looks good
This commit is contained in:
@ -7,22 +7,26 @@ import (
|
||||
)
|
||||
|
||||
type ProxyServerConfig struct {
|
||||
HTTP HTTPConfig `yaml:"http"`
|
||||
Metrics MetricsConfig `yaml:"metrics"`
|
||||
Transport TransportConfig `yaml:"transport"`
|
||||
Dial DialConfig `yaml:"dial"`
|
||||
Sentry SentryConfig `yaml:"sentry"`
|
||||
Cache CacheConfig `yaml:"cache"`
|
||||
Debug InterpolatedBool `yaml:"debug"`
|
||||
HTTP HTTPConfig `yaml:"http"`
|
||||
Metrics MetricsConfig `yaml:"metrics"`
|
||||
Transport TransportConfig `yaml:"transport"`
|
||||
Dial DialConfig `yaml:"dial"`
|
||||
Sentry SentryConfig `yaml:"sentry"`
|
||||
Cache CacheConfig `yaml:"cache"`
|
||||
Templates TemplatesConfig `yaml:"templates"`
|
||||
}
|
||||
|
||||
func NewDefaultProxyServerConfig() ProxyServerConfig {
|
||||
return ProxyServerConfig{
|
||||
Debug: false,
|
||||
HTTP: NewHTTPConfig("0.0.0.0", 8080),
|
||||
Metrics: NewDefaultMetricsConfig(),
|
||||
Transport: NewDefaultTransportConfig(),
|
||||
Dial: NewDefaultDialConfig(),
|
||||
Sentry: NewDefaultSentryConfig(),
|
||||
Cache: NewDefaultCacheConfig(),
|
||||
Templates: NewDefaultTemplatesConfig(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,3 +119,13 @@ func NewDefaultCacheConfig() CacheConfig {
|
||||
TTL: *NewInterpolatedDuration(time.Second * 30),
|
||||
}
|
||||
}
|
||||
|
||||
type TemplatesConfig struct {
|
||||
Dir InterpolatedString `yaml:"dir"`
|
||||
}
|
||||
|
||||
func NewDefaultTemplatesConfig() TemplatesConfig {
|
||||
return TemplatesConfig{
|
||||
Dir: "./templates",
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,14 @@ package proxy
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"forge.cadoles.com/Cadoles/go-proxy"
|
||||
@ -17,6 +20,8 @@ import (
|
||||
"forge.cadoles.com/cadoles/bouncer/internal/config"
|
||||
"forge.cadoles.com/cadoles/bouncer/internal/proxy/director"
|
||||
"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"
|
||||
@ -191,7 +196,63 @@ func (s *Server) errorHandler(w http.ResponseWriter, r *http.Request, err error)
|
||||
logger.Error(r.Context(), "proxy error", logger.E(err))
|
||||
sentry.CaptureException(err)
|
||||
|
||||
http.Error(w, http.StatusText(http.StatusBadGateway), http.StatusBadGateway)
|
||||
s.renderErrorPage(w, r, err, http.StatusBadGateway, http.StatusText(http.StatusBadGateway))
|
||||
}
|
||||
|
||||
func (s *Server) renderErrorPage(w http.ResponseWriter, r *http.Request, err error, statusCode int, status string) {
|
||||
templateData := struct {
|
||||
StatusCode int
|
||||
Status string
|
||||
Err error
|
||||
Debug bool
|
||||
}{
|
||||
Debug: bool(s.serverConfig.Debug),
|
||||
StatusCode: statusCode,
|
||||
Status: status,
|
||||
Err: err,
|
||||
}
|
||||
|
||||
w.WriteHeader(statusCode)
|
||||
s.renderPage(w, r, "error", strconv.FormatInt(int64(statusCode), 10), templateData)
|
||||
}
|
||||
|
||||
func (s *Server) renderPage(w http.ResponseWriter, r *http.Request, page string, block string, templateData any) {
|
||||
ctx := r.Context()
|
||||
|
||||
templatesConf := s.serverConfig.Templates
|
||||
|
||||
pattern := filepath.Join(string(templatesConf.Dir), page+".gohtml")
|
||||
|
||||
logger.Info(ctx, "loading proxy templates", logger.F("pattern", pattern))
|
||||
|
||||
tmpl, err := template.New("").Funcs(sprig.FuncMap()).ParseGlob(pattern)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not load proxy templates", logger.E(errors.WithStack(err)))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Add("Cache-Control", "no-cache")
|
||||
|
||||
blockTmpl := tmpl.Lookup(block)
|
||||
if blockTmpl == nil {
|
||||
blockTmpl = tmpl.Lookup("default")
|
||||
}
|
||||
|
||||
if blockTmpl == nil {
|
||||
logger.Error(ctx, "could not find template block nor default one", logger.F("block", block))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if err := blockTmpl.Execute(w, templateData); err != nil {
|
||||
logger.Error(ctx, "could not render proxy page", logger.E(errors.WithStack(err)))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func NewServer(funcs ...OptionFunc) *Server {
|
||||
|
Reference in New Issue
Block a user