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