diff --git a/src/main.rs b/src/main.rs index 54aad9a..921e25e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,12 +2,11 @@ mod model; mod errors; mod ext; -use std::sync::Arc; use clap::{Parser, Subcommand}; -use model::PostWomanConfig; - +pub use model::PostWomanCollection; pub use errors::PostWomanError; + pub static APP_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")); /// API tester and debugger from your CLI @@ -63,14 +62,6 @@ pub enum PostWomanActions { const TIMESTAMP_FMT: &str = "%H:%M:%S%.6f"; -fn print_results(res: String, name: String, before: chrono::DateTime, suffix: String) { - let after = chrono::Local::now(); - let elapsed = (after - before).num_milliseconds(); - let timestamp = after.format(TIMESTAMP_FMT); - eprintln!(" + [{timestamp}] {name} {suffix}done in {elapsed}ms", ); - print!("{}", res); -} - #[tokio::main] async fn main() -> Result<(), PostWomanError> { let args = PostWomanArgs::parse(); @@ -96,11 +87,11 @@ async fn main() -> Result<(), PostWomanError> { PostWomanActions::Run { query, parallel, repeat, debug } => { let pattern = regex::Regex::new(&query)?; let mut joinset = tokio::task::JoinSet::new(); - let client = Arc::new(config.client); - let env = Arc::new(config.env); - for (name, mut endpoint) in config.route { + let client = std::sync::Arc::new(collection.client); + let env = std::sync::Arc::new(collection.env); + for (name, mut endpoint) in collection.route { if pattern.find(&name).is_some() { - if debug { endpoint.extract = Some(ext::StringOr::T(model::Extractor::Debug)) }; + if debug { endpoint.extract = Some(ext::StringOr::T(model::ExtractorConfig::Debug)) }; for i in 0..repeat { let suffix = if repeat > 1 { format!("#{} ", i+1) @@ -136,11 +127,15 @@ async fn main() -> Result<(), PostWomanError> { } } }, - - // PostWomanActions::Save { name, url, method, headers, body } => { - // todo!(); - // }, } Ok(()) } + +fn print_results(res: String, name: String, before: chrono::DateTime, suffix: String) { + let after = chrono::Local::now(); + let elapsed = (after - before).num_milliseconds(); + let timestamp = after.format(TIMESTAMP_FMT); + eprintln!(" + [{timestamp}] {name} {suffix}done in {elapsed}ms", ); + print!("{}", res); +} diff --git a/src/model/client.rs b/src/model/client.rs index 76504f2..f6e8f0f 100644 --- a/src/model/client.rs +++ b/src/model/client.rs @@ -1,4 +1,6 @@ + #[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)] -pub struct PostWomanClient { +pub struct ClientConfig { + /// user agent for requests, defaults to 'postwoman/' pub user_agent: Option, } diff --git a/src/model/endpoint.rs b/src/model/endpoint.rs index af08953..50d3a4d 100644 --- a/src/model/endpoint.rs +++ b/src/model/endpoint.rs @@ -7,11 +7,11 @@ use jaq_interpret::FilterT; use crate::{PostWomanError, APP_USER_AGENT}; use crate::ext::{stringify_toml, stringify_json, StringOr}; -use super::{Extractor, PostWomanClient}; +use super::{ExtractorConfig, ClientConfig}; #[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)] -pub struct Endpoint { +pub struct EndpointConfig { /// endpoint url, required pub url: String, /// http method for request, default GET @@ -25,10 +25,10 @@ pub struct Endpoint { /// expected error code, will fail if different pub expect: Option, /// response extractor - pub extract: Option>, + pub extract: Option>, } -impl Endpoint { +impl EndpointConfig { pub fn fill(mut self, env: &toml::Table) -> Self { let mut vars: HashMap = HashMap::default(); @@ -80,7 +80,7 @@ impl Endpoint { self } - pub async fn execute(self, opts: &PostWomanClient) -> Result { + pub async fn execute(self, opts: &ClientConfig) -> Result { let method = match self.method { Some(m) => reqwest::Method::from_str(&m)?, None => reqwest::Method::GET, @@ -120,22 +120,22 @@ impl Endpoint { } Ok(match self.extract.unwrap_or_default() { - StringOr::T(Extractor::Discard) => "".to_string(), - StringOr::T(Extractor::Body) => format_body(res).await?, - StringOr::T(Extractor::Debug) => { + StringOr::T(ExtractorConfig::Discard) => "".to_string(), + StringOr::T(ExtractorConfig::Body) => format_body(res).await?, + StringOr::T(ExtractorConfig::Debug) => { // TODO needless double format let res_dbg = format!("{res:#?}"); let body = format_body(res).await?; format!("{res_dbg}\nBody: {body}\n") }, - StringOr::T(Extractor::Header { key }) => res + StringOr::T(ExtractorConfig::Header { key }) => res .headers() .get(&key) .ok_or(PostWomanError::HeaderNotFound(key))? .to_str()? .to_string() + "\n", - StringOr::T(Extractor::Regex { pattern }) => { + StringOr::T(ExtractorConfig::Regex { pattern }) => { let pattern = regex::Regex::new(&pattern)?; let body = format_body(res).await?; pattern.find(&body) @@ -145,7 +145,7 @@ impl Endpoint { + "\n" }, // bare string defaults to JQL query - StringOr::T(Extractor::JQ { query }) | StringOr::Str(query) => { + StringOr::T(ExtractorConfig::JQ { query }) | StringOr::Str(query) => { let json: serde_json::Value = res.json().await?; let selection = jq(&query, json)?; if selection.len() == 1 { diff --git a/src/model/extractor.rs b/src/model/extractor.rs index a2f20b4..ca6097b 100644 --- a/src/model/extractor.rs +++ b/src/model/extractor.rs @@ -1,7 +1,7 @@ #[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)] #[serde(tag = "type", rename_all = "lowercase")] -pub enum Extractor { +pub enum ExtractorConfig { #[default] Body, Debug, diff --git a/src/model/mod.rs b/src/model/mod.rs index 6ede9ec..c326668 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -2,14 +2,14 @@ mod client; mod endpoint; mod extractor; -pub use client::PostWomanClient; -pub use endpoint::Endpoint; -pub use extractor::Extractor; +pub use client::ClientConfig; +pub use endpoint::EndpointConfig; +pub use extractor::ExtractorConfig; #[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)] -pub struct PostWomanConfig { - pub client: PostWomanClient, +pub struct PostWomanCollection { + pub client: ClientConfig, pub env: toml::Table, // it's weird to name it singular but makes more sense in config - pub route: indexmap::IndexMap, + pub route: indexmap::IndexMap, }