|
4 | 4 |
|
5 | 5 | import threading |
6 | 6 | import time |
| 7 | +from urllib.parse import quote |
7 | 8 |
|
8 | 9 | import pytest |
9 | 10 |
|
@@ -1112,3 +1113,60 @@ def worker(worker_id: int): |
1112 | 1113 | # Check results |
1113 | 1114 | assert len(errors) == 0, f"Thread safety test failed with errors: {errors}" |
1114 | 1115 | assert len(results) == 5, f"Expected 5 successful workers, got {len(results)}" |
| 1116 | + |
| 1117 | + |
| 1118 | +def test_callback_routes_url_decoding(): |
| 1119 | + """Test that callback routes properly URL-decode callback IDs.""" |
| 1120 | + # Test callback ID with special characters that need URL encoding |
| 1121 | + callback_id = "eyJhcm4iOiJhcm4iLCJvcCI6ImVhNjZjMDZjMWUxYzA1ZmEifQ==" |
| 1122 | + encoded_callback_id = quote(callback_id, safe="") |
| 1123 | + |
| 1124 | + # Test CallbackSuccessRoute |
| 1125 | + base_route = Route.from_string( |
| 1126 | + f"/2025-12-01/durable-execution-callbacks/{encoded_callback_id}/succeed" |
| 1127 | + ) |
| 1128 | + success_route = CallbackSuccessRoute.from_route(base_route) |
| 1129 | + assert success_route.callback_id == callback_id # Should be decoded |
| 1130 | + |
| 1131 | + # Test CallbackFailureRoute |
| 1132 | + base_route = Route.from_string( |
| 1133 | + f"/2025-12-01/durable-execution-callbacks/{encoded_callback_id}/fail" |
| 1134 | + ) |
| 1135 | + failure_route = CallbackFailureRoute.from_route(base_route) |
| 1136 | + assert failure_route.callback_id == callback_id # Should be decoded |
| 1137 | + |
| 1138 | + # Test CallbackHeartbeatRoute |
| 1139 | + base_route = Route.from_string( |
| 1140 | + f"/2025-12-01/durable-execution-callbacks/{encoded_callback_id}/heartbeat" |
| 1141 | + ) |
| 1142 | + heartbeat_route = CallbackHeartbeatRoute.from_route(base_route) |
| 1143 | + assert heartbeat_route.callback_id == callback_id # Should be decoded |
| 1144 | + |
| 1145 | + |
| 1146 | +def test_router_callback_routes_url_decoding(): |
| 1147 | + """Test Router properly handles URL-encoded callback IDs.""" |
| 1148 | + router = Router() |
| 1149 | + callback_id = "eyJhcm4iOiJhcm4iLCJvcCI6ImVhNjZjMDZjMWUxYzA1ZmEifQ==" |
| 1150 | + encoded_callback_id = quote(callback_id, safe="") |
| 1151 | + |
| 1152 | + # Test success route |
| 1153 | + route = router.find_route( |
| 1154 | + f"/2025-12-01/durable-execution-callbacks/{encoded_callback_id}/succeed", "POST" |
| 1155 | + ) |
| 1156 | + assert isinstance(route, CallbackSuccessRoute) |
| 1157 | + assert route.callback_id == callback_id # Should be decoded |
| 1158 | + |
| 1159 | + # Test failure route |
| 1160 | + route = router.find_route( |
| 1161 | + f"/2025-12-01/durable-execution-callbacks/{encoded_callback_id}/fail", "POST" |
| 1162 | + ) |
| 1163 | + assert isinstance(route, CallbackFailureRoute) |
| 1164 | + assert route.callback_id == callback_id # Should be decoded |
| 1165 | + |
| 1166 | + # Test heartbeat route |
| 1167 | + route = router.find_route( |
| 1168 | + f"/2025-12-01/durable-execution-callbacks/{encoded_callback_id}/heartbeat", |
| 1169 | + "POST", |
| 1170 | + ) |
| 1171 | + assert isinstance(route, CallbackHeartbeatRoute) |
| 1172 | + assert route.callback_id == callback_id # Should be decoded |
0 commit comments