diff options
author | Mike Crute <mike@crute.us> | 2023-08-20 09:36:43 -0700 |
---|---|---|
committer | Mike Crute <mike@crute.us> | 2023-08-20 09:36:43 -0700 |
commit | 37dbd38e00bbe51d1aa2d46bf7a7f454034dd4a2 (patch) | |
tree | b1d1a40a56594d4e7ac2ec8a6655ab57d9d3556a | |
parent | d45bc849d6360b28ddb52ff49c5ef0a694c8a15b (diff) | |
download | golib-37dbd38e00bbe51d1aa2d46bf7a7f454034dd4a2.tar.bz2 golib-37dbd38e00bbe51d1aa2d46bf7a7f454034dd4a2.tar.xz golib-37dbd38e00bbe51d1aa2d46bf7a7f454034dd4a2.zip |
echo: expose error handlerecho/v0.11.2
-rw-r--r-- | TODO.md | 1 | ||||
-rw-r--r-- | echo/echo_default.go | 16 | ||||
-rw-r--r-- | echo/error_handler.go | 39 |
3 files changed, 38 insertions, 18 deletions
@@ -1,2 +1,3 @@ | |||
1 | [ ] Contribute crypto/ocsp/client.go to x/crypto | 1 | [ ] Contribute crypto/ocsp/client.go to x/crypto |
2 | [ ] secrets: add AEAD/AAD method for `associated_data` (base64 encoded) | 2 | [ ] secrets: add AEAD/AAD method for `associated_data` (base64 encoded) |
3 | [ ] echo: nicer HTML error messages (https://github.com/pkg/errors/blob/master/stack.go) | ||
diff --git a/echo/echo_default.go b/echo/echo_default.go index ff3c754..33ad015 100644 --- a/echo/echo_default.go +++ b/echo/echo_default.go | |||
@@ -71,9 +71,10 @@ type EchoConfig struct { | |||
71 | 71 | ||
72 | type EchoWrapper struct { | 72 | type EchoWrapper struct { |
73 | *echo.Echo | 73 | *echo.Echo |
74 | runner *service.AppRunner | 74 | runner *service.AppRunner |
75 | autocert autocert.PrimingCertProvider | 75 | autocert autocert.PrimingCertProvider |
76 | templateFS fs.FS | 76 | templateFS fs.FS |
77 | errorHandler ErrorHandler | ||
77 | } | 78 | } |
78 | 79 | ||
79 | // NewEchoWrapper creates a new instance of Echo and wraps it in an | 80 | // NewEchoWrapper creates a new instance of Echo and wraps it in an |
@@ -132,6 +133,10 @@ func (w *EchoWrapper) GetTemplateFS() fs.FS { | |||
132 | return w.templateFS | 133 | return w.templateFS |
133 | } | 134 | } |
134 | 135 | ||
136 | func (w *EchoWrapper) AddErrorHandler(h ContentErrorHandler, mime ...string) { | ||
137 | w.errorHandler.AddHandler(h, mime...) | ||
138 | } | ||
139 | |||
135 | func (w *EchoWrapper) Configure(c EchoConfig) error { | 140 | func (w *EchoWrapper) Configure(c EchoConfig) error { |
136 | w.configureAutocert(&c) | 141 | w.configureAutocert(&c) |
137 | 142 | ||
@@ -207,12 +212,13 @@ func (w *EchoWrapper) configureTemplates(c *EchoConfig) error { | |||
207 | return fmt.Errorf("Error loading template renderer: %w", err) | 212 | return fmt.Errorf("Error loading template renderer: %w", err) |
208 | } | 213 | } |
209 | 214 | ||
210 | w.HTTPErrorHandler = NewDefaultErrorHandler(tr).HandleError | 215 | w.errorHandler = NewDefaultErrorHandler(tr) |
211 | w.Renderer = tr | 216 | w.Renderer = tr |
212 | } else { | 217 | } else { |
213 | w.HTTPErrorHandler = NewNoHTMLErrorHandler().HandleError | 218 | w.errorHandler = NewNoHTMLErrorHandler() |
214 | } | 219 | } |
215 | 220 | ||
221 | w.HTTPErrorHandler = w.errorHandler.HandleError | ||
216 | w.templateFS = templates | 222 | w.templateFS = templates |
217 | return nil | 223 | return nil |
218 | } | 224 | } |
diff --git a/echo/error_handler.go b/echo/error_handler.go index 6874eff..a0bdd60 100644 --- a/echo/error_handler.go +++ b/echo/error_handler.go | |||
@@ -10,17 +10,22 @@ import ( | |||
10 | "github.com/labstack/echo/v4" | 10 | "github.com/labstack/echo/v4" |
11 | ) | 11 | ) |
12 | 12 | ||
13 | // TODO: This should have some kind of HTML formatting of panics in debug mode | ||
14 | |||
15 | type ContentErrorHandler interface { | 13 | type ContentErrorHandler interface { |
16 | Handle(echo.Context, *echo.HTTPError) error | 14 | Handle(echo.Context, *echo.HTTPError) error |
17 | } | 15 | } |
18 | 16 | ||
17 | type ErrorHandler interface { | ||
18 | AddHandler(ContentErrorHandler, ...string) | ||
19 | HandleError(error, echo.Context) | ||
20 | } | ||
21 | |||
19 | type HTMLErrorHandler struct { | 22 | type HTMLErrorHandler struct { |
20 | r *TemplateRenderer | 23 | r *TemplateRenderer |
21 | fallback *template.Template | 24 | fallback *template.Template |
22 | } | 25 | } |
23 | 26 | ||
27 | var _ ContentErrorHandler = (*HTMLErrorHandler)(nil) | ||
28 | |||
24 | func NewHTMLErrorHandler(r *TemplateRenderer) *HTMLErrorHandler { | 29 | func NewHTMLErrorHandler(r *TemplateRenderer) *HTMLErrorHandler { |
25 | t, err := template.New("").Parse("<html><body><h1>Error</h1><pre>{{ .Message }}</pre></body></html>\n") | 30 | t, err := template.New("").Parse("<html><body><h1>Error</h1><pre>{{ .Message }}</pre></body></html>\n") |
26 | if err != nil { | 31 | if err != nil { |
@@ -58,12 +63,16 @@ func (h *HTMLErrorHandler) Handle(c echo.Context, e *echo.HTTPError) error { | |||
58 | 63 | ||
59 | type PlainTextErrorHandler struct{} | 64 | type PlainTextErrorHandler struct{} |
60 | 65 | ||
66 | var _ ContentErrorHandler = (*PlainTextErrorHandler)(nil) | ||
67 | |||
61 | func (h *PlainTextErrorHandler) Handle(c echo.Context, e *echo.HTTPError) error { | 68 | func (h *PlainTextErrorHandler) Handle(c echo.Context, e *echo.HTTPError) error { |
62 | return c.String(e.Code, fmt.Sprintf("%s", e.Message)) | 69 | return c.String(e.Code, fmt.Sprintf("%s", e.Message)) |
63 | } | 70 | } |
64 | 71 | ||
65 | type JSONErrorHandler struct{} | 72 | type JSONErrorHandler struct{} |
66 | 73 | ||
74 | var _ ContentErrorHandler = (*JSONErrorHandler)(nil) | ||
75 | |||
67 | func (h *JSONErrorHandler) Handle(c echo.Context, e *echo.HTTPError) error { | 76 | func (h *JSONErrorHandler) Handle(c echo.Context, e *echo.HTTPError) error { |
68 | code := e.Code | 77 | code := e.Code |
69 | message := e.Message | 78 | message := e.Message |
@@ -80,28 +89,32 @@ func (h *JSONErrorHandler) Handle(c echo.Context, e *echo.HTTPError) error { | |||
80 | 89 | ||
81 | type failsafeHandler struct{} | 90 | type failsafeHandler struct{} |
82 | 91 | ||
92 | var _ ContentErrorHandler = (*failsafeHandler)(nil) | ||
93 | |||
83 | func (h *failsafeHandler) Handle(c echo.Context, e *echo.HTTPError) error { | 94 | func (h *failsafeHandler) Handle(c echo.Context, e *echo.HTTPError) error { |
84 | c.Echo().Logger.Error("Error while processing error page: %s", e) | 95 | c.Echo().Logger.Error("Error while processing error page: %s", e) |
85 | c.JSON(http.StatusInternalServerError, e) | 96 | c.JSON(http.StatusInternalServerError, e) |
86 | return nil | 97 | return nil |
87 | } | 98 | } |
88 | 99 | ||
89 | type ErrorHandler struct { | 100 | type EchoErrorHandler struct { |
90 | types []contenttype.MediaType | 101 | types []contenttype.MediaType |
91 | typeMap map[string]ContentErrorHandler | 102 | typeMap map[string]ContentErrorHandler |
92 | failsafeHandler ContentErrorHandler | 103 | failsafeHandler ContentErrorHandler |
93 | } | 104 | } |
94 | 105 | ||
95 | func NewErrorHandler() *ErrorHandler { | 106 | var _ ErrorHandler = (*EchoErrorHandler)(nil) |
96 | return &ErrorHandler{ | 107 | |
108 | func NewEchoErrorHandler() *EchoErrorHandler { | ||
109 | return &EchoErrorHandler{ | ||
97 | types: []contenttype.MediaType{}, | 110 | types: []contenttype.MediaType{}, |
98 | typeMap: map[string]ContentErrorHandler{}, | 111 | typeMap: map[string]ContentErrorHandler{}, |
99 | failsafeHandler: &failsafeHandler{}, | 112 | failsafeHandler: &failsafeHandler{}, |
100 | } | 113 | } |
101 | } | 114 | } |
102 | 115 | ||
103 | func NewDefaultErrorHandler(tr *TemplateRenderer) *ErrorHandler { | 116 | func NewDefaultErrorHandler(tr *TemplateRenderer) *EchoErrorHandler { |
104 | h := NewErrorHandler() | 117 | h := NewEchoErrorHandler() |
105 | 118 | ||
106 | // The order of these is important, especially when negotiating */* | 119 | // The order of these is important, especially when negotiating */* |
107 | h.AddHandler(&JSONErrorHandler{}, "text/json", "application/json") | 120 | h.AddHandler(&JSONErrorHandler{}, "text/json", "application/json") |
@@ -111,8 +124,8 @@ func NewDefaultErrorHandler(tr *TemplateRenderer) *ErrorHandler { | |||
111 | return h | 124 | return h |
112 | } | 125 | } |
113 | 126 | ||
114 | func NewNoHTMLErrorHandler() *ErrorHandler { | 127 | func NewNoHTMLErrorHandler() *EchoErrorHandler { |
115 | h := NewErrorHandler() | 128 | h := NewEchoErrorHandler() |
116 | 129 | ||
117 | // The order of these is important, especially when negotiating */* | 130 | // The order of these is important, especially when negotiating */* |
118 | h.AddHandler(&JSONErrorHandler{}, "text/json", "application/json") | 131 | h.AddHandler(&JSONErrorHandler{}, "text/json", "application/json") |
@@ -121,14 +134,14 @@ func NewNoHTMLErrorHandler() *ErrorHandler { | |||
121 | return h | 134 | return h |
122 | } | 135 | } |
123 | 136 | ||
124 | func (h *ErrorHandler) AddHandler(eh ContentErrorHandler, contentTypes ...string) { | 137 | func (h *EchoErrorHandler) AddHandler(eh ContentErrorHandler, contentTypes ...string) { |
125 | for _, ct := range contentTypes { | 138 | for _, ct := range contentTypes { |
126 | h.types = append(h.types, contenttype.NewMediaType(ct)) | 139 | h.types = append(h.types, contenttype.NewMediaType(ct)) |
127 | h.typeMap[ct] = eh | 140 | h.typeMap[ct] = eh |
128 | } | 141 | } |
129 | } | 142 | } |
130 | 143 | ||
131 | func (h *ErrorHandler) castToHttpError(e error) *echo.HTTPError { | 144 | func (h *EchoErrorHandler) castToHttpError(e error) *echo.HTTPError { |
132 | he, ok := e.(*echo.HTTPError) | 145 | he, ok := e.(*echo.HTTPError) |
133 | if ok { | 146 | if ok { |
134 | if he.Internal != nil { | 147 | if he.Internal != nil { |
@@ -145,7 +158,7 @@ func (h *ErrorHandler) castToHttpError(e error) *echo.HTTPError { | |||
145 | } | 158 | } |
146 | } | 159 | } |
147 | 160 | ||
148 | func (h *ErrorHandler) negotiateContentType(r *http.Request) (ContentErrorHandler, error) { | 161 | func (h *EchoErrorHandler) negotiateContentType(r *http.Request) (ContentErrorHandler, error) { |
149 | var err error | 162 | var err error |
150 | 163 | ||
151 | ct, _, err := contenttype.GetAcceptableMediaType(r, h.types) | 164 | ct, _, err := contenttype.GetAcceptableMediaType(r, h.types) |
@@ -163,7 +176,7 @@ func (h *ErrorHandler) negotiateContentType(r *http.Request) (ContentErrorHandle | |||
163 | return handle, err | 176 | return handle, err |
164 | } | 177 | } |
165 | 178 | ||
166 | func (h *ErrorHandler) HandleError(err error, c echo.Context) { | 179 | func (h *EchoErrorHandler) HandleError(err error, c echo.Context) { |
167 | defer func() { | 180 | defer func() { |
168 | if r := recover(); r != nil { | 181 | if r := recover(); r != nil { |
169 | if err, ok := r.(error); !ok { | 182 | if err, ok := r.(error); !ok { |