rama_http/service/web/endpoint/extract/
datastar.rs1use crate::service::web::{
4 extract::{FromRequest, OptionalFromRequest},
5 response::IntoResponse,
6};
7use rama_core::telemetry::tracing;
8use rama_http_types::{BodyExtractExt, Method, Request, Response, StatusCode};
9use serde::{Deserialize, de::DeserializeOwned};
10
11#[derive(Debug)]
13pub struct ReadSignals<T>(pub T);
14
15#[derive(Deserialize)]
16struct DatastarParam {
17 datastar: serde_json::Value,
18}
19
20impl<T> FromRequest for ReadSignals<T>
21where
22 T: DeserializeOwned + Send + Sync + 'static,
23{
24 type Rejection = Response;
25
26 async fn from_request(req: Request) -> Result<Self, Self::Rejection> {
27 let json = match *req.method() {
28 Method::GET => {
29 let param = req.uri().query_params::<DatastarParam>().map_err(|err| {
30 tracing::debug!(
31 "failed to parse datastar query params from GET request: {err:?}"
32 );
33 (StatusCode::BAD_REQUEST, err.to_string()).into_response()
34 })?;
35
36 let signals = param.datastar.as_str().ok_or_else(|| {
37 tracing::debug!("failed to get datastar query value from GET request");
38 (StatusCode::BAD_REQUEST, "Failed to parse JSON").into_response()
39 })?;
40
41 serde_json::from_str(signals).map_err(|err| {
42 tracing::debug!(
43 "failed to parse datastar query json value from GET request: {err:?}"
44 );
45 (StatusCode::BAD_REQUEST, err.to_string()).into_response()
46 })?
47 }
48 _ => req.into_body().try_into_json().await.map_err(|err| {
49 tracing::debug!("failed to parse datastar json payload from POST request: {err:?}");
50 (StatusCode::BAD_REQUEST, err.to_string()).into_response()
51 })?,
52 };
53
54 Ok(Self(json))
55 }
56}
57
58impl<T> OptionalFromRequest for ReadSignals<T>
59where
60 T: DeserializeOwned + Send + Sync + 'static,
61{
62 type Rejection = Response;
63
64 async fn from_request(req: Request) -> Result<Option<Self>, Self::Rejection> {
65 if req.headers().get("datastar-request").is_none() {
66 tracing::trace!(
67 "no datastar request header present: returning no read signals as such"
68 );
69 return Ok(None);
70 }
71 Ok(Some(<Self as FromRequest>::from_request(req).await?))
72 }
73}