Skip to content

Commit

Permalink
fix status code mismatch for error response
Browse files Browse the repository at this point in the history
  • Loading branch information
aki-mizu committed Apr 10, 2024
1 parent 35a1ad0 commit d3cd6b8
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 84 deletions.
35 changes: 34 additions & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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": {}
})),
Expand All @@ -48,3 +63,21 @@ impl From<JsonRejection> for AppError {
Self::JsonRejection(rejection)
}
}

impl From<nostr_sdk::client::Error> for AppError {
fn from(error: nostr_sdk::client::Error) -> Self {
Self::NostrClientError(error)
}
}

impl From<nostr_sdk::event::Error> for AppError {
fn from(error: nostr_sdk::event::Error) -> Self {
Self::NostrEventError(error)
}
}

impl From<redis::RedisError> for AppError {
fn from(error: redis::RedisError) -> Self {
Self::RedisError(error)
}
}
118 changes: 35 additions & 83 deletions src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,27 +25,13 @@ pub async fn publish_event(
body: AppJson<Event>,
) -> Result<AppJson<Value>, 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(
Expand All @@ -55,76 +41,42 @@ pub async fn get_events(
let filters: Vec<Filter> = 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<u8> = result;
let events: Vec<Event> = 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<u8> = 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<u8> = result;
let events: Vec<Event> = 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<u8> = 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,
})))
}
}

0 comments on commit d3cd6b8

Please sign in to comment.