mirror of
https://github.com/httpie/cli.git
synced 2025-06-24 11:33:48 +02:00
Changed default --print to "b" if stdout piped.
If the output is piped to another program or redirected to a file, the new default behaviour is to only print the response body. (It can still be overriden via the ``--print`` flag.)
This commit is contained in:
parent
7d82b853ae
commit
57fc606f6b
@ -143,13 +143,13 @@ case it will be used with no further processing::
|
|||||||
That can be used for **piping services together**. The following example
|
That can be used for **piping services together**. The following example
|
||||||
``GET``-s JSON data from the Github API and ``POST``-s it to httpbin.org::
|
``GET``-s JSON data from the Github API and ``POST``-s it to httpbin.org::
|
||||||
|
|
||||||
http -b GET https://api.github.com/repos/jkbr/httpie | http POST httpbin.org/post
|
http GET https://api.github.com/repos/jkbr/httpie | http POST httpbin.org/post
|
||||||
|
|
||||||
The above can be further simplified by omitting ``GET`` and ``POST`` because
|
The above can be further simplified by omitting ``GET`` and ``POST`` because
|
||||||
they are both default here. The first command has no request data, whereas
|
they are both default here. The first command has no request data, whereas
|
||||||
the second one does via ``stdin``::
|
the second one does via ``stdin``::
|
||||||
|
|
||||||
http -b https://api.github.com/repos/jkbr/httpie | http httpbin.org/post
|
http https://api.github.com/repos/jkbr/httpie | http httpbin.org/post
|
||||||
|
|
||||||
An alternative to ``stdin`` is to pass a file name whose content will be used
|
An alternative to ``stdin`` is to pass a file name whose content will be used
|
||||||
as the request body. It has the advantage that the ``Content-Type`` header
|
as the request body. It has the advantage that the ``Content-Type`` header
|
||||||
@ -284,6 +284,9 @@ Changelog
|
|||||||
---------
|
---------
|
||||||
|
|
||||||
* `0.2.6dev <https://github.com/jkbr/httpie/compare/0.2.5...master>`_
|
* `0.2.6dev <https://github.com/jkbr/httpie/compare/0.2.5...master>`_
|
||||||
|
* If the output is piped to another program or redirected to a file,
|
||||||
|
the new default behaviour is to only print the response body.
|
||||||
|
(It can still be overriden via the ``--print`` flag.)
|
||||||
* Improved highlighing of HTTP headers.
|
* Improved highlighing of HTTP headers.
|
||||||
* Added query string parameters (param=:value).
|
* Added query string parameters (param=:value).
|
||||||
* Added support for terminal colors under Windows.
|
* Added support for terminal colors under Windows.
|
||||||
|
@ -117,11 +117,14 @@ def main(args=None,
|
|||||||
stdin=sys.stdin, stdin_isatty=sys.stdin.isatty(),
|
stdin=sys.stdin, stdin_isatty=sys.stdin.isatty(),
|
||||||
stdout=sys.stdout, stdout_isatty=sys.stdout.isatty()):
|
stdout=sys.stdout, stdout_isatty=sys.stdout.isatty()):
|
||||||
parser = cli.parser
|
parser = cli.parser
|
||||||
|
|
||||||
args = parser.parse_args(
|
args = parser.parse_args(
|
||||||
args=args if args is not None else sys.argv[1:],
|
args=args if args is not None else sys.argv[1:],
|
||||||
stdin=stdin,
|
stdin=stdin,
|
||||||
stdin_isatty=stdin_isatty
|
stdin_isatty=stdin_isatty,
|
||||||
|
stdout_isatty=stdout_isatty,
|
||||||
)
|
)
|
||||||
|
|
||||||
response = _get_response(args)
|
response = _get_response(args)
|
||||||
output = _get_output(args, stdout_isatty, response)
|
output = _get_output(args, stdout_isatty, response)
|
||||||
output_bytes = output.encode('utf8')
|
output_bytes = output.encode('utf8')
|
||||||
|
@ -72,15 +72,16 @@ prettify.add_argument(
|
|||||||
|
|
||||||
output_options = parser.add_mutually_exclusive_group(required=False)
|
output_options = parser.add_mutually_exclusive_group(required=False)
|
||||||
output_options.add_argument('--print', '-p', dest='output_options',
|
output_options.add_argument('--print', '-p', dest='output_options',
|
||||||
default=cliparse.OUT_RESP_HEADERS + cliparse.OUT_RESP_BODY,
|
|
||||||
help=_('''
|
help=_('''
|
||||||
String specifying what should the output contain.
|
String specifying what the output should contain:
|
||||||
"{request_headers}" stands for the request headers and
|
"{request_headers}" stands for the request headers, and
|
||||||
"{request_body}" for the request body.
|
"{request_body}" for the request body.
|
||||||
"{response_headers}" stands for the response headers and
|
"{response_headers}" stands for the response headers and
|
||||||
"{response_body}" for response the body.
|
"{response_body}" for response the body.
|
||||||
Defaults to "hb" which means that the whole response
|
The default behaviour is "hb" (i.e., the response
|
||||||
(headers and body) is printed.
|
headers and body is printed), if standard output is not redirected.
|
||||||
|
If the output is piped to another program or to a file,
|
||||||
|
then only the body is printed by default.
|
||||||
'''.format(
|
'''.format(
|
||||||
request_headers=cliparse.OUT_REQ_HEADERS,
|
request_headers=cliparse.OUT_REQ_HEADERS,
|
||||||
request_body=cliparse.OUT_REQ_BODY,
|
request_body=cliparse.OUT_REQ_BODY,
|
||||||
|
@ -52,11 +52,12 @@ class Parser(argparse.ArgumentParser):
|
|||||||
|
|
||||||
def parse_args(self, args=None, namespace=None,
|
def parse_args(self, args=None, namespace=None,
|
||||||
stdin=sys.stdin,
|
stdin=sys.stdin,
|
||||||
stdin_isatty=sys.stdin.isatty()):
|
stdin_isatty=sys.stdin.isatty(),
|
||||||
|
stdout_isatty=sys.stdout.isatty()):
|
||||||
|
|
||||||
args = super(Parser, self).parse_args(args, namespace)
|
args = super(Parser, self).parse_args(args, namespace)
|
||||||
|
|
||||||
self._validate_output_options(args)
|
self._process_output_options(args, stdout_isatty)
|
||||||
self._validate_auth_options(args)
|
self._validate_auth_options(args)
|
||||||
self._guess_method(args, stdin_isatty)
|
self._guess_method(args, stdin_isatty)
|
||||||
self._parse_items(args)
|
self._parse_items(args)
|
||||||
@ -120,7 +121,8 @@ class Parser(argparse.ArgumentParser):
|
|||||||
|
|
||||||
def _parse_items(self, args):
|
def _parse_items(self, args):
|
||||||
"""
|
"""
|
||||||
Parse `args.items` into `args.headers`, `args.data`, `args.queries`, and `args.files`.
|
Parse `args.items` into `args.headers`,
|
||||||
|
`args.data`, `args.queries`, and `args.files`.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
args.headers = CaseInsensitiveDict()
|
args.headers = CaseInsensitiveDict()
|
||||||
@ -129,8 +131,11 @@ class Parser(argparse.ArgumentParser):
|
|||||||
args.files = OrderedDict()
|
args.files = OrderedDict()
|
||||||
args.queries = CaseInsensitiveDict()
|
args.queries = CaseInsensitiveDict()
|
||||||
try:
|
try:
|
||||||
parse_items(items=args.items, headers=args.headers,
|
parse_items(items=args.items,
|
||||||
data=args.data, files=args.files, queries=args.queries)
|
headers=args.headers,
|
||||||
|
data=args.data,
|
||||||
|
files=args.files,
|
||||||
|
queries=args.queries)
|
||||||
except ParseError as e:
|
except ParseError as e:
|
||||||
if args.traceback:
|
if args.traceback:
|
||||||
raise
|
raise
|
||||||
@ -157,7 +162,13 @@ class Parser(argparse.ArgumentParser):
|
|||||||
content_type = '%s; charset=%s' % (mime, encoding)
|
content_type = '%s; charset=%s' % (mime, encoding)
|
||||||
args.headers['Content-Type'] = content_type
|
args.headers['Content-Type'] = content_type
|
||||||
|
|
||||||
def _validate_output_options(self, args):
|
def _process_output_options(self, args, stdout_isatty):
|
||||||
|
if not args.output_options:
|
||||||
|
if stdout_isatty:
|
||||||
|
args.output_options = OUT_RESP_HEADERS + OUT_RESP_BODY
|
||||||
|
else:
|
||||||
|
args.output_options = OUT_RESP_BODY
|
||||||
|
|
||||||
unknown = set(args.output_options) - set(OUTPUT_OPTIONS)
|
unknown = set(args.output_options) - set(OUTPUT_OPTIONS)
|
||||||
if unknown:
|
if unknown:
|
||||||
self.error(
|
self.error(
|
||||||
@ -270,7 +281,11 @@ class AuthCredentialsType(KeyValueType):
|
|||||||
|
|
||||||
|
|
||||||
def parse_items(items, data=None, headers=None, files=None, queries=None):
|
def parse_items(items, data=None, headers=None, files=None, queries=None):
|
||||||
"""Parse `KeyValueType` `items` into `data`, `headers`, `files`, and `queries`."""
|
"""
|
||||||
|
Parse `KeyValueType` `items` into `data`, `headers`, `files`,
|
||||||
|
and `queries`.
|
||||||
|
|
||||||
|
"""
|
||||||
if headers is None:
|
if headers is None:
|
||||||
headers = {}
|
headers = {}
|
||||||
if data is None:
|
if data is None:
|
||||||
|
@ -34,9 +34,19 @@ def http(*args, **kwargs):
|
|||||||
"""
|
"""
|
||||||
http_kwargs = {
|
http_kwargs = {
|
||||||
'stdin_isatty': True,
|
'stdin_isatty': True,
|
||||||
'stdout_isatty': False
|
'stdout_isatty': True
|
||||||
}
|
}
|
||||||
http_kwargs.update(kwargs)
|
http_kwargs.update(kwargs)
|
||||||
|
|
||||||
|
command_line = ' '.join(args)
|
||||||
|
if ('stdout_isatty' not in kwargs
|
||||||
|
and '--pretty' not in command_line
|
||||||
|
and '--ugly' not in command_line):
|
||||||
|
# Make ugly default for testing purposes unless we're
|
||||||
|
# being explicit about it. It's so that we can test for
|
||||||
|
# strings in the response without having to always pass --ugly.
|
||||||
|
args = ['--ugly'] + list(args)
|
||||||
|
|
||||||
stdout = http_kwargs.setdefault('stdout', tempfile.TemporaryFile())
|
stdout = http_kwargs.setdefault('stdout', tempfile.TemporaryFile())
|
||||||
__main__.main(args=args, **http_kwargs)
|
__main__.main(args=args, **http_kwargs)
|
||||||
stdout.seek(0)
|
stdout.seek(0)
|
||||||
@ -168,6 +178,14 @@ class AutoContentTypeAndAcceptHeadersTest(BaseTestCase):
|
|||||||
self.assertIn('HTTP/1.1 200', r)
|
self.assertIn('HTTP/1.1 200', r)
|
||||||
self.assertIn('"Content-Type": "application/xml"', r)
|
self.assertIn('"Content-Type": "application/xml"', r)
|
||||||
|
|
||||||
|
def test_print_only_body_when_stdout_redirected_by_default(self):
|
||||||
|
r = http('GET', 'httpbin.org/get', stdout_isatty=False)
|
||||||
|
self.assertNotIn('HTTP/', r)
|
||||||
|
|
||||||
|
def test_print_overridable_when_stdout_redirected(self):
|
||||||
|
r = http('--print=h', 'GET', 'httpbin.org/get', stdout_isatty=False)
|
||||||
|
self.assertIn('HTTP/1.1 200', r)
|
||||||
|
|
||||||
|
|
||||||
class ImplicitHTTPMethodTest(BaseTestCase):
|
class ImplicitHTTPMethodTest(BaseTestCase):
|
||||||
|
|
||||||
@ -203,7 +221,7 @@ class PrettyFlagTest(BaseTestCase):
|
|||||||
r = http('GET', 'http://httpbin.org/get', stdout_isatty=True)
|
r = http('GET', 'http://httpbin.org/get', stdout_isatty=True)
|
||||||
self.assertIn(TERMINAL_COLOR_PRESENCE_CHECK, r)
|
self.assertIn(TERMINAL_COLOR_PRESENCE_CHECK, r)
|
||||||
|
|
||||||
def test_pretty_enabled_by_default_unless_stdin_redirected(self):
|
def test_pretty_enabled_by_default_unless_stdout_redirected(self):
|
||||||
r = http('GET', 'http://httpbin.org/get', stdout_isatty=False)
|
r = http('GET', 'http://httpbin.org/get', stdout_isatty=False)
|
||||||
self.assertNotIn(TERMINAL_COLOR_PRESENCE_CHECK, r)
|
self.assertNotIn(TERMINAL_COLOR_PRESENCE_CHECK, r)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user