From 5f017a8f10f23a3b5083bc78265ae37baf61b6b9 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Sat, 8 Apr 2023 17:31:53 +0800 Subject: [PATCH] fine tune template error messages --- modules/context/context.go | 8 ++++---- modules/templates/htmlrenderer.go | 23 ++++++++++++++++++++--- routers/web/auth/oauth.go | 11 +++++++---- routers/web/swagger_json.go | 14 +++++++------- 4 files changed, 38 insertions(+), 18 deletions(-) diff --git a/modules/context/context.go b/modules/context/context.go index 04f8a9bd3d483..c36d8e6dec5d2 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -47,7 +47,7 @@ import ( // Render represents a template render type Render interface { - TemplateLookup(tmpl string) *template.Template + TemplateLookup(tmpl string) (*template.Template, error) HTML(w io.Writer, status int, name string, data interface{}) error } @@ -228,7 +228,7 @@ func (ctx *Context) HTML(status int, name base.TplName) { } if err := ctx.Render.HTML(ctx.Resp, status, string(name), templates.BaseVars().Merge(ctx.Data)); err != nil { if status == http.StatusInternalServerError && name == base.TplName("status/500") { - ctx.PlainText(http.StatusInternalServerError, "Unable to find status/500 template") + ctx.PlainText(http.StatusInternalServerError, "Unable to find HTML templates, the template system is not initialized, or Gitea can't find your template files") return } if execErr, ok := err.(texttemplate.ExecError); ok { @@ -247,7 +247,7 @@ func (ctx *Context) HTML(status int, name base.TplName) { if errorTemplateName != string(name) { filename += " (subtemplate of " + string(name) + ")" } - err = fmt.Errorf("%w\nin template file %s:\n%s", err, filename, templates.GetLineFromTemplate(errorTemplateName, line, target, pos)) + err = fmt.Errorf("failed to render %s, error: %w:\n%s", filename, err, templates.GetLineFromTemplate(errorTemplateName, line, target, pos)) } else { filename, filenameErr := templates.GetAssetFilename("templates/" + execErr.Name + ".tmpl") if filenameErr != nil { @@ -256,7 +256,7 @@ func (ctx *Context) HTML(status int, name base.TplName) { if execErr.Name != string(name) { filename += " (subtemplate of " + string(name) + ")" } - err = fmt.Errorf("%w\nin template file %s", err, filename) + err = fmt.Errorf("failed to render %s, error: %w", filename, err) } } ctx.ServerError("Render failed", err) diff --git a/modules/templates/htmlrenderer.go b/modules/templates/htmlrenderer.go index 5264d65c930f3..f2c818798c72c 100644 --- a/modules/templates/htmlrenderer.go +++ b/modules/templates/htmlrenderer.go @@ -6,6 +6,7 @@ package templates import ( "bytes" "context" + "errors" "fmt" "html/template" "io" @@ -15,9 +16,11 @@ import ( "strconv" "strings" "sync/atomic" + texttemplate "text/template" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/watcher" ) @@ -34,6 +37,8 @@ type HTMLRender struct { templates atomic.Pointer[template.Template] } +var ErrTemplateNotInitialized = errors.New("template system is not initialized, check your log for errors") + func (h *HTMLRender) HTML(w io.Writer, status int, name string, data interface{}) error { if respWriter, ok := w.(http.ResponseWriter); ok { if respWriter.Header().Get("Content-Type") == "" { @@ -41,11 +46,23 @@ func (h *HTMLRender) HTML(w io.Writer, status int, name string, data interface{} } respWriter.WriteHeader(status) } - return h.templates.Load().ExecuteTemplate(w, name, data) + t, err := h.TemplateLookup(name) + if err != nil { + return texttemplate.ExecError{Name: name, Err: err} + } + return t.Execute(w, data) } -func (h *HTMLRender) TemplateLookup(t string) *template.Template { - return h.templates.Load().Lookup(t) +func (h *HTMLRender) TemplateLookup(name string) (*template.Template, error) { + tmpls := h.templates.Load() + if tmpls == nil { + return nil, ErrTemplateNotInitialized + } + tmpl := tmpls.Lookup(name) + if tmpl == nil { + return nil, util.ErrNotExist + } + return tmpl, nil } func (h *HTMLRender) CompileTemplates() error { diff --git a/routers/web/auth/oauth.go b/routers/web/auth/oauth.go index 7de63dbe94ffe..b3c4a234c1ef6 100644 --- a/routers/web/auth/oauth.go +++ b/routers/web/auth/oauth.go @@ -578,12 +578,15 @@ func GrantApplicationOAuth(ctx *context.Context) { // OIDCWellKnown generates JSON so OIDC clients know Gitea's capabilities func OIDCWellKnown(ctx *context.Context) { - t := ctx.Render.TemplateLookup("user/auth/oidc_wellknown") + t, err := ctx.Render.TemplateLookup("user/auth/oidc_wellknown") + if err != nil { + ctx.ServerError("unable to find template", err) + return + } ctx.Resp.Header().Set("Content-Type", "application/json") ctx.Data["SigningKey"] = oauth2.DefaultSigningKey - if err := t.Execute(ctx.Resp, ctx.Data); err != nil { - log.Error("%v", err) - ctx.Error(http.StatusInternalServerError) + if err = t.Execute(ctx.Resp, ctx.Data); err != nil { + ctx.ServerError("unable to execute template", err) } } diff --git a/routers/web/swagger_json.go b/routers/web/swagger_json.go index 2d626c558ed78..1844b90d95b31 100644 --- a/routers/web/swagger_json.go +++ b/routers/web/swagger_json.go @@ -4,11 +4,8 @@ package web import ( - "net/http" - "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/log" ) // tplSwaggerV1Json swagger v1 json template @@ -16,10 +13,13 @@ const tplSwaggerV1Json base.TplName = "swagger/v1_json" // SwaggerV1Json render swagger v1 json func SwaggerV1Json(ctx *context.Context) { - t := ctx.Render.TemplateLookup(string(tplSwaggerV1Json)) + t, err := ctx.Render.TemplateLookup(string(tplSwaggerV1Json)) + if err != nil { + ctx.ServerError("unable to find template", err) + return + } ctx.Resp.Header().Set("Content-Type", "application/json") - if err := t.Execute(ctx.Resp, ctx.Data); err != nil { - log.Error("%v", err) - ctx.Error(http.StatusInternalServerError) + if err = t.Execute(ctx.Resp, ctx.Data); err != nil { + ctx.ServerError("unable to execute template", err) } }