diff --git a/Cargo.lock b/Cargo.lock
index 87a5fff795..3a0b7475cc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5256,7 +5256,6 @@ dependencies = [
"etcd-client",
"flatten-json-object",
"futures",
- "futures-util",
"get_if_addrs",
"glob",
"http-auth-basic",
diff --git a/Cargo.toml b/Cargo.toml
index f000fc67ed..acffae3ea2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -70,7 +70,6 @@ env_logger = "0.10"
etcd-client = { version = "0.10.2", features = ["tls"] }
flatten-json-object = "0.6.1"
futures = "0.3"
-futures-util = "0.3.25"
get_if_addrs = "0.5.3"
glob = "0.3.0"
http-auth-basic = "0.3.3"
diff --git a/src/handler/http/router/mod.rs b/src/handler/http/router/mod.rs
index 10f306d25c..2f72dd8e72 100644
--- a/src/handler/http/router/mod.rs
+++ b/src/handler/http/router/mod.rs
@@ -13,8 +13,10 @@
// limitations under the License.
use actix_cors::Cors;
-use actix_web::{http::header, web};
+use actix_web::dev::{Service, ServiceResponse};
+use actix_web::{body::MessageBody, http::header, web, HttpResponse};
use actix_web_httpauth::middleware::HttpAuthentication;
+use futures::FutureExt;
use std::sync::Arc;
use utoipa::OpenApi;
use utoipa_swagger_ui::{SwaggerUi, Url};
@@ -65,14 +67,31 @@ pub fn get_basic_routes(cfg: &mut web::ServiceConfig) {
if CONFIG.common.ui_enabled {
cfg.service(web::redirect("/", "./web/"));
- cfg.service(web::redirect("/web/alerts/alerts", "../alerts"));
- cfg.service(web::redirect("/web/alerts/destinations", "../alerts"));
- cfg.service(web::redirect("/web/alerts/templates", "../alerts"));
- cfg.service(web::redirect("/web/ingestion/curl", "../ingestion"));
- cfg.service(web::redirect("/web/ingestion/fluentbit", "../ingestion"));
- cfg.service(web::redirect("/web/ingestion/fluentd", "../ingestion"));
- cfg.service(web::redirect("/web/ingestion/vector", "../ingestion"));
- cfg.service(ui::serve);
+ cfg.service(web::redirect("/web", "./web/"));
+ cfg.service(
+ web::scope("/web")
+ .wrap_fn(|req, srv| {
+ let prefix = format!("{}/web/", CONFIG.common.base_uri);
+ let path = req.path().strip_prefix(&prefix).unwrap().to_string();
+ srv.call(req).map(move |res| {
+ if ui::UI_PAGES.contains(&path.as_str()) {
+ let res = res.unwrap();
+ let req = res.request().clone();
+ let body = res.into_body();
+ let body = body.try_into_bytes().unwrap();
+ let body = String::from_utf8(body.to_vec()).unwrap();
+ let body = body.replace(
+ r#""#,
+ format!(r#""#, prefix).as_str(),
+ );
+ Ok(ServiceResponse::new(req, HttpResponse::Ok().body(body)))
+ } else {
+ res
+ }
+ })
+ })
+ .service(ui::serve),
+ );
}
}
diff --git a/src/handler/http/router/ui.rs b/src/handler/http/router/ui.rs
index 86d05969d7..8d2897ba06 100644
--- a/src/handler/http/router/ui.rs
+++ b/src/handler/http/router/ui.rs
@@ -22,7 +22,8 @@ use rust_embed_for_web::RustEmbed;
#[folder = "web/dist/"]
struct WebAssets;
-pub const UI_PAGES: [&str; 19] = [
+pub const UI_PAGES: [&str; 22] = [
+ "",
"login",
"logout",
"about",
@@ -31,6 +32,8 @@ pub const UI_PAGES: [&str; 19] = [
"dashboards",
"viewDashboard",
"addPanel",
+ "dashboards/view",
+ "dashboards/addPanel",
"logstreams",
"functions",
"alerts",
@@ -44,18 +47,12 @@ pub const UI_PAGES: [&str; 19] = [
"ingestion/vector",
];
-#[route("/web/{path:.*}", method = "GET", method = "HEAD")]
+#[route("/{path:.*}", method = "GET", method = "HEAD")]
pub async fn serve(path: web::Path) -> EmbedResponse {
- let mut path = if path.is_empty() {
- "index.html"
- } else {
- path.as_str()
- };
-
+ let mut path = path.as_str();
if UI_PAGES.contains(&path) {
path = "index.html";
}
-
WebAssets::get(path)
.into_response()
.use_compression(Compress::Never)
diff --git a/src/service/search/datafusion/exec.rs b/src/service/search/datafusion/exec.rs
index 3c1de5db23..757952f5ad 100644
--- a/src/service/search/datafusion/exec.rs
+++ b/src/service/search/datafusion/exec.rs
@@ -396,19 +396,32 @@ fn merge_rewrite_sql(sql: &str, schema: Arc) -> Result {
let sql_chars_len = sql_chars.len();
let mut start_pos = 0;
let mut in_word = false;
- let mut bracket = 0;
+ let mut brackets = 0;
+ let mut quotes = 0;
+ let mut quote_now = '\"';
for i in 0..sql_chars_len {
let c = sql_chars.get(i).unwrap();
if *c == '(' {
- bracket += 1;
+ brackets += 1;
continue;
}
if *c == ')' {
- bracket -= 1;
+ brackets -= 1;
continue;
}
+ if *c == '"' || *c == '\'' {
+ if quotes == 0 {
+ quotes += 1;
+ quote_now = *c;
+ continue;
+ }
+ if quotes == 1 && quote_now == *c {
+ quotes = 0;
+ continue;
+ }
+ }
if *c == ',' || *c == ' ' {
- if bracket > 0 {
+ if brackets > 0 || quotes > 0 {
continue;
}
if in_word {
diff --git a/web/index.html b/web/index.html
index b2ac75bfb5..d1069da4cd 100644
--- a/web/index.html
+++ b/web/index.html
@@ -6,6 +6,7 @@
ZincObserve
+