From 26d46d5a6e5c0c5e11bba109fa6e6ce3a5824969 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 4 Dec 2018 16:05:33 +0000 Subject: [PATCH] Hide password in URL.__repr__ (#247) --- starlette/datastructures.py | 30 ++++++++++++++++++++++++------ tests/test_datastructures.py | 11 +++++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/starlette/datastructures.py b/starlette/datastructures.py index 2848125f..4ef81def 100644 --- a/starlette/datastructures.py +++ b/starlette/datastructures.py @@ -93,13 +93,28 @@ class URL: return self.scheme in ("https", "wss") def replace(self, **kwargs: typing.Any) -> "URL": - if "hostname" in kwargs or "port" in kwargs: + if ( + "username" in kwargs + or "password" in kwargs + or "hostname" in kwargs + or "port" in kwargs + ): hostname = kwargs.pop("hostname", self.hostname) port = kwargs.pop("port", self.port) - if port is None: - kwargs["netloc"] = hostname - else: - kwargs["netloc"] = "%s:%d" % (hostname, port) + username = kwargs.pop("username", self.username) + password = kwargs.pop("password", self.password) + + netloc = hostname + if port is not None: + netloc += ":%d" % port + if username is not None: + userpass = username + if password is not None: + userpass += ":%s" % password + netloc = "%s@%s" % (userpass, netloc) + + kwargs["netloc"] = netloc + components = self.components._replace(**kwargs) return URL(components.geturl()) @@ -110,7 +125,10 @@ class URL: return self._url def __repr__(self) -> str: - return "%s(%s)" % (self.__class__.__name__, repr(self._url)) + url = str(self) + if self.password: + url = str(self.replace(password="********")) + return "%s(%s)" % (self.__class__.__name__, repr(url)) class URLPath(str): diff --git a/tests/test_datastructures.py b/tests/test_datastructures.py index 9508b8ca..9b789b49 100644 --- a/tests/test_datastructures.py +++ b/tests/test_datastructures.py @@ -27,6 +27,17 @@ def test_url(): assert new.hostname == "example.com" +def test_hidden_password(): + u = URL("https://example.org/path/to/somewhere") + assert repr(u) == "URL('https://example.org/path/to/somewhere')" + + u = URL("https://username@example.org/path/to/somewhere") + assert repr(u) == "URL('https://username@example.org/path/to/somewhere')" + + u = URL("https://username:password@example.org/path/to/somewhere") + assert repr(u) == "URL('https://username:********@example.org/path/to/somewhere')" + + def test_url_from_scope(): u = URL( scope={"path": "/path/to/somewhere", "query_string": b"abc=123", "headers": []}