While making GET calls from the canister, I am encountering a 403 status error.
I have checked possible causes, including:
- IPv6 Compatibility
- Rate Limiting
The above conditions are already met, and the API endpoint is public (the URL provided here is a placeholder). The canister makes requests successfully in a local environment, but after deployment, it throws this error.
Below is my Rust code for reference:
async fn make_http_request(request: CanisterHttpRequestArgument) -> Result<Vec<u8>, String> {
const MAX_RETRIES: u8 = 5;
let mut retries = 0;
while retries < MAX_RETRIES {
let cycles: u128 = 50_000_000_000;
match http_request(request.clone(), cycles).await {
Ok((response,)) => {
if response.status.0.to_u64().unwrap_or(0) == 200 {
return Ok(response.body);
} else {
return Err(format!("HTTP error: status {}", response.status));
}
},
Err((_, msg)) if msg.contains("No consensus") || msg.contains("SysTransient") => {
retries += 1;
ic_cdk::println!("Retry {} for request: {}", retries, request.url);
// Use ic_cdk::api::call::call_with_payment instead of timer
continue;
},
Err((_, msg)) => return Err(msg),
}
}
Err(format!("Failed after {} retries. Last error: No consensus could be reached", MAX_RETRIES))
}
#[ic_cdk::update]
async fn te_ilp2(args: ILPArgs) -> IlpResponse {
let url = format!(
"https://backend-91c09684-367d-457-5085be8c9158.bit10.app/verify-transaction?txid={}&chain={}&secret=<secret>", // placeholder url
args.tick_in_tx_block,
args.tick_in_network
);
let request = CanisterHttpRequestArgument {
url: url.clone(),
method: HttpMethod::GET,
body: None,
max_response_bytes: None,
transform: None,
headers: vec![],
};
let response_data = IlpResponseData {
tick_in_name: args.tick_in_name,
tick_in_network: args.tick_in_network,
tick_in_tx_block: args.tick_in_tx_block,
tick_out_name: args.tick_out_name
};
match make_http_request(request).await {
Ok(response_body) => {
if let Ok(response_json) = serde_json::from_slice::<serde_json::Value>(&response_body) {
if let Some(message) = response_json["transaction_data"]["message"].as_str() {
match message {
"Transaction verified successfully" => IlpResponse::Ok(response_data),
"First output address does not match expected address" => {
IlpResponse::Err("Address verification failed".to_string())
}
_ => IlpResponse::Err("Unknown verification status".to_string()),
}
} else {
IlpResponse::Err("Invalid response format".to_string())
}
} else {
IlpResponse::Err("Failed to parse response".to_string())
}
}
Err(err) => IlpResponse::Err(format!("HTTP request failed: {}", err)),
}
}
ic_cdk::export_candid!();