aboutsummaryrefslogtreecommitdiffstats
path: root/modules/context
diff options
context:
space:
mode:
authorwxiaoguang <wxiaoguang@gmail.com>2023-08-08 09:22:47 +0800
committerGitHub <noreply@github.com>2023-08-08 01:22:47 +0000
commit69130532239ee7ade82977f456c12826e1adeb1e (patch)
tree81b8131bedc592af753481b7d222263b2c2655dc /modules/context
parent0c6ae61229bce9d9ad3d359cee927464968a2dd1 (diff)
downloadgitea-69130532239ee7ade82977f456c12826e1adeb1e.tar.gz
gitea-69130532239ee7ade82977f456c12826e1adeb1e.zip
Start using template context function (#26254)
Before: * `{{.locale.Tr ...}}` * `{{$.locale.Tr ...}}` * `{{$.root.locale.Tr ...}}` * `{{template "sub" .}}` * `{{template "sub" (dict "locale" $.locale)}}` * `{{template "sub" (dict "root" $)}}` * ..... With context function: only need to `{{ctx.Locale.Tr ...}}` The "ctx" could be considered as a super-global variable for all templates including sub-templates. To avoid potential risks (any bug in the template context function package), this PR only starts using "ctx" in "head.tmpl" and "footer.tmpl" and it has a "DataRaceCheck". If there is anything wrong, the code can be fixed or reverted easily.
Diffstat (limited to 'modules/context')
-rw-r--r--modules/context/context.go15
-rw-r--r--modules/context/context_response.go4
-rw-r--r--modules/context/context_template.go49
3 files changed, 63 insertions, 5 deletions
diff --git a/modules/context/context.go b/modules/context/context.go
index de0518a1d2..b75ba9ab67 100644
--- a/modules/context/context.go
+++ b/modules/context/context.go
@@ -5,6 +5,7 @@
package context
import (
+ "context"
"html"
"html/template"
"io"
@@ -31,14 +32,16 @@ import (
// Render represents a template render
type Render interface {
- TemplateLookup(tmpl string) (templates.TemplateExecutor, error)
- HTML(w io.Writer, status int, name string, data any) error
+ TemplateLookup(tmpl string, templateCtx context.Context) (templates.TemplateExecutor, error)
+ HTML(w io.Writer, status int, name string, data any, templateCtx context.Context) error
}
// Context represents context of a request.
type Context struct {
*Base
+ TemplateContext TemplateContext
+
Render Render
PageData map[string]any // data used by JavaScript modules in one page, it's `window.config.pageData`
@@ -60,6 +63,8 @@ type Context struct {
Package *Package
}
+type TemplateContext map[string]any
+
func init() {
web.RegisterResponseStatusProvider[*Context](func(req *http.Request) web_types.ResponseStatusProvider {
return req.Context().Value(WebContextKey).(*Context)
@@ -133,8 +138,12 @@ func Contexter() func(next http.Handler) http.Handler {
}
defer baseCleanUp()
+ // TODO: "install.go" also shares the same logic, which should be refactored to a general function
+ ctx.TemplateContext = NewTemplateContext(ctx)
+ ctx.TemplateContext["Locale"] = ctx.Locale
+
ctx.Data.MergeFrom(middleware.CommonTemplateContextData())
- ctx.Data["Context"] = &ctx
+ ctx.Data["Context"] = ctx // TODO: use "ctx" in template and remove this
ctx.Data["CurrentURL"] = setting.AppSubURL + req.URL.RequestURI()
ctx.Data["Link"] = ctx.Link
ctx.Data["locale"] = ctx.Locale
diff --git a/modules/context/context_response.go b/modules/context/context_response.go
index 9dc6d1fc0e..5729865561 100644
--- a/modules/context/context_response.go
+++ b/modules/context/context_response.go
@@ -75,7 +75,7 @@ func (ctx *Context) HTML(status int, name base.TplName) {
return strconv.FormatInt(time.Since(tmplStartTime).Nanoseconds()/1e6, 10) + "ms"
}
- err := ctx.Render.HTML(ctx.Resp, status, string(name), ctx.Data)
+ err := ctx.Render.HTML(ctx.Resp, status, string(name), ctx.Data, ctx.TemplateContext)
if err == nil {
return
}
@@ -93,7 +93,7 @@ func (ctx *Context) HTML(status int, name base.TplName) {
// RenderToString renders the template content to a string
func (ctx *Context) RenderToString(name base.TplName, data map[string]any) (string, error) {
var buf strings.Builder
- err := ctx.Render.HTML(&buf, http.StatusOK, string(name), data)
+ err := ctx.Render.HTML(&buf, http.StatusOK, string(name), data, ctx.TemplateContext)
return buf.String(), err
}
diff --git a/modules/context/context_template.go b/modules/context/context_template.go
new file mode 100644
index 0000000000..ba90fc170a
--- /dev/null
+++ b/modules/context/context_template.go
@@ -0,0 +1,49 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package context
+
+import (
+ "context"
+ "errors"
+ "time"
+
+ "code.gitea.io/gitea/modules/log"
+)
+
+var _ context.Context = TemplateContext(nil)
+
+func NewTemplateContext(ctx context.Context) TemplateContext {
+ return TemplateContext{"_ctx": ctx}
+}
+
+func (c TemplateContext) parentContext() context.Context {
+ return c["_ctx"].(context.Context)
+}
+
+func (c TemplateContext) Deadline() (deadline time.Time, ok bool) {
+ return c.parentContext().Deadline()
+}
+
+func (c TemplateContext) Done() <-chan struct{} {
+ return c.parentContext().Done()
+}
+
+func (c TemplateContext) Err() error {
+ return c.parentContext().Err()
+}
+
+func (c TemplateContext) Value(key any) any {
+ return c.parentContext().Value(key)
+}
+
+// DataRaceCheck checks whether the template context function "ctx()" returns the consistent context
+// as the current template's rendering context (request context), to help to find data race issues as early as possible.
+// When the code is proven to be correct and stable, this function should be removed.
+func (c TemplateContext) DataRaceCheck(dataCtx context.Context) (string, error) {
+ if c.parentContext() != dataCtx {
+ log.Error("TemplateContext.DataRaceCheck: parent context mismatch\n%s", log.Stack(2))
+ return "", errors.New("parent context mismatch")
+ }
+ return "", nil
+}