//! //! use beteran_protobuf_rust as bpr; use prost::Message; use serde::{Deserialize, Serialize}; use std::fmt; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Parse { pub message: String, } impl fmt::Display for Parse { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "parse error: {}", self.message) } } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct InvalidRequest { pub message: String, } impl fmt::Display for InvalidRequest { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "invalid request error: {}", self.message) } } /// #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] pub enum InvalidParamsType { None, DateTime, Decimal, EqualsTo, Float, Integer, Range, RegEx, Required, StringLength, Url, } impl fmt::Display for InvalidParamsType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { InvalidParamsType::None => { write!(f, "None") } InvalidParamsType::DateTime => { write!(f, "DateTime error") } InvalidParamsType::Decimal => { write!(f, "Decimal error") } InvalidParamsType::EqualsTo => { write!(f, "EqualsTo error") } InvalidParamsType::Float => { write!(f, "Float error") } InvalidParamsType::Integer => { write!(f, "Integer error") } InvalidParamsType::Range => { write!(f, "Range error") } InvalidParamsType::RegEx => { write!(f, "RegEx error") } InvalidParamsType::Required => { write!(f, "Required error") } InvalidParamsType::StringLength => { write!(f, "String Length error") } InvalidParamsType::Url => { write!(f, "Url error") } } } } impl From for bpr::protobuf::rpc::InvalidParamsType { fn from(t: InvalidParamsType) -> Self { match t { InvalidParamsType::None => bpr::protobuf::rpc::InvalidParamsType::None, InvalidParamsType::DateTime => bpr::protobuf::rpc::InvalidParamsType::DateTime, InvalidParamsType::Decimal => bpr::protobuf::rpc::InvalidParamsType::Decimal, InvalidParamsType::EqualsTo => bpr::protobuf::rpc::InvalidParamsType::EqualsTo, InvalidParamsType::Float => bpr::protobuf::rpc::InvalidParamsType::Float, InvalidParamsType::Integer => bpr::protobuf::rpc::InvalidParamsType::Integer, InvalidParamsType::Range => bpr::protobuf::rpc::InvalidParamsType::Range, InvalidParamsType::RegEx => bpr::protobuf::rpc::InvalidParamsType::RegEx, InvalidParamsType::Required => bpr::protobuf::rpc::InvalidParamsType::Required, InvalidParamsType::StringLength => bpr::protobuf::rpc::InvalidParamsType::StringLength, InvalidParamsType::Url => bpr::protobuf::rpc::InvalidParamsType::Url, } } } impl From for InvalidParamsType { fn from(t: bpr::protobuf::rpc::InvalidParamsType) -> Self { match t { bpr::protobuf::rpc::InvalidParamsType::None => InvalidParamsType::None, bpr::protobuf::rpc::InvalidParamsType::DateTime => InvalidParamsType::DateTime, bpr::protobuf::rpc::InvalidParamsType::Decimal => InvalidParamsType::Decimal, bpr::protobuf::rpc::InvalidParamsType::EqualsTo => InvalidParamsType::EqualsTo, bpr::protobuf::rpc::InvalidParamsType::Float => InvalidParamsType::Float, bpr::protobuf::rpc::InvalidParamsType::Integer => InvalidParamsType::Integer, bpr::protobuf::rpc::InvalidParamsType::Range => InvalidParamsType::Range, bpr::protobuf::rpc::InvalidParamsType::RegEx => InvalidParamsType::RegEx, bpr::protobuf::rpc::InvalidParamsType::Required => InvalidParamsType::Required, bpr::protobuf::rpc::InvalidParamsType::StringLength => InvalidParamsType::StringLength, bpr::protobuf::rpc::InvalidParamsType::Url => InvalidParamsType::Url, } } } impl From for i32 { fn from(s: InvalidParamsType) -> Self { match s { InvalidParamsType::DateTime => InvalidParamsType::DateTime as i32, InvalidParamsType::Decimal => InvalidParamsType::Decimal as i32, InvalidParamsType::EqualsTo => InvalidParamsType::EqualsTo as i32, InvalidParamsType::Float => InvalidParamsType::Float as i32, InvalidParamsType::Integer => InvalidParamsType::Integer as i32, InvalidParamsType::Range => InvalidParamsType::Range as i32, InvalidParamsType::RegEx => InvalidParamsType::RegEx as i32, InvalidParamsType::Required => InvalidParamsType::Required as i32, InvalidParamsType::StringLength => InvalidParamsType::StringLength as i32, InvalidParamsType::Url => InvalidParamsType::Url as i32, _ => 0, } } } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct InvalidParamsDetail { pub location: String, pub param: String, pub value: String, pub error_type: InvalidParamsType, pub message: String, } impl fmt::Display for InvalidParamsDetail { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Invalid Params Detail error, location: {}, param: {}, value: {}, error_type: {}, message: {}", self.location, self.param, self.value, self.error_type, self.message) } } impl From<&InvalidParamsDetail> for bpr::protobuf::rpc::InvalidParamsDetail { fn from(d: &InvalidParamsDetail) -> Self { bpr::protobuf::rpc::InvalidParamsDetail { location: d.location.clone(), param: d.param.clone(), value: d.value.clone(), error_type: d.error_type as i32, message: d.message.clone(), } } } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct InvalidParams { pub message: String, pub detail: InvalidParamsDetail, } impl fmt::Display for InvalidParams { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Invalid Params error, message: {}, detail: {:?}", self.message, self.detail ) } } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Internal { pub message: String, } impl fmt::Display for Internal { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Internal error, message: {}", self.message) } } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Server { pub message: String, } impl fmt::Display for Server { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Server error, message: {}", self.message) } } /// #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum Error { /// Parse(Parse), /// InvalidRequest(InvalidRequest), /// InvalidParams(InvalidParams), /// Internal(Internal), /// Server(Server), } impl std::error::Error for Error {} impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Error::Parse(e) => { write!(f, "Parse error: {}", e) } Error::InvalidRequest(e) => { write!(f, "InvalidRequest error: {}", e) } Error::InvalidParams(e) => { write!(f, "InvalidParams error: {}", e) } Error::Internal(e) => { write!(f, "Internal error: {}", e) } Error::Server(e) => { write!(f, "Server error: {}", e) } } } } impl From for bpr::protobuf::rpc::Error { fn from(err: Error) -> Self { match err { Error::Parse(e) => bpr::protobuf::rpc::Error { code: -32700, message: e.message, data: None, }, Error::InvalidRequest(e) => bpr::protobuf::rpc::Error { code: -32600, message: e.message, data: None, }, Error::InvalidParams(e) => bpr::protobuf::rpc::Error { code: -32602, message: e.message.clone(), data: Some(bpr::protobuf::rpc::InvalidParamsDetail::from(&e.detail).encode_to_vec()), }, Error::Internal(e) => bpr::protobuf::rpc::Error { code: -32603, message: e.message, data: None, }, Error::Server(e) => bpr::protobuf::rpc::Error { code: -32603, message: e.message, data: None, }, } } } // 1. header parsing (-32700) // "message": "header could not be resolved.", // "detail": [ // { // "location": "header", // "msg": "must be String" // } // ] // 2. data from header (-32700) // "message": "'client'(header) must be String, input 'name': 123", // "detail": [ // { // "location": "header", // "param": "client", // "value": 123, // "error": "TypeError", // "msg": "must be String" // } // ] // 3. request parsing (-32600) // "message": "request could not be resolved.", // "detail": [ // { // "location": "request", // "msg": "must be String" // } // ] // 4. data from request (-32602) // "message": "'client'(request) must be String, input 'name': 123", // "detail": [ // { // "location": "request", // "param": "client", // "value": 123, // "error": "TypeError", // "msg": "must be String" // } // ] // 5. crud (-32603) // "message": "Internal error", // 6. return // -32700 // Parse error Invalid JSON was received by the server. // An error occurred on the server while parsing the JSON text. // -32600 // Invalid Request The JSON sent is not a valid Request object. // -32601 // Method not found The method does not exist / is not available. // -32602 // Invalid params Invalid method parameter(s). // -32603 // Internal error Internal JSON-RPC error. // -32000 to -32099 // Server error Reserved for implementation-defined server-errors. // 400 Bad Request // 클라이언트의 요청이 유효하지 않아 더 이상 작업을 진행하지 않는 경우 (필수 여부, 유효 여부, 범위, 패턴 ...) // "message": "'name'(body) must be String, input 'name': 123", // "detail": [ // { // "location": "body", // "param": "name", // "value": 123, // "error": "TypeError", // "msg": "must be String" // } // ] // 401 Unauthorized // 클라이언트가 권한이 없기 때문에 작업을 진행할 수 없는 경우 // 403 Forbidden // 클라이언트가 권한이 없기 때문에 작업을 진행할 수 없는 경우 // 404 Not Found // 클라이언트가 요청한 자원이 존재하지 않다. // 409 Conflict // 클라이언트의 요청이 서버의 상태와 충돌이 발생한 경우 // 429 Too Many Requests // 클라이언트가 일정 시간 동안 너무 많은 요청을 보낸 경우 // 500 Internal Server Error // 501 Not Implemented // 503 Service Unavailable