Skip to content

Commit 8f3f4b8

Browse files
committed
base64
1 parent 006151b commit 8f3f4b8

3 files changed

Lines changed: 53 additions & 2 deletions

File tree

src/rendezqueue/client.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ def _poll(self) -> None:
8989
# Take snapshot of queue to send
9090
snapshot_queue = list(self.outgoing_queue)
9191
b64_values = [
92-
base64.b64encode(v).decode("ascii") for v in snapshot_queue
92+
base64.urlsafe_b64encode(v).decode("ascii").rstrip("=")
93+
for v in snapshot_queue
9394
]
9495

9596
request_body = {
@@ -171,6 +172,7 @@ def _decode_response(self, msg: Dict[str, Any]) -> Dict[str, Any]:
171172
return msg
172173

173174
def _b64decode_padded(self, s: str) -> bytes:
175+
s = s.replace("-", "+").replace("_", "/")
174176
missing_padding = len(s) % 4
175177
if missing_padding:
176178
s += "=" * (4 - missing_padding)

src/rendezqueue/impl.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ def btoa(s: str) -> str:
1616

1717
def atob(s: str) -> str:
1818
# URL-safe base64 decoding with padding added
19+
s = s.replace("-", "+").replace("_", "/")
1920
missing_padding = len(s) % 4
2021
if missing_padding:
2122
s += "=" * (4 - missing_padding)
22-
return base64.urlsafe_b64decode(s).decode("latin1")
23+
return base64.b64decode(s, validate=False).decode("latin1")
2324

2425

2526
def inplace_decode_tryswap_message(msg: Dict[str, Any]) -> str:

test/b64_test.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import base64
2+
from rendezqueue.impl import (
3+
inplace_decode_tryswap_message,
4+
inplace_encode_tryswap_message,
5+
)
6+
from rendezqueue.client import RendezqueueClient
7+
8+
9+
def test_b64_decode_padding_and_standard_base64():
10+
# Test `inplace_decode_tryswap_message` (Server Side)
11+
# urlsafe with padding missing
12+
msg1 = {"b64": 1, "values": ["i-f_"]} # b'\x8b\xe7\xff'
13+
assert inplace_decode_tryswap_message(msg1) == ""
14+
assert msg1["values"] == [b"\x8b\xe7\xff".decode("latin1")]
15+
16+
# standard base64 with padding
17+
msg2 = {"b64": 1, "values": ["i+f/"]}
18+
assert inplace_decode_tryswap_message(msg2) == ""
19+
assert msg2["values"] == [b"\x8b\xe7\xff".decode("latin1")]
20+
21+
# Client Side decode
22+
client = RendezqueueClient(url="", key="", hue="")
23+
24+
# urlsafe with padding missing
25+
assert client._b64decode_padded("i-f_") == b"\x8b\xe7\xff"
26+
27+
# standard base64 with padding
28+
assert client._b64decode_padded("i+f/") == b"\x8b\xe7\xff"
29+
30+
31+
def test_b64_encode_is_urlsafe_no_padding():
32+
# Server side
33+
msg = {"b64": 1, "values": [b"\x8b\xe7\xff".decode("latin1")]}
34+
inplace_encode_tryswap_message(msg)
35+
assert msg["values"] == ["i-f_"] # no padding, urlsafe
36+
37+
# Client side encodes via list comprehension, we can just test if the replaced code works in context
38+
# or just trust the patch. Since we can't easily isolate the snapshot_queue encoding inside _poll without mocking,
39+
# we can just test the urlsafe_b64encode behavior:
40+
val = b"\x8b\xe7\xff"
41+
encoded = base64.urlsafe_b64encode(val).decode("ascii").rstrip("=")
42+
assert encoded == "i-f_"
43+
44+
45+
if __name__ == "__main__":
46+
test_b64_decode_padding_and_standard_base64()
47+
test_b64_encode_is_urlsafe_no_padding()
48+
print("All tests passed.")

0 commit comments

Comments
 (0)