Skip to content

Commit

Permalink
Added tests for binary request data.
Browse files Browse the repository at this point in the history
  • Loading branch information
jkbrzt committed Jul 31, 2012
1 parent 8905b4f commit 90d34ff
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 14 deletions.
2 changes: 1 addition & 1 deletion httpie/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def get_response(args, env):
except Exception as e:
if args.debug:
raise
env.stderr.write(str(e.message) + '\n')
env.stderr.write(str(repr(e) + '\n'))
sys.exit(1)


Expand Down
20 changes: 12 additions & 8 deletions httpie/input.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def parse_args(self, env, args=None, namespace=None):
self._parse_items(args)

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():
# Stdin already read (if not a tty) so it's save to prompt.
Expand All @@ -129,12 +129,16 @@ def _print_message(self, message, file=None):

super(Parser, self)._print_message(message, file)

def _body_from_file(self, args, data):
"""There can only be one source of request data."""
def _body_from_file(self, args, fd):
"""There can only be one source of request data.
Bytes are always read.
"""
if args.data:
self.error('Request body (from stdin or a file) and request '
'data (key=value) cannot be mixed.')
args.data = data
args.data = getattr(fd, 'buffer', fd).read()

def _guess_method(self, args, env):
"""Set `args.method` if not specified to either POST or GET
Expand Down Expand Up @@ -201,9 +205,9 @@ def _parse_items(self, args):
'Invalid file fields (perhaps you meant --form?): %s'
% ','.join(file_fields))

fn, data = args.files['']
fn, fd = args.files['']
args.files = {}
self._body_from_file(args, data)
self._body_from_file(args, fd)
if 'Content-Type' not in args.headers:
mime, encoding = mimetypes.guess_type(fn, strict=False)
if mime:
Expand Down Expand Up @@ -420,8 +424,8 @@ def parse_items(items, data=None, headers=None, files=None, params=None):
target = params
elif item.sep == SEP_FILES:
try:
with open(os.path.expanduser(value)) as f:
value = (os.path.basename(f.name), f.read())
value = (os.path.basename(value),
open(os.path.expanduser(value), 'rb'))
except IOError as e:
raise ParseError(
'Invalid argument "%s": %s' % (item.orig, e))
Expand Down
4 changes: 4 additions & 0 deletions httpie/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ def from_request(cls, request):

# Body
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)
else:
try:
Expand Down
Binary file added tests/fixtures/file.bin
Binary file not shown.
File renamed without changes.
File renamed without changes.
66 changes: 61 additions & 5 deletions tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,16 @@
HTTPBIN_URL = os.environ.get('HTTPBIN_URL',
'http://httpbin.org')

TEST_FILE_PATH = os.path.join(TESTS_ROOT, 'file.txt')
TEST_FILE2_PATH = os.path.join(TESTS_ROOT, 'file2.txt')
TEST_FILE_PATH = os.path.join(TESTS_ROOT, 'fixtures', 'file.txt')
TEST_FILE2_PATH = os.path.join(TESTS_ROOT, 'fixtures', 'file2.txt')

with open(TEST_FILE_PATH) as f:
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['


Expand Down Expand Up @@ -82,7 +88,6 @@ def http(*args, **kwargs):
and return a unicode response.
"""

if 'env' not in kwargs:
# Ensure that we have terminal by default (needed for Travis).
kwargs['env'] = Environment(
Expand All @@ -94,7 +99,11 @@ def http(*args, **kwargs):
stdout = kwargs['env'].stdout = tempfile.TemporaryFile('w+b')
stderr = kwargs['env'].stderr = tempfile.TemporaryFile('w+t')

exit_status = main(args=['--debug'] + list(args), **kwargs)
try:
exit_status = main(args=['--debug'] + list(args), **kwargs)
except (Exception, SystemExit) as e:
sys.stderr.write(stderr.read())
raise

stdout.seek(0)
stderr.seek(0)
Expand Down Expand Up @@ -564,7 +573,54 @@ def test_upload_ok(self):
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'

Expand Down

0 comments on commit 90d34ff

Please sign in to comment.