使用go Template解析页面中显示为纯文本的HTML代码

ar5n3qh5  于 2023-11-14  发布在  Go
关注(0)|答案(2)|浏览(152)

我已经开始使用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中被解析以包含有用的信息,并且一切都是正确的。
但是现在我试图在Go中使用模板来解析这两个,这里似乎出错了。
我在Go中使用了以下函数:

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


其中变量items是一个结构体,如下所示:

type WebPageHTMLItems struct{
    SonoffBasic  string
}


其中SonoffBasic字符串包含所有已填充信息的div。
当我运行程序时可以查看网页,但是当显示网页时,而不是解析div,它显示为纯文本,我在这里做错了什么?x1c 0d1x
这是将数据解析到HTML文件中的正确方法吗?我使用这种方法添加一个完整的div的原因是,我可以有多个“sonoffbasicdevice”项目,并且应该添加多个项目。

wi3ka0sx

wi3ka0sx1#

使用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代码,这将被允许通过输出,并最终在客户端的浏览器中执行。

使用{{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>


还要注意的是,为了完全安全起见,你也可以像其他模板一样创建并传递参数给你的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}}


然后你必须像这样包含它(传递针对它的参数):

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


这个“多模板”的执行可能看起来像这样:

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)

vaqhlq81

vaqhlq812#

我们有两个包用于在Golang中生成模板

  1. HTML/template
  2. text/template
    如果你确定你的数据,你可以使用text/template代替html/template

相关问题