1use crate::client::get_error_body;
2use crate::client::Result;
3use noxious::{
4 proxy::{ProxyConfig, ProxyWithToxics},
5 toxic::{StreamDirection, Toxic, ToxicKind},
6};
7use reqwest::{Client as HttpClient, StatusCode};
8
9#[derive(Debug, Clone, PartialEq)]
13pub struct Proxy {
14 base_url: String,
15 created: bool,
16 pub config: ProxyConfig,
19 toxics: Vec<Toxic>,
20}
21
22impl Proxy {
23 pub async fn save(&mut self) -> Result<()> {
26 let request = if self.created {
27 HttpClient::new()
28 .post(self.base_url.clone() + "/proxies/" + &self.config.name)
29 .json(&self.config)
30 } else {
31 HttpClient::new()
32 .post(self.base_url.clone() + "/proxies")
33 .json(&self.config)
34 };
35 let response = request.send().await?;
36 if response.status().is_success() {
37 self.created = true;
38 Ok(())
39 } else {
40 let expected_status = if self.created {
41 StatusCode::OK
42 } else {
43 StatusCode::CREATED
44 };
45 Err(get_error_body(response, expected_status).await)
46 }
47 }
48
49 pub async fn enable(&mut self) -> Result<()> {
51 self.config.enabled = true;
52 self.save().await
53 }
54
55 pub async fn disable(&mut self) -> Result<()> {
57 self.config.enabled = false;
58 self.save().await
59 }
60
61 pub fn is_enabled(&self) -> bool {
63 self.config.enabled
64 }
65
66 pub async fn change_name(&mut self, new_name: &str) -> Result<()> {
68 let old_name = self.config.name.clone();
69 self.config.name = new_name.to_owned();
70 let res = HttpClient::new()
71 .post(self.base_url.clone() + "/proxies/" + &old_name)
72 .json(&self.config)
73 .send()
74 .await?;
75 if res.status().is_success() {
76 Ok(())
77 } else {
78 Err(get_error_body(res, StatusCode::OK).await)
79 }
80 }
81
82 pub async fn delete(self) -> Result<()> {
86 let res = HttpClient::new()
87 .delete(self.base_url.clone() + "/proxies/" + &self.config.name)
88 .send()
89 .await?;
90 if res.status().is_success() {
91 Ok(())
92 } else {
93 Err(get_error_body(res, StatusCode::NO_CONTENT).await)
94 }
95 }
96
97 pub async fn toxics(&self) -> Result<Vec<Toxic>> {
99 let res = HttpClient::new()
100 .get(self.base_url.clone() + "/proxies/" + &self.config.name + "/toxics")
101 .send()
102 .await?;
103
104 if res.status().is_success() {
105 Ok(res.json::<Vec<Toxic>>().await?)
106 } else {
107 Err(get_error_body(res, StatusCode::OK).await)
108 }
109 }
110
111 pub async fn add_toxic(&self, toxic: &Toxic) -> Result<Toxic> {
132 let res = HttpClient::new()
133 .post(self.base_url.clone() + "/proxies/" + &self.config.name + "/toxics")
134 .json(toxic)
135 .send()
136 .await?;
137
138 if res.status().is_success() {
139 Ok(res.json::<Toxic>().await?)
140 } else {
141 Err(get_error_body(res, StatusCode::OK).await)
142 }
143 }
144
145 pub async fn update_toxic(
148 &self,
149 name: &str,
150 toxicity: f32,
151 kind: ToxicKind,
152 direction: StreamDirection,
153 ) -> Result<Toxic> {
154 let toxicity: f32 = if toxicity < 0.0 { 0.0 } else { toxicity };
155 let toxic = Toxic {
156 kind,
157 name: name.to_owned(),
158 toxicity,
159 direction,
160 };
161 let res = HttpClient::new()
162 .post(self.base_url.clone() + "/proxies/" + &self.config.name + "/toxics/" + name)
163 .json(&toxic)
164 .send()
165 .await?;
166
167 if res.status().is_success() {
168 Ok(res.json::<Toxic>().await?)
169 } else {
170 Err(get_error_body(res, StatusCode::OK).await)
171 }
172 }
173
174 pub async fn remove_toxic(&self, name: &str) -> Result<()> {
176 let res = HttpClient::new()
177 .delete(self.base_url.clone() + "/proxies/" + &self.config.name + "/toxics/" + name)
178 .send()
179 .await?;
180 if res.status().is_success() {
181 Ok(())
182 } else {
183 Err(get_error_body(res, StatusCode::NO_CONTENT).await)
184 }
185 }
186
187 pub(crate) fn new(base_url: &str, name: &str, listen: &str, upstream: &str) -> Proxy {
188 Proxy {
189 base_url: base_url.to_owned(),
190 created: false,
191 config: ProxyConfig {
192 name: name.to_owned(),
193 listen: listen.to_owned(),
194 upstream: upstream.to_owned(),
195 enabled: true,
196 rand_seed: None,
197 },
198 toxics: Vec::new(),
199 }
200 }
201
202 #[doc(hidden)]
203 pub fn from_proxy_with_toxics(base_url: &str, obj: ProxyWithToxics) -> Proxy {
204 Proxy {
205 base_url: base_url.to_owned(),
206 created: true,
207 config: obj.proxy,
208 toxics: obj.toxics,
209 }
210 }
211}