use console::style;
use http_method::HttpMethod;
use serde::Deserialize;
mod body;
mod headers;
pub mod http_method;
pub mod rule_op;
pub mod url_path;
mod util;
use crate::parsed_request::ParsedRequest;
use body::Body;
use headers::Headers;
use url_path::{UrlPath, UrlPathConfig};
use util::fmt_condition_connector;
#[derive(Clone, Deserialize, Debug)]
pub struct Request {
#[serde(rename = "url_path")]
pub url_path_config: Option<UrlPathConfig>,
#[serde(skip)]
pub url_path: Option<UrlPath>,
#[serde(rename = "method")]
pub http_method: Option<HttpMethod>,
pub headers: Option<Headers>,
pub body: Option<Body>,
}
impl Request {
pub fn is_match(
&self,
parsed_request: &ParsedRequest,
rule_idx: usize,
rule_set_idx: usize,
) -> bool {
let url_path_is_match = self.url_path.is_none()
|| self
.url_path
.as_ref()
.unwrap()
.is_match(parsed_request.url_path.as_str());
let http_method_is_match = self.http_method.is_none()
|| self
.http_method
.as_ref()
.unwrap()
.is_match(&parsed_request.component_parts.method);
let headers_is_match = self.headers.is_none()
|| self.headers.as_ref().unwrap().is_match(
&parsed_request.component_parts.headers,
rule_idx,
rule_set_idx,
);
let body_is_match =
self.body.is_none() || self.body.as_ref().unwrap().is_match(&parsed_request);
url_path_is_match && http_method_is_match && headers_is_match && body_is_match
}
pub fn validate(&self, rule_idx: usize, rule_set_idx: usize) -> bool {
if self.url_path.is_none()
&& self.http_method.is_none()
&& self.headers.is_none()
&& self.body.is_none()
{
log::error!(
"{} in when.request at least either of: url_path, method, headers or body (rule #{} in rule set #{})",
style("required").red(),
rule_idx + 1,
rule_set_idx + 1
);
return false;
}
let url_path_validate = match self.url_path.as_ref() {
Some(url_path) => url_path.validate(),
None => true,
};
let http_method_validate = true;
let headers_validate = match self.headers.as_ref() {
Some(headers) => {
let ret = headers.validate();
if !ret {
log::error!(
"something wrong in headers (rule #{} in rule set #{})",
rule_idx + 1,
rule_set_idx + 1
)
}
ret
}
None => true,
};
let body_validate = match self.body.as_ref() {
Some(body) => {
let ret = body.validate();
if !ret {
log::error!(
"something wrong in body (rule #{} in rule set #{})",
rule_idx + 1,
rule_set_idx + 1
)
}
ret
}
None => true,
};
url_path_validate && http_method_validate && headers_validate && body_validate
}
}
impl std::fmt::Display for Request {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut s: Vec<String> = vec![];
if let Some(x) = self.url_path_config.as_ref() {
s.push(format!("{}", x));
}
if let Some(x) = self.http_method.as_ref() {
s.push(format!("{}", x));
}
if let Some(x) = self.headers.as_ref() {
s.push(format!("{}", x));
}
if let Some(x) = self.body.as_ref() {
s.push(format!("{}", x));
}
let _ = write!(f, "{} ", s.join(fmt_condition_connector().as_str()));
Ok(())
}
}