python urllib.parse.urljoin 在以数字和冒号开头的路径上

rat*_*jas 5 python url urllib

对不起,到底是什么?

>>> import urllib.parse
>>> base = 'http://example.com'
>>> urllib.parse.urljoin(base, 'abc:123')
'http://example.com/abc:123'
>>> urllib.parse.urljoin(base, '123:abc')
'123:abc'
>>> urllib.parse.urljoin(base + '/', './123:abc')
'http://example.com/123:abc'
Run Code Online (Sandbox Code Playgroud)

python3.7文档说:

版本 3.5 中进行了更改:更新行为以匹配 RFC 3986 中定义的语义。

RFC 的哪一部分强制实施了这种疯狂行为?它是否应该被视为错误?

gdl*_*lmx 4

RFC 的哪一部分强制实施了如此疯狂的行为?

\n

此行为是正确的,并且与其他实现一致,如RFC3986所示:

\n
\n

包含冒号字符(例如“this:that”)的路径段不能用作相对路径引用的第一段,因为它会被误认为是方案名称。这样的段之前必须有一个点段(例如“./this:that”)以进行相对路径引用。

\n
\n

它已经在另一篇文章中讨论过:

\n
\n

URI 路径中允许使用冒号。但是在使用冒号编写相对 URI 路径时需要小心,因为这样使用是不允许的:

\n
<a href="tag:sample">\n
Run Code Online (Sandbox Code Playgroud)\n

在这种情况下,标记将被解释为 URI\xe2\x80\x99s 方案。相反,你需要这样写:

\n
<a href="./tag:sample">\n
Run Code Online (Sandbox Code Playgroud)\n
\n

的用法urljoin

\n

该函数urljoin只是将两个参数视为 URL(没有任何假设)。它要求它们的方案相同或者第二个方案代表相对 URI 路径。否则,它只返回第二个参数(尽管,恕我直言,它应该引发错误)。通过查看urljoin 的来源可以更好地理解逻辑。

\n
def urljoin(base, url, allow_fragments=True):\n    """Join a base URL and a possibly relative URL to form an absolute\n    interpretation of the latter."""\n    ...\n    bscheme, bnetloc, bpath, bparams, bquery, bfragment = \\\n            urlparse(base, \'\', allow_fragments)\n    scheme, netloc, path, params, query, fragment = \\\n            urlparse(url, bscheme, allow_fragments)\n\n    if scheme != bscheme or scheme not in uses_relative:\n        return _coerce_result(url)\n
Run Code Online (Sandbox Code Playgroud)\n

解析器例程的结果urlparse如下:

\n
>>> from urllib.parse import urlparse\n>>> urlparse(\'123:abc\')\nParseResult(scheme=\'123\', netloc=\'\', path=\'abc\', params=\'\', query=\'\', fragment=\'\')\n>>> urlparse(\'abc:123\')\nParseResult(scheme=\'\', netloc=\'\', path=\'abc:123\', params=\'\', query=\'\', fragment=\'\')\n>>> urlparse(\'abc:a123\')\nParseResult(scheme=\'abc\', netloc=\'\', path=\'a123\', params=\'\', query=\'\', fragment=\'\')\n
Run Code Online (Sandbox Code Playgroud)\n