use std::collections::HashMap;
use candid::CandidType;
use serde::{Deserialize, Serialize};
pub use ic_management_canister_types::{
HttpHeader, HttpMethod, HttpRequestArgs, HttpRequestResult, TransformArgs, TransformContext,
};
use crate::{canister::types::CanisterCallError, identity::CanisterId};
pub const MAX_RESPONSE_LENGTH: usize = 1024 * 1024 * 3 - 1024 * 64;
#[derive(CandidType, Serialize, Deserialize, Debug, Clone)]
pub struct CustomHttpRequest {
pub url: String,
pub method: String,
pub headers: HashMap<String, String>,
pub body: Vec<u8>,
}
#[derive(CandidType, Serialize, Deserialize, Debug, Clone)]
pub struct StreamingCallbackToken {
pub path: String,
pub token: HashMap<String, String>,
}
#[derive(CandidType, Serialize, Deserialize, Debug, Clone, Default)]
pub struct StreamingCallbackHttpResponse {
pub body: Vec<u8>,
pub token: Option<StreamingCallbackToken>,
}
impl StreamingCallbackHttpResponse {
pub fn empty() -> Self {
Self::default()
}
}
#[allow(missing_docs)]
mod callback {
use super::*;
candid::define_function!(pub HttpRequestStreamingCallback : (StreamingCallbackToken) -> (StreamingCallbackHttpResponse) query);
}
pub use callback::HttpRequestStreamingCallback;
#[derive(CandidType, Deserialize, Debug, Clone)]
pub enum StreamingStrategy {
Callback {
callback: HttpRequestStreamingCallback,
token: StreamingCallbackToken,
},
}
#[derive(CandidType, Debug, Clone)]
pub struct CustomHttpResponse {
pub status_code: u16,
pub headers: HashMap<String, String>,
pub body: Vec<u8>,
pub streaming_strategy: Option<StreamingStrategy>,
pub upgrade: Option<bool>,
}
pub fn http_transform(response: TransformArgs) -> HttpRequestResult {
let mut t = response.response;
t.headers = vec![];
t
}
pub async fn do_http_request(
arg: ic_cdk::management_canister::HttpRequestArgs,
cycles: u128,
) -> super::types::CanisterCallResult<ic_cdk::management_canister::HttpRequestResult> {
let cost = ic_cdk::management_canister::cost_http_request(&arg);
if cycles < cost {
return Err(CanisterCallError {
canister_id: CanisterId::anonymous(),
method: "ic#http_request".to_string(),
message: "Insufficient cycles".to_string(),
});
}
ic_cdk::management_canister::http_request(&arg)
.await
.map_err(|err| CanisterCallError {
canister_id: CanisterId::anonymous(),
method: "ic#http_request".to_string(),
message: err.to_string(),
})
}
#[allow(clippy::future_not_send)]
pub async fn do_http_request_with_closure(
arg: ic_cdk::management_canister::HttpRequestArgs,
cycles: u128,
transform_func: impl FnOnce(
ic_cdk::management_canister::HttpRequestResult,
) -> ic_cdk::management_canister::HttpRequestResult
+ 'static,
) -> super::types::CanisterCallResult<ic_cdk::management_canister::HttpRequestResult> {
let cost = ic_cdk::management_canister::cost_http_request(&arg);
if cycles < cost {
return Err(CanisterCallError {
canister_id: CanisterId::anonymous(),
method: "ic#http_request".to_string(),
message: "Insufficient cycles".to_string(),
});
}
ic_cdk::management_canister::http_request_with_closure(&arg, transform_func)
.await
.map_err(|err| CanisterCallError {
canister_id: CanisterId::anonymous(),
method: "ic#http_request".to_string(),
message: err.to_string(),
})
}