Skip to content

Commit 1ad644c

Browse files
committed
feat: Sanitize request body (box/box-codegen#948)
1 parent d688de8 commit 1ad644c

6 files changed

Lines changed: 69 additions & 4 deletions

File tree

‎.codegen.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{ "engineHash": "2fabf30", "specHash": "576cd17", "version": "10.9.0" }
1+
{ "engineHash": "78a8dc0", "specHash": "576cd17", "version": "10.9.0" }

‎box_sdk_gen/box/errors.py‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,24 @@ def __init__(
3737
url: str,
3838
query_params: Dict[str, str],
3939
headers: Dict[str, str],
40-
body: Optional[str] = None,
40+
body: Optional[Any] = None,
41+
content_type: Optional[str] = None,
4142
):
4243
self.method = method
4344
self.url = url
4445
self.query_params = query_params
4546
self.headers = headers
4647
self.body = body
48+
self.content_type = content_type
4749

4850
def print(self, data_sanitizer: DataSanitizer):
51+
sanitized_body = (
52+
data_sanitizer.sanitize_string_body(
53+
self.body, content_type=self.content_type
54+
)
55+
if isinstance(self.body, str)
56+
else self.body
57+
)
4958
return ''.join(
5059
(
5160
f'\n\tMethod: {self.method}',
@@ -55,8 +64,8 @@ def print(self, data_sanitizer: DataSanitizer):
5564
''.join(
5665
[
5766
'\n\tBody: ',
58-
'\n' if self.body else '',
59-
pprint.pformat(self.body, indent=8),
67+
'\n' if sanitized_body else '',
68+
pprint.pformat(sanitized_body, indent=8),
6069
]
6170
),
6271
)

‎box_sdk_gen/internal/logging.py‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
from typing import Dict
22

3+
from typing import Optional
4+
35
from box_sdk_gen.serialization.json import SerializedData
46

57
from box_sdk_gen.internal.utils import sanitize_map
68

79
from box_sdk_gen.serialization.json import sanitize_serialized_data
810

11+
from box_sdk_gen.serialization.json import sanitize_form_encoded_body_from_string
12+
13+
from box_sdk_gen.serialization.json import json_to_serialized_data
14+
15+
from box_sdk_gen.serialization.json import sd_to_json
16+
917

1018
class DataSanitizer:
1119
def __init__(self):
@@ -29,3 +37,21 @@ def sanitize_headers(self, headers: Dict[str, str]) -> Dict[str, str]:
2937

3038
def sanitize_body(self, body: SerializedData) -> SerializedData:
3139
return sanitize_serialized_data(body, self._keys_to_sanitize)
40+
41+
def sanitize_form_encoded_body(self, body: str) -> str:
42+
return sanitize_form_encoded_body_from_string(body, self._keys_to_sanitize)
43+
44+
def sanitize_string_body(
45+
self, body: str, *, content_type: Optional[str] = None
46+
) -> str:
47+
if (
48+
content_type == 'application/json'
49+
or content_type == 'application/json-patch+json'
50+
):
51+
try:
52+
return sd_to_json(self.sanitize_body(json_to_serialized_data(body)))
53+
except Exception:
54+
return body
55+
if content_type == 'application/x-www-form-urlencoded':
56+
return self.sanitize_form_encoded_body(body)
57+
return body

‎box_sdk_gen/networking/box_network_client.py‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class APIRequest:
4040
headers: Dict[str, str]
4141
params: Dict[str, str]
4242
data: Optional[Union[str, ByteStream, MultipartEncoder]]
43+
content_type: Optional[str] = None
4344
allow_redirects: bool = True
4445
timeout: Optional[Tuple[Optional[float], Optional[float]]] = None
4546

@@ -180,6 +181,7 @@ def _prepare_request(
180181
headers=headers,
181182
params=params,
182183
data=data,
184+
content_type=options.content_type,
183185
allow_redirects=allow_redirects,
184186
timeout=timeout,
185187
)
@@ -304,6 +306,7 @@ def _raise_on_unsuccessful_request(
304306
query_params=request.params,
305307
headers=request.headers,
306308
body=request.data,
309+
content_type=request.content_type,
307310
),
308311
response_info=ResponseInfo(
309312
status_code=network_response.status_code,

‎box_sdk_gen/serialization/json.py‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,32 @@ def sanitized_value() -> str:
4848
return '---[redacted]---'
4949

5050

51+
def sanitize_form_encoded_body_from_string(
52+
body: str, keys_to_sanitize: Dict[str, str]
53+
) -> str:
54+
return '&'.join(
55+
[
56+
_sanitize_form_encoded_parameter(parameter, keys_to_sanitize)
57+
for parameter in body.split('&')
58+
]
59+
)
60+
61+
62+
def _sanitize_form_encoded_parameter(
63+
parameter: str, keys_to_sanitize: Dict[str, str]
64+
) -> str:
65+
separator_index = parameter.find('=')
66+
if separator_index < 0:
67+
return parameter
68+
69+
key = parameter[:separator_index]
70+
value = parameter[separator_index + 1 :]
71+
sanitized_parameter_value = (
72+
sanitized_value() if key.lower() in keys_to_sanitize else value
73+
)
74+
return f'{key}={sanitized_parameter_value}'
75+
76+
5177
def sanitize_serialized_data(
5278
sd: SerializedData, keys_to_sanitize: Dict[str, str]
5379
) -> SerializedData:

‎test/box_network_client.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ def test_prepare_json_request(network_client, network_session_mock):
338338
},
339339
params={"param": "value"},
340340
data='{"key": "value"}',
341+
content_type="application/json",
341342
timeout=(5, 60),
342343
)
343344

0 commit comments

Comments
 (0)