From a94f10a83f2a1aa441af793e8ccf3e04a4693e0e Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Sat, 25 Jan 2014 08:39:16 +0000 Subject: Do not fail on unicode in HTTP headers --- diff --git a/sugar_network/toolkit/router.py b/sugar_network/toolkit/router.py index 7f2c268..9a430b7 100644 --- a/sugar_network/toolkit/router.py +++ b/sugar_network/toolkit/router.py @@ -396,14 +396,14 @@ class Response(dict): for key, value in dict.items(self): if type(value) in (list, tuple): for i in value: - result.append((key, str(i))) + result.append((_to_ascii(key), _to_ascii(i))) else: - result.append((key, str(value))) + result.append((_to_ascii(key), _to_ascii(value))) return result def __repr__(self): items = ['%s=%r' % i for i in self.items() + self.meta.items()] - return '' % ' '.join(items) + return '' % items def __contains__(self, key): dict.__contains__(self, key.lower()) @@ -576,7 +576,7 @@ class Router(object): response.content_length = len(result) if result else 0 for key, value in response.meta.items(): - response.set('X-SN-%s' % str(key), json.dumps(value)) + response.set('X-SN-%s' % _to_ascii(key), json.dumps(value)) if request.method == 'HEAD' and result is not None: _logger.warning('Content from HEAD response is ignored') @@ -750,7 +750,7 @@ def _filename(names, mime_type): for name in names: if isinstance(name, dict): name = toolkit.gettext(name) - parts.append(''.join([i.capitalize() for i in str(name).split()])) + parts.append(''.join([i.capitalize() for i in name.split()])) result = '-'.join(parts) if mime_type: if not mimetypes.inited: @@ -832,6 +832,14 @@ def _parse_accept_language(value): return langs +def _to_ascii(value): + if not isinstance(value, basestring): + return str(value) + if isinstance(value, unicode): + return value.encode('utf8') + return value + + class _Routes(dict): def __init__(self, parent=None): diff --git a/tests/units/toolkit/router.py b/tests/units/toolkit/router.py index e229f2d..a9b17f2 100755 --- a/tests/units/toolkit/router.py +++ b/tests/units/toolkit/router.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- # sugar-lint: disable import os @@ -8,7 +9,7 @@ from cStringIO import StringIO from __init__ import tests, src_root -from sugar_network import db +from sugar_network import db, client from sugar_network.toolkit.router import Blob, Router, Request, _parse_accept_language, route, fallbackroute, preroute, postroute, _filename from sugar_network.toolkit import default_lang, http, coroutine @@ -1175,8 +1176,6 @@ class RouterTest(tests.Test): self.assertEqual('Foo-Bar', _filename(['foo', 'bar'], None)) self.assertEqual('FOO-BaR', _filename([' f o o', ' ba r '], None)) - self.assertEqual('Foo-3', _filename(['foo', 3], None)) - self.assertEqual('12-3', _filename(['/1/2/', '/3/'], None)) self.assertEqual('Foo.png', _filename('foo', 'image/png')) @@ -1185,7 +1184,7 @@ class RouterTest(tests.Test): self.assertEqual('Eng', _filename({default_lang(): 'eng'}, None)) self.assertEqual('Eng', _filename([{default_lang(): 'eng'}], None)) - self.assertEqual('Bar-1', _filename([{'lang': 'foo', default_lang(): 'bar'}, 1], None)) + self.assertEqual('Bar-1', _filename([{'lang': 'foo', default_lang(): 'bar'}, '1'], None)) def test_BlobsDisposition(self): self.touch(('blob.data', 'value')) @@ -1384,6 +1383,25 @@ class RouterTest(tests.Test): events) del events[:] + def test_UnicodeInHeaders(self): + + class Routes(object): + + @route('HEAD') + def probe(self, request, response): + response['фоо'] = 'бар' + response[u'йцу'] = u'кен' + + server = coroutine.WSGIServer(('127.0.0.1', client.ipc_port.value), Router(Routes())) + coroutine.spawn(server.serve_forever) + coroutine.dispatch() + + conn = http.Connection('http://127.0.0.1:%s' % client.ipc_port.value) + headers = conn.request('HEAD', []).headers + + self.assertEqual('бар', headers.get('фоо')) + self.assertEqual('кен', headers.get('йцу')) + if __name__ == '__main__': tests.main() -- cgit v0.9.1