1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
use std::time::Duration;
use reqwest::{Client, Error, StatusCode};
// previously fetched from the market (in the supermarket) it should now be fetched from the Platform!
use primitives::{platform::AdSlotResponse, util::ApiUrl, IPFS};
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Clone)]
/// The `PlatformApi` is cheap to clone
pub struct PlatformApi {
pub(crate) platform_url: ApiUrl,
client: Client,
}
impl PlatformApi {
/// The Platform url that was is used for communication with the API
pub fn url(&self) -> &ApiUrl {
&self.platform_url
}
/// Duration specified will be the time to remain idle before sending a TCP keepalive probe.
/// Sets [`reqwest::Client`]'s [`reqwest::ClientBuilder::tcp_keepalive`](reqwest::ClientBuilder::tcp_keepalive))
// @TODO: maybe add timeout too?
pub fn new(platform_url: ApiUrl, keep_alive_interval: Duration) -> Result<Self> {
let client = Client::builder()
.tcp_keepalive(keep_alive_interval)
.cookie_store(true)
.build()?;
Ok(Self {
platform_url,
client,
})
}
/// Fetch the [`AdSlot`], [`AdSlot.fallback_unit`], [`AdSlot.website`] information and the `AdUnit`s
/// of the AdSlot type ( [`AdSlot.ad_type`] ).
///
/// [`AdSlot`]: primitives::AdSlot
/// [`AdSlot.fallback_unit`]: primitives::AdSlot::fallback_unit
/// [`AdSlot.website`]: primitives::AdSlot::website
/// [`AdSlot.ad_type`]: primitives::AdSlot::ad_type
pub async fn fetch_slot(&self, ipfs: IPFS) -> Result<Option<AdSlotResponse>> {
let url = self
.platform_url
.join(&format!("slot/{}", ipfs))
.expect("Wrong Platform Url for /slot/{IPFS} endpoint");
match self.client.get(url).send().await?.error_for_status() {
Ok(response) => response.json().await.map(Some),
// if we have a `404 Not Found` error, return None
Err(err) if err.status() == Some(StatusCode::NOT_FOUND) => Ok(None),
Err(err) => Err(err),
}
}
}