lynx_core/self_service/utils/
mod.rs

1use core::fmt;
2use std::collections::HashMap;
3
4use anyhow::{anyhow, Error, Result};
5use bytes::{Buf, Bytes};
6use http::header::CONTENT_TYPE;
7use http_body_util::combinators::BoxBody;
8use http_body_util::BodyExt;
9use hyper::body::Incoming;
10use hyper::Response;
11use schemars::schema::RootSchema;
12
13use crate::utils::{empty, full};
14
15pub async fn parse_body_params<Value>(body: Incoming, schema: RootSchema) -> Result<Value>
16where
17    Value: serde::de::DeserializeOwned,
18{
19    let body = body
20        .collect()
21        .await
22        .map_err(|e| anyhow!(e).context("get body error"))?;
23
24    let aggregate = body.aggregate();
25
26    let json_value: serde_json::Value = serde_json::from_reader(aggregate.reader())
27        .map_err(|e| anyhow!(e).context("parse request body json error"))?;
28
29    let schema =
30        serde_json::to_value(&schema).map_err(|e| anyhow!(e).context("schema to json error"))?;
31
32    jsonschema::validate(&schema, &json_value)
33        .map_err(|e| anyhow!(ValidateError::new(format!("{}", e))))?;
34
35    serde_json::from_value::<Value>(json_value).map_err(|e| anyhow!(format!("{}", e)))
36}
37
38pub fn parse_query_params(uri: &hyper::Uri) -> HashMap<String, String> {
39    let params: HashMap<String, String> = uri
40        .query()
41        .map(|v| {
42            url::form_urlencoded::parse(v.as_bytes())
43                .into_owned()
44                .collect()
45        })
46        .unwrap_or_default();
47    params
48}
49
50#[derive(Debug, serde::Deserialize, serde::Serialize)]
51pub struct ResponseBox<T> {
52    pub code: ResponseCode,
53    pub message: Option<String>,
54    pub data: Option<T>,
55}
56
57#[derive(Debug, serde::Deserialize, serde::Serialize)]
58pub enum ResponseCode {
59    Ok,
60    ValidateError,
61    OperationError,
62    InternalServerError,
63}
64
65#[derive(Debug, serde::Deserialize, serde::Serialize)]
66pub struct ValidateError {
67    message: String,
68}
69
70impl ValidateError {
71    pub fn new(message: String) -> Self {
72        ValidateError { message }
73    }
74}
75
76impl fmt::Display for ValidateError {
77    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
78        write!(f, "ValidateError: {}", self.message)
79    }
80}
81
82#[derive(Debug, serde::Deserialize, serde::Serialize)]
83pub struct OperationError {
84    message: String,
85}
86
87impl OperationError {
88    pub fn new(message: String) -> Self {
89        OperationError { message }
90    }
91}
92
93impl fmt::Display for OperationError {
94    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95        write!(f, "Operation: {}", self.message)
96    }
97}
98
99pub fn ok<T>(data: T) -> ResponseBox<T> {
100    ResponseBox {
101        code: ResponseCode::Ok,
102        message: None,
103        data: Some(data),
104    }
105}
106
107pub fn internal_server_error(message: String) -> ResponseBox<Option<()>> {
108    ResponseBox {
109        code: ResponseCode::InternalServerError,
110        message: Some(message),
111        data: None,
112    }
113}
114
115pub fn operation_error(message: String) -> ResponseBox<Option<()>> {
116    ResponseBox {
117        code: ResponseCode::OperationError,
118        message: Some(message),
119        data: None,
120    }
121}
122
123pub fn validate_error<T>(message: String) -> ResponseBox<T> {
124    ResponseBox {
125        code: ResponseCode::ValidateError,
126        message: Some(message),
127        data: None,
128    }
129}
130
131pub fn response_ok<T>(data: T) -> Result<Response<BoxBody<Bytes, Error>>>
132where
133    T: serde::Serialize,
134{
135    let res = ok(data);
136    let json_str = serde_json::to_string(&res)?;
137
138    Ok(Response::builder()
139        .header(CONTENT_TYPE, "application/json")
140        .body(full(Bytes::from(json_str)))?)
141}
142
143pub fn not_found() -> Response<BoxBody<Bytes, Error>> {
144    Response::builder()
145        .status(http::status::StatusCode::NOT_FOUND)
146        .body(empty())
147        .unwrap()
148}