使用模板

时间:2018-05-18 09:48:35

标签: html go go-templates

我开始使用Go语言,现在正在尝试创建HTML页面。我对Go和HTML编码都很陌生。

在Go程序中我试图将HTML页面(div)解析为主html页面(index.html) 我正在尝试使用Go中的模板将此div添加到主html页面。

我正在尝试将数据解析为的html页面如下所示:

<html>
<head>
    <meta charset="utf-8">
    <title>SmartHomePi Status</title>
    <link rel="stylesheet" href="../static/css/style.css">
</head>
<body>
    <h1>HomeControl Connection Status</h1>
    <div id="wrapper" width="100%">
        {{.SonoffBasic}}
    </div>
</body>

{{.SonoffBasic}}部分是我正在尝试添加div的部分。 我试图添加的div看起来像这样:

<div id="sonoffbasicdevice">
    <span class="%connectiondotclass%"></span>
    <p id="title">%title%</p>
    <p id="tempandhum">%humstatus%</p>
    <p id="ipaddress">%ipaddress%</p>
    <p id="portnumber">%portnumber%</p>
</div>

所有带有%xxx%的值都会被解析为包含有用的信息,一切都正确。

但是现在我正在尝试使用Go in Template解析那些2,这里看起来似乎有些不对劲。

我正在Go中执行以下功能:

func renderHomeKitTemplate(w http.ResponseWriter, tmpl string, items *WebPageHTMLItems) {
    err := templates.ExecuteTemplate(w, "index.html", items)
} 

变量项是一个如下所示的结构:

type WebPageHTMLItems struct{
    SonoffBasic  string
}

其中,theSonoffBasic字符串包含所有填写信息的div。

当我运行程序时可以查看网页,但是当显示网页时,而不是解析div,它显示为纯文本,我在这里做错了什么? HTML code shown as text

这是将数据解析为HTML文件的正确方法吗?我之所以使用这种方式添加一个完整的div,是因为我可以有多个“sonoffbasicdevice”项,并且应该添加多个。

1 个答案:

答案 0 :(得分:2)

使用template.HTML

html/template提供自动,上下文敏感的转义,以防止代码注入:

  

HTML模板将数据值视为纯文本,应对其进行编码,以便将它们安全地嵌入到HTML文档中。转义是上下文的,因此动作可以出现在JavaScript,CSS和URI上下文中。

html/template包中有一种特殊类型:template.HTML。在渲染模板时,模板中此类型的值不会被转义。

因此,将WebPageHTMLItems.SonoffBasic的类型更改为template.HTML,它将按原样呈现:

type WebPageHTMLItems struct{
    SonoffBasic template.HTML
}

template.HTML已将string作为其基础类型,因此要从string值设置此字段,请使用简单的类型转换:

params := &WebPageHTMLItems{
    SonoffBasic: template.HTML("<div>...</div>"),
}

警告语:这不会防止代码注入!因此,例如,当您替换%title%并且它包含JavaScript代码时,它将通过输出并最终在客户端中执行&#39;浏览器。

使用{{template}}操作

另请注意,您可以将<div>定义为单独的命名模板,只需使用{{template}}操作将其包含在您的网页中,如下所示:

{{define "sonoffbasicdevice"}}
    <div id="sonoffbasicdevice">
        <span class="%connectiondotclass%"></span>
        <p id="title">%title%</p>
        <p id="tempandhum">%humstatus%</p>
        <p id="ipaddress">%ipaddress%</p>
        <p id="portnumber">%portnumber%</p>
    </div>
{{end}}

在您的页面模板中:

<div id="wrapper" width="100%">
    {{template "sonoffbasicdevice"}}
</div>

另请注意,要在此处完全安全,您还可以制作并将params传递给sonoffbasicdevice模板,与其他任何模板一样,并让html/template包安全处理敏感的替代:

{{define "sonoffbasicdevice"}}
    <div id="sonoffbasicdevice">
        <span class="{{.Connectiondotclass}}"></span>
        <p id="title">{{.Title}}</p>
        <p id="tempandhum">{{.Humstatus}}</p>
        <p id="ipaddress">{{.Ipaddress}}</p>
        <p id="portnumber">{{.Portnumber}}</p>
    </div>
{{end}}

然后你必须像这样包括它(传递用于它的params):

<div id="wrapper" width="100%">
    {{template "sonoffbasicdevice" .SonoffBasic}}
</div>

执行此&#34;多模板&#34;可能看起来像这样:

type SonoffBasic struct {
    Connectiondotclass string
    Title              string
    Humstatus          string
    Ipaddress          string
    Portnumber         string
}

type WebPageHTMLItems struct{
    SonoffBasic *SonoffBasic
}

params := &WebPageHTMLItems{
    SonoffBasic: &SonoffBasic{
        Connectiondotclass: "someclass",
        Title:              "sometitle",
        Humstatus:          "somestatus",
        Ipaddress:          "someip",
        Portnumber:         "someport",
    },
}

err := templates.ExecuteTemplate(w, "index.html", params)