Merge pull request #171 from nlf/master

Allow :port style shorthand for localhost.
This commit is contained in:
Jakub Roztočil 2013-10-09 13:22:30 -07:00
commit 817165f5ff
5 changed files with 90 additions and 2 deletions

View File

@ -29,3 +29,4 @@ Patches and ideas
* `Davey Shafik <https://github.com/dshafik>`_ * `Davey Shafik <https://github.com/dshafik>`_
* `cido <https://github.com/cido>`_ * `cido <https://github.com/cido>`_
* `Justin Bonnar <https://github.com/jargonjustin>`_ * `Justin Bonnar <https://github.com/jargonjustin>`_
* `Nathan LaFreniere <https://github.com/nlf>`_

View File

@ -121,7 +121,6 @@ See also ``http --help``.
Examples Examples
-------- --------
Custom `HTTP method`_, `HTTP headers`_ and `JSON`_ data: Custom `HTTP method`_, `HTTP headers`_ and `JSON`_ data:
.. code-block:: bash .. code-block:: bash
@ -226,6 +225,31 @@ The only information HTTPie needs to perform a request is a URL.
The default scheme is, somewhat unsurprisingly, ``http://``, The default scheme is, somewhat unsurprisingly, ``http://``,
and can be omitted from the argument ``http example.org`` works just fine. 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
.. code-block:: http
GET /foo HTTP/1.1
Host: localhost
.. code-block:: bash
$ http :3000/bar
.. code-block:: http
GET /bar HTTP/1.1
Host: localhost:3000
If find yourself manually constructing URLs with **querystring parameters** If find yourself manually constructing URLs with **querystring parameters**
on the terminal, you may appreciate the ``param==value`` syntax for appending 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 ``&`` URL parameters so that you don't have to worry about escaping the ``&``
@ -1231,6 +1255,7 @@ Changelog
* `0.8.0-dev`_ * `0.8.0-dev`_
* Added ``field=@file.txt`` and ``field:=@file.json`` for embedding * Added ``field=@file.txt`` and ``field:=@file.json`` for embedding
the contents of text and JSON files into request data. the contents of text and JSON files into request data.
* Added curl-style shorthand for localhost
* `0.7.1`_ (2013-09-24) * `0.7.1`_ (2013-09-24)
* Added ``--ignore-stdin``. * Added ``--ignore-stdin``.
* Added support for auth plugins. * Added support for auth plugins.

View File

@ -88,6 +88,11 @@ positional.add_argument(
help=""" help="""
The scheme defaults to 'http://' if the URL does not include one. 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( positional.add_argument(

View File

@ -138,7 +138,17 @@ class Parser(ArgumentParser):
if not (self.args.url.startswith((HTTP, HTTPS))): if not (self.args.url.startswith((HTTP, HTTPS))):
# Default to 'https://' if invoked as `https args`. # Default to 'https://' if invoked as `https args`.
scheme = HTTPS if self.env.progname == 'https' else HTTP scheme = HTTPS if self.env.progname == 'https' else HTTP
self.args.url = scheme + 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() self._process_auth()
return self.args return self.args

View File

@ -64,6 +64,7 @@ sys.path.insert(0, os.path.realpath(os.path.join(TESTS_ROOT, '..')))
from httpie import ExitStatus from httpie import ExitStatus
from httpie import input from httpie import input
from httpie.cli import parser
from httpie.models import Environment from httpie.models import Environment
from httpie.core import main from httpie.core import main
from httpie.output import BINARY_SUPPRESSED_NOTICE from httpie.output import BINARY_SUPPRESSED_NOTICE
@ -1264,6 +1265,52 @@ class ItemParsingTest(BaseTestCase):
self.assertEqual(files['file'][1].read().strip().decode('utf8'), self.assertEqual(files['file'][1].read().strip().decode('utf8'),
FILE_CONTENT) 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): class ArgumentParserTestCase(unittest.TestCase):