Jinja: urlencode 不会转义斜杠

创建于 2015-11-20  ·  21评论  ·  资料来源: pallets/jinja

这是在 #444 中提出的,但是这段代码在 Python 3.4.1 上总是计算为b'/' ,所以斜线仍然没有转义。

最有用的评论

我在尝试通过 API 调用在 gitlab 存储库中创建文件时遇到了这个问题。 gitlab api 需要对斜杠进行编码。 为了使这项工作,我做:{{ myvar | 网址 | regex_replace('/','%2F') }}。 我正在我的剧本任务中使用 Ansible 和 Jinja2 过滤器。 对于那些遇到此问题的人来说,这可能是一种解决方法,因为我已验证它有效。

所有21条评论

只是提个醒@mitsuhiko
我不知道为什么,但是do_urlencode仍然没有转义斜杠,而unicode_urlencode可以按预期工作。

Python 3.4.3 (default, Oct 14 2015, 20:28:29)
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import jinja2
>>> jinja2.utils.unicode_urlencode("http://url.by", for_qs=True)
'http%3A%2F%2Furl.by'
>>> jinja2.filters.do_urlencode("http://url.by")
'http%3A//url.by'
>>> jinja2.__version__
'2.9.dev'

因为urlencode过滤器不会转义斜杠。 是否有特定的原因必须这样做? 为了澄清这一点:它只在传递的键/值对的值位置编码斜杠。

我相信这是用于编码 url 的函数的标准行为。 像http://meyerweb.com/eric/tools/dencoder/这样的工具就是这种方式。 此外,我公司内部至少有一个工具,它希望在 GET 请求中传递带有转义斜杠的 URL。
另外,我不明白为什么unicode_urlencodedo_urlencode内部调用for_qs=True
可能是我理解错了。

斜杠是路径组件中的保留字符,更常见的行为是在强制使用 url 编码行为时对除斜杠以外的所有内容进行编码。 替代方案(将斜杠编码为%2f )甚至没有意义,因为大多数服务器由于安全问题而直接拒绝这些请求,因为后端服务器通常无法区分%2f/路径组件,因为它们对解码的八位字节进行操作。

因此,斜线编码真正有意义的唯一部分是在查询字符串中,这就是urlencode具有的基于 dict 的编码器的工作方式。 然而,即使有斜杠也不必编码,因此没有理由强制对其进行编码。

默认情况下, urlencode函数应该对大多数人使用,这就是它不编码斜杠的原因。 如果您有自定义要求,那么您可以覆盖过滤器注册中的功能。

好的。 谢谢阿明。

嗨,我在拒绝斜杠时遇到了同样的问题,这是代码:

jinja2.Template("{{ disks|reject('sameas', '/')|list }}").render(disks=["/", "/mnt/disk0", "/mnt/disk1"])
u"['/', '/mnt/disk0', '/mnt/disk1']"

我想拒绝根磁盘,但它不再工作了,如何解决它?

>>> import jinja2
>>> jinja2.Template("{{ disks|reject('sameas', '/')|list }}").render(disks=["/", "/mnt/disk0", "/mnt/disk1"])
u"['/mnt/disk0', '/mnt/disk1']"
>>> jinja2.__version__
Out[3]: '2.8'

为我工作。

仍然不适合我, @ThiefMaster ,python 问题吗? 你用的python是什么版本。

    Python 2.7.10 (default, May 23 2015, 09:44:00) [MSC v.1500 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import jinja2
    >>> jinja2.Template("{{ disks|reject('sameas', '/')|list }}").render(disks=["/", "/mnt/disk0", "/mnt/disk1"])
    u"['/', '/mnt/disk0', '/mnt/disk1']"
    >>> jinja2.__version__
    '2.8'

哦.. sameas使用is (你不能指望'foo' is 'foo'工作)。 你想equalto它使用==

是的,它有效,我不是 Jinja2 的家人。 谢谢, @ThiefMaster

因此,斜线编码真正有意义的唯一部分是在查询字符串中,这就是 urlencode 所具有的基于 dict 的编码器的工作方式。 然而,即使有斜杠也不必编码,因此没有理由强制对其进行编码。

不,例如,您还需要在用户名和密码中对/进行编码。
这就是 JS 有encodeURI __and__ encodeURIComponent的原因。

这很公平,但实际上也没有必要存在,并且无论如何都不推荐使用包含的凭据。 由于这些不太可能在模板中生成,因此这是一个不值得考虑的边缘情况。

Ansible 使用 Jinja,在设置系统时处理安全凭证是很常见的。 我刚刚遇到一个情况,自动生成的密码包含一个斜杠,没有被urlencode替换来生成一个数据库 URL,这是非常不幸的。 虽然打破当前行为会有问题,但为什么不引入第二个过滤器来逃避斜线呢?

Ansible 可以做到这一点。 Jinja 本身不需要这样的更改 - 它具有足够的可扩展性,可以添加自定义过滤器甚至替换内置过滤器。

@ThiefMaster在确定要包含在 Jinja 本身中的有用内容时,除了构建 HTML 模板之外的用例是否无关紧要? 例如,与 Ansible 目的相似的 Saltstack 项目也使用 Jinja 进行模板化,并且将从相同的更改中受益。

@danielkza是什么阻止 saltstack 提供一个过滤器呢?

@mitsuhiko为什么 Jinja 包含任何内置过滤器呢? 我只能猜测这是因为它们在多个用例中都很有用。 我使用 Ansible 和 Salt 作为两个示例,说明需要能够在 URL 中转义斜杠,因此,让每个人都可以使用它是很有价值的。

safe参数添加到urlencode怎么样,就像 Python 的urllib.url_quote ,这样默认情况下斜杠会被保留,但以一种可以轻松覆盖的方式?

Jinja 尝试提供一些常用的功能。 我们有两种 urlencoding 模式,可以让您达到 95% 的效果。 您可以通过对 dict 进行编码来对整个查询字符串进行编码,并且您可以编码为一个公共集,该集对通过 urlencode 对字符串的路径有效。

除了 utf-8 或那个之外,我们不做任何事情。 因为它会停在哪里。 一个网址有太多的部分,有鸢尾花,它们都有自己的扭结。 当我们在那里时,为什么不也为 netloc 提供一个 punycode 编码器呢?

我在尝试通过 API 调用在 gitlab 存储库中创建文件时遇到了这个问题。 gitlab api 需要对斜杠进行编码。 为了使这项工作,我做:{{ myvar | 网址 | regex_replace('/','%2F') }}。 我正在我的剧本任务中使用 Ansible 和 Jinja2 过滤器。 对于那些遇到此问题的人来说,这可能是一种解决方法,因为我已验证它有效。

我看到一些关于应该对哪些字符进行百分比编码的争论,据我所知,目前在 RFC3986 中对此进行了讨论。 https://tools.ietf.org/html/rfc3986#section -2.2

尽管对于我的用例, @ahuffman提供了合理的解决方法。

我想关闭它,因为它又出现了。 我反对这个的论点早些时候已经在这里提出,但我想重申它们,因为目前实际上有一个 PR 开放(#864),它建议为其添加另一个过滤器以帮助 GitLab 的 API。

如果将 GitLab 的 API 置于各种代理设置之后,则它会损坏,并且存在问题(示例问题)。 相反,我建议记录一个解决方法以及为什么人们不应该这样做。

示例解决方法可能是这样的:

{{ value|urlencode|replace("/", "%2f") }}

这有点采取立场,但这样做可以鼓励人们不要重复他们之前的其他人的错误。

此页面是否有帮助?
0 / 5 - 0 等级