offchain_utils/
fetcher.rs

1use scale_info::prelude::string::{String, ToString};
2use scale_info::prelude::vec::Vec;
3use sp_runtime::offchain::{http, Duration};
4
5/// A struct representing an HTTP request configuration.
6pub struct HttpRequest {
7    pub url: String,
8    pub headers: Vec<(String, String)>,
9}
10
11impl HttpRequest {
12    /// Create a new `HttpRequest` with default values.
13    pub fn new(url: &str) -> Self {
14        Self {
15            url: url.to_string(),
16            headers: Vec::new(),
17        }
18    }
19
20    /// Add a header to the request.
21    pub fn add_header(mut self, key: &str, value: &str) -> Self {
22        self.headers.push((key.to_string(), value.to_string()));
23        self
24    }
25}
26
27/// A trait for fetching data with flexible HTTP requests.
28pub trait OffchainFetcher {
29    /// Send an HTTP request and return the response body.
30    fn fetch(request: HttpRequest) -> Result<Vec<u8>, &'static str> {
31        let mut request_builder = http::Request::get(&request.url);
32
33        // Set headers
34        for (key, value) in request.headers.iter() {
35            request_builder = request_builder.add_header(key, value);
36        }
37        let deadline = sp_io::offchain::timestamp().add(Duration::from_millis(2_000));
38        // Send request
39        let pending = request_builder
40            .deadline(deadline) // 5-second timeout
41            .send()
42            .map_err(|_| "Failed to send HTTP request")?;
43
44        let response = pending.wait().map_err(|_| "No response received")?;
45
46        if response.code != 200 {
47            return Err("Non-200 response code received");
48        }
49
50        Ok(response.body().collect::<Vec<u8>>())
51    }
52
53    /// Send an HTTP request and return the response as a UTF-8 string.
54    fn fetch_string(request: HttpRequest) -> Result<String, &'static str> {
55        let bytes = Self::fetch(request)?;
56        String::from_utf8(bytes).map_err(|_| "Failed to parse response as UTF-8")
57    }
58}
59
60/// A default implementation of `OffchainFetcher`.
61pub struct DefaultOffchainFetcher;
62
63impl OffchainFetcher for DefaultOffchainFetcher {}