Skip to content

Commit 162917c

Browse files
committed
Deserialize both standard and URL-safe base64
1 parent 6e96b85 commit 162917c

File tree

2 files changed

+22
-7
lines changed

2 files changed

+22
-7
lines changed

src/validators/config.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ impl ValBytesMode {
2828
pub fn deserialize_string<'py>(self, s: &str) -> Result<EitherBytes<'_, 'py>, ErrorType> {
2929
match self.ser {
3030
BytesMode::Utf8 => Ok(EitherBytes::Cow(Cow::Borrowed(s.as_bytes()))),
31-
BytesMode::Base64 => match base64::engine::general_purpose::URL_SAFE.decode(s) {
31+
BytesMode::Base64 => match base64::engine::general_purpose::URL_SAFE.decode(to_base64_urlsafe(s)) {
3232
Ok(bytes) => Ok(EitherBytes::from(bytes)),
3333
Err(err) => Err(ErrorType::BytesInvalidEncoding {
3434
encoding: "base64".to_string(),
@@ -47,3 +47,11 @@ impl ValBytesMode {
4747
}
4848
}
4949
}
50+
51+
fn to_base64_urlsafe(s: &str) -> String {
52+
if s.contains('+') || s.contains('/') {
53+
s.replace('+', "-").replace('/', "_")
54+
} else {
55+
s.to_string()
56+
}
57+
}

tests/test_json.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -379,19 +379,26 @@ def test_partial_parse():
379379

380380

381381
def test_json_bytes_base64_round_trip():
382-
data = b'hello'
383-
encoded = b'"aGVsbG8="'
384-
assert to_json(data, bytes_mode='base64') == encoded
382+
data = b'TDR3\xbe\x11J\xe9\x9f\xa4&\x91\xff\xc8\xef4\xdf\xd3$\xf3^\xca\xb5\x14V \xdeDH\n\x85\x8b'
383+
encoded_std = b'"VERSM74RSumfpCaR/8jvNN/TJPNeyrUUViDeREgKhYs="'
384+
encoded_url = b'"VERSM74RSumfpCaR_8jvNN_TJPNeyrUUViDeREgKhYs="'
385+
assert to_json(data, bytes_mode='base64') == encoded_url
385386

386387
v = SchemaValidator({'type': 'bytes'}, {'val_json_bytes': 'base64'})
387-
assert v.validate_json(encoded) == data
388+
assert v.validate_json(encoded_url) == data
389+
assert v.validate_json(encoded_std) == data
390+
391+
with pytest.raises(ValidationError) as exc:
392+
v.validate_json('"wrong!"')
393+
[details] = exc.value.errors()
394+
assert details['type'] == 'bytes_invalid_encoding'
388395

389-
assert to_json({'key': data}, bytes_mode='base64') == b'{"key":"aGVsbG8="}'
396+
assert to_json({'key': data}, bytes_mode='base64') == b'{"key":' + encoded_url + b'}'
390397
v = SchemaValidator(
391398
{'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'bytes'}},
392399
{'val_json_bytes': 'base64'},
393400
)
394-
assert v.validate_json('{"key":"aGVsbG8="}') == {'key': data}
401+
assert v.validate_json(b'{"key":' + encoded_url + b'}') == {'key': data}
395402

396403

397404
def test_json_bytes_base64_invalid():

0 commit comments

Comments
 (0)