pink_extension/chain_extension/
http_request.rs1use alloc::string::String;
2use alloc::vec::Vec;
3use num_enum::{IntoPrimitive, TryFromPrimitive};
4
5use super::ErrorCode;
6#[derive(scale::Encode, scale::Decode)]
7#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
8pub struct HttpRequest {
9 pub url: String,
10 pub method: String,
11 pub headers: Vec<(String, String)>,
12 pub body: Vec<u8>,
13}
14
15impl HttpRequest {
16 pub fn new(
18 url: impl Into<String>,
19 method: impl Into<String>,
20 headers: Vec<(String, String)>,
21 body: Vec<u8>,
22 ) -> Self {
23 Self {
24 url: url.into(),
25 method: method.into(),
26 headers,
27 body,
28 }
29 }
30}
31
32#[derive(scale::Encode, scale::Decode)]
33#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
34pub struct HttpResponse {
35 pub status_code: u16,
36 pub reason_phrase: String,
37 pub headers: Vec<(String, String)>,
38 pub body: Vec<u8>,
39}
40
41#[derive(scale::Encode, scale::Decode, TryFromPrimitive, IntoPrimitive, Clone, Copy, Debug)]
42#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
43#[repr(u32)]
44pub enum HttpRequestError {
45 InvalidUrl,
46 InvalidMethod,
47 InvalidHeaderName,
48 InvalidHeaderValue,
49 FailedToCreateClient,
50 Timeout,
51 NotAllowed,
52 TooManyRequests,
53 NetworkError,
54 ResponseTooLarge,
55}
56
57impl super::sealed::Sealed for HttpRequestError {}
58impl super::CodableError for HttpRequestError {
59 fn encode(&self) -> u32 {
60 let code: u32 = (*self).into();
61 code + 1
62 }
63
64 fn decode(code: u32) -> Option<Self> {
65 if code == 0 {
66 return None;
67 }
68 core::convert::TryFrom::try_from(code - 1).ok()
69 }
70}
71
72impl From<ErrorCode> for HttpRequestError {
73 fn from(value: ErrorCode) -> Self {
74 match <Self as super::CodableError>::decode(value.0) {
75 None => crate::panic!("chain extension: invalid HttpRequestError"),
76 Some(err) => err,
77 }
78 }
79}
80
81impl From<scale::Error> for HttpRequestError {
82 fn from(_value: scale::Error) -> Self {
83 crate::panic!("chain_ext: failed to decocde HttpRequestError")
84 }
85}
86
87impl HttpRequestError {
88 pub fn display(&self) -> &'static str {
89 match self {
90 Self::InvalidUrl => "Invalid URL",
91 Self::InvalidMethod => "Invalid method",
92 Self::InvalidHeaderName => "Invalid header name",
93 Self::InvalidHeaderValue => "Invalid header value",
94 Self::FailedToCreateClient => "Failed to create client",
95 Self::Timeout => "Timeout",
96 Self::NotAllowed => "Not allowed",
97 Self::TooManyRequests => "Too many requests",
98 Self::NetworkError => "Network error",
99 Self::ResponseTooLarge => "Response too large",
100 }
101 }
102}
103
104impl HttpResponse {
105 pub fn ok(body: Vec<u8>) -> Self {
106 Self {
107 status_code: 200,
108 reason_phrase: "OK".into(),
109 headers: Default::default(),
110 body,
111 }
112 }
113
114 pub fn not_found() -> Self {
115 Self {
116 status_code: 404,
117 reason_phrase: "Not Found".into(),
118 headers: Default::default(),
119 body: Default::default(),
120 }
121 }
122}
123
124#[macro_export]
125macro_rules! http_req {
126 ($method: expr, $url: expr, $data: expr, $headers: expr) => {{
127 use $crate::chain_extension::HttpRequest;
128 let headers = $headers;
129 let body = $data;
130 let request = HttpRequest {
131 url: $url.into(),
132 method: $method.into(),
133 headers,
134 body,
135 };
136 $crate::ext().http_request(request)
137 }};
138 ($method: expr, $url: expr, $data: expr) => {{
139 $crate::http_req!($method, $url, $data, Default::default())
140 }};
141}
142
143#[macro_export]
164macro_rules! http_get {
165 ($url: expr, $headers: expr) => {{
166 $crate::http_req!("GET", $url, Default::default(), $headers)
167 }};
168 ($url: expr) => {{
169 $crate::http_get!($url, Default::default())
170 }};
171}
172
173#[macro_export]
195macro_rules! http_post {
196 ($url: expr, $data: expr, $headers: expr) => {{
197 $crate::http_req!("POST", $url, $data.into(), $headers)
198 }};
199 ($url: expr, $data: expr) => {{
200 $crate::http_post!($url, $data, Default::default())
201 }};
202}
203
204#[macro_export]
219macro_rules! http_put {
220 ($url: expr, $data: expr, $headers: expr) => {{
221 $crate::http_req!("PUT", $url, $data.into(), $headers)
222 }};
223 ($url: expr, $data: expr) => {{
224 $crate::http_put!($url, $data, Default::default())
225 }};
226}