httpie-cli/httpie/core.py

125 lines
3.6 KiB
Python
Raw Normal View History

2012-07-26 06:37:03 +02:00
"""This module provides the main functionality of HTTPie.
Invocation flow:
1. Read, validate and process the input (args, `stdin`).
2. Create and send a request.
3. Stream, and possibly process and format, the requested parts
of the request-response exchange.
4. Simultaneously write to `stdout`
5. Exit.
2012-07-26 06:37:03 +02:00
"""
import sys
import errno
2012-07-26 00:26:23 +02:00
import requests
from requests.compat import str, is_py3
2012-08-07 14:50:51 +02:00
from httpie import __version__ as httpie_version
from requests import __version__ as requests_version
from pygments import __version__ as pygments_version
2012-07-26 00:26:23 +02:00
2012-07-26 06:37:03 +02:00
from .cli import parser
from .client import get_response
from .models import Environment
from .output import output_stream, write, write_with_colors_win_p3k
from .config import DEFAULT_CONFIG_DIR, Config
from . import EXIT
2012-09-07 11:58:39 +02:00
def get_exist_status(code, follow=False):
2012-07-26 06:37:03 +02:00
"""Translate HTTP status code to exit status."""
2012-09-07 11:58:39 +02:00
if 300 <= code <= 399 and not follow:
# Redirect
return EXIT.ERROR_HTTP_3XX
elif 400 <= code <= 499:
# Client Error
return EXIT.ERROR_HTTP_4XX
elif 500 <= code <= 599:
# Server Error
return EXIT.ERROR_HTTP_5XX
else:
return EXIT.OK
def print_debug_info(env):
sys.stderr.writelines([
'HTTPie %s\n' % httpie_version,
'HTTPie data: %s\n' % env.config.directory,
'Requests %s\n' % requests_version,
'Pygments %s\n' % pygments_version,
'Python %s %s\n' % (sys.version, sys.platform)
])
def main(args=sys.argv[1:], env=Environment()):
2012-07-26 06:37:03 +02:00
"""Run the main program and write the output to ``env.stdout``.
Return exit status.
"""
2012-09-17 02:15:00 +02:00
if env.config.default_options:
args = env.config.default_options + args
def error(msg, *args):
msg = msg % args
2012-08-07 00:07:04 +02:00
env.stderr.write('\nhttp: error: %s\n' % msg)
debug = '--debug' in args
2012-08-07 14:50:51 +02:00
traceback = debug or '--traceback' in args
status = EXIT.OK
2012-08-07 14:50:51 +02:00
if debug:
print_debug_info(env)
if args == ['--debug']:
sys.exit(EXIT.OK)
2012-08-07 14:50:51 +02:00
try:
args = parser.parse_args(args=args, env=env)
2012-09-17 02:15:00 +02:00
response = get_response(args, config_dir=env.config.directory)
if args.check_status:
status = get_exist_status(response.status_code,
2012-09-07 11:58:39 +02:00
args.follow)
if status and not env.stdout_isatty:
error('%s %s', response.raw.status, response.raw.reason)
stream = output_stream(args, env, response.request, response)
write_kwargs = {
'stream': stream,
'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_p3k(**write_kwargs)
else:
write(**write_kwargs)
except IOError as e:
2012-08-07 14:50:51 +02:00
if not traceback and e.errno == errno.EPIPE:
# Ignore broken pipes unless --traceback.
env.stderr.write('\n')
else:
raise
except (KeyboardInterrupt, SystemExit):
2012-08-07 14:50:51 +02:00
if traceback:
raise
env.stderr.write('\n')
status = EXIT.ERROR
except requests.Timeout:
status = EXIT.ERROR_TIMEOUT
error('Request timed out (%ss).', args.timeout)
except Exception as e:
# TODO: distinguish between expected and unexpected errors.
# network errors vs. bugs, etc.
2012-08-07 14:50:51 +02:00
if traceback:
raise
error('%s: %s', type(e).__name__, str(e))
status = EXIT.ERROR
return status