2023-06-15 16:19:46 +02:00
|
|
|
use std::str::FromStr;
|
|
|
|
|
|
|
|
use postman_collection::{v1_0_0, v2_0_0, v2_1_0};
|
2023-06-15 15:42:07 +02:00
|
|
|
|
2023-06-15 16:42:05 +02:00
|
|
|
fn fill_from_env(mut txt: String) -> String {
|
|
|
|
for (k, v) in std::env::vars() {
|
|
|
|
let key = format!("{{{{{}}}}}", k);
|
|
|
|
if txt.contains(&key) {
|
|
|
|
txt = txt.replace(&key, &v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
txt
|
|
|
|
}
|
|
|
|
|
2023-06-15 15:42:07 +02:00
|
|
|
pub trait IntoRequest {
|
2023-06-21 00:23:12 +02:00
|
|
|
fn make_request(&self) -> reqwest::RequestBuilder;
|
2023-06-15 15:42:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl IntoRequest for v2_0_0::RequestClass {
|
2023-06-21 00:23:12 +02:00
|
|
|
fn make_request(&self) -> reqwest::RequestBuilder {
|
2023-06-21 00:32:44 +02:00
|
|
|
let method = reqwest::Method::from_bytes(
|
|
|
|
self.method.as_ref().unwrap_or(&"GET".into()).as_bytes() // TODO lol?
|
|
|
|
).unwrap_or(reqwest::Method::GET); // TODO throw an error rather than replacing it silently
|
|
|
|
|
|
|
|
let mut url_str = match &self.url {
|
|
|
|
Some(v2_0_0::Url::String(x)) => x.clone(),
|
|
|
|
Some(v2_0_0::Url::UrlClass(v2_0_0::UrlClass { raw: Some(x), .. })) => x.clone(),
|
|
|
|
// TODO compose URL from UrlClass rather than only accepting those with raw set
|
|
|
|
_ => "http://localhost".into(),
|
|
|
|
};
|
|
|
|
|
|
|
|
url_str = fill_from_env(url_str);
|
|
|
|
|
|
|
|
let url = reqwest::Url::from_str(&url_str).unwrap_or_else(|e| {
|
|
|
|
eprintln!("error creating url ({}), falling back to localhost", e);
|
|
|
|
reqwest::Url::from_str("http://localhost/").unwrap()
|
|
|
|
});
|
|
|
|
|
|
|
|
let mut out = reqwest::Client::new().request(method, url);
|
|
|
|
|
|
|
|
// TODO handle more auth types than just bearer
|
|
|
|
if let Some(auth) = &self.auth {
|
|
|
|
if let Some(bearers) = &auth.bearer {
|
|
|
|
for v in bearers.values() {
|
|
|
|
if let Some(value) = &v {
|
|
|
|
out = out.header("Authorization", format!("Bearer {}", value.as_str().unwrap_or(&value.to_string())))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
match &self.header {
|
|
|
|
Some(v2_0_0::HeaderUnion::HeaderArray(x)) => {
|
|
|
|
for h in x {
|
|
|
|
let k = fill_from_env(h.key.clone());
|
|
|
|
let v = fill_from_env(h.value.clone());
|
|
|
|
out = out.header(k, v); // TODO avoid cloning
|
|
|
|
}
|
|
|
|
},
|
|
|
|
_ => {},
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
match &self.body {
|
|
|
|
Some(v2_0_0::Body { raw: Some(x), .. }) => {
|
|
|
|
out = out.body(fill_from_env(x.clone())) // TODO try to avoid cloning?
|
|
|
|
},
|
|
|
|
_ => {},
|
|
|
|
}
|
|
|
|
|
|
|
|
out
|
2023-06-15 15:42:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IntoRequest for v2_1_0::RequestClass {
|
2023-06-21 00:23:12 +02:00
|
|
|
fn make_request(&self) -> reqwest::RequestBuilder {
|
2023-06-15 16:19:46 +02:00
|
|
|
let method = reqwest::Method::from_bytes(
|
2023-06-21 00:32:44 +02:00
|
|
|
self.method.as_ref().unwrap_or(&"GET".into()).as_bytes() // TODO lol?
|
2023-06-15 16:19:46 +02:00
|
|
|
).unwrap_or(reqwest::Method::GET); // TODO throw an error rather than replacing it silently
|
|
|
|
|
2023-06-15 16:23:48 +02:00
|
|
|
let mut url_str = match &self.url {
|
|
|
|
Some(v2_1_0::Url::String(x)) => x.clone(),
|
|
|
|
Some(v2_1_0::Url::UrlClass(v2_1_0::UrlClass { raw: Some(x), .. })) => x.clone(),
|
2023-06-15 16:19:46 +02:00
|
|
|
// TODO compose URL from UrlClass rather than only accepting those with raw set
|
2023-06-15 16:23:48 +02:00
|
|
|
_ => "http://localhost".into(),
|
2023-06-15 16:19:46 +02:00
|
|
|
};
|
|
|
|
|
2023-06-15 16:42:05 +02:00
|
|
|
url_str = fill_from_env(url_str);
|
2023-06-15 16:23:48 +02:00
|
|
|
|
2023-06-20 14:04:27 +02:00
|
|
|
let url = reqwest::Url::from_str(&url_str).unwrap_or_else(|e| {
|
|
|
|
eprintln!("error creating url ({}), falling back to localhost", e);
|
|
|
|
reqwest::Url::from_str("http://localhost/").unwrap()
|
|
|
|
});
|
2023-06-15 16:19:46 +02:00
|
|
|
|
|
|
|
let mut out = reqwest::Client::new().request(method, url);
|
|
|
|
|
2023-06-20 14:04:27 +02:00
|
|
|
// TODO handle more auth types than just bearer
|
|
|
|
if let Some(auth) = &self.auth {
|
|
|
|
if let Some(bearers) = &auth.bearer {
|
|
|
|
for bearer in bearers {
|
|
|
|
if let Some(value) = &bearer.value {
|
|
|
|
out = out.header("Authorization", format!("Bearer {}", value.as_str().unwrap_or(&value.to_string())))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-15 16:19:46 +02:00
|
|
|
match &self.header {
|
|
|
|
Some(v2_1_0::HeaderUnion::HeaderArray(x)) => {
|
|
|
|
for h in x {
|
2023-06-15 16:42:05 +02:00
|
|
|
let k = fill_from_env(h.key.clone());
|
|
|
|
let v = fill_from_env(h.value.clone());
|
|
|
|
out = out.header(k, v); // TODO avoid cloning
|
2023-06-15 16:19:46 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
_ => {},
|
|
|
|
}
|
|
|
|
|
2023-06-20 14:04:27 +02:00
|
|
|
|
2023-06-15 16:19:46 +02:00
|
|
|
match &self.body {
|
|
|
|
Some(v2_1_0::Body { raw: Some(x), .. }) => {
|
2023-06-20 14:04:27 +02:00
|
|
|
out = out.body(fill_from_env(x.clone())) // TODO try to avoid cloning?
|
2023-06-15 16:19:46 +02:00
|
|
|
},
|
|
|
|
_ => {},
|
|
|
|
}
|
|
|
|
|
2023-06-21 00:23:12 +02:00
|
|
|
out
|
2023-06-15 15:42:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-15 15:59:03 +02:00
|
|
|
impl IntoRequest for v1_0_0::Request {
|
2023-06-21 00:23:12 +02:00
|
|
|
fn make_request(&self) -> reqwest::RequestBuilder {
|
2023-06-15 15:42:07 +02:00
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
}
|