Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Solves Issue #183 (--follow does not show redirects) #186

Closed
wants to merge 3 commits into from

1 participant

@tylercrompton

I implemented in a way different than described (cURL's implementation). I implemented it so that it respected the output formatting arguments. Perhaps we can add a --last argument to only output the last response? That wouldn't too much work to implement.

We still need to write one or more tests for this, though.

This is an extension of Issue #184.

@tylercrompton tylercrompton deleted the tylercrompton:follow_headers branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 88 additions and 39 deletions.
  1. +1 −0  README.rst
  2. +37 −0 httpie/client.py
  3. +50 −39 httpie/core.py
View
1  README.rst
@@ -1257,6 +1257,7 @@ Changelog
* Added ``field=@file.txt`` and ``field:=@file.json`` for embedding
the contents of text and JSON files into request data.
* Added curl-style shorthand for localhost
+ * Using ``--follow`` now shows all responses (and all requests if specified)
* `0.7.1`_ (2013-09-24)
* Added ``--ignore-stdin``.
* Added support for auth plugins.
View
37 httpie/client.py
@@ -37,6 +37,43 @@ def get_response(args, config_dir):
return response
+def get_responses(args, config_dir):
+ requests_kwargs = get_requests_kwargs(args)
+
+ if args.debug:
+ sys.stderr.write('\n>>> requests.request(%s)\n\n'
+ % pformat(requests_kwargs))
+
+ requests_kwargs['allow_redirects'] = False
+ session = requests.Session()
+ if not args.session and not args.session_read_only:
+ response = session.request(**requests_kwargs)
+ else:
+ response = sessions.get_response(
+ args=args,
+ config_dir=config_dir,
+ session_name=args.session or args.session_read_only,
+ requests_kwargs=requests_kwargs,
+ read_only=bool(args.session_read_only),
+ )
+
+ # Yielding the response before retrieving the next response (if any)
+ # causes an error.
+ redirect = None
+ redirects = ()
+ if args.follow:
+ redirects = session.resolve_redirects(response, response.request)
+ try:
+ redirect = next(redirects)
+ except StopIteration:
+ pass
+ yield response
+ if redirect is not None:
+ yield redirect
+ for response in redirects:
+ yield response
+
+
def get_requests_kwargs(args):
"""Translate our `args` into `requests.request` keyword arguments."""
View
89 httpie/core.py
@@ -19,7 +19,7 @@
from pygments import __version__ as pygments_version
from .compat import str, is_py3
-from .client import get_response
+from .client import get_responses
from .downloads import Download
from .models import Environment
from .output import build_output_stream, write, write_with_colors_win_py3
@@ -92,60 +92,71 @@ def error(msg, *args, **kwargs):
)
download.pre_request(args.headers)
- response = get_response(args, config_dir=env.config.directory)
+ last_response = None
+ # This will in fact be `stderr` with `--download`
+ outfile = env.stdout
+ flush = env.stdout_isatty or args.stream
+ for response in get_responses(args, env.config.directory):
+ if last_response is not None:
+ try:
+ write((b'\n\n',), outfile, flush)
+ except IOError as e:
+ if not traceback and e.errno == errno.EPIPE:
+ # Ignore broken pipes unless --traceback.
+ env.stderr.write('\n')
+ else:
+ raise
+ last_response = response
+
+ stream = build_output_stream(args, env, response.request, response)
+
+ try:
+ if env.is_windows and is_py3 and 'colors' in args.prettify:
+ write_with_colors_win_py3(stream, outfile, flush)
+ else:
+ write(stream, outfile, flush)
+ except IOError as e:
+ if not traceback and e.errno == errno.EPIPE:
+ # Ignore broken pipes unless --traceback.
+ env.stderr.write('\n')
+ else:
+ raise
if args.check_status or download:
-
exit_status = get_exit_status(
- http_status=response.status_code,
+ http_status=last_response.status_code,
follow=args.follow
)
if not env.stdout_isatty and exit_status != ExitStatus.OK:
error('HTTP %s %s',
- response.raw.status,
- response.raw.reason,
+ last_response.raw.status,
+ last_response.raw.reason,
level='warning')
- write_kwargs = {
- 'stream': build_output_stream(
- args, env, response.request, response),
-
- # This will in fact be `stderr` with `--download`
- 'outfile': env.stdout,
-
- 'flush': env.stdout_isatty or args.stream
- }
-
- try:
-
- if env.is_windows and is_py3 and 'colors' in args.prettify:
- write_with_colors_win_py3(**write_kwargs)
- else:
- write(**write_kwargs)
-
- if download and exit_status == ExitStatus.OK:
+ if download and exit_status == ExitStatus.OK:
+ try:
# Response body download.
- download_stream, download_to = download.start(response)
+ download_stream, download_to = download.start(last_response)
write(
stream=download_stream,
outfile=download_to,
flush=False,
)
- download.finish()
- if download.interrupted:
- exit_status = ExitStatus.ERROR
- error('Incomplete download: size=%d; downloaded=%d' % (
- download.status.total_size,
- download.status.downloaded
- ))
-
- except IOError as e:
- if not traceback and e.errno == errno.EPIPE:
- # Ignore broken pipes unless --traceback.
- env.stderr.write('\n')
- else:
- raise
+ except IOError as e:
+ if not traceback and e.errno == errno.EPIPE:
+ # Ignore broken pipes unless --traceback.
+ env.stderr.write('\n')
+ else:
+ raise
+
+ download.finish()
+ if download.interrupted:
+ exit_status = ExitStatus.ERROR
+ error('Incomplete download: size=%d; downloaded=%d' % (
+ download.status.total_size,
+ download.status.downloaded
+ ))
except (KeyboardInterrupt, SystemExit):
if traceback:
raise
Something went wrong with that request. Please try again.