use apimock_routing::{
Respond, RuleSet,
rule_set::rule::{
Rule,
when::{
When,
request::{Request, http_method::HttpMethod, url_path::UrlPathConfig},
},
},
};
use toml::{Value, value::Table};
use crate::{Config, ListenerConfig, ServiceConfig, config::log_config::LogConfig};
pub fn render_apimock_toml(config: &Config) -> String {
let mut root = Table::new();
if let Some(listener) = config.listener.as_ref() {
root.insert("listener".to_owned(), Value::Table(listener_table(listener)));
}
if let Some(log) = config.log.as_ref() {
if let Some(t) = log_table(log) {
root.insert("log".to_owned(), Value::Table(t));
}
}
root.insert("service".to_owned(), Value::Table(service_table(&config.service)));
toml::to_string_pretty(&Value::Table(root))
.unwrap_or_else(|err| format!("# failed to render apimock.toml: {}\n", err))
}
pub fn render_rule_set_toml(rule_set: &RuleSet) -> String {
let mut root = Table::new();
if let Some(prefix) = rule_set.prefix.as_ref() {
let mut p = Table::new();
if let Some(url) = prefix.url_path_prefix.as_ref() {
p.insert("url_path".to_owned(), Value::String(url.clone()));
}
if let Some(dir) = prefix.respond_dir_prefix.as_ref() {
p.insert("respond_dir".to_owned(), Value::String(dir.clone()));
}
if !p.is_empty() {
root.insert("prefix".to_owned(), Value::Table(p));
}
}
if !rule_set.rules.is_empty() {
let rules: Vec<Value> = rule_set
.rules
.iter()
.map(|r| Value::Table(rule_table(r)))
.collect();
root.insert("rules".to_owned(), Value::Array(rules));
}
toml::to_string_pretty(&Value::Table(root))
.unwrap_or_else(|err| format!("# failed to render rule set: {}\n", err))
}
fn listener_table(l: &ListenerConfig) -> Table {
let mut t = Table::new();
t.insert("ip_address".to_owned(), Value::String(l.ip_address.clone()));
t.insert(
"port".to_owned(),
Value::Integer(i64::from(l.port)),
);
if let Some(tls) = l.tls.as_ref() {
let mut tt = Table::new();
tt.insert("cert".to_owned(), Value::String(tls.cert.clone()));
tt.insert("key".to_owned(), Value::String(tls.key.clone()));
if let Some(p) = tls.port {
tt.insert("port".to_owned(), Value::Integer(i64::from(p)));
}
t.insert("tls".to_owned(), Value::Table(tt));
}
t
}
fn log_table(l: &LogConfig) -> Option<Table> {
let mut t = Table::new();
let v = &l.verbose;
let mut verbose = Table::new();
verbose.insert("header".to_owned(), Value::Boolean(v.header));
verbose.insert("body".to_owned(), Value::Boolean(v.body));
t.insert("verbose".to_owned(), Value::Table(verbose));
Some(t)
}
fn service_table(s: &ServiceConfig) -> Table {
let mut t = Table::new();
if let Some(strategy) = s.strategy.as_ref() {
t.insert(
"strategy".to_owned(),
Value::String(format!("{}", strategy)),
);
}
if let Some(paths) = s.rule_sets_file_paths.as_ref() {
let arr: Vec<Value> = paths.iter().map(|p| Value::String(p.clone())).collect();
t.insert("rule_sets".to_owned(), Value::Array(arr));
}
if let Some(paths) = s.middlewares_file_paths.as_ref() {
let arr: Vec<Value> = paths.iter().map(|p| Value::String(p.clone())).collect();
t.insert("middlewares".to_owned(), Value::Array(arr));
}
t.insert(
"fallback_respond_dir".to_owned(),
Value::String(s.fallback_respond_dir.clone()),
);
t
}
fn rule_table(r: &Rule) -> Table {
let mut t = Table::new();
t.insert("when".to_owned(), Value::Table(when_table(&r.when)));
t.insert("respond".to_owned(), Value::Table(respond_table(&r.respond)));
t
}
fn when_table(w: &When) -> Table {
let mut t = Table::new();
t.insert("request".to_owned(), Value::Table(request_table(&w.request)));
t
}
fn request_table(req: &Request) -> Table {
let mut t = Table::new();
if let Some(url_path_config) = req.url_path_config.as_ref() {
match url_path_config {
UrlPathConfig::Simple(s) => {
t.insert("url_path".to_owned(), Value::String(s.clone()));
}
UrlPathConfig::Detailed(detail) => {
let mut dt = Table::new();
dt.insert("value".to_owned(), Value::String(detail.value.clone()));
if let Some(op) = detail.op.as_ref() {
dt.insert("op".to_owned(), Value::String(format!("{}", op)));
}
t.insert("url_path".to_owned(), Value::Table(dt));
}
}
}
if let Some(method) = req.http_method.as_ref() {
t.insert("method".to_owned(), Value::String(http_method_name(method)));
}
t
}
fn http_method_name(m: &HttpMethod) -> String {
m.as_str().to_owned()
}
fn respond_table(r: &Respond) -> Table {
let mut t = Table::new();
if let Some(p) = r.file_path.as_ref() {
t.insert("file_path".to_owned(), Value::String(p.clone()));
}
if let Some(k) = r.csv_records_key.as_ref() {
t.insert("csv_records_key".to_owned(), Value::String(k.clone()));
}
if let Some(text) = r.text.as_ref() {
t.insert("text".to_owned(), Value::String(text.clone()));
}
if let Some(s) = r.status.as_ref() {
t.insert("status".to_owned(), Value::Integer(i64::from(*s)));
}
if let Some(headers) = r.headers.as_ref() {
let mut ht = Table::new();
for (k, v) in headers.iter() {
match v {
Some(val) => ht.insert(k.clone(), Value::String(val.clone())),
None => ht.insert(k.clone(), Value::Boolean(false)),
};
}
t.insert("headers".to_owned(), Value::Table(ht));
}
if let Some(d) = r.delay_response_milliseconds.as_ref() {
t.insert(
"delay_response_milliseconds".to_owned(),
Value::Integer(i64::from(*d)),
);
}
t
}