Line data Source code
1 : use anyhow::Context;
2 : use bytes::Buf;
3 : use hyper::{header, Body, Request, Response, StatusCode};
4 : use serde::{Deserialize, Serialize};
5 :
6 : use super::error::ApiError;
7 :
8 : /// Parse a json request body and deserialize it to the type `T`.
9 0 : pub async fn json_request<T: for<'de> Deserialize<'de>>(
10 0 : request: &mut Request<Body>,
11 0 : ) -> Result<T, ApiError> {
12 0 : let body = hyper::body::aggregate(request.body_mut())
13 0 : .await
14 0 : .context("Failed to read request body")
15 0 : .map_err(ApiError::BadRequest)?;
16 :
17 0 : if body.remaining() == 0 {
18 0 : return Err(ApiError::BadRequest(anyhow::anyhow!(
19 0 : "missing request body"
20 0 : )));
21 0 : }
22 0 :
23 0 : let mut deser = serde_json::de::Deserializer::from_reader(body.reader());
24 0 :
25 0 : serde_path_to_error::deserialize(&mut deser)
26 0 : // intentionally stringify because the debug version is not helpful in python logs
27 0 : .map_err(|e| anyhow::anyhow!("Failed to parse json request: {e}"))
28 0 : .map_err(ApiError::BadRequest)
29 0 : }
30 :
31 : /// Parse a json request body and deserialize it to the type `T`. If the body is empty, return `T::default`.
32 0 : pub async fn json_request_maybe<T: for<'de> Deserialize<'de> + Default>(
33 0 : request: &mut Request<Body>,
34 0 : ) -> Result<T, ApiError> {
35 0 : let body = hyper::body::aggregate(request.body_mut())
36 0 : .await
37 0 : .context("Failed to read request body")
38 0 : .map_err(ApiError::BadRequest)?;
39 :
40 0 : if body.remaining() == 0 {
41 0 : return Ok(T::default());
42 0 : }
43 0 :
44 0 : let mut deser = serde_json::de::Deserializer::from_reader(body.reader());
45 0 :
46 0 : serde_path_to_error::deserialize(&mut deser)
47 0 : // intentionally stringify because the debug version is not helpful in python logs
48 0 : .map_err(|e| anyhow::anyhow!("Failed to parse json request: {e}"))
49 0 : .map_err(ApiError::BadRequest)
50 0 : }
51 :
52 0 : pub fn json_response<T: Serialize>(
53 0 : status: StatusCode,
54 0 : data: T,
55 0 : ) -> Result<Response<Body>, ApiError> {
56 0 : let json = serde_json::to_string(&data)
57 0 : .context("Failed to serialize JSON response")
58 0 : .map_err(ApiError::InternalServerError)?;
59 0 : let response = Response::builder()
60 0 : .status(status)
61 0 : .header(header::CONTENT_TYPE, "application/json")
62 0 : .body(Body::from(json))
63 0 : .map_err(|e| ApiError::InternalServerError(e.into()))?;
64 0 : Ok(response)
65 0 : }
|