From d3cd6b8afa5b2826a1ece1aa12e92d7af3da5187 Mon Sep 17 00:00:00 2001 From: Darrell Date: Wed, 10 Apr 2024 12:09:49 +0900 Subject: [PATCH] fix status code mismatch for error response --- src/error.rs | 35 ++++++++++++++- src/handler.rs | 118 +++++++++++++++---------------------------------- 2 files changed, 69 insertions(+), 84 deletions(-) diff --git a/src/error.rs b/src/error.rs index 6be02c9..5a07103 100644 --- a/src/error.rs +++ b/src/error.rs @@ -3,6 +3,7 @@ use axum::extract::rejection::JsonRejection; use axum::extract::FromRequest; +use axum::http::StatusCode; use axum::response::{IntoResponse, Response}; use serde_json::json; @@ -20,21 +21,35 @@ where } pub enum AppError { + // Too many filters were provided in the request + FilterError(usize), // The request body contained invalid JSON JsonRejection(JsonRejection), + // An Nostr Client error occurred + NostrClientError(nostr_sdk::client::Error), + // An Nostr Event error occurred + NostrEventError(nostr_sdk::event::Error), + // A Redis error occurred + RedisError(redis::RedisError), } impl IntoResponse for AppError { fn into_response(self) -> Response { let (status, message) = match self { + AppError::FilterError(max_filters) => ( + StatusCode::BAD_REQUEST, + format!("Too many filters (max allowed {})", max_filters).to_string(), + ), AppError::JsonRejection(rejection) => (rejection.status(), rejection.body_text()), + AppError::NostrClientError(err) => (StatusCode::BAD_REQUEST, err.to_string()), + AppError::NostrEventError(err) => (StatusCode::BAD_REQUEST, err.to_string()), + AppError::RedisError(err) => (StatusCode::BAD_REQUEST, err.to_string()), }; ( status, AppJson(json!({ "success": false, - "code": status.as_u16(), "message": message, "data": {} })), @@ -48,3 +63,21 @@ impl From for AppError { Self::JsonRejection(rejection) } } + +impl From for AppError { + fn from(error: nostr_sdk::client::Error) -> Self { + Self::NostrClientError(error) + } +} + +impl From for AppError { + fn from(error: nostr_sdk::event::Error) -> Self { + Self::NostrEventError(error) + } +} + +impl From for AppError { + fn from(error: redis::RedisError) -> Self { + Self::RedisError(error) + } +} diff --git a/src/handler.rs b/src/handler.rs index f489feb..3d359a1 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -25,27 +25,13 @@ pub async fn publish_event( body: AppJson, ) -> Result, AppError> { let event: Event = body.0; - - if let Err(e) = event.verify() { - return Ok(AppJson(json!({ - "success": false, - "message": e.to_string(), - "data": {}, - }))); - } - - match state.client.send_event(event).await { - Ok(_) => Ok(AppJson(json!({ - "success": true, - "message": "Event published", - "data": {}, - }))), - Err(e) => Ok(AppJson(json!({ - "success": false, - "message": e.to_string(), - "data": {}, - }))), - } + event.verify()?; + state.client.send_event(event).await?; + Ok(AppJson(json!({ + "success": true, + "message": "Event published", + "data": {}, + }))) } pub async fn get_events( @@ -55,76 +41,42 @@ pub async fn get_events( let filters: Vec = body.0; if filters.len() > state.config.limit.max_filters { - return Ok(AppJson(json!({ - "success": false, - "message": format!("Too many filters (max allowed {})", state.config.limit.max_filters), - "data": {}, - }))); + return Err(AppError::FilterError(state.config.limit.max_filters)); } if let Some(redis) = &state.redis { let mut connection = redis.get_async_connection().await.unwrap(); let hash: String = Sha256Hash::hash(format!("{filters:?}").as_bytes()).to_string(); - match connection.exists::<&str, bool>(&hash).await { - Ok(exists) => { - if exists { - match connection.get(&hash).await { - Ok(result) => { - let bytes: Vec = result; - let events: Vec = bincode::deserialize(&bytes).unwrap(); - Ok(AppJson(json!({ - "success": true, - "message": format!("Got {} events", events.len()), - "data": events, - }))) - } - Err(e) => Ok(AppJson(json!({ - "success": false, - "message": e.to_string(), - "data": {}, - }))), - } - } else { - match state.client.get_events_of(filters, None).await { - Ok(events) => { - let encoded: Vec = bincode::serialize(&events).unwrap(); - let _: () = connection - .set_ex(hash, encoded, state.config.redis.expiration) - .await - .unwrap(); - Ok(AppJson(json!({ - "success": true, - "message": format!("Got {} events", events.len()), - "data": events, - }))) - } - Err(e) => Ok(AppJson(json!({ - "success": false, - "message": e.to_string(), - "data": {}, - }))), - } - } - } - Err(e) => Ok(AppJson(json!({ - "success": false, - "message": e.to_string(), - "data": {}, - }))), - } - } else { - // TODO: add a timeout - match state.client.get_events_of(filters, None).await { - Ok(events) => Ok(AppJson(json!({ + let exists = connection.exists::<&str, bool>(&hash).await?; + if exists { + let result = connection.get(&hash).await?; + let bytes: Vec = result; + let events: Vec = bincode::deserialize(&bytes).unwrap(); + Ok(AppJson(json!({ + "success": true, + "message": format!("Got {} events", events.len()), + "data": events, + }))) + } else { + let events = state.client.get_events_of(filters, None).await?; + let encoded: Vec = bincode::serialize(&events).unwrap(); + let _: () = connection + .set_ex(hash, encoded, state.config.redis.expiration) + .await + .unwrap(); + Ok(AppJson(json!({ "success": true, "message": format!("Got {} events", events.len()), "data": events, - }))), - Err(e) => Ok(AppJson(json!({ - "success": false, - "message": e.to_string(), - "data": {}, - }))), + }))) } + } else { + // TODO: add a timeout + let events = state.client.get_events_of(filters, None).await?; + Ok(AppJson(json!({ + "success": true, + "message": format!("Got {} events", events.len()), + "data": events, + }))) } }