在结构体中转义数组字段中的HTML。

huangapple go评论88阅读模式
英文:

Escape HTML in array field in struct

问题

当你在结构体的数组字段中进行HTML转义时,你可以使用html/template包提供的html函数来实现。

对于单个展示页面,你可以使用以下代码:

show.go:

err := ShowTmpl.ExecuteTemplate(w, "show.html", struct {
    Title    string
    SafeBody template.HTML
}{
    t.Title,
    template.HTML(t.BodyHTML),
})

对于索引页面:

index.go:

type as struct {
    Articles []*Article
}
var a as

// 一些代码来给a.Articles赋值

err := IndexTmpl.ExecuteTemplate(w, "index.html", a)
if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
}

index.html:

{{with .Articles}}
  {{range .}}
    <a href="/">{{.Title}}</a>
    {{.BodyHTML | html}} <!-- 这里不起作用 -->
  {{end}}
{{end}}

当你在结构体字段上进行迭代时,可以使用html函数来转义HTML内容,例如{{.BodyHTML | html}}。这将确保HTML标签被正确转义,以防止XSS攻击。

英文:

How do I escape HTML when I have an array field in a struct?

For a single show page, this code works:

show.go:

err := ShowTmpl.ExecuteTemplate(w, &quot;show.html&quot;, struct {
		Title    string
		SafeBody template.HTML
}{
	t.Title,
	template.HTML(t.BodyHTML),
})

For an index page:

index.go

type as struct {
		Articles []*Article
	}
var a as

// some code to give a.Articles its values

err := IndexTmpl.ExecuteTemplate(w, &quot;index.html&quot;, a)
if err != nil {
	http.Error(w, err.Error(), http.StatusInternalServerError)
}

index.html:

{{with .Articles}}
  {{range .}}
    &lt;a href=&quot;/&quot;&gt;{{.Title}}&lt;/a&gt;
    {{.BodyHTML | html}} // Doesn&#39;t work
  {{end}}
{{end}}

How do I escape HTML when I'm ranging over a struct field?

答案1

得分: 2

你可以通过以下几种方式实现这个目标:

1. 使用自定义函数

你可以使用自定义函数。Template.Funcs() 方法允许你注册任何自定义函数,这些函数可以从模板中调用。

创建一个简单的函数,将 string 转换为 template.HTML,代码如下:

func ToHtml(s string) template.HTML {
	return template.HTML(s)
}

你可以像这样注册它:

t := template.Must(template.New("index.html").
	Funcs(map[string]interface{}{"ToHtml": ToHtml}).Parse(indexHtml))

这里只是为了演示目的,indexHtml 是你的模板的 string

const indexHtml = `{{with .}}
  {{range .}}
    <a href="/">{{.Title}}</a>
    {{ToHtml .BodyHTML}}
  {{end}}
{{end}}
`

你可以在模板中这样引用和调用它:

{{ToHtml .BodyHTML}}

使用参数调用这个模板:

a := []struct {
	Title    string
	BodyHTML string
}{{"I'm the title", "I'm some <b>HTML</b> code!"}}

err := t.ExecuteTemplate(os.Stdout, "index.html", a)

这是在 Go Playground 上的完整示例。

2. 修改 Article 结构体

如果可以的话,更简单的方法是将 Article.BodyHTML 的类型更改为 template.HTML,这样它将被渲染为未转义的 HTML。这也会使意图清晰(它应该/包含安全的 HTML,并将以未转义的形式呈现)。

3. 在 Article 中添加一个方法

你还可以在 Article 类型中添加一个方法,该方法将 BodyHTML 字段作为 template.HTML 返回(与建议 #1 中的自定义函数基本相同):

func (a *Article) SafeBody() template.HTML {
    return template.HTML(a.BodyHTML)
}

有了这个方法,你可以在模板中直接调用它:

  {{range .}}
    <a href="/">{{.Title}}</a>
    {{.SafeBody}}
  {{end}}

Go Playground 上尝试这个变体。

英文:

You can achieve this in several ways:

1. With a custom function

You can use a custom function. The Template.Funcs() method allows you to register any custom functions which can be invoked from templates.

Create a simple function which converts a string to template.HTML like this:

func ToHtml(s string) template.HTML {
	return template.HTML(s)
}

You can register it like this:

t := template.Must(template.New(&quot;index.html&quot;).
	Funcs(map[string]interface{}{&quot;ToHtml&quot;: ToHtml}).Parse(indexHtml))

Where just for demonstration purposes indexHtml is a string of your template:

const indexHtml = `{{with .}}
  {{range .}}
    &lt;a href=&quot;/&quot;&gt;{{.Title}}&lt;/a&gt;
    {{ToHtml .BodyHTML}}
  {{end}}
{{end}}
`

And you can refer to it and call it from the template like this:

{{ToHtml .BodyHTML}}

Calling this template with a parameter:

a := []struct {
	Title    string
	BodyHTML string
}{{&quot;I&#39;m the title&quot;, &quot;I&#39;m some &lt;b&gt;HTML&lt;/b&gt; code!&quot;}}

err := t.ExecuteTemplate(os.Stdout, &quot;index.html&quot;, a)

Here's the complete, working example on the Go Playground.

2. Modifying Article

If you can, it would be easier to just change the type of Article.BodyHTML to template.HTML and then it would be rendered unescaped without further ado. This would also make the intent clear (that it should/does contain safe HTML which will be rendered unescaped).

3. Adding a method to Article

You can also add a method to the Article type which would return its BodyHTML field as a template.HTML (pretty much what the custom function does in proposition #1):

func (a *Article) SafeBody() template.HTML {
    return template.HTML(a.BodyHTML)
}

Having this method you can simply call it from the template:

  {{range .}}
    &lt;a href=&quot;/&quot;&gt;{{.Title}}&lt;/a&gt;
    {{.SafeBody}}
  {{end}}

Try this variant on the Go Playground.

huangapple
  • 本文由 发表于 2015年4月20日 15:18:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/29741487.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定