use crate::client::get_error_body;
use crate::client::Result;
use noxious::{
proxy::{ProxyConfig, ProxyWithToxics},
toxic::{StreamDirection, Toxic, ToxicKind},
};
use reqwest::{Client as HttpClient, StatusCode};
#[derive(Debug, Clone, PartialEq)]
pub struct Proxy {
base_url: String,
created: bool,
pub config: ProxyConfig,
toxics: Vec<Toxic>,
}
impl Proxy {
pub async fn save(&mut self) -> Result<()> {
let request = if self.created {
HttpClient::new()
.post(self.base_url.clone() + "/proxies/" + &self.config.name)
.json(&self.config)
} else {
HttpClient::new()
.post(self.base_url.clone() + "/proxies")
.json(&self.config)
};
let response = request.send().await?;
if response.status().is_success() {
self.created = true;
Ok(())
} else {
let expected_status = if self.created {
StatusCode::OK
} else {
StatusCode::CREATED
};
Err(get_error_body(response, expected_status).await)
}
}
pub async fn enable(&mut self) -> Result<()> {
self.config.enabled = true;
self.save().await
}
pub async fn disable(&mut self) -> Result<()> {
self.config.enabled = false;
self.save().await
}
pub fn is_enabled(&self) -> bool {
self.config.enabled
}
pub async fn change_name(&mut self, new_name: &str) -> Result<()> {
let old_name = self.config.name.clone();
self.config.name = new_name.to_owned();
let res = HttpClient::new()
.post(self.base_url.clone() + "/proxies/" + &old_name)
.json(&self.config)
.send()
.await?;
if res.status().is_success() {
Ok(())
} else {
Err(get_error_body(res, StatusCode::OK).await)
}
}
pub async fn delete(self) -> Result<()> {
let res = HttpClient::new()
.delete(self.base_url.clone() + "/proxies/" + &self.config.name)
.send()
.await?;
if res.status().is_success() {
Ok(())
} else {
Err(get_error_body(res, StatusCode::NO_CONTENT).await)
}
}
pub async fn toxics(&self) -> Result<Vec<Toxic>> {
let res = HttpClient::new()
.get(self.base_url.clone() + "/proxies/" + &self.config.name + "/toxics")
.send()
.await?;
if res.status().is_success() {
Ok(res.json::<Vec<Toxic>>().await?)
} else {
Err(get_error_body(res, StatusCode::OK).await)
}
}
pub async fn add_toxic(&self, toxic: &Toxic) -> Result<Toxic> {
let res = HttpClient::new()
.post(self.base_url.clone() + "/proxies/" + &self.config.name + "/toxics")
.json(toxic)
.send()
.await?;
if res.status().is_success() {
Ok(res.json::<Toxic>().await?)
} else {
Err(get_error_body(res, StatusCode::OK).await)
}
}
pub async fn update_toxic(
&self,
name: &str,
toxicity: f32,
kind: ToxicKind,
direction: StreamDirection,
) -> Result<Toxic> {
let toxicity: f32 = if toxicity < 0.0 { 0.0 } else { toxicity };
let toxic = Toxic {
kind,
name: name.to_owned(),
toxicity,
direction,
};
let res = HttpClient::new()
.post(self.base_url.clone() + "/proxies/" + &self.config.name + "/toxics/" + name)
.json(&toxic)
.send()
.await?;
if res.status().is_success() {
Ok(res.json::<Toxic>().await?)
} else {
Err(get_error_body(res, StatusCode::OK).await)
}
}
pub async fn remove_toxic(&self, name: &str) -> Result<()> {
let res = HttpClient::new()
.delete(self.base_url.clone() + "/proxies/" + &self.config.name + "/toxics/" + name)
.send()
.await?;
if res.status().is_success() {
Ok(())
} else {
Err(get_error_body(res, StatusCode::NO_CONTENT).await)
}
}
pub(crate) fn new(base_url: &str, name: &str, listen: &str, upstream: &str) -> Proxy {
Proxy {
base_url: base_url.to_owned(),
created: false,
config: ProxyConfig {
name: name.to_owned(),
listen: listen.to_owned(),
upstream: upstream.to_owned(),
enabled: true,
rand_seed: None,
},
toxics: Vec::new(),
}
}
#[doc(hidden)]
pub fn from_proxy_with_toxics(base_url: &str, obj: ProxyWithToxics) -> Proxy {
Proxy {
base_url: base_url.to_owned(),
created: true,
config: obj.proxy,
toxics: obj.toxics,
}
}
}