3
3
# standard
4
4
from functools import lru_cache
5
5
import re
6
- from urllib .parse import unquote , urlsplit
6
+ from urllib .parse import parse_qs , unquote , urlsplit
7
7
8
8
# local
9
9
from .hostname import hostname
@@ -34,11 +34,6 @@ def _path_regex():
34
34
)
35
35
36
36
37
- @lru_cache
38
- def _query_regex ():
39
- return re .compile (r"&?(\w+=?[^\s&]*)" , re .IGNORECASE )
40
-
41
-
42
37
def _validate_scheme (value : str ):
43
38
"""Validate scheme."""
44
39
# More schemes will be considered later.
@@ -108,16 +103,16 @@ def _validate_netloc(
108
103
) and _validate_auth_segment (basic_auth )
109
104
110
105
111
- def _validate_optionals (path : str , query : str , fragment : str ):
106
+ def _validate_optionals (path : str , query : str , fragment : str , strict_query : bool ):
112
107
"""Validate path query and fragments."""
113
108
optional_segments = True
114
109
if path :
115
110
optional_segments &= bool (_path_regex ().match (path ))
116
- if query :
117
- optional_segments &= bool ( _query_regex (). match ( query ))
111
+ if query and parse_qs ( query , strict_parsing = strict_query ) :
112
+ optional_segments &= True
118
113
if fragment :
119
114
fragment = fragment .lstrip ("/" ) if fragment .startswith ("/" ) else fragment
120
- optional_segments &= all (char_to_avoid not in fragment for char_to_avoid in ("/" , "?" ))
115
+ optional_segments &= all (char_to_avoid not in fragment for char_to_avoid in ("?" , ))
121
116
return optional_segments
122
117
123
118
@@ -130,6 +125,7 @@ def url(
130
125
skip_ipv4_addr : bool = False ,
131
126
may_have_port : bool = True ,
132
127
simple_host : bool = False ,
128
+ strict_query : bool = True ,
133
129
rfc_1034 : bool = False ,
134
130
rfc_2782 : bool = False ,
135
131
):
@@ -167,6 +163,8 @@ def url(
167
163
URL string may contain port number.
168
164
simple_host:
169
165
URL string maybe only hyphens and alpha-numerals.
166
+ strict_query:
167
+ Fail validation on query string parsing error.
170
168
rfc_1034:
171
169
Allow trailing dot in domain/host name.
172
170
Ref: [RFC 1034](https://www.rfc-editor.org/rfc/rfc1034).
@@ -214,5 +212,5 @@ def url(
214
212
rfc_1034 ,
215
213
rfc_2782 ,
216
214
)
217
- and _validate_optionals (path , query , fragment )
215
+ and _validate_optionals (path , query , fragment , strict_query )
218
216
)
0 commit comments