Skip to content

Commit 4e0bb04

Browse files
committed
Add WIP fix for the client side and make sure urls with unicode
characters are handled correctly.
1 parent b367ef2 commit 4e0bb04

File tree

1 file changed

+29
-0
lines changed

1 file changed

+29
-0
lines changed

st2client/st2client/utils/httpclient.py

+29
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
from __future__ import absolute_import
1717

18+
from typing import Union
19+
1820
import json
1921
import logging
2022
from pipes import quote as pquote
@@ -78,6 +80,27 @@ def get_url_without_trailing_slash(value):
7880
return result
7981

8082

83+
def sanitize_url(url: Union[bytes, str]) -> str:
84+
"""
85+
Sanitize the provided url and ensure it's a valid unicode string.
86+
87+
By default, sys.argv will contain a unicode string where the actual item values which contain
88+
unicode sequences are escaped using unicode surrogates.
89+
90+
For example, if "examples.test_rule_utf8_náme" value is specified as a CLI argument, sys.argv
91+
and as such url, would contain "examples.test_rule_utf8_n%ED%B3%83%ED%B2%A1me" which is not
92+
what we want.
93+
94+
This won't work correctly when sending requests to the API. As such, we correctly escape the
95+
value to the unicode string here and then let the http layer (requests) correctly url encode
96+
this value.
97+
"""
98+
if isinstance(url, str):
99+
url = url.encode("ascii", "surrogateescape").decode("utf-8")
100+
101+
return url
102+
103+
81104
class HTTPClient(object):
82105
def __init__(self, root, cacert=None, debug=False):
83106
self.root = get_url_without_trailing_slash(root)
@@ -87,6 +110,7 @@ def __init__(self, root, cacert=None, debug=False):
87110
@add_ssl_verify_to_kwargs
88111
@add_auth_token_to_headers
89112
def get(self, url, **kwargs):
113+
url = sanitize_url(url)
90114
response = requests.get(self.root + url, **kwargs)
91115
response = self._response_hook(response=response)
92116
return response
@@ -95,13 +119,15 @@ def get(self, url, **kwargs):
95119
@add_auth_token_to_headers
96120
@add_json_content_type_to_headers
97121
def post(self, url, data, **kwargs):
122+
url = sanitize_url(url)
98123
response = requests.post(self.root + url, json.dumps(data), **kwargs)
99124
response = self._response_hook(response=response)
100125
return response
101126

102127
@add_ssl_verify_to_kwargs
103128
@add_auth_token_to_headers
104129
def post_raw(self, url, data, **kwargs):
130+
url = sanitize_url(url)
105131
response = requests.post(self.root + url, data, **kwargs)
106132
response = self._response_hook(response=response)
107133
return response
@@ -110,6 +136,7 @@ def post_raw(self, url, data, **kwargs):
110136
@add_auth_token_to_headers
111137
@add_json_content_type_to_headers
112138
def put(self, url, data, **kwargs):
139+
url = sanitize_url(url)
113140
response = requests.put(self.root + url, json.dumps(data), **kwargs)
114141
response = self._response_hook(response=response)
115142
return response
@@ -118,13 +145,15 @@ def put(self, url, data, **kwargs):
118145
@add_auth_token_to_headers
119146
@add_json_content_type_to_headers
120147
def patch(self, url, data, **kwargs):
148+
url = sanitize_url(url)
121149
response = requests.patch(self.root + url, data, **kwargs)
122150
response = self._response_hook(response=response)
123151
return response
124152

125153
@add_ssl_verify_to_kwargs
126154
@add_auth_token_to_headers
127155
def delete(self, url, **kwargs):
156+
url = sanitize_url(url)
128157
response = requests.delete(self.root + url, **kwargs)
129158
response = self._response_hook(response=response)
130159
return response

0 commit comments

Comments
 (0)