use scale_info::prelude::string::{String, ToString};
use scale_info::prelude::vec::Vec;
use sp_runtime::offchain::{http, Duration};
pub struct HttpRequest {
pub url: String,
pub headers: Vec<(String, String)>,
}
impl HttpRequest {
pub fn new(url: &str) -> Self {
Self {
url: url.to_string(),
headers: Vec::new(),
}
}
pub fn add_header(mut self, key: &str, value: &str) -> Self {
self.headers.push((key.to_string(), value.to_string()));
self
}
}
pub trait OffchainFetcher {
fn fetch(request: HttpRequest) -> Result<Vec<u8>, &'static str> {
let mut request_builder = http::Request::get(&request.url);
for (key, value) in request.headers.iter() {
request_builder = request_builder.add_header(key, value);
}
let deadline = sp_io::offchain::timestamp().add(Duration::from_millis(2_000));
let pending = request_builder
.deadline(deadline) .send()
.map_err(|_| "Failed to send HTTP request")?;
let response = pending.wait().map_err(|_| "No response received")?;
if response.code != 200 {
return Err("Non-200 response code received");
}
Ok(response.body().collect::<Vec<u8>>())
}
fn fetch_string(request: HttpRequest) -> Result<String, &'static str> {
let bytes = Self::fetch(request)?;
String::from_utf8(bytes).map_err(|_| "Failed to parse response as UTF-8")
}
}
pub struct DefaultOffchainFetcher;
impl OffchainFetcher for DefaultOffchainFetcher {}