diff --git a/httpie/client.py b/httpie/client.py index 6eef07b7..5102ce46 100644 --- a/httpie/client.py +++ b/httpie/client.py @@ -38,6 +38,15 @@ def get_response(args, config_dir): return response +def encode_headers(headers): + # This allows for unicode headers which is non-standard but practical. + # See: https://github.com/jkbr/httpie/issues/212 + return dict( + (name, value.encode('utf8') if isinstance(value, str) else value) + for name, value in headers.items() + ) + + def get_requests_kwargs(args): """Translate our `args` into `requests.request` keyword arguments.""" @@ -80,18 +89,11 @@ def get_requests_kwargs(args): if args.certkey: cert = (cert, args.certkey) - # This allows for unicode headers which is non-standard but practical. - # See: https://github.com/jkbr/httpie/issues/212 - headers = dict( - (name, value.encode('utf8') if isinstance(value, str) else value) - for name, value in args.headers.items() - ) - kwargs = { 'stream': True, 'method': args.method.lower(), 'url': args.url, - 'headers': headers, + 'headers': encode_headers(args.headers), 'data': args.data, 'verify': { 'yes': True, diff --git a/httpie/plugins/builtin.py b/httpie/plugins/builtin.py index 12038aea..92b2f302 100644 --- a/httpie/plugins/builtin.py +++ b/httpie/plugins/builtin.py @@ -19,11 +19,16 @@ class HTTPBasicAuth(requests.auth.HTTPBasicAuth): See https://github.com/jkbr/httpie/issues/212 """ - credentials = u'%s:%s' % (self.username, self.password) - token = b64encode(credentials.encode('utf8')).strip().decode('latin1') - r.headers['Authorization'] = 'Basic %s' % token + r.headers['Authorization'] = type(self).make_header( + self.username, self.password).encode('latin1') return r + @staticmethod + def make_header(username, password): + credentials = u'%s:%s' % (username, password) + token = b64encode(credentials.encode('utf8')).strip().decode('latin1') + return 'Basic %s' % token + class BasicAuthPlugin(BuiltinAuthPlugin): diff --git a/httpie/sessions.py b/httpie/sessions.py index 7aa370dc..2404e234 100644 --- a/httpie/sessions.py +++ b/httpie/sessions.py @@ -27,6 +27,7 @@ def get_response(session_name, requests_kwargs, config_dir, args, aspects of the session to the request. """ + from .client import encode_headers if os.path.sep in session_name: path = os.path.expanduser(session_name) else: @@ -49,8 +50,9 @@ def get_response(session_name, requests_kwargs, config_dir, args, request_headers = requests_kwargs.get('headers', {}) - requests_kwargs['headers'] = dict(session.headers) - requests_kwargs['headers'].update(request_headers) + merged_headers = dict(session.headers) + merged_headers.update(request_headers) + requests_kwargs['headers'] = encode_headers(merged_headers) session.update_headers(request_headers) diff --git a/tests/test_sessions.py b/tests/test_sessions.py index efb02d38..2ef4bafd 100644 --- a/tests/test_sessions.py +++ b/tests/test_sessions.py @@ -1,5 +1,7 @@ +# coding=utf-8 import os import shutil +from httpie.plugins.builtin import HTTPBasicAuth from tests import TestEnvironment, mk_config_dir, http, httpbin, HTTP_OK @@ -121,3 +123,17 @@ class TestSession(SessionTestBase): env=self.env()) assert HTTP_OK in r2 assert r2.json['headers']['Foo'] == 'Bar' + + def test_session_unicode(self): + UNICODE = u'太陽' + r1 = http('--session=test', '--auth', u'test:' + UNICODE, + 'GET', httpbin('/get'), + u'Test:%s' % UNICODE, + env=self.env()) + assert HTTP_OK in r1 + + r2 = http('--session=test', 'GET', httpbin('/get'), env=self.env()) + assert HTTP_OK in r2 + assert (r2.json['headers']['Authorization'] + == HTTPBasicAuth.make_header(u'test', UNICODE)) + assert r2.json['headers']['Test'] == UNICODE