lynx_core/self_service/utils/
mod.rs1use 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}