Crates.io | standard-error |
lib.rs | standard-error |
version | 0.1.5 |
source | src |
created_at | 2024-08-17 12:56:58.188819 |
updated_at | 2024-09-12 05:58:17.441179 |
description | simplifies returning meaningful errors for axum services |
homepage | |
repository | |
max_upload_size | |
id | 1341626 |
size | 32,030 |
standard-error
is a Rust crate designed to simplify the handling of error messages for various locales. It reads error messages from YAML and other sources, providing a structured and efficient way to manage errors in your applications.
Axum
.Below is an example of how to use standard-error
in a web application using the Axum
framework:
use axum::{
extract::Query,
Json,
http::StatusCode,
};
use serde_json::{json, Value};
use std::collections::HashMap;
use standard_error::StandardError;
pub async fn my_handler(Query(params): Query<HashMap<String, String>>) -> Result<Json<Value>, StandardError> {
let group = match params.get("name") {
Some(g) => g,
None => {
return Err(StandardError::new("ER-0037").code(StatusCode::BAD_REQUEST));
}
};
Ok(Json(json!({"message": "success"})))
}
If a parsing error occurs (e.g., trying to convert a string to an integer), a StandardError can be returned with a default status code (500 INTERNAL_SERVER_ERROR
):
async fn parse_int(a: &str) -> Result<i32, StandardError> {
a.parse().map_err(|_| StandardError::new("ER-0004"))
}
// Example usage
let res = parse_int("abc").await;
// This will return an error with code "ER-0004" and status code 500.
You can customize the status code to something other than the default. For example, returning 400 BAD_REQUEST
:
async fn parse_int_custom(a: &str) -> Result<i32, StandardError> {
a.parse().map_err(|_| StandardError::new("ER-0004").code(StatusCode::BAD_REQUEST))
}
// Example usage
let res = parse_int_custom("abc").await;
// This will return an error with code "ER-0004" and status code 400.
StandardError
supports error message interpolation. For example, you can include the specific error details when returning the error:
async fn parse_with_error_interpolation(a: &str) -> Result<i32, StandardError> {
a.parse().map_err(|e| StandardError::new("ER-0005").interpolate_err(e.to_string()))
}
// Example usage
let res = parse_with_error_interpolation("abc").await;
// This will return an error with code "ER-0005" and message: "Should be an integer: invalid digit found in string".
You can interpolate additional values into the error message, such as user-specific data:
async fn parse_with_value_interpolation(a: &str) -> Result<i32, StandardError> {
a.parse().map_err(|_| {
let mut values = HashMap::new();
values.insert("fname".to_string(), "ashu".to_string());
values.insert("lname".to_string(), "pednekar".to_string());
StandardError::new("ER-0006").interpolate_values(values)
})
}
// Example usage
let res = parse_with_value_interpolation("abc").await;
// This will return an error with code "ER-0006" and message: "Should be an integer - fname: ashu | lname: pednekar".
You can chain multiple methods on StandardError
, like setting a custom status code and interpolating both error details and values:
async fn parse_with_chained_errors(a: &str) -> Result<i32, StandardError> {
a.parse().map_err(|e| {
let mut values = HashMap::new();
values.insert("fname".to_string(), "ashu".to_string());
values.insert("lname".to_string(), "pednekar".to_string());
StandardError::new("ER-0007")
.code(StatusCode::IM_A_TEAPOT)
.interpolate_values(values)
.interpolate_err(e.to_string())
})
}
// Example usage
let res = parse_with_chained_errors("abc").await;
// This will return an error with code "ER-0007", status code 418, and message:
// "Should be an integer - fname: ashu | lname: pednekar - invalid digit found in string".
Add standard-error to your Cargo.toml:
[dependencies]
standard-error = "0.1"
or with cargo
cargo add standard-error
Note: Add features
diesel
orgit
to auto-magically handle errors raised by these diesel and git2 crates respectively
To configure standard-error, you can provide YAML files containing error messages for different locales. The crate will automatically load the correct message based on the locale specified in your application.
Example YAML structure:
errors:
- code: ER-0004
detail_en_US: "Should be an integer"
detail_hi_IN: "एक पूर्णांक होना चाहिए"
- code: ER-0005
detail_en_US: "Should be an integer: [err]"
detail_hi_IN: "एक पूर्णांक होना चाहिए: [err]"
- code: ER-0006
detail_en_US: "Should be an integer - fname: [fname] | lname: [lname]"
detail_hi_IN: "एक पूर्णांक होना चाहिए - fname: [fname] | lname: [lname]"
- code: ER-0007
detail_en_US: "Should be an integer - fname: [fname] | lname: [lname] - [err]"
detail_hi_IN: "एक पूर्णांक होना चाहिए - fname: [fname] | lname: [lname] - [err]"
Keep this yaml file (
errors.yaml
) at the root of your directory, outsidesrc
. Or you can keep it wherever you please and set theERROR_YAML_FILE_PATH
environment variable.
As for the locale configuration, by default, the crate picks up the default value from the
DEFAULT_LOCALE
env, which is set toen_US
by default.
- You can change this env to any value you like, provided the corresponding keys are present in yout errors yaml file.
If you wish to dynamically change the locale programmatically at any given point, you can call the
standard_error::set_current_locale
function like so
use standard_error::set_current_locale;
fn my_business_logic(){
//...
set_current_locale("hi_IN");
//...
}
This sets a thread local refcell variable that'll persist throught the thread. Since it's a
RefCell
value, and not something likeArc
, you don't have to worry about it leaking into your other threads/requests.