Help: How to return errors during serde serialization and deserialization
jing-951 opened this issue · 3 comments
I have implemented WebResponseError for serde errors, but I found that the return result is not what I expected. I always feel that ntex serializes JSON data during route parsing, not when using function parameters in the processor. When I want to know, how can I capture serialization errors and convert them into the results I want before returning them。
This is my incorrect implementation
use ntex::{http::{self, StatusCode}, web};
use serde::{Deserialize,Serialize};
use serde_json::json;
#[derive(Debug,Deserialize,Serialize)]
pub struct AppRes{
code:u16,
msg:&'static str,
}
#[derive(Debug)]
pub enum AppErr {
InnError(u16,&'static str),
SqlxError(u16),
BadClientData(u16,&'static str),
SerdeError,
Timeout,
}
impl std::fmt::Display for AppErr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self {
AppErr::BadClientData(c, m) => write!(
f, "BadClientData - error_code:{} - error_info:{}", c, m),
AppErr::InnError(c, m) => write!(
f,"InnError - error_code:{} - error_info:{}",c,m
),
AppErr::SqlxError(c) => write!(
f,"sqlx query error - error_code:{} - error_info:sqlx error",c,
),
AppErr::SerdeError => write!(
f,"serde error"
),
AppErr::Timeout => write!(f,"timeout")
}
}
}
impl web::error::WebResponseError for AppErr{
fn error_response(&self, _: &web::HttpRequest) -> web::HttpResponse {
match &self{
AppErr::BadClientData(c,m ) |
AppErr::InnError(c, m) =>{
web::HttpResponse::build(self.status_code())
.set_header("content-type", "application/json; charset=utf-8")
.body(json!(AppRes{code:*c,msg:m}))
},
AppErr::Timeout => {
web::HttpResponse::build(self.status_code())
.set_header("content-type", "text/html; charset=utf-8")
.body("timeout")
},
AppErr::SqlxError(c) => {
web::HttpResponse::build(self.status_code())
.set_header("content-type", "application/json; charset=utf-8")
.body(json!(AppRes{code:*c,msg:"server error"}))
},
AppErr::SerdeError => {
web::HttpResponse::build(self.status_code())
.set_header("content-type", "application/json; charset=utf-8")
.body(json!(AppRes{code:10000,msg:"bad parameter"}))
}
}
}
fn status_code(&self) -> http::StatusCode {
match &self{
AppErr::BadClientData(_, _) => StatusCode::BAD_REQUEST,
AppErr::InnError(_, _) => StatusCode::INTERNAL_SERVER_ERROR,
AppErr::Timeout => StatusCode::REQUEST_TIMEOUT,
AppErr::SqlxError(_) => StatusCode::INTERNAL_SERVER_ERROR,
AppErr::SerdeError => StatusCode::BAD_REQUEST,
}
}
}
error handling depends on where you use it. WebResponseError is used if you return result from your handle function. could you add usage example?
web::error::WebResponseError
Thank you for your reply. I don't know where to capture deserialization errors. I thought I had implemented web:: error:: Webex ResponseError to capture the errors I wanted in the processor. Looking forward to your reply.
Here is my test code:
use ntex::web;
use ntex::web::middleware::Logger;
use ntex::web::types::Json;
use serde::Deserialize;
mod apps;
use crate::apps::apperr::AppErr;
#[ntex::main]
async fn main()->Result<(), std::io::Error> {
std::env::set_var("RUST_LOG", "info");
env_logger::init();
web::HttpServer::new(
||{
web::App::new()
.wrap(Logger::default())
.service(
web::scope("/").route("/", web::post().to(index))
)
}
)
.bind("127.0.0.1:3000")?
.run()
.await
}
#[derive(Debug,Deserialize)]
struct UserInfo{
name:String,
pwd:String,
}
async fn index(info:Json<UserInfo>)->Result<String,AppErr>{
println!("name:{},password:{}",info.name,info.pwd);
Ok(format!("Hi {}",info.name))
}