From f7b703b4bf365e5ba930649f7ba29901477e62b6 Mon Sep 17 00:00:00 2001 From: Jakub Roztocil Date: Fri, 23 Aug 2013 10:57:17 +0200 Subject: [PATCH] Added --ignore-stdin Closes #150 --- README.rst | 15 ++++++++++++--- httpie/cli.py | 9 +++++++++ httpie/input.py | 16 +++++++++++----- tests/tests.py | 30 ++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/README.rst b/README.rst index 9acf7ca4..de45f00d 100644 --- a/README.rst +++ b/README.rst @@ -717,6 +717,10 @@ on the command line: $ echo 'data' | http POST example.org more=data # This is invalid +To prevent HTTPie from reading ``stdin`` data you can use the +``--ignore-stdin`` option. + + ------------------------- Body Data From a Filename ------------------------- @@ -1060,14 +1064,18 @@ When using HTTPie from **shell scripts**, it can be handy to set the ``--check-status`` flag. It instructs HTTPie to exit with an error if the HTTP status is one of ``3xx``, ``4xx``, or ``5xx``. The exit status will be ``3`` (unless ``--follow`` is set), ``4``, or ``5``, -respectively. Also, the ``--timeout`` option allows to overwrite the default -30s timeout: +respectively. + +The ``--ignore-stdin`` option prevents HTTPie from reading data from ``stdin``, +which is usually not desirable during non-interactive invocations. + +Also, the ``--timeout`` option allows to overwrite the default 30s timeout: .. code-block:: bash #!/bin/bash - if http --timeout=2.5 --check-status HEAD example.org/health &> /dev/null; then + if http --check-status --ignore-stdin --timeout=2.5 HEAD example.org/health &> /dev/null; then echo 'OK!' else case $? in @@ -1197,6 +1205,7 @@ Changelog *You can click a version name to see a diff with the previous one.* * `0.7.0-dev`_ + * Added ``--ignore-stdin``. * `0.6.0`_ (2013-06-03) * XML data is now formatted. * ``--session`` and ``--session-read-only`` now also accept paths to diff --git a/httpie/cli.py b/httpie/cli.py index bfeb2d12..88859dfd 100644 --- a/httpie/cli.py +++ b/httpie/cli.py @@ -466,6 +466,15 @@ network.add_argument( troubleshooting = parser.add_argument_group(title='Troubleshooting') +troubleshooting.add_argument( + '--ignore-stdin', + action='store_true', + default=False, + help=""" + Do not attempt to read stdin. + + """ +) troubleshooting.add_argument( '--help', action='help', diff --git a/httpie/input.py b/httpie/input.py index 07ecb8d2..22c79b41 100644 --- a/httpie/input.py +++ b/httpie/input.py @@ -115,7 +115,7 @@ class Parser(ArgumentParser): self._process_pretty_options() self._guess_method() self._parse_items() - if not env.stdin_isatty: + if not self.args.ignore_stdin and not env.stdin_isatty: self._body_from_file(self.env.stdin) if not (self.args.url.startswith((HTTP, HTTPS))): # Default to 'https://' if invoked as `https args`. @@ -184,6 +184,9 @@ class Parser(ArgumentParser): if self.args.auth: if not self.args.auth.has_password(): # Stdin already read (if not a tty) so it's save to prompt. + if self.args.ignore_stdin: + self.error('Unable to prompt for passwords because' + ' --ignore-stdin is set.') self.args.auth.prompt_password(url.netloc) elif url.username is not None: @@ -241,7 +244,7 @@ class Parser(ArgumentParser): if self.args.method is None: # Invoked as `http URL'. assert not self.args.items - if not self.env.stdin_isatty: + if not self.args.ignore_stdin and not self.env.stdin_isatty: self.args.method = HTTP_POST else: self.args.method = HTTP_GET @@ -266,9 +269,12 @@ class Parser(ArgumentParser): # Set the URL correctly self.args.url = self.args.method # Infer the method - has_data = not self.env.stdin_isatty or any( - item.sep in SEP_GROUP_DATA_ITEMS - for item in self.args.items + has_data = ( + (not self.args.ignore_stdin and + not self.env.stdin_isatty) or any( + item.sep in SEP_GROUP_DATA_ITEMS + for item in self.args.items + ) ) self.args.method = HTTP_POST if has_data else HTTP_GET diff --git a/tests/tests.py b/tests/tests.py index 34dc2042..3cba88e3 100755 --- a/tests/tests.py +++ b/tests/tests.py @@ -812,6 +812,7 @@ class RequestBodyFromFilePathTest(BaseTestCase): # FIXME: *sometimes* fails on py33, the content-type is form. # https://github.com/jkbr/httpie/issues/140 r = http( + '--verbose', 'POST', httpbin('/post'), '@' + FILE_PATH_ARG @@ -1082,6 +1083,30 @@ class StreamTest(BaseTestCase): self.assertIn(BIN_FILE_CONTENT, r) +class IgnoreStdinTest(BaseTestCase): + + def test_ignore_stdin(self): + with open(FILE_PATH) as f: + r = http( + '--ignore-stdin', + '--verbose', + httpbin('/get'), + env=TestEnvironment(stdin=f, stdin_isatty=False) + ) + self.assertIn(OK, r) + self.assertIn('GET /get HTTP', r) # Don't default to POST. + self.assertNotIn(FILE_CONTENT, r) # Don't send stdin data. + + def test_ignore_stdin_cannot_prompt_password(self): + r = http( + '--ignore-stdin', + '--auth=username-without-password', + httpbin('/get'), + ) + self.assertEqual(r.exit_status, ExitStatus.ERROR) + self.assertIn('because --ignore-stdin', r.stderr) + + class LineEndingsTest(BaseTestCase): """Test that CRLF is properly used in headers and as the headers/body separator.""" @@ -1234,6 +1259,7 @@ class ArgumentParserTestCase(unittest.TestCase): self.parser.args.method = 'GET' self.parser.args.url = 'http://example.com/' self.parser.args.items = [] + self.parser.args.ignore_stdin = False self.parser.env = TestEnvironment() @@ -1249,6 +1275,7 @@ class ArgumentParserTestCase(unittest.TestCase): self.parser.args.method = None self.parser.args.url = 'http://example.com/' self.parser.args.items = [] + self.parser.args.ignore_stdin = False self.parser.env = TestEnvironment() self.parser._guess_method() @@ -1262,6 +1289,7 @@ class ArgumentParserTestCase(unittest.TestCase): self.parser.args.method = 'http://example.com/' self.parser.args.url = 'data=field' self.parser.args.items = [] + self.parser.args.ignore_stdin = False self.parser.env = TestEnvironment() self.parser._guess_method() @@ -1277,6 +1305,7 @@ class ArgumentParserTestCase(unittest.TestCase): self.parser.args.method = 'http://example.com/' self.parser.args.url = 'test:header' self.parser.args.items = [] + self.parser.args.ignore_stdin = False self.parser.env = TestEnvironment() @@ -1297,6 +1326,7 @@ class ArgumentParserTestCase(unittest.TestCase): input.KeyValue( key='old_item', value='b', sep='=', orig='old_item=b') ] + self.parser.args.ignore_stdin = False self.parser.env = TestEnvironment()