Improve error message when storing

This commit is contained in:
Sosthene 2024-11-19 15:15:33 +01:00
parent 821f0e6472
commit b5a238c205

View File

@ -93,24 +93,37 @@ struct RetrieveResponse {
value: String, value: String,
} }
/// Store data on the filesystem async fn get_file_path(key: &str) -> String {
async fn store_data(key: &str, value: &[u8], expires_at: SystemTime) -> Result<(), String> {
let dir_name = format!("{}/{}", STORAGE_DIR, &key[..2]); let dir_name = format!("{}/{}", STORAGE_DIR, &key[..2]);
let file_path = format!("{}/{}", dir_name, &key[2..]); let file_path = format!("{}/{}", dir_name, &key[2..]);
let metadata_path = format!("{}.meta", file_path);
file_path
}
create_dir_all(&dir_name).await.map_err(|e| e.to_string())?; /// Store data on the filesystem
async fn store_data(key: &str, value: &[u8], expires_at: SystemTime) -> Result<(), tide::Error> {
let file_name = get_file_path(key).await;
let file_path = Path::new(&file_name);
let mut file = File::create(&file_path).await.map_err(|e| e.to_string())?; // Check if key exists
file.write_all(value).await.map_err(|e| e.to_string())?; if file_path.exists().await {
return Err(tide::Error::from_str(StatusCode::Conflict, "Key already exists"));
}
create_dir_all(file_path).await.map_err(|e| tide::Error::new(StatusCode::InternalServerError, e))?;
let metadata_path = format!("{}.meta", file_name);
let mut file = File::create(&file_path).await.map_err(|e| tide::Error::new(StatusCode::InternalServerError, e))?;
file.write_all(value).await.map_err(|e| tide::Error::new(StatusCode::InternalServerError, e))?;
let metadata = Metadata { let metadata = Metadata {
expires_at: system_time_to_unix(expires_at) expires_at: system_time_to_unix(expires_at)
}; };
let metadata_json = serde_json::to_string(&metadata).map_err(|e| e.to_string())?; let metadata_json = serde_json::to_string(&metadata).map_err(|e| tide::Error::new(StatusCode::InternalServerError, e))?;
let mut meta_file = File::create(&metadata_path).await.map_err(|e| e.to_string())?; let mut meta_file = File::create(&metadata_path).await.map_err(|e| tide::Error::new(StatusCode::InternalServerError, e))?;
meta_file.write_all(metadata_json.as_bytes()).await.map_err(|e| e.to_string())?; meta_file.write_all(metadata_json.as_bytes()).await.map_err(|e| tide::Error::new(StatusCode::InternalServerError, e))?;
Ok(()) Ok(())
} }
@ -127,9 +140,14 @@ async fn retrieve_data(key: &str) -> Result<Vec<u8>, String> {
/// Handler for the /store endpoint /// Handler for the /store endpoint
async fn handle_store(mut req: Request<()>) -> tide::Result<Response> { async fn handle_store(mut req: Request<()>) -> tide::Result<Response> {
// Parse the JSON body // Parse the JSON body
let data: StoreRequest = req.body_json().await.map_err(|_| { let data: StoreRequest = match req.body_json().await {
tide::Error::from_str(StatusCode::BadRequest, "Invalid JSON payload") Ok(data) => data,
})?; Err(e) => {
return Ok(Response::builder(StatusCode::BadRequest)
.body(format!("Invalid request: {}", e))
.build());
}
};
// Validate the key // Validate the key
if data.key.len() != 64 || !data.key.chars().all(|c| c.is_ascii_hexdigit()) { if data.key.len() != 64 || !data.key.chars().all(|c| c.is_ascii_hexdigit()) {
@ -139,25 +157,36 @@ async fn handle_store(mut req: Request<()>) -> tide::Result<Response> {
} }
// Decode the value from Base64 // Decode the value from Base64
let value_bytes = base64::decode(&data.value).map_err(|_| { let value_bytes = match base64::decode(&data.value) {
tide::Error::from_str(StatusCode::BadRequest, "Invalid Base64 value") Ok(value) => value,
})?; Err(e) => {
return Ok(Response::builder(StatusCode::BadRequest)
.body(format!("Invalid request: {}", e))
.build());
}
};
let now = SystemTime::now(); let now = SystemTime::now();
let live_for = if let Some(ttl) = data.ttl { Duration::from_secs(ttl) } else { Duration::from_secs(DEFAULT_TTL) }; let live_for = if let Some(ttl) = data.ttl { Duration::from_secs(ttl) } else { Duration::from_secs(DEFAULT_TTL) };
let expires_at = now.checked_add(live_for).ok_or(tide::Error::from_str(StatusCode::BadRequest, "Invalid ttl"))?; let expires_at = now.checked_add(live_for).ok_or(tide::Error::from_str(StatusCode::BadRequest, "Invalid ttl"))?;
// Store the data // Store the data
store_data(&data.key, &value_bytes, expires_at).await.map_err(|e| { match store_data(&data.key, &value_bytes, expires_at).await {
tide::Error::from_str(StatusCode::InternalServerError, e) Ok(()) => {
})?; Ok(Response::builder(StatusCode::Ok)
.body(serde_json::to_value(&ApiResponse {
// Respond with success message: "Data stored successfully.".to_string(),
Ok(Response::builder(StatusCode::Ok) })?)
.body(serde_json::to_value(&ApiResponse { .build())
message: "Data stored successfully.".to_string(), }
})?) Err(e) => {
.build()) Ok(Response::builder(e.status())
.body(serde_json::to_value(&ApiResponse {
message: e.to_string(),
})?)
.build())
}
}
} }
async fn handle_retrieve(req: Request<()>) -> tide::Result<Response> { async fn handle_retrieve(req: Request<()>) -> tide::Result<Response> {