Add method to handle formatting of IPv6 in URLs

This commit is contained in:
Simon Li
2025-01-30 18:44:50 +00:00
parent 948e112bde
commit 5b02d9c222
4 changed files with 19 additions and 13 deletions

View File

@@ -12,6 +12,7 @@ from . import orm
from .traitlets import URLPrefix
from .utils import (
can_connect,
fmt_ip_url,
make_ssl_context,
random_port,
url_path_join,
@@ -49,11 +50,8 @@ class Server(HasTraits):
Never used in APIs, only logging,
since it can be non-connectable value, such as '', meaning all interfaces.
"""
ip = self.ip
if ":" in ip:
ip = f"[{ip}]"
if ip in {'', '0.0.0.0', '[::]'}:
return self.url.replace(self._connect_ip, self.ip or '*', 1)
if self.ip in {'', '0.0.0.0', '::'}:
return self.url.replace(self._connect_ip, fmt_ip_url(self.ip) or '*', 1)
return self.url
@observe('bind_url')
@@ -219,5 +217,4 @@ class Hub(Server):
return url_path_join(self.url, 'api')
def __repr__(self):
ip = f"[{self.ip}]" if ":" in self.ip else self.ip
return f"<{self.__class__.__name__} {ip}:{self.port}>"
return f"<{self.__class__.__name__} {fmt_ip_url(self.ip)}:{self.port}>"

View File

@@ -46,7 +46,7 @@ from sqlalchemy.pool import StaticPool
from sqlalchemy.types import LargeBinary, Text, TypeDecorator
from tornado.log import app_log
from .utils import compare_token, hash_token, new_token, random_port, utcnow
from .utils import compare_token, fmt_ip_url, hash_token, new_token, random_port, utcnow
# top-level variable for easier mocking in tests
utcnow = partial(utcnow, with_tz=False)
@@ -157,8 +157,7 @@ class Server(Base):
spawner = relationship("Spawner", back_populates="server", uselist=False)
def __repr__(self):
ip = f"[{self.ip}]" if ":" in self.ip else self.ip
return f"<Server({ip}:{self.port})>"
return f"<Server({fmt_ip_url(self.ip)}:{self.port})>"
# lots of things have roles

View File

@@ -48,6 +48,7 @@ from .traitlets import ByteSpecification, Callable, Command
from .utils import (
AnyTimeoutError,
exponential_backoff,
fmt_ip_url,
maybe_future,
random_port,
recursive_update,
@@ -1107,8 +1108,7 @@ class Spawner(LoggingConfigurable):
base_url = '/'
proto = 'https' if self.internal_ssl else 'http'
ip = f"[{self.ip}]" if ":" in self.ip else self.ip
bind_url = f"{proto}://{ip}:{self.port}{base_url}"
bind_url = f"{proto}://{fmt_ip_url(self.ip)}:{self.port}{base_url}"
env["JUPYTERHUB_SERVICE_URL"] = bind_url
# the public URLs of this server and the Hub

View File

@@ -273,7 +273,7 @@ async def wait_for_server(ip, port, timeout=10):
ip = '127.0.0.1'
elif ip == "::":
ip = "::1"
display_ip = f"[{ip}]" if ":" in ip else ip
display_ip = fmt_ip_url(ip)
app_log.debug("Waiting %ss for server at %s:%s", timeout, display_ip, port)
tic = time.perf_counter()
await exponential_backoff(
@@ -967,3 +967,13 @@ def recursive_update(target, new):
else:
target[k] = v
def fmt_ip_url(ip):
"""
Format an IP for use in URLs. IPv6 is wrapped with [], everything else is
unchanged
"""
if ":" in ip:
return f"[{ip}]"
return ip