gruns / furl

🌐 URL parsing and manipulation made easy.
Other
2.63k stars 152 forks source link

IPv6 addresses do not quite work as advertised #124

Open fingon opened 4 years ago

fingon commented 4 years ago
>>> from furl import furl
>>> f = furl()
>>> f.host = '::1'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/mstenber/.local/lib/python3.7/site-packages/furl/furl.py", line 1851, in __setattr__
    object.__setattr__(self, attr, value)
  File "/home/mstenber/.local/lib/python3.7/site-packages/furl/furl.py", line 1425, in host
    raise ValueError(errmsg % (host, INVALID_HOST_CHARS))
ValueError: Invalid host '::1'. Host strings must have at least one non-period character, can't contain any of '!@#$%^&'"*()+=:;/', and can't have adjacent periods.
>>> f.host = '[::1]'
>>> f
furl('//[::1]')

As the documentation says 'host' can accept IPv6 address, it is not quite right :)

 |    host: URL host (hostname, IPv4 address, or IPv6 address), not
 |      including port. All lowercase. Initially None.

At least as user I'd be happier if []s just showed up, and IPv6 address was compressed automatically (e.g. str(ip_address.ipaddress(addr)) )

systemcrash commented 4 years ago

[] format is the (only) correct way to enter IP only IPv6 as a URI.

fingon commented 4 years ago

Indeed. But user of convenience api should not care. Or alternatively it should be documented.

gruns commented 3 years ago

before this is implemented and added, are there any 1) ambiguous strings that are both valid IPv6 literals and valid hostnames, or 2) surprising IPv6 literals that look confusingly like a valid hostname (or vice versa)? none come to my mind

If none, I agree: furl should implicitly accept f.host = '::1' as if the user typed f.host = '[::1]'. ::1 isn't a valid host name but is an obvious IPv6 address. furl should be liberal in what it accepts, ie Postel's law

@fingon do you have time to submit a PR to fix this?

py3 has the handy https://docs.python.org/3/library/ipaddress.html module to help

a dependency may be needed for py2

azmeuk commented 2 years ago

[] format is the (only) correct way to enter IP only IPv6 as a URI.

Well, the support is not uniform at all:

>>> import socket
>>> socket.inet_pton(socket.AF_INET6,'::')
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
>>> socket.inet_pton(socket.AF_INET6,'[::]')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: illegal IP address string passed to inet_pton

On python it seems that some of the builtin features based on libc will depend on how libc handles brackets in IPV6.

fingon commented 2 years ago

Well, the support is not uniform at all:

>>> import socket
>>> socket.inet_pton(socket.AF_INET6,'::')
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
>>> socket.inet_pton(socket.AF_INET6,'[::]')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: illegal IP address string passed to inet_pton

On python it seems that some of the builtin features based on libc will depend on how libc handles brackets in IPV6.

[] format is the (only) correct way to enter IP only IPv6 as a URI.

Well, the support is not uniform at all:

>>> import socket
>>> socket.inet_pton(socket.AF_INET6,'::')
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
>>> socket.inet_pton(socket.AF_INET6,'[::]')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: illegal IP address string passed to inet_pton

On python it seems that some of the builtin features based on libc will depend on how libc handles brackets in IPV6.

Sure an api that does not accept url does not accept url style IPs. But is that unexpected? Socket deals with ips directly.