From 39a613953dbd4bc85e9f867d81af01921f7ed745 Mon Sep 17 00:00:00 2001 From: Miguel Piedrafita Date: Wed, 15 Nov 2023 23:07:39 +0000 Subject: [PATCH] ugly hack: temporarily force JSON decoding (#4) --- Cargo.lock | 27 ++++++++++++++++-- Cargo.toml | 3 ++ src/axum/mod.rs | 62 ++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 1 + src/routes/response.rs | 9 ++++-- 5 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 src/axum/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 678d3e7..8f0b296 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,9 +40,9 @@ checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", @@ -807,6 +807,26 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "thiserror" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.7" @@ -1268,12 +1288,15 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" name = "world-id-bridge" version = "0.1.0" dependencies = [ + "async-trait", "axum", "chrono", "dotenvy", "redis", "serde", "serde_json", + "serde_path_to_error", + "thiserror", "tokio", "tower", "tower-http", diff --git a/Cargo.toml b/Cargo.toml index a01e41c..d5bc919 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,9 @@ redis = { version = "0.23.0", features = ["tokio-comp", "connection-manager"] } tracing-subscriber = { version = "0.3", default-features = false, features = [ "fmt", ] } +serde_path_to_error = "0.1.14" +async-trait = "0.1.74" +thiserror = "1.0.50" [build-dependencies] chrono = "0.4.26" diff --git a/src/axum/mod.rs b/src/axum/mod.rs new file mode 100644 index 0000000..9d0d8af --- /dev/null +++ b/src/axum/mod.rs @@ -0,0 +1,62 @@ +use std::time::SystemTime; + +use async_trait::async_trait; +use axum::{ + body::{Bytes, HttpBody}, + extract::FromRequest, + http::Request, + response::IntoResponse, + BoxError, +}; +use serde::de::DeserializeOwned; + +#[derive(Debug, thiserror::Error)] +pub enum JsonError { + #[error("failed to deserialize json")] + Deserialize(#[from] serde_path_to_error::Error), + + #[error("failed to extract body")] + Body(#[from] axum::extract::rejection::BytesRejection), +} + +impl IntoResponse for JsonError { + fn into_response(self) -> axum::response::Response { + unimplemented!() + } +} + +#[derive(Debug, Clone, Copy, Default)] +#[must_use] +pub struct TemporaryForceDecodeJson(pub T); + +#[async_trait] +impl FromRequest for TemporaryForceDecodeJson +where + T: DeserializeOwned, + B: HttpBody + Send + 'static, + B::Data: Send, + B::Error: Into, + S: Send + Sync, +{ + type Rejection = JsonError; + + async fn from_request(req: Request, state: &S) -> Result { + assert!( + !is_after_nov_30(), + "This was supposed to be a very temporary hack you fools!!!! Time to use proper JSON headers." + ); + + let bytes = Bytes::from_request(req, state).await?; + let deserializer = &mut serde_json::Deserializer::from_slice(&bytes); + + Ok(Self(serde_path_to_error::deserialize(deserializer)?)) + } +} + +fn is_after_nov_30() -> bool { + SystemTime::now() + .duration_since(std::time::SystemTime::UNIX_EPOCH) + .unwrap() + .as_secs() + > 1_701_331_200 +} diff --git a/src/main.rs b/src/main.rs index 591ba05..6411ff7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ use dotenvy::dotenv; use redis::aio::ConnectionManager; use std::env; +mod axum; mod routes; mod server; mod utils; diff --git a/src/routes/response.rs b/src/routes/response.rs index f009f1a..25846c2 100644 --- a/src/routes/response.rs +++ b/src/routes/response.rs @@ -11,8 +11,11 @@ use std::str; use tower_http::cors::{AllowHeaders, Any, CorsLayer}; use uuid::Uuid; -use crate::utils::{ - handle_redis_error, RequestPayload, RequestStatus, EXPIRE_AFTER_SECONDS, REQ_STATUS_PREFIX, +use crate::{ + axum::TemporaryForceDecodeJson, + utils::{ + handle_redis_error, RequestPayload, RequestStatus, EXPIRE_AFTER_SECONDS, REQ_STATUS_PREFIX, + }, }; const RES_PREFIX: &str = "res:"; @@ -81,7 +84,7 @@ async fn get_response( async fn insert_response( Path(request_id): Path, Extension(mut redis): Extension, - Json(request): Json, + TemporaryForceDecodeJson(request): TemporaryForceDecodeJson, ) -> Result { //ANCHOR - Store the response if !redis