lynx_core/self_service/
mod.rs

1use crate::entities::rule_content::RuleContent;
2use crate::utils::full;
3use anyhow::{anyhow, Error, Result};
4use bytes::Bytes;
5use http::header::CONTENT_TYPE;
6use http::method;
7use http_body_util::combinators::BoxBody;
8use hyper::body::Incoming;
9use hyper::{Request, Response};
10use schemars::schema_for;
11use tracing::{error, trace};
12use utils::{
13    internal_server_error, not_found, operation_error, response_ok, validate_error, OperationError,
14    ValidateError,
15};
16
17pub mod api;
18pub mod utils;
19
20pub const SELF_SERVICE_PATH_PREFIX: &str = "/__self_service_path__";
21
22pub const HELLO_PATH: &str = "/__self_service_path__/hello";
23pub const RULE_GROUP_ADD: &str = "/__self_service_path__/rule_group/add";
24pub const RULE_GROUP_UPDATE: &str = "/__self_service_path__/rule_group/update";
25pub const RULE_GROUP_DELETE: &str = "/__self_service_path__/rule_group/delete";
26pub const RULE_GROUP_LIST: &str = "/__self_service_path__/rule_group/list";
27
28pub const RULE_ADD: &str = "/__self_service_path__/rule/add";
29pub const RULE_UPDATE: &str = "/__self_service_path__/rule/update";
30pub const RULE_DELETE: &str = "/__self_service_path__/rule/delete";
31pub const RULE_DETAIL: &str = "/__self_service_path__/rule";
32pub const RULE_CONTEXT_SCHEMA: &str = "/__self_service_path__/rule/context/schema";
33
34pub const REQUEST_CLEAR: &str = "/__self_service_path__/request/clear";
35pub const REQUEST_LOG: &str = "/__self_service_path__/request_log";
36pub const REQUEST_BODY: &str = "/__self_service_path__/request_body";
37
38pub const RESPONSE: &str = "/__self_service_path__/response";
39pub const RESPONSE_BODY: &str = "/__self_service_path__/response_body";
40
41pub const APP_CONFIG_RECORD_STATUS: &str = "/__self_service_path__/app_config/record_status";
42pub const APP_CONFIG_PATH: &str = "/__self_service_path__/app_config";
43
44pub const CERTIFICATE_PATH: &str = "/__self_service_path__/certificate";
45
46pub const SSL_CONFIG_SAVE: &str = "/__self_service_path__/ssl_config/save";
47
48pub const ASSERT_DIT: &str = "/__self_service_path__/static";
49pub const ASSERT_INDEX: &str = "/__self_service_path__/index.html";
50pub const ASSERT_ROOT: &str = "/__self_service_path__";
51
52pub fn match_self_service(req: &Request<Incoming>) -> bool {
53    req.uri().path().starts_with(SELF_SERVICE_PATH_PREFIX)
54}
55
56pub async fn self_service_router(
57    req: Request<Incoming>,
58) -> Result<Response<BoxBody<Bytes, Error>>> {
59    let method = req.method();
60    let path = req.uri().path();
61
62    trace!("self_service_router: method: {:?}, path: {}", method, path);
63
64    match (method, path) {
65        (&method::Method::GET, HELLO_PATH) => Ok(Response::new(full(Bytes::from("Hello, World!")))),
66        (&method::Method::GET, RULE_GROUP_LIST) => {
67            api::rule_group_api::handle_rule_group_find(req).await
68        }
69        (&method::Method::POST, RULE_GROUP_ADD) => {
70            api::rule_group_api::handle_rule_group_add(req).await
71        }
72        (&method::Method::POST, RULE_GROUP_UPDATE) => {
73            api::rule_group_api::handle_rule_group_update(req).await
74        }
75        (&method::Method::POST, RULE_GROUP_DELETE) => {
76            api::rule_group_api::handle_rule_group_delete(req).await
77        }
78
79        (&method::Method::GET, RULE_DETAIL) => api::rule_api::handle_rule_detail(req).await,
80        (&method::Method::POST, RULE_ADD) => api::rule_api::handle_rule_add(req).await,
81        (&method::Method::POST, RULE_UPDATE) => api::rule_api::handle_rule_update(req).await,
82        (&method::Method::POST, RULE_DELETE) => api::rule_api::handle_rule_delete(req).await,
83
84        (&method::Method::POST, APP_CONFIG_RECORD_STATUS) => {
85            api::app_config_api::handle_recording_status(req).await
86        }
87        (&method::Method::GET, APP_CONFIG_PATH) => {
88            api::app_config_api::handle_app_config(req).await
89        }
90        (&method::Method::GET, RULE_CONTEXT_SCHEMA) => {
91            let schema = schema_for!(RuleContent);
92            let schema = serde_json::to_value(&schema).map_err(|e| anyhow!(e))?;
93            response_ok(schema)
94        }
95
96        (&method::Method::GET, REQUEST_LOG) => api::request::handle_request_log().await,
97        (&method::Method::POST, REQUEST_CLEAR) => api::request::handle_request_clear().await,
98        (&method::Method::GET, REQUEST_BODY) => self::api::request::handle_request_body(req).await,
99
100        (&method::Method::GET, RESPONSE) => self::api::response::handle_response(req).await,
101        (&method::Method::GET, RESPONSE_BODY) => {
102            self::api::response::handle_response_body(req).await
103        }
104
105        (&method::Method::POST, SSL_CONFIG_SAVE) => {
106            self::api::ssl_config::handle_save_ssl_config(req).await
107        }
108
109        (&method::Method::GET, CERTIFICATE_PATH) => {
110            self::api::certificate::handle_certificate(req).await
111        }
112
113        (&method::Method::GET, path)
114            if path == SELF_SERVICE_PATH_PREFIX
115                || path.starts_with(ASSERT_DIT)
116                || path == ASSERT_INDEX
117                || path == ASSERT_ROOT =>
118        {
119            self::api::asserts::handle_ui_assert(req).await
120        }
121
122        _ => Ok(not_found()),
123    }
124}
125
126pub async fn handle_self_service(
127    req: Request<Incoming>,
128) -> Result<Response<BoxBody<Bytes, Error>>> {
129    let res = self_service_router(req).await;
130
131    match res {
132        Ok(res) => Ok(res),
133        Err(err) => {
134            error!("self_service error: {:?}", err);
135
136            let res = if err.downcast_ref::<ValidateError>().is_some() {
137                let err_string = format!("{}", err);
138                validate_error(err_string)
139            } else if err.downcast_ref::<OperationError>().is_some() {
140                operation_error(err.to_string())
141            } else {
142                internal_server_error(err.to_string())
143            };
144
145            let json_str = serde_json::to_string(&res)
146                .map_err(|e| anyhow!(e).context("response box to json error"))?;
147
148            let data = json_str.into_bytes();
149
150            let res = Response::builder()
151                .header(CONTENT_TYPE, "application/json")
152                .body(full(data))
153                .unwrap();
154            Ok(res)
155        }
156    }
157}