use console::style;
use hyper::StatusCode;
use serde::Deserialize;
pub mod respond;
mod util;
pub mod when;
use super::RuleSet;
use respond::Respond;
use util::url_path_with_prefix;
use when::{
request::url_path::{UrlPath, UrlPathConfig},
When,
};
type ConditionKey = String;
#[derive(Clone, Deserialize, Debug)]
pub struct Rule {
pub when: When,
pub respond: Respond,
}
impl Rule {
pub fn compute_derived_fields(
&self,
rule_set: &RuleSet,
rule_idx: usize,
rule_set_idx: usize,
) -> Self {
let mut ret = self.to_owned();
let url_path = match ret.when.request.url_path_config.as_ref() {
Some(url_path_config) => match url_path_config {
UrlPathConfig::Simple(s) => Some(UrlPath {
value: s.clone(),
value_with_prefix: url_path_with_prefix(s.as_str(), rule_set.prefix.as_ref()),
op: None,
}),
UrlPathConfig::Detailed(url_path) => Some(UrlPath {
value: url_path.value.clone(),
value_with_prefix: url_path_with_prefix(
url_path.value.as_str(),
rule_set.prefix.as_ref(),
),
op: url_path.op.clone(),
}),
},
None => None,
};
ret.when.request.url_path = url_path;
if let Some(status) = ret.respond.status {
match StatusCode::from_u16(status) {
Ok(status_code) => ret.respond.status_code = Some(status_code),
Err(err) => {
log::error!(
"{} status code {} (rule #{} in rule set #{}): {}",
style("invalid").red(),
status,
rule_idx + 1,
rule_set_idx + 1,
err,
);
ret.respond.status_code = None;
}
}
}
ret
}
pub fn validate(&self, dir_prefix: &str, rule_idx: usize, rule_set_idx: usize) -> bool {
self.when.validate(rule_idx, rule_set_idx)
&& self.respond.validate(dir_prefix, rule_idx, rule_set_idx)
}
}
impl std::fmt::Display for Rule {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let _ = write!(f, "- ");
let _ = write!(f, "{} {}", style("[when]").yellow(), self.when);
let _ = write!(f, "{} {}", style("[respond]").yellow(), self.respond);
Ok(())
}
}