Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help: How to return errors during serde serialization and deserialization #380

Open
jing-951 opened this issue Jul 15, 2024 · 3 comments
Open

Comments

@jing-951
Copy link

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,
        }
    }
}
@fafhrd91
Copy link
Member

fafhrd91 commented Jul 15, 2024

error handling depends on where you use it. WebResponseError is used if you return result from your handle function. could you add usage example?

@jing-951
Copy link
Author

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))
}


@WuJiY
Copy link

WuJiY commented Aug 13, 2024

#112 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

3 participants