1

I am trying to take the username and password from a url and put it back together to use it again in its complete form but without the basic auth part.

I am trying something like the below but the result is not what I expect.

from urllib.parse import urlsplit, urlunsplit
parts = urlsplit("http://user:pwd@host:8080/path?query=foo", allow_fragments=True)
auth = (parts.username, parts.password)
print(urlunsplit((parts.scheme, parts.hostname, str(parts.port), parts.path, parts.query)))
# http://host/8080?/path#query=foo

It would be even better if I could set username and password to None on the parts and just call geturl but I get errors that I can't change attributes.

from urllib.parse import urlsplit
parts = urlsplit("http://user:pwd@host:8080/path?query=foo", allow_fragments=True)
auth = (parts.username, parts.password)
parts.password = None
parts.username = None
print(parts.geturl())
# AttributeError: can't set attribute

Note, that I want to preserve the username and password in a separate tuple.

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
The Fool
  • 16,715
  • 5
  • 52
  • 86
  • According to the documentation [**`urlsplit`**](https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urlsplit) returns a `namedtuple`. You can [replace fields](https://docs.python.org/3/library/collections.html#collections.somenamedtuple._replace) in the tuple by saying `part._replace(password=None, username=None)`, which returns a new `namedtuple` (as `part` is immutable). – Peter Wood Oct 21 '21 at 17:18
  • Have a look at: https://stackoverflow.com/a/21629125 – gen_Eric Oct 21 '21 at 17:23
  • Have you contemplated using `re`. Example:`tuple(re.search("\/.*?\@", my_url).group(0)[2:-1].split(":"))` – j__carlson Oct 21 '21 at 17:24
  • I have tried that already peter it said unknown argument. I was thinking for a minute to include this but since its an *private* method I dont think we should actually use it anyway. `ValueError: Got unexpected field names: ['password', 'username']` – The Fool Oct 21 '21 at 17:24

1 Answers1

3

urlunsplit requires a tuple that looks like the same thing that urlsplit returned. The second element in that tuple is the netloc - which looks like: user:pwd@host:port

So you need to pass something similar to it. You can do that by modifying the parts.netloc that you get from urlsplit & passing it to urlunsplit:

from urllib.parse import urlsplit, urlunsplit

parts = urlsplit("http://user:pwd@host:8080/path?query=foo", allow_fragments=True)
auth = (parts.username, parts.password)

netloc = parts.netloc.split('@')[1]  # ignore the auth part. You should check the length after the split obviously
reconstruction_parts = (parts.scheme, netloc, parts.path, parts.query, parts.fragment)

print(urlunsplit(reconstruction_parts))

Result:

http://host:8080/path?query=foo
rdas
  • 20,604
  • 6
  • 33
  • 46