diff --git a/examples/multi-apps/doc/src/serv/doc_serv.rs b/examples/multi-apps/doc/src/serv/doc_serv.rs index 2402c492..c6851519 100644 --- a/examples/multi-apps/doc/src/serv/doc_serv.rs +++ b/examples/multi-apps/doc/src/serv/doc_serv.rs @@ -13,7 +13,7 @@ pub struct DocServ; impl<'a> DocServ { pub async fn add_doc(add_req: &DocAddReq, funs: &TardisFunsInst<'a>, cxt: &TardisContext) -> TardisResult { if funs.conf::().content_max_len < add_req.content.len() as u32 { - return Err(TardisError::BadRequest("content too long".to_string())); + return Err(TardisError::bad_request("content too long", "")); } let doc = doc::ActiveModel { name: Set(add_req.name.to_string()), diff --git a/examples/multi-apps/tag/src/serv/tag_serv.rs b/examples/multi-apps/tag/src/serv/tag_serv.rs index 76a83884..9da9f1e8 100644 --- a/examples/multi-apps/tag/src/serv/tag_serv.rs +++ b/examples/multi-apps/tag/src/serv/tag_serv.rs @@ -14,7 +14,7 @@ pub struct TagServ; impl<'a> TagServ { pub async fn add_doc(add_req: &TagAddReq, funs: &TardisFunsInst<'a>, cxt: &TardisContext) -> TardisResult { if funs.conf::().name_max_len < add_req.name.len() as u8 { - return Err(TardisError::BadRequest("name too long".to_string())); + return Err(TardisError::bad_request("name too long", "")); } let doc = tag::ActiveModel { name: Set(add_req.name.to_string()), diff --git a/examples/todos/src/processor.rs b/examples/todos/src/processor.rs index aec606cc..f8778e33 100644 --- a/examples/todos/src/processor.rs +++ b/examples/todos/src/processor.rs @@ -77,7 +77,7 @@ impl TodoApi { .and_where(todos::Column::Id.eq(id.0)), ) .await? - .ok_or_else(|| TardisError::NotFound("Not found".to_string()))?; + .ok_or_else(|| TardisError::not_found("Not found", ""))?; TardisResp::ok(todo) } diff --git a/examples/web-basic/src/processor.rs b/examples/web-basic/src/processor.rs index fd9a069b..79ee22a4 100644 --- a/examples/web-basic/src/processor.rs +++ b/examples/web-basic/src/processor.rs @@ -11,7 +11,7 @@ impl Api { async fn index(&self, name: Query>) -> TardisApiResult { match name.0 { Some(name) => TardisResp::ok(format!("hello, {}!", name)), - None => TardisResp::err(TardisError::NotFound("name does not exist".to_string())), + None => TardisResp::err(TardisError::not_found("name does not exist", "")), } } } diff --git a/res/locale/zh-cn.tardis b/res/locale/zh-cn.tardis new file mode 100644 index 00000000..54a45e11 --- /dev/null +++ b/res/locale/zh-cn.tardis @@ -0,0 +1,88 @@ +406-tardis-error-invalid 错误格式不合法 + +503-tardis-config-frozen 配置处理错误 +404-tardis-config-not-exist 配置不存在 +406-tardis-config-parse-error 配置解析错误 +-1-tardis-config-custom-error 配置处理错误 +-1-tardis-config-error 配置处理错误 + +406-tardis-json-json-to-obj-error Json转对象错误 +406-tardis-json-obj-to-json-error 对象转Json错误 +406-tardis-json-str-to-obj-error Json字符串转对象错误 +406-tardis-json-str-to-json-error Json字符串转Json错误 +406-tardis-json-obj-to-str-error 对象转Json字符串错误 +406-tardis-json-json-to-str-error Json转Json字符串错误 + +406-tardis-crypto-aes-key-invalid AES Key格式错误 +406-tardis-crypto-aes-error AES处理错误 +406-tardis-crypto-rsa-error RSA处理错误 +406-tardis-crypto-rsa-pk-error RSA公钥解析错误 +406-tardis-crypto-rsa-sk-error RSA私钥解析错误 +500-tardis-crypto-sm2-keypair-error SM2公私钥生成错误 +406-tardis-crypto-sm2-pk-error SM2公钥解析错误 +406-tardis-crypto-sm2-sk-error SM2密钥解析错误 +406-tardis-crypto-sm2-encrypt-error SM2加密错误 +406-tardis-crypto-sm2-decode-sign-error SM2签名解码错误 +406-tardis-crypto-sm2-verify-sign-error SM2签名验证错误 +406-tardis-crypto-sm2-sign-error SM2签名错误 +406-tardis-crypto-sm2-decrypt-error SM2解密错误 +406-tardis-crypto-sm4-cipher-error SM4 Cipher错误 +406-tardis-crypto-sm4-encrypt-error SM4加密错误 +406-tardis-crypto-sm4-cipher-error SM4 Cipher错误 +406-tardis-crypto-sm4-decrypt-error SM4解密错误 +406-tardis-crypto-hex-decode-error Hex解码错误 +406-tardis-crypto-base64-decode-error Base64解码错误 + +-1-tardis-webserver-error Http处理错误 +400-tardis-webserver-error 请求参数错误 +401-tardis-webserver-error 请求认证错误 +404-tardis-webserver-error 请求资源不存在 +406-tardis-webserver-error 请求格式错误 +408-tardis-webserver-error 请求超时 +409-tardis-webserver-error 请求资源冲突 +500-tardis-webserver-error Http处理错误 +501-tardis-webserver-error 请求的方法未实现 +400-tardis-webserver-context-header-not-exist 头信息中找不到请求上下文 +400-tardis-webserver-context-not-str 请求上下文不是合法的字符串 +400-tardis-webserver-context-not-base64 请求上下文不是合法的Base64编码字符串 +400-tardis-webserver-context-not-utf8 请求上下文不是合法的utf8字符串 +400-tardis-webserver-context-not-json 请求上下文不是合法的Json字符串 +400-tardis-webserver-context-not-valid 请求上下文格式错误 +400-tardis-webserver-context-not-in-cache 缓存中找不到请求上下文 + +406-tardis-webclient-json-error Http返回体不是合法的Json +406-tardis-webclient-text-error Http返回体不是合法的文本 +-1-tardis-webclient-error Http请求错误 + +-1-tardis-cache-error 缓存处理错误 +406-tardis-cache-url-error 缓存Url解析错误 + +-1-tardis-search-error 搜索处理错误 +400-tardis-search-id-not-exist 搜索记录缺少_id字段 +406-tardis-search-hit-not-exist 搜索记录缺少hit字段 + +-1-tardis-mq-error MQ处理错误 +500-tardis-mq-confirm-error MQ请求确认错误 +406-tardis-mq-url-error MQ Url解析错误 + +-1-tardis-reldb-error SQL执行错误 +406-tardis-reldb-url-error SQL Url解析错误 +406-tardis-reldb-sql-error SQL解析错误 +500-tardis-reldb-id-not-char 主键不是字符串 +500-tardis-reldb-id-not-num 主键不是数值 +500-tardis-reldb-count-empty 统计查询结果为空 +404-tardis-reldb-tx-empty 当前连接没有事务 +404-tardis-reldb-soft-delete-table-not-exit 软删操作找不到对应的表名 + +-1-tardis-mail-error 邮件发送错误 +406-tardis-mail-addr-error 邮件地址解析错误 +500-tardis-mail-init-error 邮件初始化错误 + +-1-tardis-os-error 对象存储操作错误 +501-tardis-os-kind-error 对象存储类型[{1}]不支持 [Tardis.OSClient] Unsupported OS kind (\w+) +404-tardis-os-default-bucket-not-exist 默认存储空间不存在 +-1-tardis-os-create-object-error 对象存储创建对象错误 +-1-tardis-os-get-object-error 对象存储获取对象错误 +-1-tardis-os-delete-object-error 对象存储删除对象错误 +-1-tardis-os-create-bucket-error 对象存储创建空间错误 +-1-tardis-os-delete-bucket-error 对象存储删除空间错误 diff --git a/src/basic/config.rs b/src/basic/config.rs index 8ebabe83..6c482069 100644 --- a/src/basic/config.rs +++ b/src/basic/config.rs @@ -11,7 +11,7 @@ use std::path::Path; use config::{Config, ConfigError, Environment, File}; use serde_json::Value; -use crate::basic::error::{TardisError, ERROR_DEFAULT_CODE}; +use crate::basic::error::TardisError; use crate::basic::fetch_profile; use crate::basic::result::TardisResult; use crate::log::{debug, info}; @@ -741,15 +741,13 @@ impl TardisConfig { }) } else { #[cfg(not(feature = "crypto"))] - return Err(TardisError::FormatError( - "[Tardis.Config] Configuration encryption must depend on the crypto feature".to_string(), - )); + return Err(TardisError::format_error("[Tardis.Config] Configuration encryption must depend on the crypto feature", "")); #[cfg(feature = "crypto")] { // decryption processing let salt = framework_config.adv.salt.clone(); if salt.len() != 16 { - return Err(TardisError::FormatError("[Tardis.Config] [salt] length must be 16".to_string())); + return Err(TardisError::format_error("[Tardis.Config] [salt] Length must be 16", "")); } fn decryption(text: &str, salt: &str) -> String { let enc_r = regex::Regex::new(r"(?PENC\([A-Za-z0-9+/]*\))").unwrap(); @@ -781,13 +779,13 @@ impl TardisConfig { impl From for TardisError { fn from(error: ConfigError) -> Self { match error { - ConfigError::Frozen => TardisError::IOError(error.to_string()), - ConfigError::NotFound(_) => TardisError::NotFound(error.to_string()), - ConfigError::PathParse(_) => TardisError::IOError(error.to_string()), - ConfigError::FileParse { .. } => TardisError::IOError(error.to_string()), - ConfigError::Type { .. } => TardisError::FormatError(error.to_string()), - ConfigError::Message(s) => TardisError::Custom(ERROR_DEFAULT_CODE.to_string(), s), - ConfigError::Foreign(err) => TardisError::Box(err), + ConfigError::Frozen => TardisError::io_error(&format!("[Tardis.Config] {:?}", error), "503-tardis-config-frozen"), + ConfigError::NotFound(_) => TardisError::not_found(&format!("[Tardis.Config] {:?}", error), "404-tardis-config-not-exist"), + ConfigError::PathParse(_) => TardisError::format_error(&format!("[Tardis.Config] {:?}", error), "406-tardis-config-parse-error"), + ConfigError::FileParse { .. } => TardisError::format_error(&format!("[Tardis.Config] {:?}", error), "406-tardis-config-parse-error"), + ConfigError::Type { .. } => TardisError::format_error(&format!("[Tardis.Config] {:?}", error), "406-tardis-config-parse-error"), + ConfigError::Message(s) => TardisError::wrap(&format!("[Tardis.Config] {:?}", s), "-1-tardis-config-custom-error"), + ConfigError::Foreign(err) => TardisError::wrap(&format!("[Tardis.Config] {:?}", err), "-1-tardis-config-error"), } } } diff --git a/src/basic/crypto.rs b/src/basic/crypto.rs index bb150b1a..8d7bf424 100644 --- a/src/basic/crypto.rs +++ b/src/basic/crypto.rs @@ -81,7 +81,10 @@ impl TardisCryptoHex { pub fn decode>(&self, data: T) -> TardisResult> { match hex::decode(data) { Ok(result) => Ok(result), - Err(e) => Err(TardisError::FormatError(format!("[Tardis.Crypto] Hex decode error:{}", e))), + Err(e) => Err(TardisError::format_error( + &format!("[Tardis.Crypto] Hex decode error:{}", e), + "406-tardis-crypto-hex-decode-error", + )), } } @@ -94,7 +97,10 @@ impl TardisCryptoBase64 { pub fn decode(&self, data: &str) -> TardisResult { match base64::decode(data) { Ok(result) => Ok(String::from_utf8(result)?), - Err(e) => Err(TardisError::FormatError(format!("[Tardis.Crypto] Base64 decode error:{}", e))), + Err(e) => Err(TardisError::format_error( + &format!("[Tardis.Crypto] Base64 decode error:{}", e), + "406-tardis-crypto-base64-decode-error", + )), } } @@ -128,7 +134,12 @@ impl TardisCryptoAes { 16 => crypto::aes::KeySize::KeySize128, 24 => crypto::aes::KeySize::KeySize192, 32 => crypto::aes::KeySize::KeySize256, - _ => return Err(TardisError::BadRequest("[Tardis.Crypto] AES error, invalid key size".to_string())), + _ => { + return Err(TardisError::format_error( + "[Tardis.Crypto] AES error, invalid key size", + "406-tardis-crypto-aes-key-invalid", + )) + } }; let mut encryptor = if cbc_mode { @@ -166,7 +177,12 @@ impl TardisCryptoAes { 16 => crypto::aes::KeySize::KeySize128, 24 => crypto::aes::KeySize::KeySize192, 32 => crypto::aes::KeySize::KeySize256, - _ => return Err(TardisError::BadRequest("[Tardis.Crypto] AES error, invalid key size".to_string())), + _ => { + return Err(TardisError::format_error( + "[Tardis.Crypto] AES error, invalid key size", + "406-tardis-crypto-aes-key-invalid", + )) + } }; let encrypted_data = hex::decode(encrypted_data)?; @@ -241,12 +257,17 @@ impl TardisCryptoRsaPrivateKey { pub fn from(private_key_pem: &str) -> TardisResult { Ok(TardisCryptoRsaPrivateKey { - pri_key: rsa::RsaPrivateKey::from_pkcs8_pem(private_key_pem).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] RSA crypto error, {}", e)))?, + pri_key: rsa::RsaPrivateKey::from_pkcs8_pem(private_key_pem) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] RSA crypto sk load error, {}", e), "406-tardis-crypto-rsa-sk-error"))?, }) } pub fn serialize(&self) -> TardisResult { - Ok(self.pri_key.to_pkcs8_pem(LineEnding::LF).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] RSA crypto error, {}", e)))?.to_string()) + Ok(self + .pri_key + .to_pkcs8_pem(LineEnding::LF) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] RSA crypto sk serialize error, {}", e), "406-tardis-crypto-rsa-sk-error"))? + .to_string()) } pub fn decrypt(&self, encrypted_data: &str) -> TardisResult { @@ -268,19 +289,23 @@ impl TardisCryptoRsaPublicKey { } pub fn from_private_key_str(private_key_pem: &str) -> TardisResult { - let private_key = rsa::RsaPrivateKey::from_pkcs8_pem(private_key_pem).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] RSA crypto error, {}", e)))?; + let private_key = rsa::RsaPrivateKey::from_pkcs8_pem(private_key_pem) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] RSA crypto sk load error, {}", e), "406-tardis-crypto-rsa-sk-error"))?; let public_key = rsa::RsaPublicKey::from(private_key); Ok(TardisCryptoRsaPublicKey { pub_key: public_key }) } pub fn from_public_key_str(public_key_pem: &str) -> TardisResult { Ok(TardisCryptoRsaPublicKey { - pub_key: rsa::RsaPublicKey::from_public_key_pem(public_key_pem).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] RSA crypto error, {}", e)))?, + pub_key: rsa::RsaPublicKey::from_public_key_pem(public_key_pem) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] RSA crypto pk load error, {}", e), "406-tardis-crypto-rsa-pk-error"))?, }) } pub fn serialize(&self) -> TardisResult { - self.pub_key.to_public_key_pem(LineEnding::LF).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] RSA crypto error, {}", e))) + self.pub_key + .to_public_key_pem(LineEnding::LF) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] RSA crypto pk serialize error, {}", e), "406-tardis-crypto-rsa-pk-error")) } pub fn encrypt(&self, data: &str) -> TardisResult { @@ -343,17 +368,22 @@ impl TardisCryptoSm2 { #[cfg(feature = "crypto_with_sm")] impl TardisCryptoSm2PrivateKey { pub fn new() -> TardisResult { - let (_, sk) = SigCtx::new().new_keypair().map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] SM2 new keypair error:{}", e)))?; + let (_, sk) = + SigCtx::new().new_keypair().map_err(|e| TardisError::internal_error(&format!("[Tardis.Crypto] SM2 new keypair error:{}", e), "500-tardis-crypto-sm2-keypair-error"))?; Ok(TardisCryptoSm2PrivateKey { pri_key: sk }) } pub fn from(private_key: &str) -> TardisResult { - let sk = SigCtx::new().load_seckey(&hex::decode(private_key)?).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] SM2 load sk error:{}", e)))?; + let sk = SigCtx::new() + .load_seckey(&hex::decode(private_key)?) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] SM2 load sk error:{}", e), "406-tardis-crypto-sm2-sk-error"))?; Ok(TardisCryptoSm2PrivateKey { pri_key: sk }) } pub fn serialize(&self) -> TardisResult { - let sk = SigCtx::new().serialize_seckey(&self.pri_key).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] SM2 serialize sk error:{}", e)))?; + let sk = SigCtx::new() + .serialize_seckey(&self.pri_key) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] SM2 serialize sk error:{}", e), "406-tardis-crypto-sm2-sk-error"))?; Ok(hex::encode(sk)) } @@ -362,14 +392,16 @@ impl TardisCryptoSm2PrivateKey { // https://github.com/citahub/libsm/issues/46 let data = DecryptCtx::new(encrypted_data.len() - 97, self.pri_key.clone()) .decrypt(&encrypted_data) - .map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] SM2 decrypt error:{}", e)))?; + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] SM2 decrypt error:{}", e), "406-tardis-crypto-sm2-decrypt-error"))?; Ok(String::from_utf8(data)?) } pub fn sign(&self, data: &str) -> TardisResult { let ctx = SigCtx::new(); - let pk = ctx.pk_from_sk(&self.pri_key).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] SM2 get pk error:{}", e)))?; - let signature = ctx.sign(data.as_bytes(), &self.pri_key, &pk).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] SM2 sign error:{}", e)))?; + let pk = ctx.pk_from_sk(&self.pri_key).map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] SM2 get pk error:{}", e), "406-tardis-crypto-sm2-pk-error"))?; + let signature = ctx + .sign(data.as_bytes(), &self.pri_key, &pk) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] SM2 sign error:{}", e), "406-tardis-crypto-sm2-sign-error"))?; Ok(hex::encode(signature.der_encode())) } } @@ -377,37 +409,49 @@ impl TardisCryptoSm2PrivateKey { #[cfg(feature = "crypto_with_sm")] impl TardisCryptoSm2PublicKey { pub fn from_private_key(private_key: &TardisCryptoSm2PrivateKey) -> TardisResult { - let pk = SigCtx::new().pk_from_sk(&private_key.pri_key).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] SM2 get pk error:{}", e)))?; + let pk = SigCtx::new() + .pk_from_sk(&private_key.pri_key) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] SM2 get pk error:{}", e), "406-tardis-crypto-sm2-pk-error"))?; Ok(TardisCryptoSm2PublicKey { pub_key: pk }) } pub fn from_private_key_str(private_key: &str) -> TardisResult { let ctx = SigCtx::new(); - let sk = ctx.load_seckey(&hex::decode(private_key)?).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] SM2 load sk error:{}", e)))?; - let pk = ctx.pk_from_sk(&sk).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] SM2 get pk error:{}", e)))?; + let sk = ctx + .load_seckey(&hex::decode(private_key)?) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] SM2 load sk error:{}", e), "406-tardis-crypto-sm2-sk-error"))?; + let pk = ctx.pk_from_sk(&sk).map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] SM2 get pk error:{}", e), "406-tardis-crypto-sm2-pk-error"))?; Ok(TardisCryptoSm2PublicKey { pub_key: pk }) } pub fn from_public_key_str(public_key: &str) -> TardisResult { - let pk = SigCtx::new().load_pubkey(&hex::decode(public_key)?).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] SM2 load pk error:{}", e)))?; + let pk = SigCtx::new() + .load_pubkey(&hex::decode(public_key)?) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] SM2 load pk error:{}", e), "406-tardis-crypto-sm2-pk-error"))?; Ok(TardisCryptoSm2PublicKey { pub_key: pk }) } pub fn serialize(&self) -> TardisResult { - let pk = SigCtx::new().serialize_pubkey(&self.pub_key, true).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] SM2 serialize pk error:{}", e)))?; + let pk = SigCtx::new() + .serialize_pubkey(&self.pub_key, true) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] SM2 serialize pk error:{}", e), "406-tardis-crypto-sm2-pk-error"))?; Ok(hex::encode(pk)) } pub fn encrypt(&self, data: &str) -> TardisResult { - let encrypted_data = - EncryptCtx::new(data.len(), self.pub_key).encrypt(data.as_bytes()).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] SM2 encrypt error:{}", e)))?; + let encrypted_data = EncryptCtx::new(data.len(), self.pub_key) + .encrypt(data.as_bytes()) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] SM2 encrypt error:{}", e), "406-tardis-crypto-sm2-encrypt-error"))?; Ok(hex::encode(encrypted_data)) } pub fn verify(&self, data: &str, signed_data: &str) -> TardisResult { let signed_data = hex::decode(signed_data)?; - let signature = Signature::der_decode(&signed_data).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] SM2 decode signature error:{}", e)))?; - let result = SigCtx::new().verify(data.as_bytes(), &self.pub_key, &signature).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] SM2 verify error:{}", e)))?; + let signature = Signature::der_decode(&signed_data) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] SM2 decode signature error:{}", e), "406-tardis-crypto-sm2-decode-sign-error"))?; + let result = SigCtx::new() + .verify(data.as_bytes(), &self.pub_key, &signature) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] SM2 verify error:{}", e), "406-tardis-crypto-sm2-verify-sign-error"))?; Ok(result) } } @@ -426,15 +470,21 @@ impl TardisCryptoSm2PublicKey { #[cfg(feature = "crypto_with_sm")] impl TardisCryptoSm4 { pub fn encrypt_cbc(&self, data: &str, hex_key: &str, hex_iv: &str) -> TardisResult { - let cipher = Cipher::new(hex_key.as_bytes(), Mode::Cbc).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] SM4 new cipher error:{}", e)))?; - let encrypted_data = cipher.encrypt(data.as_bytes(), hex_iv.as_bytes()).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] SM4 encrypt error:{}", e)))?; + let cipher = Cipher::new(hex_key.as_bytes(), Mode::Cbc) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] SM4 new cipher error:{}", e), "406-tardis-crypto-sm4-cipher-error"))?; + let encrypted_data = cipher + .encrypt(data.as_bytes(), hex_iv.as_bytes()) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] SM4 encrypt error:{}", e), "406-tardis-crypto-sm4-encrypt-error"))?; Ok(hex::encode(encrypted_data)) } pub fn decrypt_cbc(&self, encrypted_data: &str, hex_key: &str, hex_iv: &str) -> TardisResult { - let cipher = Cipher::new(hex_key.as_bytes(), Mode::Cbc).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] SM4 new cipher error:{}", e)))?; + let cipher = Cipher::new(hex_key.as_bytes(), Mode::Cbc) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] SM4 new cipher error:{}", e), "406-tardis-crypto-sm4-cipher-error"))?; let encrypted_data = hex::decode(encrypted_data)?; - let data = cipher.decrypt(encrypted_data.as_slice(), hex_iv.as_bytes()).map_err(|e| TardisError::FormatError(format!("[Tardis.Crypto] SM4 decrypt error:{}", e)))?; + let data = cipher + .decrypt(encrypted_data.as_slice(), hex_iv.as_bytes()) + .map_err(|e| TardisError::format_error(&format!("[Tardis.Crypto] SM4 decrypt error:{}", e), "406-tardis-crypto-sm4-decrypt-error"))?; Ok(String::from_utf8(data)?) } } @@ -557,12 +607,12 @@ impl TardisCryptoKey { impl From for TardisError { fn from(error: crypto::symmetriccipher::SymmetricCipherError) -> Self { - TardisError::FormatError(format!("[Tardis.Crypto] AES crypto error, {:?}", error)) + TardisError::format_error(&format!("[Tardis.Crypto] AES crypto error, {:?}", error), "406-tardis-crypto-aes-error") } } impl From for TardisError { fn from(error: rsa::errors::Error) -> Self { - TardisError::FormatError(format!("[Tardis.Crypto] RSA crypto error, {}", error)) + TardisError::format_error(&format!("[Tardis.Crypto] RSA crypto error, {:?}", error), "406-tardis-crypto-rsa-error") } } diff --git a/src/basic/error.rs b/src/basic/error.rs index a49af9e8..2abcb921 100644 --- a/src/basic/error.rs +++ b/src/basic/error.rs @@ -1,6 +1,6 @@ +use core::fmt::Display; use std::collections::HashMap; use std::convert::Infallible; -use std::error::Error; use std::fs::File; use std::io::{prelude::*, BufReader}; use std::num::ParseIntError; @@ -9,12 +9,11 @@ use std::str::Utf8Error; use std::string::FromUtf8Error; use std::sync::Mutex; -use derive_more::Display; use log::{info, warn}; use regex::Regex; -use crate::basic::field::GENERAL_SPLIT; -use crate::TardisResult; +use crate::serde::{Deserialize, Serialize}; +use crate::{TardisFuns, TardisResult}; pub static ERROR_DEFAULT_CODE: &str = "-1"; @@ -23,32 +22,16 @@ lazy_static! { } /// Tardis unified error wrapper / Tardis统一错误封装 -#[derive(Display, Debug)] -pub enum TardisError { - #[display(fmt = "{}##{}", _0, _1)] - Custom(String, String), - #[display(fmt = "000##{:?}", _0)] - Box(Box), - #[display(fmt = "500##{}", _0)] - InternalError(String), - #[display(fmt = "501##{}", _0)] - NotImplemented(String), - #[display(fmt = "503##{}", _0)] - IOError(String), - #[display(fmt = "400##{}", _0)] - BadRequest(String), - #[display(fmt = "401##{}", _0)] - Unauthorized(String), - #[display(fmt = "404##{}", _0)] - NotFound(String), - #[display(fmt = "406##{}", _0)] - FormatError(String), - #[display(fmt = "408##{}", _0)] - Timeout(String), - #[display(fmt = "409##{}", _0)] - Conflict(String), - #[display(fmt = "000##{}", _0)] - _Inner(String), +#[derive(Deserialize, Serialize, Clone, Debug)] +pub struct TardisError { + pub code: String, + pub message: String, +} + +impl Display for TardisError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}:{}", self.code, self.message) + } } impl TardisError { @@ -58,14 +41,14 @@ impl TardisError { return Ok(()); } info!("[Tardis.Error] Initializing, base path:{:?}", path); - let mut conf = LOCALE_CONFIG.lock().map_err(|e| TardisError::InternalError(format!("{:?}", e)))?; - let paths = path.read_dir().map_err(|e| TardisError::BadRequest(format!("[Tardis.Error] path {:#?} dir error:{:#?}", path, e)))?; + let mut conf = LOCALE_CONFIG.lock().map_err(|e| TardisError::internal_error(&format!("{:?}", e), ""))?; + let paths = path.read_dir().map_err(|e| TardisError::bad_request(&format!("[Tardis.Error] Path {:#?} dir error:{:#?}", path, e), ""))?; for entry in paths { let entry = entry?; let name = entry.file_name(); let lang = name .to_str() - .ok_or_else(|| TardisError::BadRequest(format!("[Tardis.Error] file name error {:#?}", entry)))? + .ok_or_else(|| TardisError::bad_request(&format!("[Tardis.Error] File name error {:#?}", entry), ""))? // Ignore module name, just take language flag .split('.') .next() @@ -81,10 +64,10 @@ impl TardisError { continue; } let mut items = line.split('\t'); - let code = items.next().ok_or_else(|| TardisError::BadRequest(format!("[Tardis.Error] code not exist in {}", line)))?.trim(); - let message = items.next().ok_or_else(|| TardisError::BadRequest(format!("[Tardis.Error] message not exist in {}", line)))?.trim(); + let code = items.next().ok_or_else(|| TardisError::bad_request(&format!("[Tardis.Error] Code not exist in {}", line), ""))?.trim(); + let message = items.next().ok_or_else(|| TardisError::bad_request(&format!("[Tardis.Error] Message not exist in {}", line), ""))?.trim(); let regex = if let Some(regex) = items.next() { - Some(Regex::new(regex.trim()).map_err(|_| TardisError::BadRequest(format!("[Tardis.Error] regex illegal in {}", line)))?) + Some(Regex::new(regex.trim()).map_err(|_| TardisError::bad_request(&format!("[Tardis.Error] Regex illegal in {}", line), ""))?) } else { None }; @@ -96,7 +79,7 @@ impl TardisError { pub fn get_localized_message(code: &str, default_message: &str, lang: &str) -> TardisResult { let lang = lang.to_lowercase(); - let conf = LOCALE_CONFIG.lock().map_err(|e| TardisError::Conflict(format!("[Tardis.Error] locale config lock error: {:?}", e)))?; + let conf = LOCALE_CONFIG.lock().map_err(|e| TardisError::conflict(&format!("[Tardis.Error] locale config lock error: {:?}", e), ""))?; if let Some(conf) = conf.get(&lang) { if let Some((message, regex)) = conf.get(code) { let mut localized_message = message.clone(); @@ -121,50 +104,62 @@ impl TardisError { Ok(default_message.to_string()) } - pub fn form(msg: &str) -> TardisError { - let (code, message) = Self::to_tuple(msg.to_string()); - TardisError::Custom(code, message) + fn error(code: &str, msg: &str, locale_code: &str) -> TardisError { + warn!("[Tardis.Error] {}:{}", code, msg); + let message = Self::localized_message(if locale_code.trim().is_empty() { code } else { locale_code }, msg); + TardisError { code: code.to_string(), message } + } + + pub fn localized_message(locale_code: &str, msg: &str) -> String { + if let Some(lang) = &TardisFuns::default_lang() { + TardisError::get_localized_message(locale_code, msg, lang).unwrap_or_else(|_| msg.to_string()) + } else { + msg.to_string() + } } - fn to_tuple(msg: String) -> (String, String) { - let split_idx = msg.find(GENERAL_SPLIT).expect("[Tardis.Error] illegal error description format"); - let code = &msg[..split_idx]; - let message = &msg[split_idx + 2..]; - (code.to_string(), message.to_string()) + pub fn internal_error(msg: &str, locale_code: &str) -> TardisError { + Self::error("500", msg, locale_code) } - pub fn parse(&self) -> (String, String) { - Self::to_tuple(self.to_string()) + pub fn not_implemented(msg: &str, locale_code: &str) -> TardisError { + Self::error("501", msg, locale_code) } - pub fn new(code: u16, msg: &str) -> Option { - match code { - c if (200..300).contains(&c) => None, - 500 => Some(Self::InternalError(msg.to_string())), - 501 => Some(Self::NotImplemented(msg.to_string())), - 503 => Some(Self::IOError(msg.to_string())), - 400 => Some(Self::BadRequest(msg.to_string())), - 401 => Some(Self::Unauthorized(msg.to_string())), - 404 => Some(Self::NotFound(msg.to_string())), - 406 => Some(Self::FormatError(msg.to_string())), - 408 => Some(Self::Timeout(msg.to_string())), - 409 => Some(Self::Conflict(msg.to_string())), - _ => Some(Self::Custom(code.to_string(), msg.to_string())), - } + pub fn io_error(msg: &str, locale_code: &str) -> TardisError { + Self::error("503", msg, locale_code) + } + + pub fn bad_request(msg: &str, locale_code: &str) -> TardisError { + Self::error("400", msg, locale_code) + } + + pub fn unauthorized(msg: &str, locale_code: &str) -> TardisError { + Self::error("401", msg, locale_code) + } + + pub fn not_found(msg: &str, locale_code: &str) -> TardisError { + Self::error("404", msg, locale_code) + } + + pub fn format_error(msg: &str, locale_code: &str) -> TardisError { + Self::error("406", msg, locale_code) + } + + pub fn timeout(msg: &str, locale_code: &str) -> TardisError { + Self::error("408", msg, locale_code) + } + + pub fn conflict(msg: &str, locale_code: &str) -> TardisError { + Self::error("409", msg, locale_code) } - pub fn code(&self) -> String { - let text = self.to_string(); - let split_idx = text.find(GENERAL_SPLIT).expect("[Tardis.Error] illegal code description format"); - let code = &text[..split_idx]; - code.to_string() + pub fn custom(code: &str, msg: &str, locale_code: &str) -> TardisError { + Self::error(code, msg, locale_code) } - pub fn message(&self) -> String { - let text = self.to_string(); - let split_idx = text.find(GENERAL_SPLIT).expect("[Tardis.Error] illegal message description format"); - let message = &text[split_idx + 2..]; - message.to_string() + pub fn wrap(msg: &str, locale_code: &str) -> TardisError { + Self::error(ERROR_DEFAULT_CODE, msg, locale_code) } } @@ -178,8 +173,8 @@ impl TardisErrorWithExt { fn error(&self, code: &str, obj_name: &str, obj_opt: &str, msg: &str, locale_code: &str) -> TardisError { let code = format!("{}-{}-{}-{}", code, self.ext, obj_name, obj_opt); warn!("[Tardis.Error] {}:{}", code, msg); - let msg = self.localized_message(if locale_code.trim().is_empty() { &code } else { locale_code }, msg); - TardisError::Custom(code, msg) + let message = self.localized_message(if locale_code.trim().is_empty() { &code } else { locale_code }, msg); + TardisError { code, message } } pub fn localized_message(&self, locale_code: &str, msg: &str) -> String { @@ -229,54 +224,54 @@ impl TardisErrorWithExt { impl From for TardisError { fn from(error: std::io::Error) -> Self { - TardisError::IOError(error.to_string()) + TardisError::io_error(&format!("[Tardis.Basic] {}", error), "") } } impl From for TardisError { fn from(error: Utf8Error) -> Self { - TardisError::FormatError(error.to_string()) + TardisError::format_error(&format!("[Tardis.Basic] {}", error), "") } } impl From for TardisError { fn from(error: FromUtf8Error) -> Self { - TardisError::FormatError(error.to_string()) + TardisError::format_error(&format!("[Tardis.Basic] {}", error), "") } } impl From for TardisError { fn from(error: url::ParseError) -> Self { - TardisError::FormatError(error.to_string()) + TardisError::format_error(&format!("[Tardis.Basic] {}", error), "") } } impl From for TardisError { fn from(error: ParseIntError) -> Self { - TardisError::FormatError(error.to_string()) + TardisError::format_error(&format!("[Tardis.Basic] {}", error), "") } } impl From for TardisError { fn from(error: Infallible) -> Self { - TardisError::FormatError(error.to_string()) + TardisError::format_error(&format!("[Tardis.Basic] {}", error), "") } } impl From for TardisError { fn from(error: base64::DecodeError) -> Self { - TardisError::FormatError(error.to_string()) + TardisError::format_error(&format!("[Tardis.Basic] {}", error), "") } } impl From for TardisError { fn from(error: hex::FromHexError) -> Self { - TardisError::FormatError(error.to_string()) + TardisError::format_error(&format!("[Tardis.Basic] {}", error), "") } } impl From for TardisError { fn from(error: regex::Error) -> Self { - TardisError::FormatError(error.to_string()) + TardisError::format_error(&format!("[Tardis.Basic] {}", error), "") } } diff --git a/src/basic/field.rs b/src/basic/field.rs index c16d7730..f82c93b7 100644 --- a/src/basic/field.rs +++ b/src/basic/field.rs @@ -14,8 +14,6 @@ lazy_static! { static BASE62: &str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; static BASE36: &str = "0123456789abcdefghijklmnopqrstuvwxyz"; -pub static GENERAL_SPLIT: &str = "##"; - /// Field handle / 字段处理 /// /// Provides some common regular, Id generation and other functions. diff --git a/src/basic/json.rs b/src/basic/json.rs index 51f66123..9b9f0f0a 100644 --- a/src/basic/json.rs +++ b/src/basic/json.rs @@ -56,7 +56,7 @@ impl TardisJson { let result = serde_json::from_str::<'a, T>(str); match result { Ok(r) => Ok(r), - Err(e) => Err(TardisError::Box(Box::new(e))), + Err(err) => Err(TardisError::format_error(&format!("[Tardis.Json] {:?}", err), "406-tardis-json-str-to-obj-error")), } } @@ -75,7 +75,7 @@ impl TardisJson { let result = serde_json::from_str::<'a, Value>(str); match result { Ok(r) => Ok(r), - Err(e) => Err(TardisError::Box(Box::new(e))), + Err(err) => Err(TardisError::format_error(&format!("[Tardis.Json] {:?}", err), "406-tardis-json-str-to-json-error")), } } @@ -94,7 +94,7 @@ impl TardisJson { let result = serde_json::from_value::(value); match result { Ok(r) => Ok(r), - Err(e) => Err(TardisError::Box(Box::new(e))), + Err(err) => Err(TardisError::format_error(&format!("[Tardis.Json] {:?}", err), "406-tardis-json-json-to-obj-error")), } } @@ -113,7 +113,7 @@ impl TardisJson { let result = serde_json::to_string(obj); match result { Ok(r) => Ok(r), - Err(e) => Err(TardisError::Box(Box::new(e))), + Err(err) => Err(TardisError::format_error(&format!("[Tardis.Json] {:?}", err), "406-tardis-json-obj-to-str-error")), } } @@ -132,7 +132,7 @@ impl TardisJson { let result = serde_json::to_value(obj); match result { Ok(r) => Ok(r), - Err(e) => Err(TardisError::Box(Box::new(e))), + Err(err) => Err(TardisError::format_error(&format!("[Tardis.Json] {:?}", err), "406-tardis-json-obj-to-json-error")), } } @@ -151,7 +151,7 @@ impl TardisJson { let result = serde_json::to_string(&value); match result { Ok(r) => Ok(r), - Err(e) => Err(TardisError::Box(Box::new(e))), + Err(err) => Err(TardisError::format_error(&format!("[Tardis.Json] {:?}", err), "406-tardis-json-json-to-str-error")), } } } diff --git a/src/cache/cache_client.rs b/src/cache/cache_client.rs index 5518683a..6937da28 100644 --- a/src/cache/cache_client.rs +++ b/src/cache/cache_client.rs @@ -47,7 +47,7 @@ impl TardisCacheClient { /// Initialize configuration / 初始化配置 pub async fn init(str_url: &str) -> TardisResult { - let url = Url::parse(str_url).map_err(|_| TardisError::BadRequest(format!("[Tardis.CacheClient] Invalid url {}", str_url)))?; + let url = Url::parse(str_url).map_err(|_| TardisError::format_error(&format!("[Tardis.CacheClient] Invalid url {}", str_url), "406-tardis-cache-url-error"))?; info!( "[Tardis.CacheClient] Initializing, host:{}, port:{}, db:{}", url.host_str().unwrap_or(""), @@ -250,6 +250,6 @@ impl TardisCacheClient { impl From for TardisError { fn from(error: RedisError) -> Self { error!("[Tardis.CacheClient] [{}]{},", error.code().unwrap_or(""), error.detail().unwrap_or("")); - TardisError::Box(Box::new(error)) + TardisError::wrap(&format!("[Tardis.CacheClient] {:?}", error), "-1-tardis-cache-error") } } diff --git a/src/db/reldb_client.rs b/src/db/reldb_client.rs index bd6a1db4..1bce4e0d 100644 --- a/src/db/reldb_client.rs +++ b/src/db/reldb_client.rs @@ -161,7 +161,7 @@ impl TardisRelDBClient { connect_timeout_sec: Option, idle_timeout_sec: Option, ) -> TardisResult { - let url = Url::parse(str_url).map_err(|_| TardisError::BadRequest(format!("[Tardis.RelDBClient] Invalid url {}", str_url)))?; + let url = Url::parse(str_url).map_err(|_| TardisError::format_error(&format!("[Tardis.RelDBClient] Invalid url {}", str_url), "406-tardis-reldb-url-error"))?; info!( "[Tardis.RelDBClient] Initializing, host:{}, port:{}, max_connections:{}", url.host_str().unwrap_or(""), @@ -331,10 +331,10 @@ impl TardisRelDBClient { let count_result = CountResp::find_by_statement(count_statement).one(db).await?; match count_result { Some(r) => TardisResult::Ok(r.count as u64), - None => TardisResult::Err(TardisError::InternalError(format!( - "[Tardis.RelDBClient] No results found for count query by {}", - count_sql - ))), + None => TardisResult::Err(TardisError::internal_error( + &format!("[Tardis.RelDBClient] No results found for count query by {}", count_sql), + "500-tardis-reldb-count-empty", + )), } } @@ -429,7 +429,10 @@ impl<'a> TardisRelDBlConnection<'a> { if let Some(tx) = &self.tx { Ok(tx) } else { - Err(TardisError::NotFound("[Tardis.RelDBClient] The current connection has no transactions".to_string())) + Err(TardisError::not_found( + "[Tardis.RelDBClient] The current connection has no transactions", + "404-tardis-reldb-tx-empty", + )) } } @@ -950,7 +953,12 @@ where let sql = self.build(db_backend).sql.replace('?', "''"); let ast = match Parser::parse_sql(&MySqlDialect {}, &sql)?.pop() { Some(ast) => ast, - None => return Err(TardisError::BadRequest("[Tardis.RelDBClient] Sql parsing error, no valid Statement found".to_string())), + None => { + return Err(TardisError::format_error( + "[Tardis.RelDBClient] Sql parsing error, no valid Statement found", + "406-tardis-reldb-sql-error", + )) + } }; let mut table_name = String::new(); if let ast::Statement::Query(query) = ast { @@ -961,8 +969,9 @@ where } } if table_name.is_empty() { - return TardisResult::Err(TardisError::Conflict( - "sql parsing error, the name of the table to be soft deleted was not found".to_string(), + return TardisResult::Err(TardisError::not_found( + "[Tardis.RelDBClient] Sql parsing error, the name of the table to be soft deleted was not found", + "404-tardis-reldb-soft-delete-table-not-exit", )); } @@ -979,14 +988,24 @@ where ids.push( id.as_str() .as_ref() - .ok_or_else(|| TardisError::InternalError(format!("[Tardis.RelDBClient] The primary key [{}] in a soft delete operation is not a character type", id)))? + .ok_or_else(|| { + TardisError::internal_error( + &format!("[Tardis.RelDBClient] The primary key [{}] in a soft delete operation is not a character type", id), + "500-tardis-reldb-id-not-char", + ) + })? .to_string() .into(), ); } else { ids.push( id.as_u64() - .ok_or_else(|| TardisError::InternalError(format!("[Tardis.RelDBClient] The primary key [{}] in a soft delete operation is not a number type", id)))? + .ok_or_else(|| { + TardisError::internal_error( + &format!("[Tardis.RelDBClient] The primary key [{}] in a soft delete operation is not a number type", id), + "500-tardis-reldb-id-not-num", + ) + })? .into(), ); } @@ -1148,13 +1167,13 @@ pub struct IdResp { impl From for TardisError { fn from(error: DbErr) -> Self { error!("[Tardis.RelDBClient] DbErr: {}", error.to_string()); - TardisError::Box(Box::new(error)) + TardisError::wrap(&format!("[Tardis.RelDBClient] {:?}", error), "-1-tardis-reldb-error") } } impl From for TardisError { fn from(error: ParserError) -> Self { error!("[Tardis.RelDBClient] ParserError: {}", error.to_string()); - TardisError::Box(Box::new(error)) + TardisError::wrap(&format!("[Tardis.RelDBClient] {:?}", error), "406-tardis-reldb-sql-error") } } diff --git a/src/lib.rs b/src/lib.rs index 8147ebc7..d4ed238a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -489,6 +489,15 @@ impl TardisFuns { } } + pub fn default_lang() -> Option { + unsafe { + match &TARDIS_INST.framework_config { + None => None, + Some(t) => t.app.default_lang.clone(), + } + } + } + /// Get the Tardis configuration object / 获取Tardis配置对象 pub fn fw_config() -> &'static FrameworkConfig { unsafe { diff --git a/src/mail/mail_client.rs b/src/mail/mail_client.rs index 6a2a2183..e701b483 100644 --- a/src/mail/mail_client.rs +++ b/src/mail/mail_client.rs @@ -38,7 +38,7 @@ impl TardisMailClient { info!("[Tardis.MailClient] Initializing"); let creds = Credentials::new(smtp_username.to_string(), smtp_password.to_string()); let client = AsyncSmtpTransport::::relay(smtp_host) - .map_err(|_| TardisError::InternalError(format!("[Tardis.MailClient] Failed to create SMTP client: {}", smtp_host)))? + .map_err(|_| TardisError::internal_error(&format!("[Tardis.MailClient] Failed to create SMTP client: {}", smtp_host), "500-tardis-mail-init-error"))? .credentials(creds) .port(smtp_port) .build(); @@ -92,7 +92,10 @@ impl TardisMailClient { ); match self.client.send(email).await { Ok(_) => Ok(()), - Err(e) => Err(TardisError::InternalError(format!("[Tardis.MailClient] Could not send email: {}", e))), + Err(e) => Err(TardisError::internal_error( + &format!("[Tardis.MailClient] Could not send email: {}", e), + "-1-tardis-mail-error", + )), } } @@ -123,13 +126,13 @@ pub struct TardisMailSendReq { impl From for TardisError { fn from(error: address::AddressError) -> Self { error!("[Tardis.MailClient] AddressError: {}", error.to_string()); - TardisError::Box(Box::new(error)) + TardisError::wrap(&format!("[Tardis.MailClient] {:?}", error), "-1-tardis-mail-error") } } impl From for TardisError { fn from(error: error::Error) -> Self { error!("[Tardis.MailClient] Error: {}", error.to_string()); - TardisError::Box(Box::new(error)) + TardisError::wrap(&format!("[Tardis.MailClient] {:?}", error), "406-tardis-mail-addr-error") } } diff --git a/src/mq/mq_client.rs b/src/mq/mq_client.rs index 00e77762..c569edee 100644 --- a/src/mq/mq_client.rs +++ b/src/mq/mq_client.rs @@ -28,7 +28,7 @@ impl TardisMQClient { } pub async fn init(str_url: &str) -> TardisResult { - let url = Url::parse(str_url).map_err(|_| TardisError::BadRequest(format!("[Tardis.MQClient] Invalid url {}", str_url)))?; + let url = Url::parse(str_url).map_err(|_| TardisError::format_error(&format!("[Tardis.MQClient] Invalid url {}", str_url), "406-tardis-mq-url-error"))?; info!("[Tardis.MQClient] Initializing, host:{}, port:{}", url.host_str().unwrap_or(""), url.port().unwrap_or(0)); let con = Connection::connect(str_url, ConnectionProperties::default().with_connection_name("tardis".into())).await?; info!("[Tardis.MQClient] Initialized, host:{}, port:{}", url.host_str().unwrap_or(""), url.port().unwrap_or(0)); @@ -70,7 +70,7 @@ impl TardisMQClient { channel.close(200u16, "").await?; Ok(()) } else { - Err(TardisError::InternalError("MQ request confirmation error".to_string())) + Err(TardisError::internal_error("MQ request confirmation error", "500-tardis-mq-confirm-error")) } } @@ -134,7 +134,7 @@ impl TardisMQClient { channel.close(200u16, "").await?; Ok(()) } else { - Err(TardisError::InternalError("MQ request confirmation error".to_string())) + Err(TardisError::internal_error("MQ request confirmation error", "500-tardis-mq-confirm-error")) } } @@ -257,6 +257,6 @@ impl TardisMQClient { impl From for TardisError { fn from(error: lapin::Error) -> Self { error!("[Tardis.MQClient] Error: {}", error.to_string()); - TardisError::Box(Box::new(error)) + TardisError::wrap(&format!("[Tardis.MQClient] {:?}", error), "-1-tardis-mq-error") } } diff --git a/src/os/os_client.rs b/src/os/os_client.rs index 6ce98092..d6f10122 100644 --- a/src/os/os_client.rs +++ b/src/os/os_client.rs @@ -6,7 +6,7 @@ use log::{error, info, trace}; use s3::creds::Credentials; use s3::{Bucket, BucketConfiguration, Region}; -use crate::basic::error::TardisError; +use crate::basic::error::{TardisError, ERROR_DEFAULT_CODE}; use crate::{FrameworkConfig, TardisResult}; pub struct TardisOSClient { @@ -63,7 +63,10 @@ impl TardisOSClient { info!("[Tardis.OSClient] Initialized"); Ok(TardisOSClient { client: Box::new(s3) }) } - _ => Err(TardisError::BadRequest(format!("[Tardis.OSClient] Unsupported OS kind {}", kind))), + _ => Err(TardisError::not_implemented( + &format!("[Tardis.OSClient] Unsupported OS kind {}", kind), + "501-tardis-os-kind-error", + )), } } @@ -141,13 +144,18 @@ impl TardisOSOperations for TardisOSS3Client { if is_private { BucketConfiguration::private() } else { BucketConfiguration::public() }, ) .await?; + if resp.success() { Ok(()) } else { - Err(TardisError::_Inner(format!( - "[Tardis.OSClient] Failed to create bucket {} with error [{}]{}", - bucket_name, resp.response_code, resp.response_text - ))) + Err(TardisError::custom( + &resp.response_code.to_string(), + &format!( + "[Tardis.OSClient] Failed to create bucket {} with error [{}]{}", + bucket_name, resp.response_code, resp.response_text + ), + "-1-tardis-os-create-bucket-error", + )) } } @@ -156,10 +164,11 @@ impl TardisOSOperations for TardisOSS3Client { if code == 200 || code == 204 { Ok(()) } else { - Err(TardisError::_Inner(format!( - "[Tardis.OSClient] Failed to delete bucket {} with error [{}]", - bucket_name, code - ))) + Err(TardisError::custom( + &code.to_string(), + &format!("[Tardis.OSClient] Failed to delete bucket {} with error [{}]", bucket_name, code), + "-1-tardis-os-delete-bucket-error", + )) } } @@ -173,10 +182,11 @@ impl TardisOSOperations for TardisOSS3Client { if code == 200 { Ok(()) } else { - Err(TardisError::_Inner(format!( - "[Tardis.OSClient] Failed to create object {}:{} with error [{}]", - bucket.name, path, code - ))) + Err(TardisError::custom( + &code.to_string(), + &format!("[Tardis.OSClient] Failed to create object {}:{} with error [{}]", bucket.name, path, code), + "-1-tardis-os-create-object-error", + )) } } @@ -186,10 +196,11 @@ impl TardisOSOperations for TardisOSS3Client { if code == 200 { Ok(data) } else { - Err(TardisError::_Inner(format!( - "[Tardis.OSClient] Failed to get object {}:{} with error [{}]", - bucket.name, path, code - ))) + Err(TardisError::custom( + &code.to_string(), + &format!("[Tardis.OSClient] Failed to get object {}:{} with error [{}]", bucket.name, path, code), + "-1-tardis-os-get-object-error", + )) } } @@ -199,10 +210,11 @@ impl TardisOSOperations for TardisOSS3Client { if code == 200 || code == 204 { Ok(()) } else { - Err(TardisError::_Inner(format!( - "[Tardis.OSClient] Failed to delete object {}:{} with error [{}]", - bucket.name, path, code - ))) + Err(TardisError::custom( + &code.to_string(), + &format!("[Tardis.OSClient] Failed to delete object {}:{} with error [{}]", bucket.name, path, code), + "-1-tardis-os-delete-object-error", + )) } } @@ -224,7 +236,8 @@ impl TardisOSS3Client { if let Some(bucket_name) = bucket_name { Ok(Bucket::new(bucket_name, self.region.clone(), self.credentials.clone())?.with_path_style()) } else { - let bucket = self.default_bucket.as_ref().ok_or_else(|| TardisError::BadRequest("[Tardis.OSClient] No default bucket configured".to_string()))?; + let bucket = + self.default_bucket.as_ref().ok_or_else(|| TardisError::not_found("[Tardis.OSClient] No default bucket configured", "404-tardis-os-default-bucket-not-exist"))?; Ok(bucket.clone()) } } @@ -319,6 +332,6 @@ impl TardisOSS3Client { impl From for TardisError { fn from(error: s3::error::S3Error) -> Self { error!("[Tardis.OSClient] Error: {}", error.to_string()); - TardisError::_Inner(error.to_string()) + TardisError::custom(ERROR_DEFAULT_CODE, &format!("[Tardis.OSClient] Error: {:?}", error), "-1-tardis-os-error") } } diff --git a/src/search/search_client.rs b/src/search/search_client.rs index 89b49bc1..0072abfc 100644 --- a/src/search/search_client.rs +++ b/src/search/search_client.rs @@ -68,10 +68,14 @@ impl TardisSearchClient { trace!("[Tardis.SearchClient] Creating index: {}", index_name); let url = format!("{}/{}", self.server_url, index_name); let resp = self.client.put_str_to_str(&url, "", None).await?; - if let Some(err) = TardisError::new(resp.code, resp.body.as_ref().unwrap_or(&"".to_string())) { - Err(err) - } else { + if resp.code >= 200 && resp.code <= 300 { Ok(()) + } else { + Err(TardisError::custom( + &resp.code.to_string(), + &format!("[Tardis.SearchClient] Create index error: {}", resp.body.as_ref().unwrap_or(&"".to_string())), + "-1-tardis-search-error", + )) } } @@ -91,11 +95,15 @@ impl TardisSearchClient { trace!("[Tardis.SearchClient] Creating record: {}, data:{}", index_name, data); let url = format!("{}/{}/_doc/", self.server_url, index_name); let resp = self.client.post_str_to_str(&url, data, None).await?; - if let Some(err) = TardisError::new(resp.code, resp.body.as_ref().unwrap_or(&"".to_string())) { - Err(err) - } else { + if resp.code >= 200 && resp.code <= 300 { let result = TardisFuns::json.str_to_json(&resp.body.unwrap_or_else(|| "".to_string()))?; - Ok(result["_id"].as_str().ok_or_else(|| TardisError::FormatError("[Tardis.SearchClient] [_id] structure not found".to_string()))?.to_string()) + Ok(result["_id"].as_str().ok_or_else(|| TardisError::bad_request("[Tardis.SearchClient] [_id] structure not found", "400-tardis-search-id-not-exist"))?.to_string()) + } else { + Err(TardisError::custom( + &resp.code.to_string(), + &format!("[Tardis.SearchClient] Create record error: {}", resp.body.as_ref().unwrap_or(&"".to_string())), + "-1-tardis-search-error", + )) } } @@ -115,11 +123,15 @@ impl TardisSearchClient { trace!("[Tardis.SearchClient] Getting record: {}, id:{}", index_name, id); let url = format!("{}/{}/_doc/{}", self.server_url, index_name, id); let resp = self.client.get_to_str(&url, None).await?; - if let Some(err) = TardisError::new(resp.code, resp.body.as_ref().unwrap_or(&"".to_string())) { - Err(err) - } else { + if resp.code >= 200 && resp.code <= 300 { let result = TardisFuns::json.str_to_json(&resp.body.unwrap_or_else(|| "".to_string()))?; Ok(result["_source"].to_string()) + } else { + Err(TardisError::custom( + &resp.code.to_string(), + &format!("[Tardis.SearchClient] Get record error: {}", resp.body.as_ref().unwrap_or(&"".to_string())), + "-1-tardis-search-error", + )) } } @@ -139,10 +151,14 @@ impl TardisSearchClient { trace!("[Tardis.SearchClient] Simple search: {}, q:{}", index_name, q); let url = format!("{}/{}/_search?q={}", self.server_url, index_name, q); let resp = self.client.get_to_str(&url, None).await?; - if let Some(err) = TardisError::new(resp.code, resp.body.as_ref().unwrap_or(&"".to_string())) { - Err(err) - } else { + if resp.code >= 200 && resp.code <= 300 { Self::parse_search_result(&resp.body.unwrap_or_else(|| "".to_string())) + } else { + Err(TardisError::custom( + &resp.code.to_string(), + &format!("[Tardis.SearchClient] Simple search error: {}", resp.body.as_ref().unwrap_or(&"".to_string())), + "-1-tardis-search-error", + )) } } @@ -181,10 +197,14 @@ impl TardisSearchClient { trace!("[Tardis.SearchClient] Raw search: {}, q:{}", index_name, q); let url = format!("{}/{}/_search", self.server_url, index_name); let resp = self.client.post_str_to_str(&url, q, None).await?; - if let Some(err) = TardisError::new(resp.code, resp.body.as_ref().unwrap_or(&"".to_string())) { - Err(err) - } else { + if resp.code >= 200 && resp.code <= 300 { Self::parse_search_result(&resp.body.unwrap_or_else(|| "".to_string())) + } else { + Err(TardisError::custom( + &resp.code.to_string(), + &format!("[Tardis.SearchClient] Raw search error: {}", resp.body.as_ref().unwrap_or(&"".to_string())), + "-1-tardis-search-error", + )) } } @@ -192,7 +212,7 @@ impl TardisSearchClient { let json = TardisFuns::json.str_to_json(result)?; let json = json["hits"]["hits"] .as_array() - .ok_or_else(|| TardisError::FormatError("[Tardis.SearchClient] [hit.hit] structure not found".to_string()))? + .ok_or_else(|| TardisError::format_error("[Tardis.SearchClient] [hit.hit] structure not found", "406-tardis-search-hit-not-exist"))? .iter() .map(|x| x["_source"].to_string()) .collect(); diff --git a/src/web/context_extractor.rs b/src/web/context_extractor.rs index 5434bc86..6c54712a 100644 --- a/src/web/context_extractor.rs +++ b/src/web/context_extractor.rs @@ -19,7 +19,7 @@ async fn context_checker(req: &Request, _: ApiKey) -> Option { match extract_context(req).await { Ok(context) => Some(context), Err(err) => { - log::warn!("{} at {}", err.message(), req.uri()); + log::warn!("[Tardis.WebServer] [{}]{} at {}", err.code, err.message, req.uri()); None } } @@ -30,26 +30,42 @@ async fn extract_context(req: &Request) -> TardisResult { let context = req .headers() .get(context_header_name) - .ok_or_else(|| TardisError::BadRequest(format!("[Tardis.WebServer] {} is not found", context_header_name)))? + .ok_or_else(|| { + TardisError::bad_request( + &format!("[Tardis.WebServer] {} is not found", context_header_name), + "400-tardis-webserver-context-header-not-exist", + ) + })? .to_str() - .map_err(|_| TardisError::BadRequest("[Tardis.WebServer] Context header is not string".to_string()))?; + .map_err(|_| TardisError::bad_request("[Tardis.WebServer] Context header is not string", "400-tardis-webserver-context-not-str"))?; if !context.starts_with(TOKEN_FLAG) { - let context = base64::decode(context).map_err(|_| TardisError::BadRequest("[Tardis.WebServer] Context header is not base64".to_string()))?; - let context = String::from_utf8(context).map_err(|_| TardisError::BadRequest("[Tardis.WebServer] Context header is not utf8".to_string()))?; - let context = TardisFuns::json.str_to_obj(&context).map_err(|_| TardisError::BadRequest("[Tardis.WebServer] Context header is not valid json".to_string()))?; + let context = + base64::decode(context).map_err(|_| TardisError::bad_request("[Tardis.WebServer] Context header is not base64", "400-tardis-webserver-context-not-base64"))?; + let context = String::from_utf8(context).map_err(|_| TardisError::bad_request("[Tardis.WebServer] Context header is not utf8", "400-tardis-webserver-context-not-utf8"))?; + let context = TardisFuns::json + .str_to_obj(&context) + .map_err(|_| TardisError::bad_request("[Tardis.WebServer] Context header is invalid json", "400-tardis-webserver-context-not-json"))?; Ok(context) } else { #[cfg(feature = "cache")] { - let token = context.split(TOKEN_FLAG).nth(1).ok_or_else(|| TardisError::BadRequest("[Tardis.WebServer] Context header is not valid".to_string()))?; + let token = context + .split(TOKEN_FLAG) + .nth(1) + .ok_or_else(|| TardisError::bad_request("[Tardis.WebServer] Context header is invalid", "400-tardis-webserver-context-not-valid"))?; let context = TardisFuns::cache().get(format!("{}{}", TardisFuns::fw_config().web_server.context_conf.token_cache_key, token).as_str()).await?; - let context = context.ok_or_else(|| TardisError::BadRequest("[Tardis.WebServer] Token is not in cache".to_string()))?; - let context = TardisFuns::json.str_to_obj(&context).map_err(|_| TardisError::BadRequest("[Tardis.WebServer] Context cache is not valid json".to_string()))?; + let context = context.ok_or_else(|| TardisError::bad_request("[Tardis.WebServer] Token is not in cache", "400-tardis-webserver-context-not-in-cache"))?; + let context = TardisFuns::json + .str_to_obj(&context) + .map_err(|_| TardisError::bad_request("[Tardis.WebServer] Context cache is invalid json", "400-tardis-webserver-context-not-json"))?; Ok(context) } #[cfg(not(feature = "cache"))] { - Err(TardisError::BadRequest("[Tardis.WebServer] Context is not found".to_string())) + Err(TardisError::bad_request( + "[Tardis.WebServer] Context is not found", + "400-tardis-webserver-context-header-not-exist", + )) } } } diff --git a/src/web/uniform_error_mw.rs b/src/web/uniform_error_mw.rs index 9ee363e1..ce2e99fc 100644 --- a/src/web/uniform_error_mw.rs +++ b/src/web/uniform_error_mw.rs @@ -65,7 +65,7 @@ impl Endpoint for UniformErrorImpl { ); let (bus_code, msg) = if let Some(error) = mapping_http_code_to_error(http_code, &msg) { - error.parse() + (error.code, error.message) } else { (TARDIS_RESULT_SUCCESS_CODE.to_string(), "".to_string()) }; @@ -80,11 +80,10 @@ impl Endpoint for UniformErrorImpl { } Err(err) => { let error: TardisError = err.into(); - let (bus_code, msg) = error.parse(); Ok(Response::builder().status(StatusCode::OK).header("Content-Type", "application/json; charset=utf8").body( json!({ - "code": bus_code, - "msg": process_err_msg(bus_code.as_str(),msg), + "code": error.code, + "msg": process_err_msg(error.code.as_str(),error.message), }) .to_string(), )) @@ -96,7 +95,7 @@ impl Endpoint for UniformErrorImpl { fn process_err_msg(code: &str, msg: String) -> String { if TardisFuns::fw_config().web_server.security_hide_err_msg { warn!("[Tardis.WebServer] Pesponse error,code:{},msg:{}", code, msg); - "Security is enabled, detailed errors are hidden, please check the server logs".to_string() + "[Tardis.WebServer] Security is enabled, detailed errors are hidden, please check the server logs".to_string() } else { msg } diff --git a/src/web/web_client.rs b/src/web/web_client.rs index e8bc2ed9..21cfdc4e 100644 --- a/src/web/web_client.rs +++ b/src/web/web_client.rs @@ -181,14 +181,14 @@ impl TardisWebClient { async fn to_text(&self, code: u16, headers: HashMap, response: Response) -> TardisResult> { match response.text().await { Ok(body) => Ok(TardisHttpResponse { code, headers, body: Some(body) }), - Err(err) => Err(TardisError::Box(Box::new(err))), + Err(err) => Err(TardisError::format_error(&format!("[Tardis.WebClient] {:?}", err), "406-tardis-webclient-text-error")), } } async fn to_json(&self, code: u16, headers: HashMap, response: Response) -> TardisResult> { match response.json().await { Ok(body) => Ok(TardisHttpResponse { code, headers, body: Some(body) }), - Err(err) => Err(TardisError::Box(Box::new(err))), + Err(err) => Err(TardisError::format_error(&format!("[Tardis.WebClient] {:?}", err), "406-tardis-webclient-json-error")), } } @@ -207,6 +207,6 @@ pub struct TardisHttpResponse { impl From for TardisError { fn from(error: reqwest::Error) -> Self { error!("[Tardis.WebClient] Error: {}", error.to_string()); - TardisError::Box(Box::new(error)) + TardisError::wrap(&format!("[Tardis.WebClient] {:?}", error), "-1-tardis-webclient-error") } } diff --git a/src/web/web_resp.rs b/src/web/web_resp.rs index 46b2ff8e..f3fe6a10 100644 --- a/src/web/web_resp.rs +++ b/src/web/web_resp.rs @@ -1,6 +1,7 @@ use crate::basic::error::TardisError; use crate::basic::result::TARDIS_RESULT_SUCCESS_CODE; use crate::serde::{Deserialize, Serialize}; +use crate::TardisFuns; use poem::http::StatusCode; use poem_openapi::payload::Json; use poem_openapi::{ @@ -14,24 +15,50 @@ pub type TardisApiResult = poem::Result>>; impl From for poem::Error { fn from(error: TardisError) -> Self { - let status_code = match error { - // TODO - TardisError::Custom(_, _) => StatusCode::BAD_REQUEST, - // TODO - TardisError::_Inner(_) => StatusCode::BAD_REQUEST, - // TODO - TardisError::Box(_) => StatusCode::BAD_REQUEST, - TardisError::InternalError(_) => StatusCode::INTERNAL_SERVER_ERROR, - TardisError::NotImplemented(_) => StatusCode::NOT_IMPLEMENTED, - TardisError::IOError(_) => StatusCode::INTERNAL_SERVER_ERROR, - TardisError::BadRequest(_) => StatusCode::BAD_REQUEST, - TardisError::Unauthorized(_) => StatusCode::UNAUTHORIZED, - TardisError::NotFound(_) => StatusCode::NOT_FOUND, - TardisError::FormatError(_) => StatusCode::BAD_REQUEST, - TardisError::Timeout(_) => StatusCode::REQUEST_TIMEOUT, - TardisError::Conflict(_) => StatusCode::CONFLICT, + let status_code = match &error.code { + c if c.starts_with("400") => StatusCode::BAD_REQUEST, + c if c.starts_with("401") => StatusCode::UNAUTHORIZED, + c if c.starts_with("403") => StatusCode::FORBIDDEN, + c if c.starts_with("404") => StatusCode::NOT_FOUND, + c if c.starts_with("405") => StatusCode::METHOD_NOT_ALLOWED, + c if c.starts_with("406") => StatusCode::NOT_ACCEPTABLE, + c if c.starts_with("408") => StatusCode::REQUEST_TIMEOUT, + c if c.starts_with("409") => StatusCode::CONFLICT, + c if c.starts_with("410") => StatusCode::GONE, + c if c.starts_with("411") => StatusCode::LENGTH_REQUIRED, + c if c.starts_with("412") => StatusCode::PRECONDITION_FAILED, + c if c.starts_with("413") => StatusCode::PAYLOAD_TOO_LARGE, + c if c.starts_with("414") => StatusCode::URI_TOO_LONG, + c if c.starts_with("415") => StatusCode::UNSUPPORTED_MEDIA_TYPE, + c if c.starts_with("416") => StatusCode::RANGE_NOT_SATISFIABLE, + c if c.starts_with("417") => StatusCode::EXPECTATION_FAILED, + c if c.starts_with("418") => StatusCode::IM_A_TEAPOT, + c if c.starts_with("421") => StatusCode::MISDIRECTED_REQUEST, + c if c.starts_with("422") => StatusCode::UNPROCESSABLE_ENTITY, + c if c.starts_with("423") => StatusCode::LOCKED, + c if c.starts_with("424") => StatusCode::FAILED_DEPENDENCY, + c if c.starts_with("426") => StatusCode::UPGRADE_REQUIRED, + c if c.starts_with("428") => StatusCode::PRECONDITION_REQUIRED, + c if c.starts_with("429") => StatusCode::TOO_MANY_REQUESTS, + c if c.starts_with("431") => StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE, + c if c.starts_with("451") => StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS, + c if c.starts_with("500") => StatusCode::INTERNAL_SERVER_ERROR, + c if c.starts_with("501") => StatusCode::NOT_IMPLEMENTED, + c if c.starts_with("502") => StatusCode::BAD_GATEWAY, + c if c.starts_with("503") => StatusCode::SERVICE_UNAVAILABLE, + c if c.starts_with("504") => StatusCode::GATEWAY_TIMEOUT, + c if c.starts_with("505") => StatusCode::HTTP_VERSION_NOT_SUPPORTED, + c if c.starts_with("506") => StatusCode::VARIANT_ALSO_NEGOTIATES, + c if c.starts_with("507") => StatusCode::INSUFFICIENT_STORAGE, + c if c.starts_with("508") => StatusCode::LOOP_DETECTED, + c if c.starts_with("510") => StatusCode::NOT_EXTENDED, + c if c.starts_with("511") => StatusCode::NETWORK_AUTHENTICATION_REQUIRED, + _ => StatusCode::INTERNAL_SERVER_ERROR, }; - poem::Error::from_string(format!("{}{}", TARDIS_ERROR_FLAG, error), status_code) + poem::Error::from_string( + format!("{}{}", TARDIS_ERROR_FLAG, TardisFuns::json.obj_to_string(&error).unwrap_or_else(|_| "".to_string())), + status_code, + ) } } @@ -40,7 +67,7 @@ impl From for TardisError { let msg = error.to_string(); if msg.starts_with(TARDIS_ERROR_FLAG) { let msg = msg.split_at(TARDIS_ERROR_FLAG.len()).1.to_string(); - return TardisError::form(&msg); + return TardisFuns::json.str_to_obj(&msg).unwrap_or_else(|_| TardisError::format_error("[Tardis.WebServer] Invalid format error", "406-tardis-error-invalid")); } let msg = &error.to_string(); let http_code = error.into_response().status(); @@ -51,16 +78,23 @@ impl From for TardisError { pub fn mapping_http_code_to_error(http_code: StatusCode, msg: &str) -> Option { if msg.starts_with(TARDIS_ERROR_FLAG) { let msg = msg.split_at(TARDIS_ERROR_FLAG.len()).1.to_string(); - return Some(TardisError::form(&msg)); + let error = TardisFuns::json.str_to_obj(&msg).unwrap_or_else(|_| TardisError::format_error("[Tardis.WebServer] Invalid format error", "406-tardis-error-invalid")); + return Some(error); } match http_code { StatusCode::OK => None, - StatusCode::BAD_REQUEST => Some(TardisError::BadRequest(msg.to_string())), - StatusCode::UNAUTHORIZED => Some(TardisError::Unauthorized(msg.to_string())), - StatusCode::NOT_FOUND => Some(TardisError::NotFound(msg.to_string())), - StatusCode::INTERNAL_SERVER_ERROR => Some(TardisError::InternalError(msg.to_string())), - StatusCode::SERVICE_UNAVAILABLE => Some(TardisError::InternalError(msg.to_string())), - _ => Some(TardisError::BadRequest(msg.to_string())), + _ => Some(TardisError::custom( + http_code.as_str(), + &format!("[Tardis.WebServer] Process error: {}", msg), + &format!( + "{}-tardis-webserver-error", + if [400, 401, 404, 406, 408, 409, 500, 501].contains(&http_code.as_u16()) { + http_code.as_str() + } else { + "-1" + } + ), + )), } } diff --git a/tests/test_basic_error.rs b/tests/test_basic_error.rs index 3778080a..97f217e1 100644 --- a/tests/test_basic_error.rs +++ b/tests/test_basic_error.rs @@ -25,15 +25,15 @@ async fn test_basic_error() -> TardisResult<()> { let inst = TardisFuns::inst("m1".to_string(), Some("zh-CN".to_string())); - assert_eq!(inst.err().not_found("res", "add", "Not found RES1 resource in m1", "").message(), "在m1中找不到[RES1]资源"); + assert_eq!(inst.err().not_found("res", "add", "Not found RES1 resource in m1", "").message, "在m1中找不到[RES1]资源"); assert_eq!( - inst.err().not_found("xx", "add", "Not found RES1 resource in m1", "").message(), + inst.err().not_found("xx", "add", "Not found RES1 resource in m1", "").message, "Not found RES1 resource in m1" ); assert_eq!( - inst.err().not_found("xx", "add", "Not found RES1 resource in m1", "404-m1-res-add").message(), + inst.err().not_found("xx", "add", "Not found RES1 resource in m1", "404-m1-res-add").message, "在m1中找不到[RES1]资源" ); diff --git a/tests/test_cache_client.rs b/tests/test_cache_client.rs index 993a2695..90987f6f 100644 --- a/tests/test_cache_client.rs +++ b/tests/test_cache_client.rs @@ -204,7 +204,7 @@ async fn test_concurrent() -> TardisResult<()> { let _ = threads .into_iter() - .map(|i| { + .map(|_| { tokio::task::spawn(async { let client = TardisFuns::cache_by_module("m1"); let id = TardisFuns::field.nanoid(); diff --git a/tests/test_reldb_client.rs b/tests/test_reldb_client.rs index 12a76837..69d8ebfb 100644 --- a/tests/test_reldb_client.rs +++ b/tests/test_reldb_client.rs @@ -80,7 +80,7 @@ async fn test_raw_query(client: &TardisRelDBClient) -> TardisResult<()> { ) .await?; - #[derive(Debug, FromQueryResult)] + #[derive(FromQueryResult)] struct TenantResp { id: String, name: String, diff --git a/tests/test_web_server.rs b/tests/test_web_server.rs index 5faee485..0611c3fa 100644 --- a/tests/test_web_server.rs +++ b/tests/test_web_server.rs @@ -168,23 +168,23 @@ async fn test_basic(url: &str) -> TardisResult<()> { // Business Error let response = TardisFuns::web_client().get::>(format!("{}/todo/todos/1/err", url).as_str(), None).await?.body.unwrap(); - assert_eq!(response.code, TardisError::Conflict("异常".to_string()).code()); - assert_eq!(response.msg, TardisError::Conflict("异常".to_string()).message()); + assert_eq!(response.code, TardisError::conflict("异常", "").code); + assert_eq!(response.msg, TardisError::conflict("异常", "").message); // Not Found let response = TardisFuns::web_client().get::>(format!("{}/todo/todos/1/ss", url).as_str(), None).await?.body.unwrap(); - assert_eq!(response.code, TardisError::NotFound("".to_string()).code()); - assert_eq!(response.msg, "not found"); + assert_eq!(response.code, TardisError::not_found("", "").code); + assert_eq!(response.msg, "[Tardis.WebServer] Process error: not found"); Ok(()) } async fn test_validate(url: &str) -> TardisResult<()> { let response = TardisFuns::web_client().get::>(format!("{}/todo/todos/ss", url).as_str(), None).await?.body.unwrap(); - assert_eq!(response.code, TardisError::NotFound("".to_string()).code()); + assert_eq!(response.code, TardisError::not_found("", "").code); assert_eq!( response.msg, - r#"failed to parse path `id`: failed to parse "integer(int64)": invalid digit found in string"# + r#"[Tardis.WebServer] Process error: failed to parse path `id`: failed to parse "integer(int64)": invalid digit found in string"# ); let response = TardisFuns::web_client() @@ -205,10 +205,10 @@ async fn test_validate(url: &str) -> TardisResult<()> { .await? .body .unwrap(); - assert_eq!(response.code, TardisError::BadRequest("".to_string()).code()); + assert_eq!(response.code, TardisError::bad_request("", "").code); assert_eq!( response.msg, - r#"parse request payload error: failed to parse "ValidateReq": field `len` verification failed. minLength(1)"# + r#"[Tardis.WebServer] Process error: parse request payload error: failed to parse "ValidateReq": field `len` verification failed. minLength(1)"# ); let response = TardisFuns::web_client() @@ -229,10 +229,10 @@ async fn test_validate(url: &str) -> TardisResult<()> { .await? .body .unwrap(); - assert_eq!(response.code, TardisError::BadRequest("".to_string()).code()); + assert_eq!(response.code, TardisError::bad_request("", "").code); assert_eq!( response.msg, - r#"parse request payload error: failed to parse "ValidateReq": field `eq` verification failed. minLength(5)"# + r#"[Tardis.WebServer] Process error: parse request payload error: failed to parse "ValidateReq": field `eq` verification failed. minLength(5)"# ); let response = TardisFuns::web_client() @@ -253,10 +253,10 @@ async fn test_validate(url: &str) -> TardisResult<()> { .await? .body .unwrap(); - assert_eq!(response.code, TardisError::BadRequest("".to_string()).code()); + assert_eq!(response.code, TardisError::bad_request("", "").code); assert_eq!( response.msg, - r#"parse request payload error: failed to parse "ValidateReq": field `range` verification failed. minimum(1, exclusive: false)"# + r#"[Tardis.WebServer] Process error: parse request payload error: failed to parse "ValidateReq": field `range` verification failed. minimum(1, exclusive: false)"# ); let response = TardisFuns::web_client() @@ -277,10 +277,10 @@ async fn test_validate(url: &str) -> TardisResult<()> { .await? .body .unwrap(); - assert_eq!(response.code, TardisError::BadRequest("".to_string()).code()); + assert_eq!(response.code, TardisError::bad_request("", "").code); assert_eq!( response.msg, - r#"parse request payload error: failed to parse "ValidateReq": field `mail` verification failed. Invalid mail format"# + r#"[Tardis.WebServer] Process error: parse request payload error: failed to parse "ValidateReq": field `mail` verification failed. Invalid mail format"# ); let response = TardisFuns::web_client() @@ -301,10 +301,10 @@ async fn test_validate(url: &str) -> TardisResult<()> { .await? .body .unwrap(); - assert_eq!(response.code, TardisError::BadRequest("".to_string()).code()); + assert_eq!(response.code, TardisError::bad_request("", "").code); assert_eq!( response.msg, - r#"parse request payload error: failed to parse "ValidateReq": field `contain` verification failed. pattern(".*gmail.*")"# + r#"[Tardis.WebServer] Process error: parse request payload error: failed to parse "ValidateReq": field `contain` verification failed. pattern(".*gmail.*")"# ); let response = TardisFuns::web_client() @@ -325,10 +325,10 @@ async fn test_validate(url: &str) -> TardisResult<()> { .await? .body .unwrap(); - assert_eq!(response.code, TardisError::BadRequest("".to_string()).code()); + assert_eq!(response.code, TardisError::bad_request("", "").code); assert_eq!( response.msg, - r#"parse request payload error: failed to parse "ValidateReq": field `phone` verification failed. Invalid phone number format"# + r#"[Tardis.WebServer] Process error: parse request payload error: failed to parse "ValidateReq": field `phone` verification failed. Invalid phone number format"# ); let response = TardisFuns::web_client() @@ -349,10 +349,10 @@ async fn test_validate(url: &str) -> TardisResult<()> { .await? .body .unwrap(); - assert_eq!(response.code, TardisError::BadRequest("".to_string()).code()); + assert_eq!(response.code, TardisError::bad_request("", "").code); assert_eq!( response.msg, - r#"parse request payload error: failed to parse "ValidateReq": field `item_len` verification failed. minItems(1)"# + r#"[Tardis.WebServer] Process error: parse request payload error: failed to parse "ValidateReq": field `item_len` verification failed. minItems(1)"# ); let response = TardisFuns::web_client() @@ -373,10 +373,10 @@ async fn test_validate(url: &str) -> TardisResult<()> { .await? .body .unwrap(); - assert_eq!(response.code, TardisError::BadRequest("".to_string()).code()); + assert_eq!(response.code, TardisError::bad_request("", "").code); assert_eq!( response.msg, - r#"parse request payload error: failed to parse "ValidateReq": field `item_unique` verification failed. uniqueItems()"# + r#"[Tardis.WebServer] Process error: parse request payload error: failed to parse "ValidateReq": field `item_unique` verification failed. uniqueItems()"# ); let response = TardisFuns::web_client() @@ -404,8 +404,8 @@ async fn test_validate(url: &str) -> TardisResult<()> { async fn test_context(url: &str) -> TardisResult<()> { let response = TardisFuns::web_client().get::>(format!("{}/other/context_in_header", url).as_str(), None).await?.body.unwrap(); - assert_eq!(response.code, TardisError::Unauthorized("".to_string()).code()); - assert_eq!(response.msg, "authorization error"); + assert_eq!(response.code, TardisError::unauthorized("", "").code); + assert_eq!(response.msg, "[Tardis.WebServer] Process error: authorization error"); // from header let response = TardisFuns::web_client() @@ -416,8 +416,8 @@ async fn test_context(url: &str) -> TardisResult<()> { .await? .body .unwrap(); - assert_eq!(response.code, TardisError::Unauthorized("".to_string()).code()); - assert_eq!(response.msg, "authorization error"); + assert_eq!(response.code, TardisError::unauthorized("", "").code); + assert_eq!(response.msg, "[Tardis.WebServer] Process error: authorization error"); let response = TardisFuns::web_client() .get::>( @@ -427,8 +427,8 @@ async fn test_context(url: &str) -> TardisResult<()> { .await? .body .unwrap(); - assert_eq!(response.code, TardisError::Unauthorized("".to_string()).code()); - assert_eq!(response.msg, "authorization error"); + assert_eq!(response.code, TardisError::unauthorized("", "").code); + assert_eq!(response.msg, "[Tardis.WebServer] Process error: authorization error"); let context = TardisContext { own_paths: "tenant1/app1".to_string(), @@ -448,8 +448,8 @@ async fn test_context(url: &str) -> TardisResult<()> { .await? .body .unwrap(); - assert_eq!(response.code, TardisError::Unauthorized("".to_string()).code()); - assert_eq!(response.msg, "authorization error"); + assert_eq!(response.code, TardisError::unauthorized("", "").code); + assert_eq!(response.msg, "[Tardis.WebServer] Process error: authorization error"); let response = TardisFuns::web_client() .get::>( @@ -477,8 +477,8 @@ async fn test_context(url: &str) -> TardisResult<()> { .await? .body .unwrap(); - assert_eq!(response.code, TardisError::Unauthorized("".to_string()).code()); - assert_eq!(response.msg, "authorization error"); + assert_eq!(response.code, TardisError::unauthorized("", "").code); + assert_eq!(response.msg, "[Tardis.WebServer] Process error: authorization error"); let context = TardisContext { own_paths: "tenant1/app1".to_string(), @@ -600,13 +600,19 @@ async fn test_security() -> TardisResult<()> { // Business Error let response = TardisFuns::web_client().get::>(format!("{}/todo/todos/1/err", url).as_str(), None).await?.body.unwrap(); - assert_eq!(response.code, TardisError::Conflict("异常".to_string()).code()); - assert_eq!(response.msg, "Security is enabled, detailed errors are hidden, please check the server logs"); + assert_eq!(response.code, TardisError::conflict("异常", "").code); + assert_eq!( + response.msg, + "[Tardis.WebServer] Security is enabled, detailed errors are hidden, please check the server logs" + ); // Not Found let response = TardisFuns::web_client().get::>(format!("{}/todo/todos/1/ss", url).as_str(), None).await?.body.unwrap(); - assert_eq!(response.code, TardisError::NotFound("".to_string()).code()); - assert_eq!(response.msg, "Security is enabled, detailed errors are hidden, please check the server logs"); + assert_eq!(response.code, TardisError::not_found("", "").code); + assert_eq!( + response.msg, + "[Tardis.WebServer] Security is enabled, detailed errors are hidden, please check the server logs" + ); let response = TardisFuns::web_client() .post::>( @@ -626,8 +632,11 @@ async fn test_security() -> TardisResult<()> { .await? .body .unwrap(); - assert_eq!(response.code, TardisError::BadRequest("".to_string()).code()); - assert_eq!(response.msg, "Security is enabled, detailed errors are hidden, please check the server logs"); + assert_eq!(response.code, TardisError::bad_request("", "").code); + assert_eq!( + response.msg, + "[Tardis.WebServer] Security is enabled, detailed errors are hidden, please check the server logs" + ); Ok(()) } @@ -700,7 +709,7 @@ impl TodosApi { #[oai(path = "/todos/:id/err", method = "get")] async fn get_by_error(&self, id: Path) -> TardisApiResult { - TardisResp::err(TardisError::Conflict("异常".to_string())) + TardisResp::err(TardisError::conflict("异常", "")) } }