Send filenames with multipart/form-data file uploads.

This commit is contained in:
Jakub Roztocil 2012-07-28 13:24:44 +02:00
parent 1efea59a8d
commit f5bc081fda
4 changed files with 19 additions and 30 deletions

View File

@ -384,8 +384,8 @@ Changelog
Authors Authors
======= =======
`Jakub Roztocil`_ (`@jkbrzt`_) created HTTPie and `these fine people`_ have `Jakub Roztocil`_ (`@jakubroztocil`_) created HTTPie and `these fine people`_
contributed. have contributed.
.. _suite of tests: https://github.com/jkbr/httpie/blob/master/tests/tests.py .. _suite of tests: https://github.com/jkbr/httpie/blob/master/tests/tests.py
@ -400,7 +400,7 @@ contributed.
.. _the repository: https://github.com/jkbr/httpie .. _the repository: https://github.com/jkbr/httpie
.. _these fine people: https://github.com/jkbr/httpie/contributors .. _these fine people: https://github.com/jkbr/httpie/contributors
.. _Jakub Roztocil: http://roztocil.name .. _Jakub Roztocil: http://roztocil.name
.. _@jkbrzt: https://twitter.com/jkbrzt .. _@jakubroztocil: https://twitter.com/jakubroztocil
.. _existing issues: https://github.com/jkbr/httpie/issues?state=open .. _existing issues: https://github.com/jkbr/httpie/issues?state=open
.. _0.1.6: https://github.com/jkbr/httpie/compare/0.1.4...0.1.6 .. _0.1.6: https://github.com/jkbr/httpie/compare/0.1.4...0.1.6
.. _0.2.0: https://github.com/jkbr/httpie/compare/0.1.6...0.2.0 .. _0.2.0: https://github.com/jkbr/httpie/compare/0.1.6...0.2.0

View File

@ -97,28 +97,19 @@ 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) self._body_from_file(args, env.stdin.read())
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.
args.auth.prompt_password() args.auth.prompt_password()
if args.files:
# Will be read multiple times.
for name in args.files:
args.files[name] = args.files[name].read()
if args.prettify == PRETTIFY_STDOUT_TTY_ONLY: if args.prettify == PRETTIFY_STDOUT_TTY_ONLY:
args.prettify = env.stdout_isatty args.prettify = env.stdout_isatty
return args return args
def _body_from_file(self, args, data): def _body_from_file(self, args, data):
"""Use the content of `f` as the `request.data`. """There can only be one source of request data."""
There can only be one source of request data.
"""
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.')
@ -192,14 +183,14 @@ class Parser(argparse.ArgumentParser):
' --form is used. File fields: %s' ' --form is used. File fields: %s'
% ','.join(args.files.keys())) % ','.join(args.files.keys()))
f = list(args.files.values())[0] fn, data = list(args.files.values())[0]
self._body_from_file(args, f) self._body_from_file(args, data)
# Reset files # Reset files
args.files = {} args.files = {}
if 'Content-Type' not in args.headers: if 'Content-Type' not in args.headers:
mime, encoding = mimetypes.guess_type(f.name, strict=False) mime, encoding = mimetypes.guess_type(fn, strict=False)
if mime: if mime:
content_type = mime content_type = mime
if encoding: if encoding:
@ -414,7 +405,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:
value = open(os.path.expanduser(value), 'r') with open(os.path.expanduser(value), 'r') as f:
value = (os.path.basename(f.name), f.read())
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

@ -11,7 +11,7 @@ from pygments.lexers import get_lexer_for_mimetype
from pygments.formatters.terminal import TerminalFormatter from pygments.formatters.terminal import TerminalFormatter
from pygments.formatters.terminal256 import Terminal256Formatter from pygments.formatters.terminal256 import Terminal256Formatter
from pygments.util import ClassNotFound from pygments.util import ClassNotFound
from requests.compat import is_windows, bytes from requests.compat import is_windows
from . import solarized from . import solarized
from .models import Environment from .models import Environment

View File

@ -60,21 +60,18 @@ def httpbin(path):
return HTTPBIN_URL + path return HTTPBIN_URL + path
class BytesResponse(bytes): class ResponseMixin(object):
exit_status = None exit_status = None
stderr = None stderr = None
json = None json = None
def __eq__(self, other):
return super(BytesResponse, self).__eq__(other)
class StrResponse(str): class BytesResponse(bytes, ResponseMixin):
exit_status = None pass
stderr = None
json = None
def __eq__(self, other): class StrResponse(str, ResponseMixin):
return super(StrResponse, self).__eq__(other) pass
def http(*args, **kwargs): def http(*args, **kwargs):
@ -543,7 +540,7 @@ class MultipartFormDataFileUploadTest(BaseTestCase):
self.assertIn('HTTP/1.1 200', r) self.assertIn('HTTP/1.1 200', r)
self.assertIn('Content-Disposition: form-data; name="foo"', r) self.assertIn('Content-Disposition: form-data; name="foo"', r)
self.assertIn('Content-Disposition: form-data; name="test-file";' self.assertIn('Content-Disposition: form-data; name="test-file";'
' filename="test-file"', r) ' filename="%s"' % os.path.basename(TEST_FILE_PATH), r)
self.assertEqual(r.count(TEST_FILE_CONTENT), 2) self.assertEqual(r.count(TEST_FILE_CONTENT), 2)
self.assertIn('"foo": "bar"', r) self.assertIn('"foo": "bar"', r)