go 建议:html/template:先引用未加引号的属性,再对其进行转义

r1zhe5dt  于 3个月前  发布在  Go
关注(0)|答案(9)|浏览(79)

当前行为
我们允许在“未加引号的属性”上下文中出现动作。
这意味着这个模板是有效的:

<img src={{.}}>

为了支持这一点,当我们转义时,我们需要采取一些额外的小心来转义所有空白(这会破坏令牌)并依赖于一些规范的某些特殊行为。
例如,如果我们使用上面的模板渲染"da ta/",我们得到

<img src=da&#32;ta/>

这看起来像一个非常模糊的语法。( Playground link )
事实证明,如果你遵循规范,这应该解析为

<img src="data/">

但我发现这种行为非常脆弱,尤其是考虑到我们目前使用的转义字符集是通过使用规范的一部分和一个自定义脚本获得的,而这个脚本我们从未重新运行:
go/src/html/template/html.go
第81行到第93行 75e16f5
| | // 要转义的字符集是HTML特殊字符和通过在浏览器中运行下面的JS确定的那些字符的并集: |
| | // |
| | // (function () { |
| | // var a = [], d = document.getElementById("d"), i, c, s; |
| | // for (i = 0; i < 0x10000; ++i) { |
| | // c = String.fromCharCode(i); |
| | // d.innerHTML = "<span title=" + c + "lt" + c + ">" |
| | // s = d.getElementsByTagName("SPAN")[0]; |
| | // if (!s || s.title !== c + "lt" + c) { a.push(i.toString(16)); } |
| | // } |
| | // document.write(a.join(", ")); |
| | // })() |

建议

将此转义更改为运行两遍:

  • 首先,将属性转义为双引号形式
  • 然后在一对引号内发出值

这将消除对 htmlNospace(Norm)ReplacementTable 的需求,并使逻辑更加健壮和简单。

注意

我在研究 #42506 时发现了这个问题。

uoifb46i

uoifb46i1#

@ianlancetaylor

这里似乎没有API的变化,所以我认为这不需要经过提案过程。除非我漏掉了什么。

这肯定会破坏一些测试,所以我提议这个变化与你们大家权衡一下,看看这是否值得付出代价。如果你认为这会让事情变得更清楚,表明这不是一个API的变化,我可以将这个重命名为一个正常的功能请求,而不是一个提案。

@antichris 谢谢你的建议。我提出这个建议的原因之一是简化这个包中的逻辑,使其更加一致。虽然你的建议确实会使转义字符串变短,但它肯定会使逻辑变得更复杂,渲染的HTML也更不一致。除非你能找到一个共同的使用场景,预见到HTML属性值中有很多引号,否则我宁愿保持简单,总是使用相同的引号。你觉得这样合理吗?

n3schb8v

n3schb8v3#

我支持这个观点。html/template的目的是确保安全性并易于使用,而不是允许对生成的HTML外观进行最终控制(与行为相反)。如果我们能生成等效但更安全、更简单的输出,那就太好了。

oprakyz7

oprakyz74#

除非你能找到一个常见的用例,预见到HTML属性值中有很多引号,否则我宁愿保持简单,总是使用相同的引号。

我立刻想到了两个例子:data:image/svg+xml URIs和JSON数据。对于后者的例子,你可以查看这个页面的源代码,并查找optimizely-datafile元标签:它将近40%的content&quot;实体。我认为这很重要。当前实现下的SVG URIs也受到转义字符(如<>)的影响(在引用时这些字符没有特殊含义,因此不需要转义)。

当然,还有内联样式和脚本(如on<event>等),但人们应该在CSS和JS中使用单引号。此外,人们通常应该避免使用内联内容,但这并不意味着很多人关心这个问题。

p1iqtdky

p1iqtdky5#

然后还有内联样式和脚本(on<event> 等),当然,人们应该在CSS和JS中使用单引号。此外,人们通常应该避免使用内联内容,但这并不像很多人关心的那样。
你当然是对的。然而,在某些常见情况下,内联资源是不可避免的,例如:电子邮件。
是否有必要向API引入一个新的功能,以在这些特定情况下更具主观性?通过暴露一个稍微更丰富的API来提供更多上下文可能会:保持逻辑更简单,允许保持向后兼容性,同时为提案提供支持。
我提出这个问题的原因是因为 #42506 可能可以通过解决这个问题而得到解决

6gpjuf90

6gpjuf906#

为了确保我理解,您所关心的问题纯粹是生成的HTML的可读性和大小吗?还是有其他情况会导致语义变化或破坏?

tv6aics1

tv6aics17#

我经常遇到不需要转义的字符串需要转义的问题,想知道是否有解决方案。
如果我将SVG文件传递给JavaScript,我必须使用JS unescape,但我收到警告说它已被弃用。如果我直接将SVG复制到JS中,那么它可以完美工作。例如:https://go.dev/play/p/s17gBsHNMFi
如果我做了一些愚蠢的事情,请告诉我。

6rvt4ljy

6rvt4ljy8#

这里似乎没有API的变化,所以我认为这不需要经过提案过程。除非我漏掉了什么。

9gm1akwq

9gm1akwq9#

如何首先检测是否需要引用和/或转义,如果不需要,则跳过它?
我编写的第一个Go代码片段就是为了这个目的:

  1. 将所有&符号替换为 &amp; 实体。
  2. 确定属性值是否需要引用,即是否包含可引用的("'、```、=<>)和/或空白字符。
    如果不需要,我们在这里完成,返回字符串(在转义 &amp; 之后)。
  3. 选择在数据中较少出现的引号(单引号或双引号),对其进行转义。
    这可以避免将 foo 的值从 "b""a""r" 转换为 foo="&#34;b&#34;&#34;a&#34;&#34;r&#34;" 时,它可以是 foo='"b""a""r"' 的情况。
  4. 将转义后的值用相反的引号包裹并返回。
    虽然它确实需要最多两遍遍历字符串(一遍用于检测可引用字符并选择引号,另一遍用于输出转义引号),但我认为收益与成本相抵消。

相关问题