diff --git a/common/djangoapps/track/backends/tests/test_logger.py b/common/djangoapps/track/backends/tests/test_logger.py index 8ff0099db0..dbe59cdf19 100644 --- a/common/djangoapps/track/backends/tests/test_logger.py +++ b/common/djangoapps/track/backends/tests/test_logger.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- +"""Tests for Event tracker backend.""" from __future__ import absolute_import import json diff --git a/common/djangoapps/track/middleware.py b/common/djangoapps/track/middleware.py index d8dbcbc25c..dadd3d771e 100644 --- a/common/djangoapps/track/middleware.py +++ b/common/djangoapps/track/middleware.py @@ -142,6 +142,10 @@ class TrackMiddleware(object): for header_name, context_key in META_KEY_TO_CONTEXT_KEY.iteritems(): context[context_key] = request.META.get(header_name, '') + # HTTP_USER_AGENT user might can contain the information that include latin1 characters + # decoding this using latin1 scheme will prevent to raise UnicodeDecodeError when using + # json.dumps for tracking purpose. + context['agent'] = context['agent'].decode('latin1') # Google Analytics uses the clientId to keep track of unique visitors. A GA cookie looks like # this: _ga=GA1.2.1033501218.1368477899. The clientId is this part: 1033501218.1368477899. google_analytics_cookie = request.COOKIES.get('_ga') diff --git a/common/djangoapps/track/tests/test_middleware.py b/common/djangoapps/track/tests/test_middleware.py index bcb8d6a817..4c83824966 100644 --- a/common/djangoapps/track/tests/test_middleware.py +++ b/common/djangoapps/track/tests/test_middleware.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- +"""Tests for tracking middleware.""" from mock import patch from mock import sentinel @@ -27,6 +29,18 @@ class TrackMiddlewareTestCase(TestCase): self.track_middleware.process_request(request) self.assertTrue(self.mock_server_track.called) + def test_request_with_latin1_characters(self): + """ + When HTTP_USER_AGENT in request.META contains latin1 characters. + """ + request = self.request_factory.get('/somewhere') + request.META['HTTP_USER_AGENT'] = 'test latin1 \xd3 \xe9 \xf1' # pylint: disable=no-member + + context = self.get_context_for_request(request) + # The bytes in the string on the right are utf8 encoded in the source file, so we decode them to construct + # a valid unicode string. + self.assertEqual(context['agent'], 'test latin1 Ó é ñ'.decode('utf8')) + def test_default_filters_do_not_render_view(self): for url in ['/event', '/event/1', '/login', '/heartbeat']: request = self.request_factory.get(url) diff --git a/common/djangoapps/track/views/__init__.py b/common/djangoapps/track/views/__init__.py index b3b18bf498..e34ebea3b8 100644 --- a/common/djangoapps/track/views/__init__.py +++ b/common/djangoapps/track/views/__init__.py @@ -105,7 +105,7 @@ def server_track(request, event_type, event, page=None): "event_source": "server", "event_type": event_type, "event": event, - "agent": _get_request_header(request, 'HTTP_USER_AGENT'), + "agent": _get_request_header(request, 'HTTP_USER_AGENT').decode('latin1'), "page": page, "time": datetime.datetime.utcnow(), "host": _get_request_header(request, 'SERVER_NAME'), diff --git a/lms/djangoapps/instructor_task/api_helper.py b/lms/djangoapps/instructor_task/api_helper.py index 0e1a3a019a..32a2db2586 100644 --- a/lms/djangoapps/instructor_task/api_helper.py +++ b/lms/djangoapps/instructor_task/api_helper.py @@ -88,7 +88,7 @@ def _get_xmodule_instance_args(request, task_id): """ request_info = {'username': request.user.username, 'ip': request.META['REMOTE_ADDR'], - 'agent': request.META.get('HTTP_USER_AGENT', ''), + 'agent': request.META.get('HTTP_USER_AGENT', '').decode('latin1'), 'host': request.META['SERVER_NAME'], }