diff --git a/httpie/cli/argparser.py b/httpie/cli/argparser.py index 9bf09b3b73..284904953c 100644 --- a/httpie/cli/argparser.py +++ b/httpie/cli/argparser.py @@ -5,7 +5,7 @@ import sys from argparse import RawDescriptionHelpFormatter from textwrap import dedent -from urllib.parse import urlsplit +from urllib.parse import urlsplit, unquote from requests.utils import get_netrc_auth @@ -289,8 +289,8 @@ def _process_auth(self): if self.args.auth is None and not auth_type_set: if url.username is not None: # Handle http://username:password@hostname/ - username = url.username - password = url.password or '' + username = unquote(url.username) + password = unquote(url.password) if url.password else '' self.args.auth = AuthCredentials( key=username, value=password, diff --git a/tests/test_auth.py b/tests/test_auth.py index 83423efec0..654bd1f608 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -65,6 +65,27 @@ def test_credentials_in_url_auth_flag_has_priority(httpbin_both): assert r.json == {'authenticated': True, 'user': 'user'} +@pytest.mark.parametrize('url, expected_username, expected_password', [ + # %40 = @, %3d = =, %3f = ? + ('u%40d:1%3d2%3f@example.org', 'u@d', '1=2?'), + # %3A = : + ('user%3Aname:pass%3Aword@example.org', 'user:name', 'pass:word'), + # Simple case without encoding + ('user:password@example.org', 'user', 'password'), +]) +def test_percent_encoded_credentials_in_url(url, expected_username, expected_password): + """ + Percent-encoded characters in URL credentials should be decoded. + + https://github.com/httpie/cli/issues/1623 + + """ + args = httpie.cli.definition.parser.parse_args(args=[url], env=MockEnvironment()) + assert args.auth + assert args.auth.username == expected_username + assert args.auth.password == expected_password + + @pytest.mark.parametrize('url', [ 'username@example.org', 'username:@example.org',