Skip to content

Commit cddf74f

Browse files
jclapisnilsfs7
authored andcommitted
Support SSV API URLs without trailing slashes (Commit-Boost#396)
1 parent e8b3f64 commit cddf74f

File tree

5 files changed

+23
-8
lines changed

5 files changed

+23
-8
lines changed

crates/common/src/config/mux.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ async fn fetch_lido_registry_keys(
369369
}
370370

371371
async fn fetch_ssv_pubkeys(
372-
api_url: Url,
372+
mut api_url: Url,
373373
chain: Chain,
374374
node_operator_id: U256,
375375
http_timeout: Duration,
@@ -386,6 +386,15 @@ async fn fetch_ssv_pubkeys(
386386
let mut pubkeys: Vec<BlsPublicKey> = vec![];
387387
let mut page = 1;
388388

389+
// Validate the URL - this appends a trailing slash if missing as efficiently as
390+
// possible
391+
if !api_url.path().ends_with('/') {
392+
match api_url.path_segments_mut() {
393+
Ok(mut segments) => segments.push(""), // Analogous to a trailing slash
394+
Err(_) => bail!("SSV API URL is not a valid base URL"),
395+
};
396+
}
397+
389398
loop {
390399
let route = format!(
391400
"{chain_name}/validators/in_operator/{node_operator_id}?perPage={MAX_PER_PAGE}&page={page}",

crates/common/src/config/pbs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,5 +404,5 @@ pub async fn load_pbs_custom_config<T: DeserializeOwned>() -> Result<(PbsModuleC
404404

405405
/// Default URL for the SSV network API
406406
fn default_ssv_api_url() -> Url {
407-
Url::parse("https://api.ssv.network/api/v4").expect("default URL is valid")
407+
Url::parse("https://api.ssv.network/api/v4/").expect("default URL is valid")
408408
}

tests/src/mock_ssv.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ pub async fn create_mock_ssv_server(
3737
force_timeout: Arc::new(RwLock::new(false)),
3838
});
3939
let router = axum::Router::new()
40-
.route("/{chain_name}/validators/in_operator/{node_operator_id}", get(handle_validators))
40+
.route(
41+
"/api/v4/{chain_name}/validators/in_operator/{node_operator_id}",
42+
get(handle_validators),
43+
)
4144
.route("/big_data", get(handle_big_data))
4245
.with_state(state)
4346
.into_make_service();

tests/tests/pbs_mux.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ async fn test_ssv_network_fetch() -> Result<()> {
2929
// Start the mock server
3030
let port = 30100;
3131
let _server_handle = create_mock_ssv_server(port, None).await?;
32-
let url = Url::parse(&format!("http://localhost:{port}/test_chain/validators/in_operator/1"))
33-
.unwrap();
32+
let url =
33+
Url::parse(&format!("http://localhost:{port}/api/v4/test_chain/validators/in_operator/1"))
34+
.unwrap();
3435
let response =
3536
fetch_ssv_pubkeys_from_url(url, Duration::from_secs(HTTP_TIMEOUT_SECONDS_DEFAULT)).await?;
3637

@@ -100,8 +101,9 @@ async fn test_ssv_network_fetch_timeout() -> Result<()> {
100101
force_timeout: Arc::new(RwLock::new(true)),
101102
};
102103
let server_handle = create_mock_ssv_server(port, Some(state)).await?;
103-
let url = Url::parse(&format!("http://localhost:{port}/test_chain/validators/in_operator/1"))
104-
.unwrap();
104+
let url =
105+
Url::parse(&format!("http://localhost:{port}/api/v4/test_chain/validators/in_operator/1"))
106+
.unwrap();
105107
let response = fetch_ssv_pubkeys_from_url(url, Duration::from_secs(TEST_HTTP_TIMEOUT)).await;
106108

107109
// The response should fail due to timeout

tests/tests/pbs_mux_refresh.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ async fn test_auto_refresh() -> Result<()> {
4242

4343
// Start the mock SSV API server
4444
let ssv_api_port = pbs_port + 1;
45-
let ssv_api_url = Url::parse(&format!("http://localhost:{ssv_api_port}"))?;
45+
// Intentionally missing a trailing slash to ensure this is handled properly
46+
let ssv_api_url = Url::parse(&format!("http://localhost:{ssv_api_port}/api/v4"))?;
4647
let mock_ssv_state = SsvMockState {
4748
validators: Arc::new(RwLock::new(vec![SSVValidator {
4849
pubkey: existing_mux_pubkey.clone(),

0 commit comments

Comments
 (0)