1
0
mirror of https://github.com/httpie/cli.git synced 2024-11-24 08:22:22 +02:00

Added tests for binary request data.

This commit is contained in:
Jakub Roztocil 2012-08-01 00:52:30 +02:00
parent 8905b4fc72
commit 90d34ffd0d
7 changed files with 78 additions and 14 deletions

View File

@ -85,7 +85,7 @@ def get_response(args, env):
except Exception as e: except Exception as e:
if args.debug: if args.debug:
raise raise
env.stderr.write(str(e.message) + '\n') env.stderr.write(str(repr(e) + '\n'))
sys.exit(1) sys.exit(1)

View File

@ -103,7 +103,7 @@ class Parser(argparse.ArgumentParser):
self._parse_items(args) self._parse_items(args)
if not env.stdin_isatty: if not env.stdin_isatty:
self._body_from_file(args, env.stdin.read()) self._body_from_file(args, env.stdin)
if args.auth and not args.auth.has_password(): if args.auth and not args.auth.has_password():
# Stdin already read (if not a tty) so it's save to prompt. # Stdin already read (if not a tty) so it's save to prompt.
@ -129,12 +129,16 @@ class Parser(argparse.ArgumentParser):
super(Parser, self)._print_message(message, file) super(Parser, self)._print_message(message, file)
def _body_from_file(self, args, data): def _body_from_file(self, args, fd):
"""There can only be one source of request data.""" """There can only be one source of request data.
Bytes are always read.
"""
if args.data: if args.data:
self.error('Request body (from stdin or a file) and request ' self.error('Request body (from stdin or a file) and request '
'data (key=value) cannot be mixed.') 'data (key=value) cannot be mixed.')
args.data = data args.data = getattr(fd, 'buffer', fd).read()
def _guess_method(self, args, env): def _guess_method(self, args, env):
"""Set `args.method` if not specified to either POST or GET """Set `args.method` if not specified to either POST or GET
@ -201,9 +205,9 @@ class Parser(argparse.ArgumentParser):
'Invalid file fields (perhaps you meant --form?): %s' 'Invalid file fields (perhaps you meant --form?): %s'
% ','.join(file_fields)) % ','.join(file_fields))
fn, data = args.files[''] fn, fd = args.files['']
args.files = {} args.files = {}
self._body_from_file(args, data) self._body_from_file(args, fd)
if 'Content-Type' not in args.headers: if 'Content-Type' not in args.headers:
mime, encoding = mimetypes.guess_type(fn, strict=False) mime, encoding = mimetypes.guess_type(fn, strict=False)
if mime: if mime:
@ -420,8 +424,8 @@ def parse_items(items, data=None, headers=None, files=None, params=None):
target = params target = params
elif item.sep == SEP_FILES: elif item.sep == SEP_FILES:
try: try:
with open(os.path.expanduser(value)) as f: value = (os.path.basename(value),
value = (os.path.basename(f.name), f.read()) open(os.path.expanduser(value), 'rb'))
except IOError as e: except IOError as e:
raise ParseError( raise ParseError(
'Invalid argument "%s": %s' % (item.orig, e)) 'Invalid argument "%s": %s' % (item.orig, e))

View File

@ -120,6 +120,10 @@ class HTTPMessage(object):
# Body # Body
if request.files: if request.files:
# TODO: would be nice if we didn't need to encode the files again
for fn, fd in request.files.values():
# Rewind the files as they have already been read before.
fd.seek(0)
body, _ = request._encode_files(request.files) body, _ = request._encode_files(request.files)
else: else:
try: try:

BIN
tests/fixtures/file.bin vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -51,10 +51,16 @@ from httpie.input import ParseError
HTTPBIN_URL = os.environ.get('HTTPBIN_URL', HTTPBIN_URL = os.environ.get('HTTPBIN_URL',
'http://httpbin.org') 'http://httpbin.org')
TEST_FILE_PATH = os.path.join(TESTS_ROOT, 'file.txt') TEST_FILE_PATH = os.path.join(TESTS_ROOT, 'fixtures', 'file.txt')
TEST_FILE2_PATH = os.path.join(TESTS_ROOT, 'file2.txt') TEST_FILE2_PATH = os.path.join(TESTS_ROOT, 'fixtures', 'file2.txt')
with open(TEST_FILE_PATH) as f: with open(TEST_FILE_PATH) as f:
TEST_FILE_CONTENT = f.read().strip() TEST_FILE_CONTENT = f.read().strip()
TEST_BIN_FILE_PATH = os.path.join(TESTS_ROOT, 'fixtures', 'file.bin')
with open(TEST_BIN_FILE_PATH, 'rb') as f:
TEST_BIN_FILE_CONTENT = f.read()
TERMINAL_COLOR_PRESENCE_CHECK = '\x1b[' TERMINAL_COLOR_PRESENCE_CHECK = '\x1b['
@ -82,7 +88,6 @@ def http(*args, **kwargs):
and return a unicode response. and return a unicode response.
""" """
if 'env' not in kwargs: if 'env' not in kwargs:
# Ensure that we have terminal by default (needed for Travis). # Ensure that we have terminal by default (needed for Travis).
kwargs['env'] = Environment( kwargs['env'] = Environment(
@ -94,7 +99,11 @@ def http(*args, **kwargs):
stdout = kwargs['env'].stdout = tempfile.TemporaryFile('w+b') stdout = kwargs['env'].stdout = tempfile.TemporaryFile('w+b')
stderr = kwargs['env'].stderr = tempfile.TemporaryFile('w+t') stderr = kwargs['env'].stderr = tempfile.TemporaryFile('w+t')
try:
exit_status = main(args=['--debug'] + list(args), **kwargs) exit_status = main(args=['--debug'] + list(args), **kwargs)
except (Exception, SystemExit) as e:
sys.stderr.write(stderr.read())
raise
stdout.seek(0) stdout.seek(0)
stderr.seek(0) stderr.seek(0)
@ -564,7 +573,54 @@ class MultipartFormDataFileUploadTest(BaseTestCase):
self.assertIn('"foo": "bar"', r) self.assertIn('"foo": "bar"', r)
class TestBinaryResponses(BaseTestCase): class BinaryRequestDataTest(BaseTestCase):
def test_binary_stdin(self):
env = Environment(
stdin=open(TEST_BIN_FILE_PATH, 'rb'),
stdin_isatty=False,
stdout_isatty=False
)
r = http(
'--print=B',
'POST',
httpbin('/post'),
env=env,
)
self.assertEqual(r, TEST_BIN_FILE_CONTENT)
def test_binary_file_path(self):
env = Environment(
stdin_isatty=True,
stdout_isatty=False
)
r = http(
'--print=B',
'POST',
httpbin('/post'),
'@' + TEST_BIN_FILE_PATH,
env=env,
)
self.assertEqual(r, TEST_BIN_FILE_CONTENT)
def test_binary_file_form(self):
env = Environment(
stdin_isatty=True,
stdout_isatty=False
)
r = http(
'--print=B',
'--form',
'POST',
httpbin('/post'),
'test@' + TEST_BIN_FILE_PATH,
env=env,
)
self.assertIn(bytes(TEST_BIN_FILE_CONTENT), bytes(r))
class BinaryResponseDataTest(BaseTestCase):
url = 'http://www.google.com/favicon.ico' url = 'http://www.google.com/favicon.ico'