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

时间:2019-03-17 00:40:53

标签: 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'

python3.7 文档说:

  

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

该RFC的哪一部分实施了这种疯狂行为,以及是否应将其视为错误?

1 个答案:

答案 0 :(得分:1)

该RFC的哪一部分实施了这种疯狂?

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

  

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

已经在另一个post中进行了讨论:

  

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

<a href="tag:sample">
     

在这种情况下,标记将被解释为URI的方案。相反,您需要这样写:

<a href="./tag:sample">

urljoin的使用

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

def urljoin(base, url, allow_fragments=True):
    """Join a base URL and a possibly relative URL to form an absolute
    interpretation of the latter."""
    ...
    bscheme, bnetloc, bpath, bparams, bquery, bfragment = \
            urlparse(base, '', allow_fragments)
    scheme, netloc, path, params, query, fragment = \
            urlparse(url, bscheme, allow_fragments)

    if scheme != bscheme or scheme not in uses_relative:
        return _coerce_result(url)

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

>>> from urllib.parse import urlparse
>>> urlparse('123:abc')
ParseResult(scheme='123', netloc='', path='abc', params='', query='', fragment='')
>>> urlparse('abc:123')
ParseResult(scheme='', netloc='', path='abc:123', params='', query='', fragment='')
>>> urlparse('abc:a123')
ParseResult(scheme='abc', netloc='', path='a123', params='', query='', fragment='')