go html/template: 在href属性中保留的字符"()"已自动转义,

bkkx9g8r  于 6个月前  发布在  Go
关注(0)|答案(6)|浏览(60)

我认为保留字符百分比编码没有按照RFC 3986规范进行。

你使用的Go版本是什么(go version)?

1.21

你做了什么?

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/()"></a>

你看到了什么?

<a href="https://example.com/%28%29%22"></a>
pb3s4cty

pb3s4cty2#

从html/template/url.go文件中:

// Single quote and parens are sub-delims in RFC 3986, but we
// escape them so the output can be embedded in single
// quoted attributes and unquoted CSS url(...) constructs.
whitzsjs

whitzsjs3#

Format (webp) is incorrectly encoded to format%28webp%29, and the browser will not encode Format (webp)

package main

import (
	"fmt"
	"net/url"
)

func main() {
	href := "https://img.asuracomics.com/unsafe/fit-in/330x450/filters:format(webp)/https://asuratoon.com/wp-content/uploads/2023/12/¸A°×AC_½AA¼AY´A_AµAcAuc_A¸AIAE²_AOA¾.jpg"
	CorrectURL := "https://img.asuracomics.com/unsafe/fit-in/330x450/filters:format(webp)/https://asuratoon.com/wp-content/uploads/2023/12/%C2%B8A%C2%B0%C3%97AC_%C2%BDAA%C2%BCAY%C2%B4A_A%C2%B5AcAuc_A%C2%B8AIAE%C2%B2_AOA%C2%BE.jpg"
	url, _ := url.Parse(href)
	fmt.Println("Correct URL: ", CorrectURL)
	fmt.Println("net/url URL: ", url.String())
}
Correct URL:  https://img.asuracomics.com/unsafe/fit-in/330x450/filters:format(webp)/https://asuratoon.com/wp-content/uploads/2023/12/%C2%B8A%C2%B0%C3%97AC_%C2%BDAA%C2%BCAY%C2%B4A_A%C2%B5AcAuc_A%C2%B8AIAE%C2%B2_AOA%C2%BE.jpg
net/url URL:  https://img.asuracomics.com/unsafe/fit-in/330x450/filters:format%28webp%29/https://asuratoon.com/wp-content/uploads/2023/12/%C2%B8A%C2%B0%C3%97AC_%C2%BDAA%C2%BCAY%C2%B4A_A%C2%B5AcAuc_A%C2%B8AIAE%C2%B2_AOA%C2%BE.jpg
js81xvg6

js81xvg64#

我相信服务器正确地使用了')'作为分隔符,转义的URI用于另一个(不存在的)资源。
https://www.rfc-editor.org/%72%66%63/%72%66%63%33%39%38%36#%73%65%63%74%69%6F%6E%2D%32.%32
2.2
因此,保留字符集中的字符受到规范化保护,因此可以安全地由特定于方案和生产者算法用于在URI中分隔数据子组件。更改分隔符的编码可能无法通过规范化撤销。
2.3
URI中不同之处在于将非保留字符替换为其相应的百分比编码的US-ASCII八位字节,它们是等价的:它们标识相同的资源。
只提到了非保留字符。
3.3
除了层次结构路径中的点段外,路径段在通用语法中被认为是不透明的。URI生成应用程序通常使用段中允许的保留字符来分隔特定于方案或解引用处理程序的子组件。
'('可以是分隔符(路径、子分隔符、保留)或八位字节/字符。
'%28'可以是没有特殊含义的百分比编码八位字节。
'('和'&'在同一类中,对'&'进行百分比编码会破坏大多数查询。
看起来'('并不等于'%28',尽管许多实现不将'('用作分隔符。
Go http库在解析URL时将'('转义为'%28',并将';'反转义为';'。两者都是子分隔符。

sz81bmfz

sz81bmfz5#

浏览器和html/模板有时在所需的转义程度上存在分歧。
我不认为转义( )是错误的,并且在某些情况下需要转义它们。
在asuracomics URL中,使用格式:%28webp)可以正常工作,但格式:%28webp%29不行。
有趣的是,服务器可以解码%28,但不能解码%。
请注意,维基百科没有问题提供https://en.wikipedia.org/wiki/Comma_%28disambiguation%29
在我看来,将此宣布为服务器错误并让html/模板保持原样是合理的。

vktxenjb

vktxenjb6#

我今天遇到了一个我认为更通用的这个bug的情况,那就是 html/template 似乎是在锚点 href 属性内的字符中逃逸,这使得生成包含链接的模板变得困难。一个简单的复现是在 go1.22.5 在Playground上运行的 here

相关问题