From 8a52bef559e58d98efa1bd6e12be0c060f95f4d7 Mon Sep 17 00:00:00 2001 From: Nathan LaFreniere Date: Wed, 9 Oct 2013 11:32:41 -0700 Subject: [PATCH] make shorthand parsing more robust, add unit tests and documentation --- README.rst | 10 +++++++++- httpie/input.py | 11 +++++++++-- tests/tests.py | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 551fbab6..b85b00ca 100644 --- a/README.rst +++ b/README.rst @@ -121,7 +121,6 @@ See also ``http --help``. Examples -------- - Custom `HTTP method`_, `HTTP headers`_ and `JSON`_ data: .. code-block:: bash @@ -226,6 +225,15 @@ The only information HTTPie needs to perform a request is a URL. The default scheme is, somewhat unsurprisingly, ``http://``, and can be omitted from the argument – ``http example.org`` works just fine. +Additionally, curl-like shorthand for localhost is supported. +This means that, for example ``:3000`` would expand to ``http://localhost:3000`` +If the port is omitted, then port 80 is assumed. + +.. code-block:: bash + + $ http :/foo + $ http :3000/bar + If find yourself manually constructing URLs with **querystring parameters** on the terminal, you may appreciate the ``param==value`` syntax for appending URL parameters so that you don't have to worry about escaping the ``&`` diff --git a/httpie/input.py b/httpie/input.py index 50f2e882..07c2d451 100644 --- a/httpie/input.py +++ b/httpie/input.py @@ -138,8 +138,15 @@ class Parser(ArgumentParser): if not (self.args.url.startswith((HTTP, HTTPS))): # Default to 'https://' if invoked as `https args`. scheme = HTTPS if self.env.progname == 'https' else HTTP - if self.args.url.startswith(':'): - self.args.url = scheme + 'localhost' + self.args.url + # See if we're using curl style shorthand for localhost (:3000/foo) + shorthand = re.match(r'^:(?!:)(\d*)(\/?.*)$', self.args.url) + if shorthand: + port = shorthand.group(1) + rest = shorthand.group(2) + self.args.url = scheme + 'localhost' + if port: + self.args.url += ':' + port + self.args.url += rest else: self.args.url = scheme + self.args.url self._process_auth() diff --git a/tests/tests.py b/tests/tests.py index d967b47c..7d61771a 100755 --- a/tests/tests.py +++ b/tests/tests.py @@ -64,6 +64,7 @@ sys.path.insert(0, os.path.realpath(os.path.join(TESTS_ROOT, '..'))) from httpie import ExitStatus from httpie import input +from httpie.cli import parser from httpie.models import Environment from httpie.core import main from httpie.output import BINARY_SUPPRESSED_NOTICE @@ -1264,6 +1265,52 @@ class ItemParsingTest(BaseTestCase): self.assertEqual(files['file'][1].read().strip().decode('utf8'), FILE_CONTENT) +class CLIParserTestCase(unittest.TestCase): + + def test_expand_localhost_shorthand(self): + args = parser.parse_args(args=[':'], env=TestEnvironment()) + + self.assertEqual(args.url, 'http://localhost') + + def test_expand_localhost_shorthand_with_slash(self): + args = parser.parse_args(args=[':/'], env=TestEnvironment()) + + self.assertEqual(args.url, 'http://localhost/') + + def test_expand_locahost_shorthand_with_port(self): + args = parser.parse_args(args=[':3000'], env=TestEnvironment()) + + self.assertEqual(args.url, 'http://localhost:3000') + + def test_expand_localhost_shorthand_with_path(self): + args = parser.parse_args(args=[':/path'], env=TestEnvironment()) + + self.assertEqual(args.url, 'http://localhost/path') + + def test_expand_localhost_shorthand_with_port_and_slash(self): + args = parser.parse_args(args=[':3000/'], env=TestEnvironment()) + + self.assertEqual(args.url, 'http://localhost:3000/') + + def test_expand_localhost_shorthand_with_port_and_path(self): + args = parser.parse_args(args=[':3000/path'], env=TestEnvironment()) + + self.assertEqual(args.url, 'http://localhost:3000/path') + + def test_dont_expand_shorthand_ipv6_as_shorthand(self): + args = parser.parse_args(args=['::1'], env=TestEnvironment()) + + self.assertEqual(args.url, 'http://::1') + + def test_dont_expand_longer_ipv6_as_shorthand(self): + args = parser.parse_args(args=['::ffff:c000:0280'], env=TestEnvironment()) + + self.assertEqual(args.url, 'http://::ffff:c000:0280') + + def test_dont_expand_full_ipv6_as_shorthand(self): + args = parser.parse_args(args=['0000:0000:0000:0000:0000:0000:0000:0001'], env=TestEnvironment()) + + self.assertEqual(args.url, 'http://0000:0000:0000:0000:0000:0000:0000:0001') class ArgumentParserTestCase(unittest.TestCase):