Skip to main content

apimock_routing/rule_set/rule/when/
request.rs

1use console::style;
2use http_method::HttpMethod;
3use serde::Deserialize;
4
5mod body;
6mod headers;
7pub mod http_method;
8pub mod rule_op;
9pub mod url_path;
10mod util;
11
12use crate::parsed_request::ParsedRequest;
13use body::Body;
14use headers::Headers;
15use url_path::{UrlPath, UrlPathConfig};
16use util::fmt_condition_connector;
17
18#[derive(Clone, Deserialize, Debug)]
19pub struct Request {
20    #[serde(rename = "url_path")]
21    pub url_path_config: Option<UrlPathConfig>,
22    #[serde(skip)]
23    pub url_path: Option<UrlPath>,
24    #[serde(rename = "method")]
25    pub http_method: Option<HttpMethod>,
26    pub headers: Option<Headers>,
27    pub body: Option<Body>,
28}
29
30impl Request {
31    /// match with condition
32    pub fn is_match(
33        &self,
34        parsed_request: &ParsedRequest,
35        rule_idx: usize,
36        rule_set_idx: usize,
37    ) -> bool {
38        let url_path_is_match = self.url_path.is_none()
39            || self
40                .url_path
41                .as_ref()
42                .unwrap()
43                .is_match(parsed_request.url_path.as_str());
44
45        let http_method_is_match = self.http_method.is_none()
46            || self
47                .http_method
48                .as_ref()
49                .unwrap()
50                .is_match(&parsed_request.component_parts.method);
51
52        let headers_is_match = self.headers.is_none()
53            || self.headers.as_ref().unwrap().is_match(
54                &parsed_request.component_parts.headers,
55                rule_idx,
56                rule_set_idx,
57            );
58
59        let body_is_match =
60            self.body.is_none() || self.body.as_ref().unwrap().is_match(&parsed_request);
61
62        url_path_is_match && http_method_is_match && headers_is_match && body_is_match
63    }
64
65    /// validate
66    pub fn validate(&self, rule_idx: usize, rule_set_idx: usize) -> bool {
67        if self.url_path.is_none()
68            && self.http_method.is_none()
69            && self.headers.is_none()
70            && self.body.is_none()
71        {
72            log::error!(
73                "{} in when.request at least either of: url_path, method, headers or body (rule #{} in rule set #{})",
74                style("required").red(),
75                rule_idx + 1,
76                rule_set_idx + 1
77            );
78            return false;
79        }
80
81        let url_path_validate = match self.url_path.as_ref() {
82            Some(url_path) => url_path.validate(),
83            None => true,
84        };
85
86        let http_method_validate = true;
87
88        let headers_validate = match self.headers.as_ref() {
89            Some(headers) => {
90                let ret = headers.validate();
91                if !ret {
92                    log::error!(
93                        "something wrong in headers (rule #{} in rule set #{})",
94                        rule_idx + 1,
95                        rule_set_idx + 1
96                    )
97                }
98                ret
99            }
100            None => true,
101        };
102
103        let body_validate = match self.body.as_ref() {
104            Some(body) => {
105                let ret = body.validate();
106                if !ret {
107                    log::error!(
108                        "something wrong in body (rule #{} in rule set #{})",
109                        rule_idx + 1,
110                        rule_set_idx + 1
111                    )
112                }
113                ret
114            }
115            None => true,
116        };
117
118        url_path_validate && http_method_validate && headers_validate && body_validate
119    }
120}
121
122impl std::fmt::Display for Request {
123    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124        let mut s: Vec<String> = vec![];
125
126        if let Some(x) = self.url_path_config.as_ref() {
127            s.push(format!("{}", x));
128        }
129        if let Some(x) = self.http_method.as_ref() {
130            s.push(format!("{}", x));
131        }
132        if let Some(x) = self.headers.as_ref() {
133            s.push(format!("{}", x));
134        }
135        if let Some(x) = self.body.as_ref() {
136            s.push(format!("{}", x));
137        }
138
139        let _ = write!(f, "{} ", s.join(fmt_condition_connector().as_str()));
140        Ok(())
141    }
142}