From d87b2aa0e5667f3ac240eb3a9a2f9dc3626abb0e Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Thu, 8 Nov 2012 22:29:54 +0100 Subject: [PATCH] Added support for credentials in URL. Closes #100 :cake: --- README.rst | 3 +++ httpie/input.py | 22 +++++++++++++++++++--- tests/tests.py | 25 +++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 084a375f..dc31f478 100644 --- a/README.rst +++ b/README.rst @@ -447,6 +447,9 @@ come). There are two flags that control authentication: (``-a username``), you'll be prompted for the password before the request is sent. To send a an empty password, pass ``username:``. + The ``username:password@hostname`` URL syntax is + supported as well (but credentials passed via ``-a`` + have higher priority). ``--auth-type`` Specify the auth mechanism. Possible values are ``basic`` and ``digest``. The default value is diff --git a/httpie/input.py b/httpie/input.py index 9dcb6acf..510d3af1 100644 --- a/httpie/input.py +++ b/httpie/input.py @@ -123,12 +123,28 @@ class Parser(ArgumentParser): scheme = HTTPS if env.progname == 'https' else HTTP args.url = scheme + args.url - if args.auth and not args.auth.has_password(): - # Stdin already read (if not a tty) so it's save to prompt. - args.auth.prompt_password(urlparse(args.url).netloc) + self._process_auth(args) return args + def _process_auth(self, args): + url = urlparse(args.url) + + if args.auth: + if not args.auth.has_password(): + # Stdin already read (if not a tty) so it's save to prompt. + args.auth.prompt_password(url.netloc) + + elif url.username is not None: + # Handle http://username:password@hostname/ + username, password = url.username, url.password + args.auth = AuthCredentials( + key=username, + value=password, + sep=SEP_CREDENTIALS, + orig=SEP_CREDENTIALS.join([username, password]) + ) + def _apply_no_options(self, args, no_options): """For every `--no-OPTION` in `no_options`, set `args.OPTION` to its default value. This allows for un-setting of options, e.g., diff --git a/tests/tests.py b/tests/tests.py index f794ea49..ba60f22c 100755 --- a/tests/tests.py +++ b/tests/tests.py @@ -858,6 +858,31 @@ class AuthTest(BaseTestCase): self.assertIn('"authenticated": true', r) self.assertIn('"user": "user"', r) + def test_credentials_in_url(self): + url = httpbin('/basic-auth/user/password') + url = 'http://user:password@' + url.split('http://', 1)[1] + r = http( + 'GET', + url + ) + self.assertIn(OK, r) + self.assertIn('"authenticated": true', r) + self.assertIn('"user": "user"', r) + + def test_credentials_in_url_auth_flag_has_priority(self): + """When credentials are passed in URL and via -a at the same time, + then the ones from -a are used.""" + url = httpbin('/basic-auth/user/password') + url = 'http://user:wrong_password@' + url.split('http://', 1)[1] + r = http( + '--auth=user:password', + 'GET', + url + ) + self.assertIn(OK, r) + self.assertIn('"authenticated": true', r) + self.assertIn('"user": "user"', r) + class ExitStatusTest(BaseTestCase):