diff --git a/httpie/cli/argparser.py b/httpie/cli/argparser.py index 9bf09b3b73..308917d6ba 100644 --- a/httpie/cli/argparser.py +++ b/httpie/cli/argparser.py @@ -6,6 +6,7 @@ from argparse import RawDescriptionHelpFormatter from textwrap import dedent from urllib.parse import urlsplit +from urllib.parse import unquote from requests.utils import get_netrc_auth @@ -289,8 +290,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) if url.username else None + 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..22598f79a7 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -153,3 +153,11 @@ def test_ignore_netrc_null_auth(): env=MockEnvironment(), ) assert isinstance(args.auth, ExplicitNullAuth) + +def test_percent_encoded_credentials_in_url(httpbin_both): + encoded_url = httpbin_both.url.replace("://", "://u%40d:1%3d2%3f@") + '/basic-auth/u%40d/1%3d2%3f' + + r = http('GET', encoded_url) + + assert HTTP_OK in r + assert r.json == {'authenticated': True, 'user': 'u@d'} \ No newline at end of file diff --git a/tests/test_cli_ui.py b/tests/test_cli_ui.py index bb744cdc4e..ba6664c973 100644 --- a/tests/test_cli_ui.py +++ b/tests/test_cli_ui.py @@ -27,7 +27,7 @@ NAKED_HELP_MESSAGE_PRETTY_WITH_INVALID_ARG = NAKED_BASE_TEMPLATE.format( extra_args="--pretty {all, colors, format, none} ", - error_msg="argument --pretty: invalid choice: '$invalid' (choose from 'all', 'colors', 'format', 'none')" + error_msg="argument --pretty: invalid choice: '$invalid' (choose from all, colors, format, none)" )