Replace --show-redirects with --all and add --print-others, -P

With --all, any intermediary requests/responses are shown (such as redirects
 or the initial unauthorized Digest auth request).

 The --print-others, -P option works like --print, -p, but only applies to
 intermediary requests/responses. The default behaviour is to inherit
 the value of -p.
This commit is contained in:
Jakub Roztocil 2016-03-06 02:09:52 +08:00
parent a6ebc44a48
commit 6e1dbadff9
7 changed files with 137 additions and 52 deletions

View File

@ -14,7 +14,8 @@ This project adheres to `Semantic Versioning <http://semver.org/>`_.
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``

View File

@ -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=<limit>`` 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
-------------------------

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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