Fixed Content-Type for requests with no data.

Closes #62.
This commit is contained in:
Jakub Roztocil 2012-07-04 01:39:21 +02:00
parent 50196be0f2
commit 6ab03b21b4
3 changed files with 82 additions and 24 deletions

View File

@ -16,23 +16,29 @@ TYPE_FORM = 'application/x-www-form-urlencoded; charset=utf-8'
TYPE_JSON = 'application/json; charset=utf-8'
def _get_response(parser, args, stdin, stdin_isatty):
def _get_response(args):
if args.json or (not args.form and args.data):
auto_json = args.data and not args.form
if args.json or auto_json:
# JSON
if not args.files and (
'Content-Type' not in args.headers
and (args.data or args.json)):
args.headers['Content-Type'] = TYPE_JSON
if isinstance(args.data, dict):
# Serialize the data dict parsed from arguments.
args.data = json.dumps(args.data)
if 'Content-Type' not in args.headers:
args.headers['Content-Type'] = TYPE_JSON
if 'Accept' not in args.headers:
# Default Accept to JSON as well.
args.headers['Accept'] = 'application/json'
elif not args.files and 'Content-Type' not in args.headers:
if isinstance(args.data, dict):
# If not empty, serialize the data `dict` parsed from arguments.
# Otherwise set it to `None` avoid sending "{}".
args.data = json.dumps(args.data) if args.data else None
elif args.form:
# Form
args.headers['Content-Type'] = TYPE_FORM
if not args.files and 'Content-Type' not in args.headers:
# If sending files, `requests` will set
# the `Content-Type` for us.
args.headers['Content-Type'] = TYPE_FORM
# Fire the request.
try:
@ -113,7 +119,7 @@ def main(args=None,
stdin=stdin,
stdin_isatty=stdin_isatty
)
response = _get_response(parser, args, stdin, stdin_isatty)
response = _get_response(args)
output = _get_output(args, stdout_isatty, response)
output_bytes = output.encode('utf8')
f = (stdout.buffer if hasattr(stdout, 'buffer') else stdout)

View File

@ -146,7 +146,6 @@ class Parser(argparse.ArgumentParser):
content_type = '%s; charset=%s' % (mime, encoding)
args.headers['Content-Type'] = content_type
def _validate_output_options(self, args):
unknown_output_options = set(args.output_options) - set(OUTPUT_OPTIONS)
if unknown_output_options:

View File

@ -80,16 +80,6 @@ class HTTPieTest(BaseTestCase):
self.assertIn('HTTP/1.1 200', r)
self.assertIn('"foo": "bar"', r)
def test_GET_JSON_implicit_accept(self):
r = http('-j', 'GET', 'http://httpbin.org/headers')
self.assertIn('HTTP/1.1 200', r)
self.assertIn('"Accept": "application/json"', r)
def test_GET_JSON_explicit_accept(self):
r = http('-j', 'GET', 'http://httpbin.org/headers', 'Accept:application/xml')
self.assertIn('HTTP/1.1 200', r)
self.assertIn('"Accept": "application/xml"', r)
def test_POST_form(self):
r = http('--form', 'POST', 'http://httpbin.org/post', 'foo=bar')
self.assertIn('HTTP/1.1 200', r)
@ -108,6 +98,69 @@ class HTTPieTest(BaseTestCase):
self.assertIn('"Foo": "bar"', r)
class AutoContentTypeAndAcceptHeadersTest(BaseTestCase):
"""
Test that Accept and Content-Type correctly defaults to JSON,
but can still be overridden. The same with Content-Type when --form
-f is used.
"""
def test_GET_no_data_no_auto_headers(self):
# https://github.com/jkbr/httpie/issues/62
r = http('GET', 'http://httpbin.org/headers')
self.assertIn('HTTP/1.1 200', r)
self.assertIn('"Accept": "*/*"', r)
# Although an empty header is present in the response from httpbin,
# it's not included in the request.
self.assertIn('"Content-Type": ""', r)
def test_POST_no_data_no_auto_headers(self):
# JSON headers shouldn't be automatically set for POST with no data.
r = http('POST', 'http://httpbin.org/post')
self.assertIn('HTTP/1.1 200', r)
self.assertIn('"Accept": "*/*"', r)
# Although an empty header is present in the response from httpbin,
# it's not included in the request.
self.assertIn(' "Content-Type": ""', r)
def test_POST_with_data_auto_JSON_headers(self):
r = http('POST', 'http://httpbin.org/post', 'a=b')
self.assertIn('HTTP/1.1 200', r)
self.assertIn('"Accept": "application/json"', r)
self.assertIn('"Content-Type": "application/json; charset=utf-8', r)
def test_GET_with_data_auto_JSON_headers(self):
# JSON headers should automatically be set also for GET with data.
r = http('POST', 'http://httpbin.org/post', 'a=b')
self.assertIn('HTTP/1.1 200', r)
self.assertIn('"Accept": "application/json"', r)
self.assertIn('"Content-Type": "application/json; charset=utf-8', r)
def test_POST_explicit_JSON_auto_JSON_headers(self):
r = http('-j', 'POST', 'http://httpbin.org/post')
self.assertIn('HTTP/1.1 200', r)
self.assertIn('"Accept": "application/json"', r)
self.assertIn('"Content-Type": "application/json; charset=utf-8', r)
def test_GET_explicit_JSON_explicit_headers(self):
r = http('-j', 'GET', 'http://httpbin.org/headers',
'Accept:application/xml',
'Content-Type:application/xml')
self.assertIn('HTTP/1.1 200', r)
self.assertIn('"Accept": "application/xml"', r)
self.assertIn('"Content-Type": "application/xml"', r)
def test_POST_form_auto_Content_Type(self):
r = http('-f', 'POST', 'http://httpbin.org/post')
self.assertIn('HTTP/1.1 200', r)
self.assertIn('"Content-Type": "application/x-www-form-urlencoded; charset=utf-8"', r)
def test_POST_form_Content_Type_override(self):
r = http('-f', 'POST', 'http://httpbin.org/post', 'Content-Type:application/xml')
self.assertIn('HTTP/1.1 200', r)
self.assertIn('"Content-Type": "application/xml"', r)
class ImplicitHTTPMethodTest(BaseTestCase):
def test_implicit_GET(self):
@ -209,7 +262,7 @@ class RequestBodyFromFilePathTest(BaseTestCase):
'@' + TEST_FILE_PATH,
'@' + TEST_FILE2_PATH))
def test_request_body_from_file_by_path_only_no_data_items_allowed(self):
def test_request_body_from_file_by_path_no_data_items_allowed(self):
self.assertRaises(SystemExit, lambda: http(
'POST',
'http://httpbin.org/post',