1
0
mirror of https://github.com/httpie/cli.git synced 2026-04-24 19:53:55 +02:00

Add one-by-one processing of each HTTP request or response and --offline

This commit is contained in:
Jakub Roztocil
2019-09-03 17:14:39 +02:00
parent c946b3d34f
commit bece3c77bb
22 changed files with 536 additions and 483 deletions
+1 -1
View File
@@ -71,7 +71,7 @@ def test_missing_auth(httpbin):
'--auth-type=basic',
'GET',
httpbin + '/basic-auth/user/password',
error_exit_ok=True
tolerate_error_exit_status=True
)
assert HTTP_OK not in r
assert '--auth required' in r.stderr
+2 -2
View File
@@ -303,7 +303,7 @@ class TestNoOptions:
def test_invalid_no_options(self, httpbin):
r = http('--no-war', 'GET', httpbin.url + '/get',
error_exit_ok=True)
tolerate_error_exit_status=True)
assert r.exit_status == ExitStatus.ERROR
assert 'unrecognized arguments: --no-war' in r.stderr
assert 'GET /get HTTP/1.1' not in r
@@ -322,7 +322,7 @@ class TestStdin:
def test_ignore_stdin_cannot_prompt_password(self, httpbin):
r = http('--ignore-stdin', '--auth=no-password', httpbin.url + '/get',
error_exit_ok=True)
tolerate_error_exit_status=True)
assert r.exit_status == ExitStatus.ERROR
assert 'because --ignore-stdin' in r.stderr
+18 -9
View File
@@ -135,10 +135,13 @@ class TestDownloads:
def test_download_with_Content_Length(self, httpbin_both):
with open(os.devnull, 'w') as devnull:
downloader = Downloader(output_file=devnull, progress_file=devnull)
downloader.start(Response(
url=httpbin_both.url + '/',
headers={'Content-Length': 10}
))
downloader.start(
initial_url='/',
final_response=Response(
url=httpbin_both.url + '/',
headers={'Content-Length': 10}
)
)
time.sleep(1.1)
downloader.chunk_downloaded(b'12345')
time.sleep(1.1)
@@ -150,7 +153,10 @@ class TestDownloads:
def test_download_no_Content_Length(self, httpbin_both):
with open(os.devnull, 'w') as devnull:
downloader = Downloader(output_file=devnull, progress_file=devnull)
downloader.start(Response(url=httpbin_both.url + '/'))
downloader.start(
final_response=Response(url=httpbin_both.url + '/'),
initial_url='/'
)
time.sleep(1.1)
downloader.chunk_downloaded(b'12345')
downloader.finish()
@@ -160,10 +166,13 @@ class TestDownloads:
def test_download_interrupted(self, httpbin_both):
with open(os.devnull, 'w') as devnull:
downloader = Downloader(output_file=devnull, progress_file=devnull)
downloader.start(Response(
url=httpbin_both.url + '/',
headers={'Content-Length': 5}
))
downloader.start(
final_response=Response(
url=httpbin_both.url + '/',
headers={'Content-Length': 5}
),
initial_url='/'
)
downloader.chunk_downloaded(b'1234')
downloader.finish()
assert downloader.interrupted
+5 -5
View File
@@ -1,17 +1,17 @@
import mock
from pytest import raises
from requests import Request, Timeout
from requests import Request
from requests.exceptions import ConnectionError
from httpie import ExitStatus
from httpie.core import main
from utils import http, HTTP_OK
from utils import HTTP_OK, http
error_msg = None
@mock.patch('httpie.core.get_response')
@mock.patch('httpie.core.program')
def test_error(get_response):
def error(msg, *args, **kwargs):
global error_msg
@@ -24,11 +24,11 @@ def test_error(get_response):
assert ret == ExitStatus.ERROR
assert error_msg == (
'ConnectionError: '
'Connection aborted while doing GET request to URL: '
'Connection aborted while doing a GET request to URL: '
'http://www.google.com')
@mock.patch('httpie.core.get_response')
@mock.patch('httpie.core.program')
def test_error_traceback(get_response):
exc = ConnectionError('Connection aborted')
exc.request = Request(method='GET', url='http://www.google.com')
+7 -7
View File
@@ -7,14 +7,14 @@ from utils import MockEnvironment, http, HTTP_OK
def test_keyboard_interrupt_during_arg_parsing_exit_status(httpbin):
with mock.patch('httpie.cli.definition.parser.parse_args',
side_effect=KeyboardInterrupt()):
r = http('GET', httpbin.url + '/get', error_exit_ok=True)
r = http('GET', httpbin.url + '/get', tolerate_error_exit_status=True)
assert r.exit_status == ExitStatus.ERROR_CTRL_C
def test_keyboard_interrupt_in_program_exit_status(httpbin):
with mock.patch('httpie.core.program',
side_effect=KeyboardInterrupt()):
r = http('GET', httpbin.url + '/get', error_exit_ok=True)
r = http('GET', httpbin.url + '/get', tolerate_error_exit_status=True)
assert r.exit_status == ExitStatus.ERROR_CTRL_C
@@ -34,7 +34,7 @@ def test_error_response_exits_0_without_check_status(httpbin):
def test_timeout_exit_status(httpbin):
r = http('--timeout=0.01', 'GET', httpbin.url + '/delay/0.5',
error_exit_ok=True)
tolerate_error_exit_status=True)
assert r.exit_status == ExitStatus.ERROR_TIMEOUT
@@ -43,7 +43,7 @@ def test_3xx_check_status_exits_3_and_stderr_when_stdout_redirected(
env = MockEnvironment(stdout_isatty=False)
r = http('--check-status', '--headers',
'GET', httpbin.url + '/status/301',
env=env, error_exit_ok=True)
env=env, tolerate_error_exit_status=True)
assert '301 MOVED PERMANENTLY' in r
assert r.exit_status == ExitStatus.ERROR_HTTP_3XX
assert '301 moved permanently' in r.stderr.lower()
@@ -52,7 +52,7 @@ def test_3xx_check_status_exits_3_and_stderr_when_stdout_redirected(
def test_3xx_check_status_redirects_allowed_exits_0(httpbin):
r = http('--check-status', '--follow',
'GET', httpbin.url + '/status/301',
error_exit_ok=True)
tolerate_error_exit_status=True)
# The redirect will be followed so 200 is expected.
assert HTTP_OK in r
assert r.exit_status == ExitStatus.SUCCESS
@@ -60,7 +60,7 @@ def test_3xx_check_status_redirects_allowed_exits_0(httpbin):
def test_4xx_check_status_exits_4(httpbin):
r = http('--check-status', 'GET', httpbin.url + '/status/401',
error_exit_ok=True)
tolerate_error_exit_status=True)
assert '401 UNAUTHORIZED' in r
assert r.exit_status == ExitStatus.ERROR_HTTP_4XX
# Also stderr should be empty since stdout isn't redirected.
@@ -69,6 +69,6 @@ def test_4xx_check_status_exits_4(httpbin):
def test_5xx_check_status_exits_5(httpbin):
r = http('--check-status', 'GET', httpbin.url + '/status/500',
error_exit_ok=True)
tolerate_error_exit_status=True)
assert '500 INTERNAL SERVER ERROR' in r
assert r.exit_status == ExitStatus.ERROR_HTTP_5XX
+2 -2
View File
@@ -15,13 +15,13 @@ def test_debug():
def test_help():
r = http('--help', error_exit_ok=True)
r = http('--help', tolerate_error_exit_status=True)
assert r.exit_status == httpie.ExitStatus.SUCCESS
assert 'https://github.com/jakubroztocil/httpie/issues' in r
def test_version():
r = http('--version', error_exit_ok=True)
r = http('--version', tolerate_error_exit_status=True)
assert r.exit_status == httpie.ExitStatus.SUCCESS
# FIXME: py3 has version in stdout, py2 in stderr
assert httpie.__version__ == r.strip()
+18 -13
View File
@@ -28,20 +28,25 @@ def test_follow_all_output_options_used_for_redirects(httpbin):
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',
'--history-print=H',
httpbin.url + '/redirect/2')
assert r.count('GET /') == 2
assert 'HTTP/1.1 302 FOUND' not in r
assert HTTP_OK in r
#
# def test_follow_redirect_output_options(httpbin):
# r = http('--check-status',
# '--follow',
# '--all',
# '--print=h',
# '--history-print=H',
# httpbin.url + '/redirect/2')
# assert r.count('GET /') == 2
# assert 'HTTP/1.1 302 FOUND' not in r
# assert HTTP_OK in r
#
def test_max_redirects(httpbin):
r = http('--max-redirects=1', '--follow', httpbin.url + '/redirect/3',
error_exit_ok=True)
r = http(
'--max-redirects=1',
'--follow',
httpbin.url + '/redirect/3',
tolerate_error_exit_status=True,
)
assert r.exit_status == ExitStatus.ERROR_TOO_MANY_REDIRECTS
+9 -4
View File
@@ -45,10 +45,15 @@ class TestSessionFlow(SessionTestBase):
"""
super().start_session(httpbin)
r1 = http('--follow', '--session=test', '--auth=username:password',
'GET', httpbin.url + '/cookies/set?hello=world',
'Hello:World',
env=self.env())
r1 = http(
'--follow',
'--session=test',
'--auth=username:password',
'GET',
httpbin.url + '/cookies/set?hello=world',
'Hello:World',
env=self.env()
)
assert HTTP_OK in r1
def test_session_created_and_reused(self, httpbin):
+1 -1
View File
@@ -66,7 +66,7 @@ class TestClientCert:
def test_cert_file_not_found(self, httpbin_secure):
r = http(httpbin_secure + '/get',
'--cert', '/__not_found__',
error_exit_ok=True)
tolerate_error_exit_status=True)
assert r.exit_status == ExitStatus.ERROR
assert 'No such file or directory' in r.stderr
+8 -3
View File
@@ -64,12 +64,17 @@ class TestRequestBodyFromFilePath:
self, httpbin):
env = MockEnvironment(stdin_isatty=True)
r = http('POST', httpbin.url + '/post', 'field-name@' + FILE_PATH_ARG,
env=env, error_exit_ok=True)
env=env, tolerate_error_exit_status=True)
assert 'perhaps you meant --form?' in r.stderr
def test_request_body_from_file_by_path_no_data_items_allowed(
self, httpbin):
env = MockEnvironment(stdin_isatty=False)
r = http('POST', httpbin.url + '/post', '@' + FILE_PATH_ARG, 'foo=bar',
env=env, error_exit_ok=True)
r = http(
'POST',
httpbin.url + '/post',
'@' + FILE_PATH_ARG, 'foo=bar',
env=env,
tolerate_error_exit_status=True,
)
assert 'cannot be mixed' in r.stderr
+1 -1
View File
@@ -27,5 +27,5 @@ class TestFakeWindows:
)
r = http('--output', output_file,
'--pretty=all', 'GET', httpbin.url + '/get',
env=env, error_exit_ok=True)
env=env, tolerate_error_exit_status=True)
assert 'Only terminal output can be colorized on Windows' in r.stderr
+5 -5
View File
@@ -167,7 +167,7 @@ def http(*args, program_name='http', **kwargs):
Exceptions are propagated.
If you pass ``error_exit_ok=True``, then error exit statuses
If you pass ``tolerate_error_exit_status=True``, then error exit statuses
won't result into an exception.
Example:
@@ -188,7 +188,7 @@ def http(*args, program_name='http', **kwargs):
True
"""
error_exit_ok = kwargs.pop('error_exit_ok', False)
tolerate_error_exit_status = kwargs.pop('tolerate_error_exit_status', False)
env = kwargs.get('env')
if not env:
env = kwargs['env'] = MockEnvironment()
@@ -200,7 +200,7 @@ def http(*args, program_name='http', **kwargs):
args_with_config_defaults = args + env.config.default_options
add_to_args = []
if '--debug' not in args_with_config_defaults:
if not error_exit_ok and '--traceback' not in args_with_config_defaults:
if not tolerate_error_exit_status and '--traceback' not in args_with_config_defaults:
add_to_args.append('--traceback')
if not any('--timeout' in arg for arg in args_with_config_defaults):
add_to_args.append('--timeout=3')
@@ -218,7 +218,7 @@ def http(*args, program_name='http', **kwargs):
# Let the progress reporter thread finish.
time.sleep(.5)
except SystemExit:
if error_exit_ok:
if tolerate_error_exit_status:
exit_status = ExitStatus.ERROR
else:
dump_stderr()
@@ -228,7 +228,7 @@ def http(*args, program_name='http', **kwargs):
sys.stderr.write(stderr.read())
raise
else:
if not error_exit_ok and exit_status != ExitStatus.SUCCESS:
if not tolerate_error_exit_status and exit_status != ExitStatus.SUCCESS:
dump_stderr()
raise ExitStatusError(
'httpie.core.main() unexpectedly returned'