Golang中如何转义A标签href属性中的保留字符
Golang中如何转义A标签href属性中的保留字符 我使用 html/template 生成 HTML,但在 a 标签的 href 属性中,保留字符被 html/template 转义了。
我知道根据 RFC 3986,保留字符不应被转义。如何避免在 href 属性中转义保留字符?
例如…
dict := make(map[string]interface{})
dict["link"] = `https://example.com/()"`
tag := `<a href="{{ $.link }}"></a>`
t, _ := template.New("tag").Parse(tag)
var tpl bytes.Buffer
e := t.Execute(&tpl, dict)
if e != nil {
fmt.Println(e)
}
fmt.Println(tpl.String())
// <a href="https://example.com/%28%29%22"></a>
我期望的结果是
// <a href="https://example.com/()"></a>
更多关于Golang中如何转义A标签href属性中的保留字符的实战教程也可以访问 https://www.itying.com/category-94-b0.html
这两个URL是同一资源的不同等价表示。
更多关于Golang中如何转义A标签href属性中的保留字符的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
两者都正确吗? 我认为根据 RFC 3986 规范,并未执行百分号编码。
尽管您可以直接使用许多字符,但始终可以使用百分比编码。
例如,“A”可以直接书写,但 %41 必须被视为等效。
// 代码示例:演示百分比编码处理
func main() {
// 直接字符和编码字符应被同等处理
fmt.Println("直接字符: A")
fmt.Println("编码字符: %41")
}
在 html/template 中,href 属性默认会被 URL 转义。要避免转义保留字符,可以使用 template.URL 类型包装你的 URL 字符串。
package main
import (
"bytes"
"fmt"
"html/template"
)
func main() {
dict := make(map[string]interface{})
dict["link"] = template.URL(`https://example.com/()"`)
tag := `<a href="{{ $.link }}"></a>`
t, _ := template.New("tag").Parse(tag)
var tpl bytes.Buffer
e := t.Execute(&tpl, dict)
if e != nil {
fmt.Println(e)
}
fmt.Println(tpl.String())
// 输出: <a href="https://example.com/()"></a>
}
template.URL 类型实现了 template.URL 接口,告诉模板引擎这个值已经是安全的 URL,不需要额外转义。注意双引号 " 仍然会被转义,因为它在 HTML 属性值中是特殊字符。
对于更复杂的场景,比如需要保留查询参数中的保留字符:
dict["link"] = template.URL(`https://example.com/path?query=foo&bar=baz&special=()*`)
// 输出: <a href="https://example.com/path?query=foo&bar=baz&special=()*"></a>
如果 URL 中包含用户输入,需要确保安全性:
import "net/url"
func safeURL(rawURL string) (template.URL, error) {
parsed, err := url.Parse(rawURL)
if err != nil {
return "", err
}
// 验证协议,防止 javascript: 等危险协议
if parsed.Scheme != "http" && parsed.Scheme != "https" {
return "", fmt.Errorf("unsupported scheme")
}
return template.URL(rawURL), nil
}
// 使用
safe, err := safeURL(userInput)
if err != nil {
// 处理错误
}
dict["link"] = safe
对于需要完全控制 URL 编码的情况,可以手动处理:
dict["link"] = template.URL(`https://example.com/` + url.PathEscape(`path with spaces`) + `?q=` + url.QueryEscape(`query with & and =`))
这样可以在不同部分应用适当的编码规则。

