fix processing unicode symbols in query_string by Python 2

This commit is contained in:
Yuri Nikulin 2017-11-02 14:21:56 +03:00
parent 5d71d8d4b8
commit e687e70de3
2 changed files with 66 additions and 3 deletions

View File

@ -1,3 +1,4 @@
from django.utils.encoding import force_str
from django.utils.six.moves.urllib import parse as urlparse from django.utils.six.moves.urllib import parse as urlparse
@ -6,9 +7,9 @@ def replace_query_param(url, key, val):
Given a URL and a key/val pair, set or replace an item in the query Given a URL and a key/val pair, set or replace an item in the query
parameters of the URL, and return the new URL. parameters of the URL, and return the new URL.
""" """
(scheme, netloc, path, query, fragment) = urlparse.urlsplit(url) (scheme, netloc, path, query, fragment) = urlparse.urlsplit(force_str(url))
query_dict = urlparse.parse_qs(query, keep_blank_values=True) query_dict = urlparse.parse_qs(query, keep_blank_values=True)
query_dict[key] = [val] query_dict[force_str(key)] = [force_str(val)]
query = urlparse.urlencode(sorted(list(query_dict.items())), doseq=True) query = urlparse.urlencode(sorted(list(query_dict.items())), doseq=True)
return urlparse.urlunsplit((scheme, netloc, path, query, fragment)) return urlparse.urlunsplit((scheme, netloc, path, query, fragment))
@ -18,7 +19,7 @@ def remove_query_param(url, key):
Given a URL and a key/val pair, remove an item in the query Given a URL and a key/val pair, remove an item in the query
parameters of the URL, and return the new URL. parameters of the URL, and return the new URL.
""" """
(scheme, netloc, path, query, fragment) = urlparse.urlsplit(url) (scheme, netloc, path, query, fragment) = urlparse.urlsplit(force_str(url))
query_dict = urlparse.parse_qs(query, keep_blank_values=True) query_dict = urlparse.parse_qs(query, keep_blank_values=True)
query_dict.pop(key, None) query_dict.pop(key, None)
query = urlparse.urlencode(sorted(list(query_dict.items())), doseq=True) query = urlparse.urlencode(sorted(list(query_dict.items())), doseq=True)

View File

@ -11,6 +11,7 @@ from rest_framework.routers import SimpleRouter
from rest_framework.serializers import ModelSerializer from rest_framework.serializers import ModelSerializer
from rest_framework.utils import json from rest_framework.utils import json
from rest_framework.utils.breadcrumbs import get_breadcrumbs from rest_framework.utils.breadcrumbs import get_breadcrumbs
from rest_framework.utils.urls import remove_query_param, replace_query_param
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet from rest_framework.viewsets import ModelViewSet
from tests.models import BasicModel from tests.models import BasicModel
@ -205,3 +206,64 @@ class NonStrictJsonFloatTests(JsonFloatTests):
""" """
'STRICT_JSON = False' should not somehow affect internal json behavior 'STRICT_JSON = False' should not somehow affect internal json behavior
""" """
class UrlsReplaceQueryParamTests(TestCase):
"""
Tests the replace_query_param functionality.
"""
def test_valid_unicode_preserved(self):
q = '/?q=%E6%9F%A5%E8%AF%A2'
new_key = 'page'
new_value = 2
value = '%E6%9F%A5%E8%AF%A2'
assert new_key in replace_query_param(q, new_key, new_value)
assert value in replace_query_param(q, new_key, new_value)
def test_valid_unicode_replaced(self):
q = '/?page=1'
value = '1'
new_key = 'q'
new_value = '%E6%9F%A5%E8%AF%A2'
assert new_key in replace_query_param(q, new_key, new_value)
assert value in replace_query_param(q, new_key, new_value)
def test_invalid_unicode(self):
q = '/e/?%FF%FE%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%33%31%33%29%3C%2F%73%63%72%69%70%74%3E=1'
key = 'from'
value = 'login'
assert key in replace_query_param(q, key, value)
class UrlsRemoveQueryParamTests(TestCase):
"""
Tests the remove_query_param functionality.
"""
def test_valid_unicode_preserved(self):
q = '/?q=%E6%9F%A5%E8%AF%A2'
new_key = 'page'
new_value = 2
value = '%E6%9F%A5%E8%AF%A2'
assert new_key in replace_query_param(q, new_key, new_value)
assert value in replace_query_param(q, new_key, new_value)
def test_valid_unicode_removed(self):
q = '/?page=2345&q=%E6%9F%A5%E8%AF%A2'
key = 'page'
value = '2345'
removed_key = 'q'
assert key in remove_query_param(q, removed_key)
assert value in remove_query_param(q, removed_key)
assert '%' not in remove_query_param(q, removed_key)
def test_invalid_unicode(self):
q = '/?from=login&page=2&%FF%FE%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%33%31%33%29%3C%2F%73%63%72%69%70%74%3E=1'
key = 'from'
removed_key = 'page'
assert key in remove_query_param(q, removed_key)