From e3b1c0e0138ee6b811f1e2c643898fe502d157de Mon Sep 17 00:00:00 2001 From: Valerio Ageno <51341197+Valerioageno@users.noreply.github.com> Date: Fri, 14 Feb 2025 17:39:37 +0100 Subject: [PATCH] feat: create body extractor function (#561) --- crates/tuono_lib/src/request.rs | 92 ++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/crates/tuono_lib/src/request.rs b/crates/tuono_lib/src/request.rs index e915bb72..a273c39d 100644 --- a/crates/tuono_lib/src/request.rs +++ b/crates/tuono_lib/src/request.rs @@ -1,4 +1,4 @@ -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::collections::HashMap; use axum::http::{HeaderMap, Uri}; @@ -51,4 +51,94 @@ impl Request { pub fn location(&self) -> Location { Location::from(self.uri.to_owned()) } + + pub fn body<'de, T: Deserialize<'de>>(&'de self) -> Result { + if let Some(body) = self.headers.get("body") { + if let Ok(body) = body.to_str() { + let body = serde_json::from_str::(body)?; + return Ok(body); + } + return Err(BodyParseError::Io(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "Failed to read body", + ))); + } + Err(BodyParseError::Io(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "No body found", + ))) + } +} + +#[derive(Debug)] +pub enum BodyParseError { + Io(std::io::Error), + Serde(serde_json::Error), +} + +impl From for BodyParseError { + fn from(err: serde_json::Error) -> BodyParseError { + BodyParseError::Serde(err) + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[derive(Debug, Deserialize)] + struct FakeBody { + field1: bool, + field2: String, + } + + #[test] + fn it_correctly_parse_the_body() { + let mut request = Request::new( + Uri::from_static("http://localhost:3000"), + HeaderMap::new(), + HashMap::new(), + ); + + request.headers.insert( + "body", + r#"{"field1": true, "field2": "hello"}"#.parse().unwrap(), + ); + + let body: FakeBody = request.body().expect("Failed to parse body"); + + assert!(body.field1); + assert_eq!(body.field2, "hello".to_string()); + } + + #[test] + fn it_should_trigger_an_error_when_no_body_is_found() { + let request = Request::new( + Uri::from_static("http://localhost:3000"), + HeaderMap::new(), + HashMap::new(), + ); + + let body: Result = request.body(); + + assert!(body.is_err()); + } + + #[test] + fn it_should_trigger_an_error_when_body_is_invalid() { + let mut request = Request::new( + Uri::from_static("http://localhost:3000"), + HeaderMap::new(), + HashMap::new(), + ); + + request + .headers + .insert("body", r#"{"field1": true"#.parse().unwrap()); + + let body: Result = request.body(); + + assert!(body.is_err()); + } }