canic_core/ops/ic/
http.rs1pub use crate::cdk::mgmt::{HttpHeader, HttpMethod, HttpRequestResult};
2
3use crate::{
4 Error,
5 cdk::mgmt::{HttpRequestArgs, http_request},
6 model::metrics::{
7 http::HttpMetrics,
8 system::{SystemMetricKind, SystemMetrics},
9 },
10};
11use num_traits::ToPrimitive;
12use serde::de::DeserializeOwned;
13
14pub struct Http;
19
20impl Http {
21 pub const MAX_RESPONSE_BYTES: u64 = 200_000;
22
23 fn record_metrics(verb: &'static str, url: &str, label: Option<&str>) {
24 SystemMetrics::increment(SystemMetricKind::HttpOutcall);
25 HttpMetrics::increment_with_label(verb, url, label);
26 }
27
28 pub async fn get<T: DeserializeOwned>(
29 url: &str,
30 headers: impl AsRef<[(&str, &str)]>,
31 ) -> Result<T, Error> {
32 Self::get_with_label(url, headers, None).await
33 }
34
35 pub async fn get_with_label<T: DeserializeOwned>(
36 url: &str,
37 headers: impl AsRef<[(&str, &str)]>,
38 label: Option<&str>,
39 ) -> Result<T, Error> {
40 Self::record_metrics("GET", url, label);
42
43 let headers: Vec<HttpHeader> = headers
44 .as_ref()
45 .iter()
46 .map(|(name, value)| HttpHeader {
47 name: name.to_string(),
48 value: value.to_string(),
49 })
50 .collect();
51
52 let args = HttpRequestArgs {
53 url: url.to_string(),
54 method: HttpMethod::GET,
55 headers,
56 max_response_bytes: Some(Self::MAX_RESPONSE_BYTES),
57 ..Default::default()
58 };
59
60 let res = http_request(&args)
61 .await
62 .map_err(|e| Error::HttpRequest(e.to_string()))?;
63
64 let status: u32 = res.status.0.to_u32().unwrap_or(0);
65 if status != 200 {
66 return Err(Error::HttpErrorCode(status));
67 }
68
69 serde_json::from_slice(&res.body).map_err(Into::into)
70 }
71
72 pub async fn get_raw<T: DeserializeOwned>(
73 args: HttpRequestArgs,
74 ) -> Result<HttpRequestResult, Error> {
75 Self::get_raw_with_label(args, None).await
76 }
77
78 pub async fn get_raw_with_label(
79 args: HttpRequestArgs,
80 label: Option<&str>,
81 ) -> Result<HttpRequestResult, Error> {
82 Self::record_metrics("GET", &args.url, label);
84
85 http_request(&args)
86 .await
87 .map_err(|e| crate::Error::HttpRequest(e.to_string()))
88 }
89}