diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 8c37eafa..c70698d5 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -14,7 +14,8 @@ This project adheres to `Semantic Versioning `_.
to use for HTTPS requests.
* Added JSON detection with ``--json, -j`` to work around incorrect
``Content-Type``
-* Added ``--show-redirects, -R`` to show intermediate responses with ``--follow``
+* Added ``--all`` to show intermediate responses such as redirects (with ``--follow``)
+* Added ``--print-others, -P WHAT``
* Added ``--max-redirects`` (default 30)
* Added ``-A`` as short name for ``--auth-type``
* Added ``-F`` as short name for ``--follow``
diff --git a/README.rst b/README.rst
index 99416073..50ab6937 100644
--- a/README.rst
+++ b/README.rst
@@ -636,7 +636,7 @@ response is shown. To instruct HTTPie to follow the ``Location`` header of
``30x`` responses and show the final response instead, use the ``--follow, -F`` option.
If you additionally wish to see the intermediary requests/responses,
-then use the ``--show-redirects, -R`` option as well.
+then use the ``--all`` option as well.
To change the default limit of maximum 30 redirects, use the
``--max-redirects=`` option.
@@ -644,7 +644,7 @@ To change the default limit of maximum 30 redirects, use the
.. code-block:: bash
- $ http --follow --show-redirects --max-redirects=5 httpbin.org/redirect/3
+ $ http --follow --all --max-redirects=5 httpbin.org/redirect/3
=======
@@ -771,8 +771,8 @@ You can use the following command to test SNI support:
Output Options
==============
-By default, HTTPie outputs the whole response message (headers as well as the
-body).
+By default, HTTPie only outputs the final response and whole response message
+is printed (headers as well as the body).
You can control what should be printed via several options:
@@ -780,6 +780,7 @@ You can control what should be printed via several options:
``--headers, -h`` Only the response headers are printed.
``--body, -b`` Only the response body is printed.
``--verbose, -v`` Print the whole HTTP exchange (request and response).
+ This option also enables ``--all`` (see bellow).
``--print, -p`` Selects parts of the HTTP exchange.
================= =====================================================
@@ -833,6 +834,33 @@ Print request and response headers:
$ http --print=Hh PUT httpbin.org/put hello=world
+---------------------------------------
+Viewing Intermediary Requests/Responses
+---------------------------------------
+
+If you'd like to see any intermediary requests/responses together with the
+final one, then use the ``--all`` option. Intermediary requests include
+followed redirects (with ``--follow``), the first unauthorized request when
+Digest auth is used (``--auth=digest``), etc. They are by default also
+formatted according to ``--print, -p`` (and its shortcuts described above),
+which can be customized with ``--print-others, -P`` which takes the same
+arguments as ``--print, -p`` but applies to the intermediary requests only.
+
+
+View all responses that lead to the final one:
+
+.. code-block:: bash
+
+ $ http --all --follow httpbin.org/redirect/3
+
+
+Print the final and the intermediary requests/responses differently:
+
+.. code-block:: bash
+
+ $ http --all --follow --print=hH --print-others=H httpbin.org/redirect/3
+
+
-------------------------
Conditional Body Download
-------------------------
diff --git a/httpie/cli.py b/httpie/cli.py
index f964b233..5ddfe472 100644
--- a/httpie/cli.py
+++ b/httpie/cli.py
@@ -250,17 +250,6 @@ output_options.add_argument(
default=OUTPUT_OPTIONS_DEFAULT,
)
)
-output_options.add_argument(
- '--verbose', '-v',
- dest='output_options',
- action='store_const',
- const=''.join(OUTPUT_OPTIONS),
- help="""
- Print the whole request as well as the response. Shortcut for --print={0}.
-
- """
- .format(''.join(OUTPUT_OPTIONS))
-)
output_options.add_argument(
'--headers', '-h',
dest='output_options',
@@ -284,6 +273,42 @@ output_options.add_argument(
.format(OUT_RESP_BODY)
)
+output_options.add_argument(
+ '--verbose', '-v',
+ dest='verbose',
+ action='store_true',
+ help="""
+ Verbose output. Print the whole request as well as the response. Also print
+ any intermediary requests/responses (such as redirects).
+ It's a shortcut for: --all --print={0}
+
+ """
+ .format(''.join(OUTPUT_OPTIONS))
+)
+output_options.add_argument(
+ '--all',
+ default=False,
+ action='store_true',
+ help="""
+ By default, only the final request/response is shown. Use this flag to show
+ any intermediary requests/responses as well. Intermediary requests include
+ followed redirects (with --follow), the first unauthorized request when
+ Digest auth is used (--auth=digest), etc.
+
+ """
+)
+output_options.add_argument(
+ '--print-others', '-P',
+ dest='output_options_others',
+ metavar='WHAT',
+ help="""
+ The same as --print, -p but applies only to intermediary requests/responses
+ (such as redirects) when their inclusion is enabled with --all. If this
+ options is not specified, then they are formatted the same way as the final
+ response.
+
+ """
+)
output_options.add_argument(
'--stream', '-S',
action='store_true',
@@ -454,16 +479,6 @@ network.add_argument(
"""
)
-network.add_argument(
- '--show-redirects', '-R',
- default=False,
- action='store_true',
- help="""
- Show all responses within the redirect chain (works with --follow).
-
- """
-)
-
network.add_argument(
'--max-redirects',
type=int,
diff --git a/httpie/core.py b/httpie/core.py
index 4c224b8a..c3c9b33a 100644
--- a/httpie/core.py
+++ b/httpie/core.py
@@ -96,11 +96,11 @@ def program(args, env, log_error):
)
downloader.pre_request(args.headers)
- last_response = get_response(args, config_dir=env.config.directory)
- if args.show_redirects:
- responses = last_response.history + [last_response]
+ final_response = get_response(args, config_dir=env.config.directory)
+ if args.all:
+ responses = final_response.history + [final_response]
else:
- responses = [last_response]
+ responses = [final_response]
for response in responses:
@@ -121,6 +121,11 @@ def program(args, env, log_error):
env=env,
request=response.request,
response=response,
+ output_options=(
+ args.output_options
+ if response is final_response
+ else args.output_options_others
+ )
),
# NOTE: `env.stdout` will in fact be `stderr` with `--download`
'outfile': env.stdout,
@@ -140,7 +145,7 @@ def program(args, env, log_error):
if downloader and exit_status == ExitStatus.OK:
# Last response body download.
- download_stream, download_to = downloader.start(last_response)
+ download_stream, download_to = downloader.start(final_response)
write_stream(
stream=download_stream,
outfile=download_to,
diff --git a/httpie/input.py b/httpie/input.py
index c622b65b..39c112d3 100644
--- a/httpie/input.py
+++ b/httpie/input.py
@@ -359,18 +359,32 @@ class HTTPieArgumentParser(ArgumentParser):
The default output options are stdout-type-sensitive.
"""
- if not self.args.output_options:
- self.args.output_options = (
- OUTPUT_OPTIONS_DEFAULT
- if self.env.stdout_isatty
- else OUTPUT_OPTIONS_DEFAULT_STDOUT_REDIRECTED
- )
+ def check_options(value, option):
+ unknown = set(value) - OUTPUT_OPTIONS
+ if unknown:
+ self.error('Unknown output options: {0}={1}'.format(
+ option,
+ ','.join(unknown)
+ ))
- unknown_output_options = set(self.args.output_options) - OUTPUT_OPTIONS
- if unknown_output_options:
- self.error(
- 'Unknown output options: %s' % ','.join(unknown_output_options)
- )
+ if self.args.verbose:
+ self.args.all = True
+
+ if self.args.output_options is None:
+ if self.args.verbose:
+ self.args.output_options = ''.join(OUTPUT_OPTIONS)
+ else:
+ self.args.output_options = (
+ OUTPUT_OPTIONS_DEFAULT
+ if self.env.stdout_isatty
+ else OUTPUT_OPTIONS_DEFAULT_STDOUT_REDIRECTED
+ )
+
+ if self.args.output_options_others is None:
+ self.args.output_options_others = self.args.output_options
+
+ check_options(self.args.output_options, '--print')
+ check_options(self.args.output_options_others, '--print-others')
if self.args.download and OUT_RESP_BODY in self.args.output_options:
# Response body is always downloaded with --download and it goes
diff --git a/httpie/output/streams.py b/httpie/output/streams.py
index b2269814..3483a6d3 100644
--- a/httpie/output/streams.py
+++ b/httpie/output/streams.py
@@ -55,15 +55,15 @@ def write_stream_with_colors_win_py3(stream, outfile, flush):
outfile.flush()
-def build_output_stream(args, env, request, response):
+def build_output_stream(args, env, request, response, output_options):
"""Build and return a chain of iterators over the `request`-`response`
exchange each of which yields `bytes` chunks.
"""
- req_h = OUT_REQ_HEAD in args.output_options
- req_b = OUT_REQ_BODY in args.output_options
- resp_h = OUT_RESP_HEAD in args.output_options
- resp_b = OUT_RESP_BODY in args.output_options
+ req_h = OUT_REQ_HEAD in output_options
+ req_b = OUT_REQ_BODY in output_options
+ resp_h = OUT_RESP_HEAD in output_options
+ resp_b = OUT_RESP_BODY in output_options
req = req_h or req_b
resp = resp_h or resp_b
diff --git a/tests/test_redirects.py b/tests/test_redirects.py
index e96ea8e5..579f5c6c 100644
--- a/tests/test_redirects.py
+++ b/tests/test_redirects.py
@@ -3,16 +3,38 @@ from httpie import ExitStatus
from utils import http, HTTP_OK
-def test_follow_no_show_redirects(httpbin):
+def test_follow_all_redirects_shown(httpbin):
+ r = http('--follow', '--all', httpbin.url + '/redirect/2')
+ assert r.count('HTTP/1.1') == 3
+ assert r.count('HTTP/1.1 302 FOUND', 2)
+ assert HTTP_OK in r
+
+
+def test_follow_without_all_redirects_hidden(httpbin):
r = http('--follow', httpbin.url + '/redirect/2')
assert r.count('HTTP/1.1') == 1
assert HTTP_OK in r
-def test_follow_show_redirects(httpbin):
- r = http('--follow', '--show-redirects', httpbin.url + '/redirect/2')
- assert r.count('HTTP/1.1') == 3
- assert r.count('HTTP/1.1 302 FOUND', 2)
+def test_follow_all_output_options_used_for_redirects(httpbin):
+ r = http('--check-status',
+ '--follow',
+ '--all',
+ '--print=H',
+ httpbin.url + '/redirect/2')
+ assert r.count('GET /') == 3
+ assert HTTP_OK not in r
+
+
+def test_follow_redirect_output_options(httpbin):
+ r = http('--check-status',
+ '--follow',
+ '--all',
+ '--print=h',
+ '--print-others=H',
+ httpbin.url + '/redirect/2')
+ assert r.count('GET /') == 2
+ assert 'HTTP/1.1 302 FOUND' not in r
assert HTTP_OK in r