Closed noesis-labs closed 1 year ago
You can run the example using rust-script repro.rs
(if you have rust-script
installed).
Thank you for using my library and providing the code to reproduce the issue. I'm glad to hear that it works amazingly well with Valid(Json(...))
. However, I understand that you are facing difficulties in making it work with Valid<Path<String>>
.
Using basic data types directly with the Valid<Path<...>>
approach is not supported. Instead, you will need to define a custom struct that implements the Deserialize
and Validate
traits (and the crate will implement HasValidate
trait for it automatically, that's how it works).
This is the modified code that can be compiled successfully:
// using your dependencies
use axum::{
extract::{Extension, Path},
http::StatusCode,
routing::get,
Json, Router,
};
use axum_valid::Valid;
use regex::Regex;
use serde::{Deserialize, Serialize};
use validator::{Validate, ValidationError};
#[derive(Debug, Serialize, Validate)]
struct Profile {
id: String,
profile_name: String,
}
pub fn uuid(id: &str) -> Result<(), ValidationError> {
// Define the regular expression pattern for UUIDv4
let pattern =
Regex::new(r"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$")
.expect("Failed to compile UUID regex pattern");
if !pattern.is_match(id) {
let mut error = ValidationError::new("Invalid UUID format");
error.add_param(std::borrow::Cow::Borrowed("pattern"), &pattern.to_string());
return Err(error);
}
Ok(())
}
#[tokio::main]
async fn main() {
let app_state = SharedState {};
let app = Router::new()
.route("/:profileId", get(get_profile_handler))
.layer(Extension(app_state));
axum::Server::bind(&"127.0.0.1:3000".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}
#[derive(Debug, Deserialize, Validate)]
pub struct ProfileId {
#[validate(custom = "uuid")]
profile_id: String,
}
async fn get_profile_handler(
Extension(_app_state): Extension<SharedState>,
Valid(Path(profile_id)): Valid<Path<ProfileId>>,
) -> Result<Json<Profile>, StatusCode> {
let profile_id = profile_id.profile_id;
println!("profile_id = {}", profile_id);
let profile = Profile {
id: profile_id,
profile_name: "Captain Flint".to_string(),
};
Ok(Json(profile))
}
#[derive(Debug, Clone)]
struct SharedState {}
- Implement
Serialize
forProfile
(notDeserialize
)- Define a
ProfileId
struct with named fields, and implementDeserialize
andValidate
for it- Implement
Clone
forSharedState
If you have any further questions or need additional assistance, please let me know. And your question also reminded me that I will add some examples and test code later.
btw: Using the Uuid
type in uuid crate with serde
feature would be better in this scenario.
Examples & tests added: tests/basic.rs, tests/custom.rs
Great library!! It works amazing for
Valid(Json(...))
, but I couldn't make it to work withValid(Path(path: String))
The error is
Single file reproducer