ic_web3/transports/
ic_http_client.rs1use serde::{self, Deserialize, Serialize};
4use candid::CandidType;
5use jsonrpc_core::Request;
6use candid::{Principal, candid_method};
7use ic_cdk::api::management_canister::http_request::{
8 CanisterHttpRequestArgument, HttpHeader, HttpMethod,
9 HttpResponse, http_request,
10 TransformFunc, TransformContext,
11};
12
13#[derive(Clone, Debug)]
24pub struct ICHttpClient {
25 pub max_response_bytes: u64,
26 pub cycles: u64,
27}
28
29impl ICHttpClient {
30 pub fn new(max_resp: Option<u64>, default_cycles: Option<u64>) -> Self {
31 ICHttpClient {
32 max_response_bytes: if let Some(v) = max_resp { v } else { 500_000 },
33 cycles: if let Some(v) = default_cycles { v } else { 1_000_000_000_000 },
34 }
35 }
36
37 pub fn set_max_response_bytes(&mut self, v: u64) {
38 self.max_response_bytes = v;
39 }
40
41 pub fn set_cycles_per_call(&mut self, v: u64) {
42 self.cycles = v;
43 }
44
45 async fn request(
46 &self,
47 url: String,
48 req_type: HttpMethod,
49 req_headers: Vec<HttpHeader>,
50 payload: &Request,
51 max_resp: Option<u64>,
52 cycles: Option<u64>
53 ) -> Result<Vec<u8>, String> {
54 let request = CanisterHttpRequestArgument {
55 url: url.clone(),
56 max_response_bytes: if let Some(v) = max_resp { Some(v) } else { Some(self.max_response_bytes) },
57 method: req_type,
58 headers: req_headers,
59 body: Some(serde_json::to_vec(&payload).unwrap()),
60 transform: Some(TransformContext {
65 function: TransformFunc(candid::Func {
66 principal: ic_cdk::api::id(),
67 method: "transform".to_string(),
68 }),
69 context: vec![],
70 }),
71 };
72
73 match http_request(request).await {
74 Ok((result, )) => {
75 Ok(result.body)
76 }
77 Err((r, m)) => {
78 let message =
79 format!("The http_request resulted into error. RejectionCode: {r:?}, Error: {m}");
80 ic_cdk::api::print(message.clone());
81 Err(message)
82 }
83 }
84 }
85
86 pub async fn get(&self, url: String, payload: &Request, max_resp: Option<u64>, cycles: Option<u64>) -> Result<Vec<u8>, String> {
87 let request_headers = vec![
88 HttpHeader {
89 name: "Content-Type".to_string(),
90 value: "application/json".to_string(),
91 },
92 ];
93
94 self.request(url, HttpMethod::GET, request_headers, payload, max_resp, cycles).await
95 }
96
97 pub async fn post(&self, url: String, payload: &Request, max_resp: Option<u64>, cycles: Option<u64>) -> Result<Vec<u8>, String> {
98 let request_headers = vec![
99 HttpHeader {
100 name: "Content-Type".to_string(),
101 value: "application/json".to_string(),
102 },
103 ];
104
105 self.request(url, HttpMethod::POST, request_headers, payload, max_resp, cycles).await
106 }
107}
108