feat: client is fillable too, generalized trait
This commit is contained in:
parent
8544d0d720
commit
afc554f497
4 changed files with 87 additions and 53 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -815,7 +815,7 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
|||
|
||||
[[package]]
|
||||
name = "postwoman"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"chrono",
|
||||
|
|
20
src/ext.rs
20
src/ext.rs
|
@ -38,3 +38,23 @@ pub fn stringify_json(v: &serde_json::Value) -> String {
|
|||
pub fn full_name(namespace: &str, name: &str) -> String {
|
||||
format!("{namespace}:{name}")
|
||||
}
|
||||
|
||||
pub trait FillableFromEnvironment {
|
||||
fn fill(self, env: &toml::Table) -> Self;
|
||||
|
||||
fn default_vars(env: &toml::Table) -> std::collections::HashMap<String, String> {
|
||||
let mut vars: std::collections::HashMap<String, String> = std::collections::HashMap::default();
|
||||
|
||||
vars.insert("POSTWOMAN_TIMESTAMP".to_string(), chrono::Local::now().timestamp().to_string());
|
||||
|
||||
for (k, v) in env {
|
||||
vars.insert(k.to_string(), stringify_toml(v));
|
||||
}
|
||||
|
||||
for (k, v) in std::env::vars() {
|
||||
vars.insert(k, v);
|
||||
}
|
||||
|
||||
vars
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use crate::ext::FillableFromEnvironment;
|
||||
|
||||
|
||||
#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub struct ClientConfig {
|
||||
|
@ -12,3 +14,23 @@ pub struct ClientConfig {
|
|||
/// accept invalid SSL certificates, defaults to false (be careful: this is dangerous!)
|
||||
pub accept_invalid_certs: Option<bool>,
|
||||
}
|
||||
|
||||
impl FillableFromEnvironment for ClientConfig {
|
||||
fn fill(mut self, env: &toml::Table) -> Self {
|
||||
let vars = Self::default_vars(env);
|
||||
|
||||
for (k, v) in vars {
|
||||
let k_var = format!("${{{k}}}");
|
||||
|
||||
if let Some(base) = self.base {
|
||||
self.base = Some(base.replace(&k_var, &v));
|
||||
}
|
||||
|
||||
if let Some(user_agent) = self.user_agent {
|
||||
self.user_agent = Some(user_agent.replace(&k_var, &v));
|
||||
}
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use jaq_interpret::FilterT;
|
|||
use crate::errors::InvalidHeaderError;
|
||||
use crate::{PostWomanError, APP_USER_AGENT};
|
||||
|
||||
use crate::ext::{stringify_toml, stringify_json, StringOr};
|
||||
use crate::ext::{stringify_json, stringify_toml, FillableFromEnvironment, StringOr};
|
||||
use super::{ExtractorConfig, ClientConfig};
|
||||
|
||||
|
||||
|
@ -75,57 +75,6 @@ impl EndpointConfig {
|
|||
url
|
||||
}
|
||||
|
||||
pub fn fill(mut self, env: &toml::Table) -> Self {
|
||||
let mut vars: HashMap<String, String> = HashMap::default();
|
||||
|
||||
vars.insert("POSTWOMAN_TIMESTAMP".to_string(), chrono::Local::now().timestamp().to_string());
|
||||
|
||||
for (k, v) in env {
|
||||
vars.insert(k.to_string(), stringify_toml(v));
|
||||
}
|
||||
|
||||
for (k, v) in std::env::vars() {
|
||||
vars.insert(k, v);
|
||||
}
|
||||
|
||||
for (k, v) in vars {
|
||||
let k_var = format!("${{{k}}}");
|
||||
self.path = self.path.replace(&k_var, &v);
|
||||
if let Some(method) = self.method {
|
||||
self.method = Some(method.replace(&k_var, &v));
|
||||
}
|
||||
if let Some(b) = self.body {
|
||||
match b {
|
||||
StringOr::Str(body) => {
|
||||
self.body = Some(StringOr::Str(body.replace(&k_var, &v)));
|
||||
},
|
||||
StringOr::T(json) => {
|
||||
let wrap = toml::Value::Table(json.clone());
|
||||
let toml::Value::Table(out) = replace_recursive(wrap, &k_var, &v)
|
||||
else { unreachable!("we put in a table, we get out a table") };
|
||||
self.body = Some(StringOr::T(out));
|
||||
},
|
||||
}
|
||||
}
|
||||
if let Some(query) = self.query {
|
||||
self.query = Some(
|
||||
query.into_iter()
|
||||
.map(|x| x.replace(&k_var, &v))
|
||||
.collect()
|
||||
);
|
||||
}
|
||||
if let Some(headers) = self.headers {
|
||||
self.headers = Some(
|
||||
headers.into_iter()
|
||||
.map(|x| x.replace(&k_var, &v))
|
||||
.collect()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn execute(self, opts: &ClientConfig) -> Result<String, PostWomanError> {
|
||||
let body = self.body()?;
|
||||
let method = self.method()?;
|
||||
|
@ -196,6 +145,49 @@ impl EndpointConfig {
|
|||
}
|
||||
}
|
||||
|
||||
impl FillableFromEnvironment for EndpointConfig {
|
||||
fn fill(mut self, env: &toml::Table) -> Self {
|
||||
let vars = Self::default_vars(env);
|
||||
|
||||
for (k, v) in vars {
|
||||
let k_var = format!("${{{k}}}");
|
||||
self.path = self.path.replace(&k_var, &v);
|
||||
if let Some(method) = self.method {
|
||||
self.method = Some(method.replace(&k_var, &v));
|
||||
}
|
||||
if let Some(b) = self.body {
|
||||
match b {
|
||||
StringOr::Str(body) => {
|
||||
self.body = Some(StringOr::Str(body.replace(&k_var, &v)));
|
||||
},
|
||||
StringOr::T(json) => {
|
||||
let wrap = toml::Value::Table(json.clone());
|
||||
let toml::Value::Table(out) = replace_recursive(wrap, &k_var, &v)
|
||||
else { unreachable!("we put in a table, we get out a table") };
|
||||
self.body = Some(StringOr::T(out));
|
||||
},
|
||||
}
|
||||
}
|
||||
if let Some(query) = self.query {
|
||||
self.query = Some(
|
||||
query.into_iter()
|
||||
.map(|x| x.replace(&k_var, &v))
|
||||
.collect()
|
||||
);
|
||||
}
|
||||
if let Some(headers) = self.headers {
|
||||
self.headers = Some(
|
||||
headers.into_iter()
|
||||
.map(|x| x.replace(&k_var, &v))
|
||||
.collect()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
fn replace_recursive(element: toml::Value, from: &str, to: &str) -> toml::Value {
|
||||
match element {
|
||||
toml::Value::Float(x) => toml::Value::Float(x),
|
||||
|
|
Loading…
Reference in a new issue