1use pingap_config::PluginConf;
16use pingap_core::PluginStep;
17use snafu::Snafu;
18use std::str::FromStr;
19
20#[derive(Debug, Snafu)]
21pub enum Error {
22 #[snafu(display("Plugin {category} invalid, message: {message}"))]
23 Invalid { category: String, message: String },
24 #[snafu(display("Plugin {category} not found"))]
25 NotFound { category: String },
26 #[snafu(display("Plugin {category}, base64 decode error {source}"))]
27 Base64Decode {
28 category: String,
29 source: base64::DecodeError,
30 },
31 #[snafu(display("Plugin {category}, exceed limit {value}/{max}"))]
32 Exceed {
33 category: String,
34 max: isize,
35 value: isize,
36 },
37 #[snafu(display("Plugin {category}, regex error {source}"))]
38 Regex {
39 category: String,
40 source: Box<fancy_regex::Error>,
41 },
42 #[snafu(display("Plugin {category}, base64 decode error {source}"))]
43 ParseDuration {
44 category: String,
45 source: humantime::DurationError,
46 },
47}
48
49pub fn get_str_conf(value: &PluginConf, key: &str) -> String {
51 if let Some(value) = value.get(key) {
52 value.as_str().unwrap_or_default().to_string()
53 } else {
54 "".to_string()
55 }
56}
57
58pub(crate) fn get_str_slice_conf(value: &PluginConf, key: &str) -> Vec<String> {
59 if let Some(value) = value.get(key) {
60 if let Some(values) = value.as_array() {
61 return values
62 .iter()
63 .map(|item| item.as_str().unwrap_or_default().to_string())
64 .collect();
65 }
66 }
67 vec![]
68}
69
70pub(crate) fn get_bool_conf(value: &PluginConf, key: &str) -> bool {
71 if let Some(value) = value.get(key) {
72 value.as_bool().unwrap_or_default()
73 } else {
74 false
75 }
76}
77
78pub fn get_int_conf(value: &PluginConf, key: &str) -> i64 {
79 if let Some(value) = value.get(key) {
80 value.as_integer().unwrap_or_default()
81 } else {
82 0
83 }
84}
85
86pub(crate) fn get_step_conf(
87 value: &PluginConf,
88 default_value: PluginStep,
89) -> PluginStep {
90 let step = get_str_conf(value, "step");
91 if step.is_empty() {
92 return default_value;
93 }
94
95 PluginStep::from_str(step.as_str()).unwrap_or(default_value)
96}
97
98pub fn get_hash_key(conf: &PluginConf) -> String {
106 let mut keys: Vec<String> =
107 conf.keys().map(|item| item.to_string()).collect();
108 keys.sort();
109 let mut lines = vec![];
110 for key in keys {
111 let value = if let Some(value) = conf.get(&key) {
112 value.to_string()
113 } else {
114 "".to_string()
115 };
116 lines.push(format!("{key}:{value}"));
117 }
118 let hash = crc32fast::hash(lines.join("\n").as_bytes());
119 format!("{hash:X}")
120}
121
122mod accept_encoding;
123mod basic_auth;
124mod cache;
125mod combined_auth;
126mod compression;
127mod cors;
128mod csrf;
129mod directory;
130mod ip_restriction;
131mod jwt;
132mod key_auth;
133mod limit;
134mod mock;
135mod ping;
136mod redirect;
137mod referer_restriction;
138mod request_id;
139mod response_headers;
140mod sub_filter;
141mod ua_restriction;
142
143mod plugin;
144
145pub use plugin::get_plugin_factory;