From 711168a899819105c2a61d132dda7a037aaf2301 Mon Sep 17 00:00:00 2001 From: Nathan LaFreniere Date: Tue, 8 Oct 2013 22:41:38 -0700 Subject: [PATCH 1/6] allow :port style shorthand --- httpie/input.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/httpie/input.py b/httpie/input.py index 9e159948..50f2e882 100644 --- a/httpie/input.py +++ b/httpie/input.py @@ -138,7 +138,10 @@ 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 - self.args.url = scheme + self.args.url + if self.args.url.startswith(':'): + self.args.url = scheme + 'localhost' + self.args.url + else: + self.args.url = scheme + self.args.url self._process_auth() return self.args From 8a52bef559e58d98efa1bd6e12be0c060f95f4d7 Mon Sep 17 00:00:00 2001 From: Nathan LaFreniere Date: Wed, 9 Oct 2013 11:32:41 -0700 Subject: [PATCH 2/6] 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): From 70eb97dece6cf20668391427f9cca75e4092d7ed Mon Sep 17 00:00:00 2001 From: Nathan LaFreniere Date: Wed, 9 Oct 2013 11:34:22 -0700 Subject: [PATCH 3/6] tweak readme to show http requests --- README.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.rst b/README.rst index b85b00ca..b3d003eb 100644 --- a/README.rst +++ b/README.rst @@ -232,8 +232,19 @@ If the port is omitted, then port 80 is assumed. .. code-block:: bash $ http :/foo + +.. code-block:: http + + GET http://localhost/foo + +.. code-block:: bash + $ http :3000/bar +.. code-block:: http + + GET http://localhost: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 ``&`` From 2c12fd99f9d4f60220a2a022345be317762cadbc Mon Sep 17 00:00:00 2001 From: Nathan LaFreniere Date: Wed, 9 Oct 2013 11:36:01 -0700 Subject: [PATCH 4/6] tweak readme more --- README.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index b3d003eb..b7f026e2 100644 --- a/README.rst +++ b/README.rst @@ -235,7 +235,8 @@ If the port is omitted, then port 80 is assumed. .. code-block:: http - GET http://localhost/foo + GET /foo + Host: localhost .. code-block:: bash @@ -243,7 +244,8 @@ If the port is omitted, then port 80 is assumed. .. code-block:: http - GET http://localhost:3000/bar + GET /bar + Host: localhost:3000 If find yourself manually constructing URLs with **querystring parameters** on the terminal, you may appreciate the ``param==value`` syntax for appending From 9034546b804fd0fa99cdc41e4f800f1d36c87a13 Mon Sep 17 00:00:00 2001 From: Nathan LaFreniere Date: Wed, 9 Oct 2013 11:37:05 -0700 Subject: [PATCH 5/6] tweak readme more --- README.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index b7f026e2..955383e7 100644 --- a/README.rst +++ b/README.rst @@ -233,18 +233,21 @@ If the port is omitted, then port 80 is assumed. $ http :/foo + .. code-block:: http - GET /foo + GET /foo HTTP/1.1 Host: localhost + .. code-block:: bash $ http :3000/bar + .. code-block:: http - GET /bar + GET /bar HTTP/1.1 Host: localhost:3000 If find yourself manually constructing URLs with **querystring parameters** From 4fe3deb9d916023b3bffe60e0d655216bcb9276a Mon Sep 17 00:00:00 2001 From: Nathan LaFreniere Date: Wed, 9 Oct 2013 13:21:14 -0700 Subject: [PATCH 6/6] add self to authors, update changelog, and mention shorthand in --help output --- AUTHORS.rst | 1 + README.rst | 1 + httpie/cli.py | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/AUTHORS.rst b/AUTHORS.rst index 20c4efa3..126e6a7b 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -29,3 +29,4 @@ Patches and ideas * `Davey Shafik `_ * `cido `_ * `Justin Bonnar `_ +* `Nathan LaFreniere `_ diff --git a/README.rst b/README.rst index 955383e7..184ae969 100644 --- a/README.rst +++ b/README.rst @@ -1255,6 +1255,7 @@ Changelog * `0.8.0-dev`_ * Added ``field=@file.txt`` and ``field:=@file.json`` for embedding the contents of text and JSON files into request data. + * Added curl-style shorthand for localhost * `0.7.1`_ (2013-09-24) * Added ``--ignore-stdin``. * Added support for auth plugins. diff --git a/httpie/cli.py b/httpie/cli.py index beb78bbd..75dfd845 100644 --- a/httpie/cli.py +++ b/httpie/cli.py @@ -88,6 +88,11 @@ positional.add_argument( help=""" The scheme defaults to 'http://' if the URL does not include one. + You can also use a shorthand for localhost + + $ http :3000 # => http://localhost:3000 + $ http :/foo # => http://localhost/foo + """ ) positional.add_argument(