From b35e8daf54c6bdfdfb4c889d19ce8f5dff2830f8 Mon Sep 17 00:00:00 2001 From: Stavros Sachtouris Date: Tue, 12 Mar 2013 15:04:30 +0200 Subject: [PATCH] Add utf-8 params/headers checks in perform_request --- kamaki/clients/connection/kamakicon.py | 2 ++ kamaki/clients/connection/test.py | 59 ++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/kamaki/clients/connection/kamakicon.py b/kamaki/clients/connection/kamakicon.py index 4fdf98a..4ef3491 100644 --- a/kamaki/clients/connection/kamakicon.py +++ b/kamaki/clients/connection/kamakicon.py @@ -135,6 +135,8 @@ class KamakiHTTPConnection(KamakiConnection): params = dict(self.params) params.update(extra_params) for i, (key, val) in enumerate(params.items()): + if isinstance(val, unicode): + val = quote(val.encode('utf-8')) url += '%s%s' % ('&' if i else '?', key) if val: url += '=%s' % val diff --git a/kamaki/clients/connection/test.py b/kamaki/clients/connection/test.py index 8ee4cd5..2386c7a 100644 --- a/kamaki/clients/connection/test.py +++ b/kamaki/clients/connection/test.py @@ -32,13 +32,20 @@ # or implied, of GRNET S.A. from unittest import TestCase, TestSuite, makeSuite, TextTestRunner -from mock import Mock, patch +from mock import Mock, patch, call from random import randrange +from urllib2 import quote from kamaki.clients import connection from kamaki.clients.connection import errors, kamakicon +def _encode(v): + if v and isinstance(v, unicode): + return quote(v.encode('utf-8')) + return v + + class KamakiConnection(TestCase): v_samples = {'title': 'value', 5: 'value'} n_samples = {'title': None, 5: None} @@ -47,6 +54,8 @@ class KamakiConnection(TestCase): def setUp(self): from kamaki.clients.connection import KamakiConnection as HTTPC self.conn = HTTPC() + self.conn.reset_headers() + self.conn.reset_params() def test_poolsize(self): @@ -154,6 +163,8 @@ class KamakiHTTPConnection(TestCase): def setUp(self): self.conn = kamakicon.KamakiHTTPConnection() + self.conn.reset_params() + self.conn.reset_headers() def test__retrieve_connection_info(self): async_params = dict(param1='val1', param2=None, param3=42) @@ -188,14 +199,58 @@ class KamakiHTTPConnection(TestCase): method='GET', async_headers=dict(), async_params=dict()) + utf_test = u'\u03a6\u03bf\u03cd\u03c4\u03c3\u03bf\u03c2' + utf_dict = dict(utf=utf_test) + ascii_dict = dict(ascii1='myAscii', ascii2=None) + kwargs0 = dict( + data='', + method='get', + async_headers=utf_dict, + async_params=ascii_dict) + + def get_expected(): + expected = [] + for k, v in kwargs0['async_params'].items(): + v = _encode(v) + expected.append(('%s=%s' % (k, v)) if v else ('%s' % k)) + return '&'.join(expected) KCError = errors.KamakiConnectionError fakecon = HTTPConnection('X', 'Y') with patch.object(http, 'get_http_connection', return_value=fakecon): - with patch.object(HTTPConnection, 'request', return_value=None): + with patch.object(HTTPConnection, 'request') as request: r = pr(**kwargs) self.assertTrue(isinstance(r, kamakicon.KamakiHTTPResponse)) + self.assertEquals( + request.mock_calls[-1], + call(body='', headers={}, url='/', method='GET')) + + pr(**kwargs0) + + exp_headers = dict(kwargs0['async_headers']) + exp_headers['utf'] = _encode(exp_headers['utf']) + + self.assertEquals( + request.mock_calls[-1], + call( + body=kwargs0['data'], + headers=exp_headers, + url='/?%s' % get_expected(), + method=kwargs0['method'].upper())) + + self.conn = kamakicon.KamakiHTTPConnection() + (kwargs0['async_params'], kwargs0['async_headers']) = ( + kwargs0['async_headers'], kwargs0['async_params']) + kwargs0['async_headers']['ascii2'] = 'None' + self.conn.perform_request(**kwargs0) + self.assertEquals( + request.mock_calls[-1], + call( + body=kwargs0['data'], + headers=kwargs0['async_headers'], + url='/?%s' % get_expected(), + method=kwargs0['method'].upper())) err = IOError('IO Error') with patch.object(HTTPConnection, 'request', side_effect=err): -- 1.7.10.4