|
@@ -16,14 +16,16 @@
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
*/
|
|
|
|
|
|
+use crate::data_server::*;
|
|
|
use crate::db::*;
|
|
|
use crate::smartdns::LogLevel;
|
|
|
use serde_json::json;
|
|
|
+use std::collections::HashMap;
|
|
|
use std::error::Error;
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
pub struct AuthUser {
|
|
|
- pub user: String,
|
|
|
+ pub username: String,
|
|
|
pub password: String,
|
|
|
}
|
|
|
|
|
@@ -35,9 +37,9 @@ pub struct TokenResponse {
|
|
|
|
|
|
pub fn api_msg_parse_auth(data: &str) -> Result<AuthUser, Box<dyn Error>> {
|
|
|
let v: serde_json::Value = serde_json::from_str(data)?;
|
|
|
- let user = v["user"].as_str();
|
|
|
- if user.is_none() {
|
|
|
- return Err("user not found".into());
|
|
|
+ let username = v["username"].as_str();
|
|
|
+ if username.is_none() {
|
|
|
+ return Err("username not found".into());
|
|
|
}
|
|
|
let password = v["password"].as_str();
|
|
|
if password.is_none() {
|
|
@@ -45,14 +47,40 @@ pub fn api_msg_parse_auth(data: &str) -> Result<AuthUser, Box<dyn Error>> {
|
|
|
}
|
|
|
|
|
|
Ok(AuthUser {
|
|
|
- user: user.unwrap().to_string(),
|
|
|
+ username: username.unwrap().to_string(),
|
|
|
password: password.unwrap().to_string(),
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+pub fn api_msg_parse_auth_password_change(data: &str) -> Result<(String, String), Box<dyn Error>> {
|
|
|
+ let v: serde_json::Value = serde_json::from_str(data)?;
|
|
|
+ let old_password = v["old_password"].as_str();
|
|
|
+ if old_password.is_none() {
|
|
|
+ return Err("old_password not found".into());
|
|
|
+ }
|
|
|
+ let password = v["password"].as_str();
|
|
|
+ if password.is_none() {
|
|
|
+ return Err("password not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ Ok((
|
|
|
+ old_password.unwrap().to_string(),
|
|
|
+ password.unwrap().to_string(),
|
|
|
+ ))
|
|
|
+}
|
|
|
+
|
|
|
+pub fn api_msg_gen_auth_password_change(old_password: &str, password: &str) -> String {
|
|
|
+ let json_str = json!({
|
|
|
+ "old_password": old_password,
|
|
|
+ "password": password,
|
|
|
+ });
|
|
|
+
|
|
|
+ json_str.to_string()
|
|
|
+}
|
|
|
+
|
|
|
pub fn api_msg_gen_auth_login(auth: &AuthUser) -> String {
|
|
|
let json_str = json!({
|
|
|
- "user": auth.user,
|
|
|
+ "username": auth.username,
|
|
|
"password": auth.password,
|
|
|
});
|
|
|
|
|
@@ -77,35 +105,62 @@ pub fn api_msg_gen_count(count: i64) -> String {
|
|
|
json_str.to_string()
|
|
|
}
|
|
|
|
|
|
-pub fn api_msg_parse_domain(data: &str) -> Result<DomainData, Box<dyn Error>> {
|
|
|
- let v: serde_json::Value = serde_json::from_str(data)?;
|
|
|
- let id = v["id"].as_u64();
|
|
|
+pub fn api_msg_parse_json_object_domain_value(
|
|
|
+ data: &serde_json::Value,
|
|
|
+) -> Result<DomainData, Box<dyn Error>> {
|
|
|
+ let id = data["id"].as_u64();
|
|
|
if id.is_none() {
|
|
|
return Err("id not found".into());
|
|
|
}
|
|
|
- let timestamp = v["timestamp"].as_u64();
|
|
|
+
|
|
|
+ let timestamp = data["timestamp"].as_u64();
|
|
|
if timestamp.is_none() {
|
|
|
return Err("timestamp not found".into());
|
|
|
}
|
|
|
- let domain = v["domain"].as_str();
|
|
|
+
|
|
|
+ let domain = data["domain"].as_str();
|
|
|
if domain.is_none() {
|
|
|
return Err("domain not found".into());
|
|
|
}
|
|
|
- let domain_type = v["domain-type"].as_u64();
|
|
|
+
|
|
|
+ let domain_type = data["domain_type"].as_u64();
|
|
|
if domain_type.is_none() {
|
|
|
- return Err("domain-type not found".into());
|
|
|
+ return Err("domain_type not found".into());
|
|
|
}
|
|
|
- let client = v["client"].as_str();
|
|
|
+
|
|
|
+ let client = data["client"].as_str();
|
|
|
if client.is_none() {
|
|
|
return Err("client not found".into());
|
|
|
}
|
|
|
- let domain_group = v["domain-group"].as_str();
|
|
|
+
|
|
|
+ let domain_group = data["domain_group"].as_str();
|
|
|
if domain_group.is_none() {
|
|
|
- return Err("domain-group not found".into());
|
|
|
+ return Err("domain_group not found".into());
|
|
|
}
|
|
|
- let reply_code = v["reply-code"].as_u64();
|
|
|
+
|
|
|
+ let reply_code = data["reply_code"].as_u64();
|
|
|
if reply_code.is_none() {
|
|
|
- return Err("reply-code not found".into());
|
|
|
+ return Err("reply_code not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ let query_time = data["query_time"].as_i64();
|
|
|
+ if query_time.is_none() {
|
|
|
+ return Err("query_time not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ let ping_time = data["ping_time"].as_f64();
|
|
|
+ if ping_time.is_none() {
|
|
|
+ return Err("ping_time not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ let is_blocked = data["is_blocked"].as_bool();
|
|
|
+ if is_blocked.is_none() {
|
|
|
+ return Err("is_blocked not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ let is_cached = data["is_cached"].as_bool();
|
|
|
+ if is_cached.is_none() {
|
|
|
+ return Err("is_cached not found".into());
|
|
|
}
|
|
|
|
|
|
Ok(DomainData {
|
|
@@ -116,94 +171,70 @@ pub fn api_msg_parse_domain(data: &str) -> Result<DomainData, Box<dyn Error>> {
|
|
|
client: client.unwrap().to_string(),
|
|
|
domain_group: domain_group.unwrap().to_string(),
|
|
|
reply_code: reply_code.unwrap() as u16,
|
|
|
+ query_time: query_time.unwrap() as i32,
|
|
|
+ ping_time: ping_time.unwrap(),
|
|
|
+ is_blocked: is_blocked.unwrap(),
|
|
|
+ is_cached: is_cached.unwrap(),
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-pub fn api_msg_gen_domain(domain: &DomainData) -> String {
|
|
|
- let json_str = json!({
|
|
|
+pub fn api_msg_parse_domain(data: &str) -> Result<DomainData, Box<dyn Error>> {
|
|
|
+ let v: serde_json::Value = serde_json::from_str(data)?;
|
|
|
+ api_msg_parse_json_object_domain_value(&v)
|
|
|
+}
|
|
|
+
|
|
|
+pub fn api_msg_gen_json_object_domain(domain: &DomainData) -> serde_json::Value {
|
|
|
+ json!({
|
|
|
"id": domain.id,
|
|
|
"timestamp": domain.timestamp,
|
|
|
"domain": domain.domain,
|
|
|
- "domain-type": domain.domain_type,
|
|
|
+ "domain_type": domain.domain_type,
|
|
|
"client": domain.client,
|
|
|
- "domain-group": domain.domain_group,
|
|
|
- "reply-code": domain.reply_code,
|
|
|
- });
|
|
|
+ "domain_group": domain.domain_group,
|
|
|
+ "reply_code": domain.reply_code,
|
|
|
+ "query_time": domain.query_time,
|
|
|
+ "ping_time": domain.ping_time,
|
|
|
+ "is_blocked": domain.is_blocked,
|
|
|
+ "is_cached": domain.is_cached,
|
|
|
+ })
|
|
|
+}
|
|
|
|
|
|
+pub fn api_msg_gen_domain(domain: &DomainData) -> String {
|
|
|
+ let json_str = api_msg_gen_json_object_domain(domain);
|
|
|
json_str.to_string()
|
|
|
}
|
|
|
|
|
|
pub fn api_msg_parse_domain_list(data: &str) -> Result<Vec<DomainData>, Box<dyn Error>> {
|
|
|
let v: serde_json::Value = serde_json::from_str(data)?;
|
|
|
- let list_count = v["list-count"].as_u64();
|
|
|
+ let list_count = v["list_count"].as_u64();
|
|
|
if list_count.is_none() {
|
|
|
- return Err("list-count not found".into());
|
|
|
+ return Err("list_count not found".into());
|
|
|
}
|
|
|
let list_count = list_count.unwrap();
|
|
|
let mut domain_list = Vec::new();
|
|
|
for i in 0..list_count {
|
|
|
- let domain = &v["domian-list"][i as usize];
|
|
|
- let id = domain["id"].as_u64();
|
|
|
- if id.is_none() {
|
|
|
- return Err("id not found".into());
|
|
|
- }
|
|
|
- let timestamp = domain["timestamp"].as_u64();
|
|
|
- if timestamp.is_none() {
|
|
|
- return Err("timestamp not found".into());
|
|
|
- }
|
|
|
- let domain_str = domain["domain"].as_str();
|
|
|
- if domain_str.is_none() {
|
|
|
- return Err("domain not found".into());
|
|
|
- }
|
|
|
- let domain_type = domain["domain-type"].as_u64();
|
|
|
- if domain_type.is_none() {
|
|
|
- return Err("domain-type not found".into());
|
|
|
- }
|
|
|
- let client = domain["client"].as_str();
|
|
|
- if client.is_none() {
|
|
|
- return Err("client not found".into());
|
|
|
- }
|
|
|
- let domain_group = domain["domain-group"].as_str();
|
|
|
- if domain_group.is_none() {
|
|
|
- return Err("domain-group not found".into());
|
|
|
- }
|
|
|
- let reply_code = domain["reply-code"].as_u64();
|
|
|
- if reply_code.is_none() {
|
|
|
- return Err("reply-code not found".into());
|
|
|
- }
|
|
|
-
|
|
|
- domain_list.push(DomainData {
|
|
|
- id: id.unwrap(),
|
|
|
- timestamp: timestamp.unwrap(),
|
|
|
- domain: domain_str.unwrap().to_string(),
|
|
|
- domain_type: domain_type.unwrap() as u32,
|
|
|
- client: client.unwrap().to_string(),
|
|
|
- domain_group: domain_group.unwrap().to_string(),
|
|
|
- reply_code: reply_code.unwrap() as u16,
|
|
|
- });
|
|
|
+ let domain_object = &v["domain_list"][i as usize];
|
|
|
+ let domain_data = api_msg_parse_json_object_domain_value(domain_object)?;
|
|
|
+ domain_list.push(domain_data);
|
|
|
}
|
|
|
|
|
|
Ok(domain_list)
|
|
|
}
|
|
|
|
|
|
-pub fn api_msg_gen_domain_list(domain_list: Vec<DomainData>, total_page: u32) -> String {
|
|
|
+pub fn api_msg_gen_domain_list(
|
|
|
+ domain_list: &Vec<DomainData>,
|
|
|
+ total_page: u32,
|
|
|
+ total_count: u32,
|
|
|
+) -> String {
|
|
|
let json_str = json!({
|
|
|
- "list-count": domain_list.len(),
|
|
|
- "total-page": total_page,
|
|
|
- "domian-list":
|
|
|
+ "list_count": domain_list.len(),
|
|
|
+ "total_page": total_page,
|
|
|
+ "total_count": total_count,
|
|
|
+ "domain_list":
|
|
|
domain_list
|
|
|
.iter()
|
|
|
.map(|x| {
|
|
|
- let s = json!({
|
|
|
- "id": x.id,
|
|
|
- "timestamp": x.timestamp,
|
|
|
- "domain": x.domain,
|
|
|
- "domain-type": x.domain_type,
|
|
|
- "client": x.client,
|
|
|
- "domain-group": x.domain_group,
|
|
|
- "reply-code": x.reply_code,
|
|
|
- });
|
|
|
- s
|
|
|
+ api_msg_gen_json_object_domain(x)
|
|
|
})
|
|
|
.collect::<Vec<serde_json::Value>>()
|
|
|
|
|
@@ -212,16 +243,45 @@ pub fn api_msg_gen_domain_list(domain_list: Vec<DomainData>, total_page: u32) ->
|
|
|
json_str.to_string()
|
|
|
}
|
|
|
|
|
|
-pub fn api_msg_gen_client_list(client_list: Vec<ClientData>) -> String {
|
|
|
+pub fn api_msg_parse_client_list(data: &str) -> Result<Vec<ClientData>, Box<dyn Error>> {
|
|
|
+ let v: serde_json::Value = serde_json::from_str(data)?;
|
|
|
+ let list_count = v["list_count"].as_u64();
|
|
|
+ if list_count.is_none() {
|
|
|
+ return Err("list_count not found".into());
|
|
|
+ }
|
|
|
+ let list_count = list_count.unwrap();
|
|
|
+ let mut client_list = Vec::new();
|
|
|
+ for i in 0..list_count {
|
|
|
+ let client_object = &v["client-list"][i as usize];
|
|
|
+ let id = client_object["id"].as_u64();
|
|
|
+ if id.is_none() {
|
|
|
+ return Err("id not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ let client_ip = client_object["client_ip"].as_str();
|
|
|
+ if client_ip.is_none() {
|
|
|
+ return Err("client_ip not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ client_list.push(ClientData {
|
|
|
+ id: id.unwrap() as u32,
|
|
|
+ client_ip: client_ip.unwrap().to_string(),
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ Ok(client_list)
|
|
|
+}
|
|
|
+
|
|
|
+pub fn api_msg_gen_client_list(client_list: &Vec<ClientData>) -> String {
|
|
|
let json_str = json!({
|
|
|
- "list-count": client_list.len(),
|
|
|
+ "list_count": client_list.len(),
|
|
|
"client-list":
|
|
|
client_list
|
|
|
.iter()
|
|
|
.map(|x| {
|
|
|
let s = json!({
|
|
|
"id": x.id,
|
|
|
- "client-ip": x.client_ip,
|
|
|
+ "client_ip": x.client_ip,
|
|
|
});
|
|
|
s
|
|
|
})
|
|
@@ -235,7 +295,8 @@ pub fn api_msg_gen_client_list(client_list: Vec<ClientData>) -> String {
|
|
|
pub fn api_msg_auth_token(token: &str, expired: &str) -> String {
|
|
|
let json_str = json!({
|
|
|
"token": token,
|
|
|
- "expires-in": expired,
|
|
|
+ "token_type": "Bearer",
|
|
|
+ "expires_in": expired,
|
|
|
});
|
|
|
|
|
|
json_str.to_string()
|
|
@@ -247,9 +308,9 @@ pub fn api_msg_parse_auth_token(data: &str) -> Result<TokenResponse, Box<dyn Err
|
|
|
if token.is_none() {
|
|
|
return Err("token not found".into());
|
|
|
}
|
|
|
- let expired = v["expires-in"].as_str();
|
|
|
+ let expired = v["expires_in"].as_str();
|
|
|
if expired.is_none() {
|
|
|
- return Err("expires-in not found".into());
|
|
|
+ return Err("expires_in not found".into());
|
|
|
}
|
|
|
|
|
|
Ok(TokenResponse {
|
|
@@ -260,7 +321,7 @@ pub fn api_msg_parse_auth_token(data: &str) -> Result<TokenResponse, Box<dyn Err
|
|
|
|
|
|
pub fn api_msg_gen_cache_number(cache_number: i32) -> String {
|
|
|
let json_str = json!({
|
|
|
- "cache-number": cache_number,
|
|
|
+ "cache_number": cache_number,
|
|
|
});
|
|
|
|
|
|
json_str.to_string()
|
|
@@ -268,9 +329,9 @@ pub fn api_msg_gen_cache_number(cache_number: i32) -> String {
|
|
|
|
|
|
pub fn api_msg_parse_cache_number(data: &str) -> Result<i32, Box<dyn Error>> {
|
|
|
let v: serde_json::Value = serde_json::from_str(data)?;
|
|
|
- let cache_number = v["cache-number"].as_i64();
|
|
|
+ let cache_number = v["cache_number"].as_i64();
|
|
|
if cache_number.is_none() {
|
|
|
- return Err("cache-number not found".into());
|
|
|
+ return Err("cache_number not found".into());
|
|
|
}
|
|
|
|
|
|
Ok(cache_number.unwrap() as i32)
|
|
@@ -296,34 +357,23 @@ pub fn api_msg_parse_error(data: &str) -> Result<String, Box<dyn Error>> {
|
|
|
|
|
|
pub fn api_msg_parse_loglevel(data: &str) -> Result<LogLevel, Box<dyn Error>> {
|
|
|
let v: serde_json::Value = serde_json::from_str(data)?;
|
|
|
- let loglevel = v["log-level"].as_str();
|
|
|
+ let loglevel = v["log_level"].as_str();
|
|
|
if loglevel.is_none() {
|
|
|
return Err("loglevel not found".into());
|
|
|
}
|
|
|
|
|
|
- let loglevel = loglevel.unwrap();
|
|
|
- match loglevel {
|
|
|
- "debug" => Ok(LogLevel::DEBUG),
|
|
|
- "info" => Ok(LogLevel::INFO),
|
|
|
- "notice" => Ok(LogLevel::NOTICE),
|
|
|
- "warn" => Ok(LogLevel::WARN),
|
|
|
- "error" => Ok(LogLevel::ERROR),
|
|
|
- "fatal" => Ok(LogLevel::FATAL),
|
|
|
- _ => Err("loglevel not found".into()),
|
|
|
+ let ret = loglevel.unwrap().try_into();
|
|
|
+ if ret.is_err() {
|
|
|
+ return Err("log level is invalid".into());
|
|
|
}
|
|
|
+
|
|
|
+ Ok(ret.unwrap())
|
|
|
}
|
|
|
|
|
|
pub fn api_msg_gen_loglevel(loglevel: LogLevel) -> String {
|
|
|
- let loglevel = match loglevel {
|
|
|
- LogLevel::DEBUG => "debug",
|
|
|
- LogLevel::INFO => "info",
|
|
|
- LogLevel::NOTICE => "notice",
|
|
|
- LogLevel::WARN => "warn",
|
|
|
- LogLevel::ERROR => "error",
|
|
|
- LogLevel::FATAL => "fatal",
|
|
|
- };
|
|
|
+ let loglevel_str = loglevel.to_string();
|
|
|
let json_str = json!({
|
|
|
- "log-level": loglevel,
|
|
|
+ "log_level": loglevel_str,
|
|
|
});
|
|
|
|
|
|
json_str.to_string()
|
|
@@ -332,7 +382,7 @@ pub fn api_msg_gen_loglevel(loglevel: LogLevel) -> String {
|
|
|
pub fn api_msg_gen_version(smartdns_version: &str, ui_version: &str) -> String {
|
|
|
let json_str = json!({
|
|
|
"smartdns": smartdns_version,
|
|
|
- "smartdns-ui": ui_version,
|
|
|
+ "smartdns_ui": ui_version,
|
|
|
});
|
|
|
|
|
|
json_str.to_string()
|
|
@@ -344,10 +394,213 @@ pub fn api_msg_parse_version(data: &str) -> Result<(String, String), Box<dyn Err
|
|
|
if smartdns.is_none() {
|
|
|
return Err("smartdns not found".into());
|
|
|
}
|
|
|
- let ui = v["smartdns-ui"].as_str();
|
|
|
+ let ui = v["smartdns_ui"].as_str();
|
|
|
if ui.is_none() {
|
|
|
return Err("ui not found".into());
|
|
|
}
|
|
|
|
|
|
Ok((smartdns.unwrap().to_string(), ui.unwrap().to_string()))
|
|
|
+}
|
|
|
+
|
|
|
+pub fn api_msg_gen_key_value(data: &HashMap<String, String>) -> String {
|
|
|
+ let mut json_map = serde_json::Map::new();
|
|
|
+
|
|
|
+ for (key, value) in data {
|
|
|
+ json_map.insert(key.clone(), serde_json::Value::String(value.clone()));
|
|
|
+ }
|
|
|
+
|
|
|
+ serde_json::Value::Object(json_map).to_string()
|
|
|
+}
|
|
|
+
|
|
|
+pub fn api_msg_parse_key_value(data: &str) -> Result<HashMap<String, String>, Box<dyn Error>> {
|
|
|
+ let v: serde_json::Value = serde_json::from_str(data)?;
|
|
|
+ let mut conf_map = HashMap::new();
|
|
|
+
|
|
|
+ if let serde_json::Value::Object(map) = v {
|
|
|
+ for (key, value) in map {
|
|
|
+ if let serde_json::Value::String(value_str) = value {
|
|
|
+ conf_map.insert(key, value_str);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Ok(conf_map)
|
|
|
+}
|
|
|
+
|
|
|
+pub fn api_msg_gen_top_client_list(client_list: &Vec<ClientQueryCount>) -> String {
|
|
|
+ let json_str = json!({
|
|
|
+ "client_top_list":
|
|
|
+ client_list
|
|
|
+ .iter()
|
|
|
+ .map(|x| {
|
|
|
+ let s = json!({
|
|
|
+ "client_ip": x.client_ip,
|
|
|
+ "query_count": x.count,
|
|
|
+ });
|
|
|
+ s
|
|
|
+ })
|
|
|
+ .collect::<Vec<serde_json::Value>>()
|
|
|
+ });
|
|
|
+
|
|
|
+ json_str.to_string()
|
|
|
+}
|
|
|
+
|
|
|
+pub fn api_msg_parse_top_client_list(data: &str) -> Result<Vec<ClientQueryCount>, Box<dyn Error>> {
|
|
|
+ let v: serde_json::Value = serde_json::from_str(data)?;
|
|
|
+ let mut client_list = Vec::new();
|
|
|
+ let top_list = v["client_top_list"].as_array();
|
|
|
+ if top_list.is_none() {
|
|
|
+ return Err("list_count not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ for item in top_list.unwrap() {
|
|
|
+ let client_ip = item["client_ip"].as_str();
|
|
|
+ if client_ip.is_none() {
|
|
|
+ return Err("client_ip not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ let query_count = item["query_count"].as_u64();
|
|
|
+ if query_count.is_none() {
|
|
|
+ return Err("query_count not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ client_list.push(ClientQueryCount {
|
|
|
+ client_ip: client_ip.unwrap().to_string(),
|
|
|
+ count: query_count.unwrap() as u32,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ Ok(client_list)
|
|
|
+}
|
|
|
+
|
|
|
+pub fn api_msg_gen_top_domain_list(domain_list: &Vec<DomainQueryCount>) -> String {
|
|
|
+ let json_str = json!({
|
|
|
+ "domain_top_list":
|
|
|
+ domain_list
|
|
|
+ .iter()
|
|
|
+ .map(|x| {
|
|
|
+ let s = json!({
|
|
|
+ "domain": x.domain,
|
|
|
+ "query_count": x.count,
|
|
|
+ });
|
|
|
+ s
|
|
|
+ })
|
|
|
+ .collect::<Vec<serde_json::Value>>()
|
|
|
+ });
|
|
|
+
|
|
|
+ json_str.to_string()
|
|
|
+}
|
|
|
+
|
|
|
+pub fn api_msg_parse_top_domain_list(data: &str) -> Result<Vec<DomainQueryCount>, Box<dyn Error>> {
|
|
|
+ let v: serde_json::Value = serde_json::from_str(data)?;
|
|
|
+ let mut domain_list = Vec::new();
|
|
|
+ let top_list = v["domain_top_list"].as_array();
|
|
|
+ if top_list.is_none() {
|
|
|
+ return Err("list_count not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ for item in top_list.unwrap() {
|
|
|
+ let domain = item["domain"].as_str();
|
|
|
+ if domain.is_none() {
|
|
|
+ return Err("domain not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ let query_count = item["query_count"].as_u64();
|
|
|
+ if query_count.is_none() {
|
|
|
+ return Err("query_count not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ domain_list.push(DomainQueryCount {
|
|
|
+ domain: domain.unwrap().to_string(),
|
|
|
+ count: query_count.unwrap() as u32,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ Ok(domain_list)
|
|
|
+}
|
|
|
+
|
|
|
+pub fn api_msg_gen_stats_overview(data: &OverviewData) -> String {
|
|
|
+ let json_str = json!({
|
|
|
+ "total_query_count": data.total_query_count,
|
|
|
+ "block_query_count": data.block_query_count,
|
|
|
+ "avg_query_time": data.avg_query_time,
|
|
|
+ "cache_hit_rate": data.cache_hit_rate,
|
|
|
+ });
|
|
|
+
|
|
|
+ json_str.to_string()
|
|
|
+}
|
|
|
+
|
|
|
+pub fn api_msg_parse_stats_overview(data: &str) -> Result<OverviewData, Box<dyn Error>> {
|
|
|
+ let v: serde_json::Value = serde_json::from_str(data)?;
|
|
|
+ let total_query_count = v["total_query_count"].as_u64();
|
|
|
+ if total_query_count.is_none() {
|
|
|
+ return Err("total_query_count not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ let block_query_count = v["block_query_count"].as_u64();
|
|
|
+ if block_query_count.is_none() {
|
|
|
+ return Err("block_query_count not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ let avg_query_time = v["avg_query_time"].as_f64();
|
|
|
+ if avg_query_time.is_none() {
|
|
|
+ return Err("avg_query_time not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ let cache_hit_rate = v["cache_hit_rate"].as_f64();
|
|
|
+ if cache_hit_rate.is_none() {
|
|
|
+ return Err("cache_hit_rate not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ Ok(OverviewData {
|
|
|
+ total_query_count: total_query_count.unwrap() as u64,
|
|
|
+ block_query_count: block_query_count.unwrap() as u64,
|
|
|
+ avg_query_time: avg_query_time.unwrap(),
|
|
|
+ cache_hit_rate: cache_hit_rate.unwrap(),
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+pub fn api_msg_gen_hourly_query_count(data: &Vec<HourlyQueryCount>) -> String {
|
|
|
+ let json_str = json!({
|
|
|
+ "hourly_query_count":
|
|
|
+ data
|
|
|
+ .iter()
|
|
|
+ .map(|x| {
|
|
|
+ let s = json!({
|
|
|
+ "hour": x.hour,
|
|
|
+ "query_count": x.query_count,
|
|
|
+ });
|
|
|
+ s
|
|
|
+ })
|
|
|
+ .collect::<Vec<serde_json::Value>>()
|
|
|
+ });
|
|
|
+ json_str.to_string()
|
|
|
+}
|
|
|
+
|
|
|
+pub fn api_msg_parse_hourly_query_count(data: &str) -> Result<Vec<HourlyQueryCount>, Box<dyn Error>> {
|
|
|
+ let v: serde_json::Value = serde_json::from_str(data)?;
|
|
|
+ let mut hourly_query_count = Vec::new();
|
|
|
+ let hourly_list = v["hourly_query_count"].as_array();
|
|
|
+ if hourly_list.is_none() {
|
|
|
+ return Err("hourly_query_count not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ for item in hourly_list.unwrap() {
|
|
|
+ let hour = item["hour"].as_str();
|
|
|
+ if hour.is_none() {
|
|
|
+ return Err("hour not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ let query_count = item["query_count"].as_u64();
|
|
|
+ if query_count.is_none() {
|
|
|
+ return Err("query_count not found".into());
|
|
|
+ }
|
|
|
+
|
|
|
+ hourly_query_count.push(HourlyQueryCount {
|
|
|
+ hour: hour.unwrap().to_string(),
|
|
|
+ query_count: query_count.unwrap() as u32,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ Ok(hourly_query_count)
|
|
|
}
|