Skip to content

Commit 7a278b3

Browse files
nikulincarltongibson
authored andcommitted
fix processing unicode symbols in query_string by Python 2 (#5552)
* fix processing unicode symbols in query_string by Python 2 * Add comments for encoded test strings. * Add file encoding for Python 2.
1 parent d49d796 commit 7a278b3

File tree

2 files changed

+69
-3
lines changed

2 files changed

+69
-3
lines changed

rest_framework/utils/urls.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from django.utils.encoding import force_str
12
from django.utils.six.moves.urllib import parse as urlparse
23

34

@@ -6,9 +7,9 @@ def replace_query_param(url, key, val):
67
Given a URL and a key/val pair, set or replace an item in the query
78
parameters of the URL, and return the new URL.
89
"""
9-
(scheme, netloc, path, query, fragment) = urlparse.urlsplit(url)
10+
(scheme, netloc, path, query, fragment) = urlparse.urlsplit(force_str(url))
1011
query_dict = urlparse.parse_qs(query, keep_blank_values=True)
11-
query_dict[key] = [val]
12+
query_dict[force_str(key)] = [force_str(val)]
1213
query = urlparse.urlencode(sorted(list(query_dict.items())), doseq=True)
1314
return urlparse.urlunsplit((scheme, netloc, path, query, fragment))
1415

@@ -18,7 +19,7 @@ def remove_query_param(url, key):
1819
Given a URL and a key/val pair, remove an item in the query
1920
parameters of the URL, and return the new URL.
2021
"""
21-
(scheme, netloc, path, query, fragment) = urlparse.urlsplit(url)
22+
(scheme, netloc, path, query, fragment) = urlparse.urlsplit(force_str(url))
2223
query_dict = urlparse.parse_qs(query, keep_blank_values=True)
2324
query_dict.pop(key, None)
2425
query = urlparse.urlencode(sorted(list(query_dict.items())), doseq=True)

tests/test_utils.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# -*- coding: utf-8 -*-
12
from __future__ import unicode_literals
23

34
from django.conf.urls import url
@@ -11,6 +12,7 @@
1112
from rest_framework.serializers import ModelSerializer
1213
from rest_framework.utils import json
1314
from rest_framework.utils.breadcrumbs import get_breadcrumbs
15+
from rest_framework.utils.urls import remove_query_param, replace_query_param
1416
from rest_framework.views import APIView
1517
from rest_framework.viewsets import ModelViewSet
1618
from tests.models import BasicModel
@@ -205,3 +207,66 @@ class NonStrictJsonFloatTests(JsonFloatTests):
205207
"""
206208
'STRICT_JSON = False' should not somehow affect internal json behavior
207209
"""
210+
211+
212+
class UrlsReplaceQueryParamTests(TestCase):
213+
"""
214+
Tests the replace_query_param functionality.
215+
"""
216+
def test_valid_unicode_preserved(self):
217+
# Encoded string: '查询'
218+
q = '/?q=%E6%9F%A5%E8%AF%A2'
219+
new_key = 'page'
220+
new_value = 2
221+
value = '%E6%9F%A5%E8%AF%A2'
222+
223+
assert new_key in replace_query_param(q, new_key, new_value)
224+
assert value in replace_query_param(q, new_key, new_value)
225+
226+
def test_valid_unicode_replaced(self):
227+
q = '/?page=1'
228+
value = '1'
229+
new_key = 'q'
230+
new_value = '%E6%9F%A5%E8%AF%A2'
231+
232+
assert new_key in replace_query_param(q, new_key, new_value)
233+
assert value in replace_query_param(q, new_key, new_value)
234+
235+
def test_invalid_unicode(self):
236+
# Encoded string: '��<script>alert(313)</script>=1'
237+
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'
238+
key = 'from'
239+
value = 'login'
240+
241+
assert key in replace_query_param(q, key, value)
242+
243+
244+
class UrlsRemoveQueryParamTests(TestCase):
245+
"""
246+
Tests the remove_query_param functionality.
247+
"""
248+
def test_valid_unicode_preserved(self):
249+
q = '/?q=%E6%9F%A5%E8%AF%A2'
250+
new_key = 'page'
251+
new_value = 2
252+
value = '%E6%9F%A5%E8%AF%A2'
253+
254+
assert new_key in replace_query_param(q, new_key, new_value)
255+
assert value in replace_query_param(q, new_key, new_value)
256+
257+
def test_valid_unicode_removed(self):
258+
q = '/?page=2345&q=%E6%9F%A5%E8%AF%A2'
259+
key = 'page'
260+
value = '2345'
261+
removed_key = 'q'
262+
263+
assert key in remove_query_param(q, removed_key)
264+
assert value in remove_query_param(q, removed_key)
265+
assert '%' not in remove_query_param(q, removed_key)
266+
267+
def test_invalid_unicode(self):
268+
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'
269+
key = 'from'
270+
removed_key = 'page'
271+
272+
assert key in remove_query_param(q, removed_key)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy