You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by mo...@apache.org on 2023/04/12 17:02:53 UTC

[doris] 09/33: [Enhancement](HttpServer) Support https interface (#16834)

This is an automated email from the ASF dual-hosted git repository.

morningman pushed a commit to branch doris-for-zhongjin
in repository https://gitbox.apache.org/repos/asf/doris.git

commit d13cb02e8c026a45866a0130075c69788d7559a7
Author: yongjinhou <10...@users.noreply.github.com>
AuthorDate: Mon Apr 3 14:18:17 2023 +0800

    [Enhancement](HttpServer) Support https interface (#16834)
    
    1. Organize http documents
    2. Add http interface authentication for FE
    3. **Support https interface for FE**
    4. Provide authentication interface
    5. Add http interface authentication for BE
    6. Support https interface for BE
---
 build.sh                                           |  1 +
 docs/en/docs/admin-manual/config/fe-config.md      | 17 ++++++-
 .../admin-manual/http-actions/fe/cluster-action.md | 12 +++++
 .../http-actions/fe/colocate-meta-action.md        |  8 +++-
 .../admin-manual/http-actions/fe/metrics-action.md |  3 ++
 docs/zh-CN/docs/admin-manual/config/fe-config.md   | 13 +++++
 .../admin-manual/http-actions/fe/cluster-action.md | 12 +++++
 .../http-actions/fe/colocate-meta-action.md        |  8 +++-
 .../admin-manual/http-actions/fe/metrics-action.md |  3 ++
 .../admin-manual/http-actions/fe/profile-action.md |  2 +-
 .../main/java/org/apache/doris/common/Config.java  | 39 ++++++++++++++-
 .../src/main/java/org/apache/doris/DorisFE.java    | 10 ++++
 .../org/apache/doris/common/util/NetUtils.java     |  2 +
 .../java/org/apache/doris/httpv2/HttpServer.java   | 50 +++++++++++++++++--
 .../httpv2/config/HttpToHttpsJettyConfig.java      | 54 +++++++++++++++++++++
 .../config/WebServerFactoryCustomizerConfig.java   | 56 ++++++++++++++++++++++
 .../doris/httpv2/controller/BaseController.java    |  7 ++-
 .../doris/httpv2/meta/ColocateMetaService.java     |  8 ++++
 .../apache/doris/httpv2/rest/CancelLoadAction.java |  5 +-
 .../org/apache/doris/httpv2/rest/LoadAction.java   | 16 +++++++
 .../org/apache/doris/httpv2/rest/MultiAction.java  | 24 ++++++++++
 .../doris/httpv2/rest/RestBaseController.java      | 18 +++++++
 .../doris/httpv2/rest/StmtExecutionAction.java     | 10 +++-
 .../doris/httpv2/rest/TableQueryPlanAction.java    |  4 ++
 .../org/apache/doris/httpv2/rest/UploadAction.java |  3 ++
 .../apache/doris/httpv2/restv2/ImportAction.java   |  4 ++
 26 files changed, 375 insertions(+), 14 deletions(-)

diff --git a/build.sh b/build.sh
index 7f173015ab..0df9fc0b8c 100755
--- a/build.sh
+++ b/build.sh
@@ -529,6 +529,7 @@ if [[ "${BUILD_FE}" -eq 1 ]]; then
     copy_common_files "${DORIS_OUTPUT}/fe/"
     mkdir -p "${DORIS_OUTPUT}/fe/log"
     mkdir -p "${DORIS_OUTPUT}/fe/doris-meta"
+    mkdir -p "${DORIS_OUTPUT}/fe/conf/ssl"
 fi
 
 if [[ "${BUILD_SPARK_DPP}" -eq 1 ]]; then
diff --git a/docs/en/docs/admin-manual/config/fe-config.md b/docs/en/docs/admin-manual/config/fe-config.md
index 3158cc8eed..b1a9a01aa3 100644
--- a/docs/en/docs/admin-manual/config/fe-config.md
+++ b/docs/en/docs/admin-manual/config/fe-config.md
@@ -392,13 +392,26 @@ Default value: 0.0.0.0
 
 Default:none
 
-Declare a selection strategy for those servers have many ips.  Note that there should at most one ip match this list.  this is a list in semicolon-delimited format, in CIDR notation, e.g. 10.10.10.0/24 , If no ip match this rule, will choose one randomly..
+Declare a selection strategy for those servers have many ips.  Note that there should at most one ip match this list.  this is a list in semicolon-delimited format, in CIDR notation, e.g. 10.10.10.0/24 , If no ip match this rule, will choose one randomly.
 
 #### `http_port`
 
 Default:8030
 
-HTTP bind port. Defaults to 8030
+HTTP bind port. All FE http ports must be same currently.
+
+#### `https_port`
+
+Default:8050
+
+HTTPS bind port. All FE https ports must be same currently.
+
+#### `enable_https`
+
+Default:false
+
+Https enable flag. If the value is false, http is supported. Otherwise, both http and https are supported, and http requests are automatically redirected to https.
+If enable_https is true, you need to configure ssl certificate information in fe.conf.
 
 #### `qe_max_connection`
 
diff --git a/docs/en/docs/admin-manual/http-actions/fe/cluster-action.md b/docs/en/docs/admin-manual/http-actions/fe/cluster-action.md
index b9328cc249..657b9577da 100644
--- a/docs/en/docs/admin-manual/http-actions/fe/cluster-action.md
+++ b/docs/en/docs/admin-manual/http-actions/fe/cluster-action.md
@@ -38,6 +38,18 @@ under the License.
 
 Used to get cluster http, mysql connection information.
 
+## Path parameters
+
+None
+
+## Query parameters
+
+None
+
+## Request body
+
+None
+
 ### Response
 
 ```
diff --git a/docs/en/docs/admin-manual/http-actions/fe/colocate-meta-action.md b/docs/en/docs/admin-manual/http-actions/fe/colocate-meta-action.md
index 99a07597b5..38e8b64e19 100644
--- a/docs/en/docs/admin-manual/http-actions/fe/colocate-meta-action.md
+++ b/docs/en/docs/admin-manual/http-actions/fe/colocate-meta-action.md
@@ -42,7 +42,13 @@ None
 
 ## Query parameters
 
-None
+* `db_id`
+
+    Specify database id
+
+* `group_id`
+    
+    Specify group id
 
 ## Request body
 
diff --git a/docs/en/docs/admin-manual/http-actions/fe/metrics-action.md b/docs/en/docs/admin-manual/http-actions/fe/metrics-action.md
index 0ad53640f9..b1caadb1f9 100644
--- a/docs/en/docs/admin-manual/http-actions/fe/metrics-action.md
+++ b/docs/en/docs/admin-manual/http-actions/fe/metrics-action.md
@@ -46,3 +46,6 @@ None
 
 None
 
+## Response
+
+TO DO
\ No newline at end of file
diff --git a/docs/zh-CN/docs/admin-manual/config/fe-config.md b/docs/zh-CN/docs/admin-manual/config/fe-config.md
index 369220d732..8241a268a8 100644
--- a/docs/zh-CN/docs/admin-manual/config/fe-config.md
+++ b/docs/zh-CN/docs/admin-manual/config/fe-config.md
@@ -400,6 +400,19 @@ Doris FE 通过 mysql 协议查询连接端口
 
 FE http 端口,当前所有 FE http 端口都必须相同
 
+#### `https_port`
+
+默认值:8050
+
+FE https 端口,当前所有 FE https 端口都必须相同
+
+#### `enable_https`
+
+默认值:false
+
+FE https 使能标志位,false 表示支持 http,true 表示同时支持 http 与 https,并且会自动将 http 请求重定向到 https
+如果 enable_https 为 true,需要在 fe.conf 中配置 ssl 证书信息
+
 #### `qe_max_connection`
 
 默认值:1024
diff --git a/docs/zh-CN/docs/admin-manual/http-actions/fe/cluster-action.md b/docs/zh-CN/docs/admin-manual/http-actions/fe/cluster-action.md
index 74bf68d86e..bfb4de6b12 100644
--- a/docs/zh-CN/docs/admin-manual/http-actions/fe/cluster-action.md
+++ b/docs/zh-CN/docs/admin-manual/http-actions/fe/cluster-action.md
@@ -38,6 +38,18 @@ under the License.
 
 用于获取集群http、mysql连接信息。
 
+## Path parameters
+
+无
+
+## Query parameters
+
+无
+
+## Request body
+
+无
+
 ### Response
 
 ```
diff --git a/docs/zh-CN/docs/admin-manual/http-actions/fe/colocate-meta-action.md b/docs/zh-CN/docs/admin-manual/http-actions/fe/colocate-meta-action.md
index fecaf01d1a..988380830f 100644
--- a/docs/zh-CN/docs/admin-manual/http-actions/fe/colocate-meta-action.md
+++ b/docs/zh-CN/docs/admin-manual/http-actions/fe/colocate-meta-action.md
@@ -42,7 +42,13 @@ under the License.
 
 ## Query parameters
 
-无
+* `db_id`
+
+    指定数据库id
+
+* `group_id`
+    
+    指定组id
 
 ## Request body
 
diff --git a/docs/zh-CN/docs/admin-manual/http-actions/fe/metrics-action.md b/docs/zh-CN/docs/admin-manual/http-actions/fe/metrics-action.md
index 4e4b305b11..0c6cc8fbea 100644
--- a/docs/zh-CN/docs/admin-manual/http-actions/fe/metrics-action.md
+++ b/docs/zh-CN/docs/admin-manual/http-actions/fe/metrics-action.md
@@ -46,3 +46,6 @@ under the License.
 
 无
 
+## Response
+
+TO DO
\ No newline at end of file
diff --git a/docs/zh-CN/docs/admin-manual/http-actions/fe/profile-action.md b/docs/zh-CN/docs/admin-manual/http-actions/fe/profile-action.md
index 71e7d5dda0..f02380d125 100644
--- a/docs/zh-CN/docs/admin-manual/http-actions/fe/profile-action.md
+++ b/docs/zh-CN/docs/admin-manual/http-actions/fe/profile-action.md
@@ -126,7 +126,7 @@ Query:
 
 ## Query parameters
 
-* query_id
+* `query_id`
 
     指定的 query id
 
diff --git a/fe/fe-common/src/main/java/org/apache/doris/common/Config.java b/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
index 53daefcf83..1960f8a97c 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
@@ -338,6 +338,11 @@ public class Config extends ConfigBase {
      */
     @ConfField public static long max_bdbje_clock_delta_ms = 5000; // 5s
 
+    /**
+     * Whether to enable all http interface authentication
+     */
+    @ConfField public static boolean enable_all_http_auth = false;
+
     /**
      * Fe http port
      * Currently, all FEs' http port must be same.
@@ -345,9 +350,39 @@ public class Config extends ConfigBase {
     @ConfField public static int http_port = 8030;
 
     /**
-     * Whether to enable all http interface authentication
+     * Fe https port
+     * Currently, all FEs' https port must be same.
      */
-    @ConfField public static boolean enable_all_http_auth = false;
+    @ConfField public static int https_port = 8050;
+
+    /**
+     * ssl key store path.
+     * If you want to change the path, you need to create corresponding directory.
+     */
+    @ConfField public static String key_store_path = System.getenv("DORIS_HOME")
+        + "/conf/ssl/doris_ssl_certificate.keystore";
+
+    /**
+     * ssl key store password. Null by default.
+     */
+    @ConfField public static String key_store_password = "";
+
+    /**
+     * ssl key store type. "JKS" by default.
+     */
+    @ConfField public static String key_store_type = "JKS";
+
+    /**
+     * ssl key store alias. "doris_ssl_certificate" by default.
+     */
+    @ConfField public static String key_store_alias = "doris_ssl_certificate";
+
+    /**
+     * https enable flag. false by default.
+     * If the value is false, http is supported. Otherwise, https is supported.
+     * Currently doris uses many ports, so http and https are not supported at the same time.
+     */
+    @ConfField public static boolean enable_https = false;
 
     /**
      * Jetty container default configuration
diff --git a/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java b/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java
index 7bebd6ac25..26bfc139df 100755
--- a/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java
@@ -158,10 +158,16 @@ public class DorisFE {
             if (options.enableHttpServer) {
                 HttpServer httpServer = new HttpServer();
                 httpServer.setPort(Config.http_port);
+                httpServer.setHttpsPort(Config.https_port);
                 httpServer.setMaxHttpPostSize(Config.jetty_server_max_http_post_size);
                 httpServer.setAcceptors(Config.jetty_server_acceptors);
                 httpServer.setSelectors(Config.jetty_server_selectors);
                 httpServer.setWorkers(Config.jetty_server_workers);
+                httpServer.setKeyStorePath(Config.key_store_path);
+                httpServer.setKeyStorePassword(Config.key_store_password);
+                httpServer.setKeyStoreType(Config.key_store_type);
+                httpServer.setKeyStoreAlias(Config.key_store_alias);
+                httpServer.setEnableHttps(Config.enable_https);
                 httpServer.setMaxThreads(Config.jetty_threadPool_maxThreads);
                 httpServer.setMinThreads(Config.jetty_threadPool_minThreads);
                 httpServer.setMaxHttpHeaderSize(Config.jetty_server_max_http_header_size);
@@ -192,6 +198,10 @@ public class DorisFE {
                 "Http port", NetUtils.HTTP_PORT_SUGGESTION)) {
             throw new IOException("port " + Config.http_port + " already in use");
         }
+        if (Config.enable_https && !NetUtils.isPortAvailable(FrontendOptions.getLocalHostAddress(),
+                Config.https_port, "Https port", NetUtils.HTTPS_PORT_SUGGESTION)) {
+            throw new IOException("port " + Config.https_port + " already in use");
+        }
         if (!NetUtils.isPortAvailable(FrontendOptions.getLocalHostAddress(), Config.query_port,
                 "Query port", NetUtils.QUERY_PORT_SUGGESTION)) {
             throw new IOException("port " + Config.query_port + " already in use");
diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/util/NetUtils.java b/fe/fe-core/src/main/java/org/apache/doris/common/util/NetUtils.java
index 61f288b20a..0318a7abdb 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/util/NetUtils.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/NetUtils.java
@@ -45,6 +45,8 @@ public class NetUtils {
     public static final String QUERY_PORT_SUGGESTION = "Please change the 'query_port' in fe.conf and try again.";
     public static final String HTTP_PORT_SUGGESTION = "Please change the 'http_port' in fe.conf and try again. "
             + "But you need to make sure that ALL FEs http_port are same.";
+    public static final String HTTPS_PORT_SUGGESTION = "Please change the 'https_port' in fe.conf and try again. "
+            + "But you need to make sure that ALL FEs https_port are same.";
     public static final String RPC_PORT_SUGGESTION = "Please change the 'rpc_port' in fe.conf and try again.";
 
     // Target format is "host:port"
diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/HttpServer.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/HttpServer.java
index 922efe5ea7..88ec1a1b9f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/HttpServer.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/HttpServer.java
@@ -36,13 +36,19 @@ import java.util.Map;
 @EnableConfigurationProperties
 @ServletComponentScan
 public class HttpServer extends SpringBootServletInitializer {
-
     private int port;
+    private int httpsPort;
     private int acceptors;
     private int selectors;
     private int maxHttpPostSize;
     private int workers;
 
+    private String keyStorePath;
+    private String keyStorePassword;
+    private String keyStoreType;
+    private String keyStoreAlias;
+    private boolean enableHttps;
+
     private int minThreads;
     private int maxThreads;
     private int maxHttpHeaderSize;
@@ -91,6 +97,30 @@ public class HttpServer extends SpringBootServletInitializer {
         this.port = port;
     }
 
+    public void setHttpsPort(int httpsPort) {
+        this.httpsPort = httpsPort;
+    }
+
+    public void setKeyStorePath(String keyStorePath) {
+        this.keyStorePath = keyStorePath;
+    }
+
+    public void setKeyStorePassword(String keyStorePassword) {
+        this.keyStorePassword = keyStorePassword;
+    }
+
+    public void setKeyStoreType(String keyStoreType) {
+        this.keyStoreType = keyStoreType;
+    }
+
+    public void setKeyStoreAlias(String keyStoreAlias) {
+        this.keyStoreAlias = keyStoreAlias;
+    }
+
+    public void setEnableHttps(boolean enableHttps) {
+        this.enableHttps = enableHttps;
+    }
+
     @Override
     protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
         return application.sources(HttpServer.class);
@@ -98,7 +128,19 @@ public class HttpServer extends SpringBootServletInitializer {
 
     public void start() {
         Map<String, Object> properties = new HashMap<>();
-        properties.put("server.port", port);
+        if (enableHttps) {
+            properties.put("server.http.port", port);
+            properties.put("server.port", httpsPort);
+            // ssl config
+            properties.put("server.ssl.key-store", keyStorePath);
+            properties.put("server.ssl.key-store-password", keyStorePassword);
+            properties.put("server.ssl.key-store-type", keyStoreType);
+            properties.put("server.ssl.keyalias", keyStoreAlias);
+            properties.put("server.ssl.enabled", enableHttps);
+        } else {
+            properties.put("server.port", port);
+            properties.put("server.ssl.enabled", enableHttps);
+        }
         if (FrontendOptions.isBindIPV6()) {
             properties.put("server.address", "::0");
         } else {
@@ -109,14 +151,14 @@ public class HttpServer extends SpringBootServletInitializer {
         properties.put("spring.http.encoding.charset", "UTF-8");
         properties.put("spring.http.encoding.enabled", true);
         properties.put("spring.http.encoding.force", true);
-        //enable jetty config
+        // enable jetty config
         properties.put("server.jetty.acceptors", this.acceptors);
         properties.put("server.jetty.max-http-post-size", this.maxHttpPostSize);
         properties.put("server.jetty.selectors", this.selectors);
         properties.put("server.jetty.threadPool.maxThreads", this.maxThreads);
         properties.put("server.jetty.threadPool.minThreads", this.minThreads);
         properties.put("server.max-http-header-size", this.maxHttpHeaderSize);
-        //Worker thread pool is not set by default, set according to your needs
+        // Worker thread pool is not set by default, set according to your needs
         if (this.workers > 0) {
             properties.put("server.jetty.workers", this.workers);
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/config/HttpToHttpsJettyConfig.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/config/HttpToHttpsJettyConfig.java
new file mode 100644
index 0000000000..84b81f6c72
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/config/HttpToHttpsJettyConfig.java
@@ -0,0 +1,54 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.httpv2.config;
+
+import org.eclipse.jetty.security.ConstraintMapping;
+import org.eclipse.jetty.security.ConstraintSecurityHandler;
+import org.eclipse.jetty.util.security.Constraint;
+import org.eclipse.jetty.webapp.AbstractConfiguration;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+public class HttpToHttpsJettyConfig extends AbstractConfiguration {
+    @Override
+    public void configure(WebAppContext context) throws Exception {
+        Constraint constraint = new Constraint();
+        constraint.setDataConstraint(Constraint.DC_CONFIDENTIAL);
+
+        ConstraintSecurityHandler handler = new ConstraintSecurityHandler();
+
+        ConstraintMapping mappingGet = new ConstraintMapping();
+        mappingGet.setConstraint(constraint);
+        mappingGet.setPathSpec("/*");
+        mappingGet.setMethod("GET");
+        handler.addConstraintMapping(mappingGet);
+
+        ConstraintMapping mappingDel = new ConstraintMapping();
+        mappingDel.setConstraint(constraint);
+        mappingDel.setPathSpec("/*");
+        mappingDel.setMethod("DELETE");
+        handler.addConstraintMapping(mappingDel);
+
+        ConstraintMapping mappingRest = new ConstraintMapping();
+        mappingRest.setConstraint(constraint);
+        mappingRest.setPathSpec("/rest/*");
+        mappingRest.setMethod("POST");
+        handler.addConstraintMapping(mappingRest);
+
+        context.setSecurityHandler(handler);
+    }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/config/WebServerFactoryCustomizerConfig.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/config/WebServerFactoryCustomizerConfig.java
new file mode 100644
index 0000000000..c0eb2dc7c7
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/config/WebServerFactoryCustomizerConfig.java
@@ -0,0 +1,56 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.httpv2.config;
+
+import org.apache.doris.common.Config;
+
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.ServerConnector;
+import org.springframework.boot.web.embedded.jetty.ConfigurableJettyWebServerFactory;
+import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
+import org.springframework.boot.web.server.WebServerFactoryCustomizer;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Collections;
+
+@Configuration
+public class WebServerFactoryCustomizerConfig implements WebServerFactoryCustomizer<ConfigurableJettyWebServerFactory> {
+    @Override
+    public void customize(ConfigurableJettyWebServerFactory factory) {
+        if (Config.enable_https) {
+            ((JettyServletWebServerFactory) factory).setConfigurations(
+                    Collections.singleton(new HttpToHttpsJettyConfig())
+            );
+
+            factory.addServerCustomizers(
+                    server -> {
+                        HttpConfiguration httpConfiguration = new HttpConfiguration();
+                        httpConfiguration.setSecurePort(Config.https_port);
+                        httpConfiguration.setSecureScheme("https");
+
+                        ServerConnector connector = new ServerConnector(server);
+                        connector.addConnectionFactory(new HttpConnectionFactory(httpConfiguration));
+                        connector.setPort(Config.http_port);
+
+                        server.addConnector(connector);
+                    }
+            );
+        }
+    }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/BaseController.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/BaseController.java
index cc1a208a2e..59cde0093b 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/BaseController.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/BaseController.java
@@ -296,6 +296,11 @@ public class BaseController {
     }
 
     protected String getCurrentFrontendURL() {
-        return "http://" + FrontendOptions.getLocalHostAddress() + ":" + Config.http_port;
+        if (Config.enable_https) {
+            // this could be the result of redirection.
+            return "https://" + FrontendOptions.getLocalHostAddress() + ":" + Config.https_port;
+        } else {
+            return "http://" + FrontendOptions.getLocalHostAddress() + ":" + Config.http_port;
+        }
     }
 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/meta/ColocateMetaService.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/meta/ColocateMetaService.java
index 9be85cd86e..9d63a00501 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/meta/ColocateMetaService.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/meta/ColocateMetaService.java
@@ -103,6 +103,10 @@ public class ColocateMetaService extends RestBaseController {
     @RequestMapping(path = "/api/colocate/group_stable", method = {RequestMethod.POST, RequestMethod.DELETE})
     public Object group_stable(HttpServletRequest request, HttpServletResponse response)
             throws DdlException {
+        if (needRedirect(request.getScheme())) {
+            return redirectToHttps(request);
+        }
+
         executeWithoutPassword(request, response);
         GroupId groupId = checkAndGetGroupId(request);
 
@@ -118,6 +122,10 @@ public class ColocateMetaService extends RestBaseController {
     @RequestMapping(path = "/api/colocate/bucketseq", method = RequestMethod.POST)
     public Object bucketseq(HttpServletRequest request, HttpServletResponse response, @RequestBody String meta)
             throws DdlException {
+        if (needRedirect(request.getScheme())) {
+            return redirectToHttps(request);
+        }
+
         executeWithoutPassword(request, response);
         final String clusterName = ConnectContext.get().getClusterName();
         GroupId groupId = checkAndGetGroupId(request);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/CancelLoadAction.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/CancelLoadAction.java
index b215b3c711..5468bf812a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/CancelLoadAction.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/CancelLoadAction.java
@@ -45,8 +45,11 @@ public class CancelLoadAction extends RestBaseController {
     @RequestMapping(path = "/api/{" + DB_KEY + "}/_cancel", method = RequestMethod.POST)
     public Object execute(@PathVariable(value = DB_KEY) final String dbName,
                           HttpServletRequest request, HttpServletResponse response) {
-        executeCheckPassword(request, response);
+        if (needRedirect(request.getScheme())) {
+            return redirectToHttps(request);
+        }
 
+        executeCheckPassword(request, response);
         RedirectView redirectView = redirectToMaster(request, response);
         if (redirectView != null) {
             return redirectView;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/LoadAction.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/LoadAction.java
index 0e2eb815fd..df0f689953 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/LoadAction.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/LoadAction.java
@@ -59,6 +59,10 @@ public class LoadAction extends RestBaseController {
     @RequestMapping(path = "/api/{" + DB_KEY + "}/{" + TABLE_KEY + "}/_load", method = RequestMethod.PUT)
     public Object load(HttpServletRequest request, HttpServletResponse response,
                        @PathVariable(value = DB_KEY) String db, @PathVariable(value = TABLE_KEY) String table) {
+        if (needRedirect(request.getScheme())) {
+            return redirectToHttps(request);
+        }
+
         if (Config.disable_mini_load) {
             ResponseEntity entity = ResponseEntityBuilder.notFound("The mini load operation has been"
                     + " disabled by default, if you need to add disable_mini_load=false in fe.conf.");
@@ -73,6 +77,10 @@ public class LoadAction extends RestBaseController {
     public Object streamLoad(HttpServletRequest request,
                              HttpServletResponse response,
                              @PathVariable(value = DB_KEY) String db, @PathVariable(value = TABLE_KEY) String table) {
+        if (needRedirect(request.getScheme())) {
+            return redirectToHttps(request);
+        }
+
         executeCheckPassword(request, response);
         return executeWithoutPassword(request, response, db, table, true);
     }
@@ -81,6 +89,10 @@ public class LoadAction extends RestBaseController {
     public Object streamLoad2PC(HttpServletRequest request,
                                    HttpServletResponse response,
                                    @PathVariable(value = DB_KEY) String db) {
+        if (needRedirect(request.getScheme())) {
+            return redirectToHttps(request);
+        }
+
         executeCheckPassword(request, response);
         return executeStreamLoad2PC(request, db);
     }
@@ -90,6 +102,10 @@ public class LoadAction extends RestBaseController {
                                       HttpServletResponse response,
                                       @PathVariable(value = DB_KEY) String db,
                                       @PathVariable(value = TABLE_KEY) String table) {
+        if (needRedirect(request.getScheme())) {
+            return redirectToHttps(request);
+        }
+
         executeCheckPassword(request, response);
         return executeStreamLoad2PC(request, db);
     }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/MultiAction.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/MultiAction.java
index 14d79ab15c..b04005ae7c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/MultiAction.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/MultiAction.java
@@ -52,6 +52,10 @@ public class MultiAction extends RestBaseController {
     public Object multi_desc(
             @PathVariable(value = DB_KEY) final String dbName,
             HttpServletRequest request, HttpServletResponse response) {
+        if (needRedirect(request.getScheme())) {
+            return redirectToHttps(request);
+        }
+
         try {
             executeCheckPassword(request, response);
 
@@ -84,6 +88,10 @@ public class MultiAction extends RestBaseController {
             @PathVariable(value = DB_KEY) final String dbName,
             HttpServletRequest request, HttpServletResponse response)
             throws DdlException {
+        if (needRedirect(request.getScheme())) {
+            return redirectToHttps(request);
+        }
+
         try {
             executeCheckPassword(request, response);
             execEnv = ExecuteEnv.getInstance();
@@ -110,6 +118,10 @@ public class MultiAction extends RestBaseController {
             @PathVariable(value = DB_KEY) final String dbName,
             HttpServletRequest request, HttpServletResponse response)
             throws DdlException {
+        if (needRedirect(request.getScheme())) {
+            return redirectToHttps(request);
+        }
+
         try {
             executeCheckPassword(request, response);
             execEnv = ExecuteEnv.getInstance();
@@ -154,6 +166,10 @@ public class MultiAction extends RestBaseController {
     public Object multi_unload(
             @PathVariable(value = DB_KEY) final String dbName,
             HttpServletRequest request, HttpServletResponse response) {
+        if (needRedirect(request.getScheme())) {
+            return redirectToHttps(request);
+        }
+
         try {
             executeCheckPassword(request, response);
             execEnv = ExecuteEnv.getInstance();
@@ -188,6 +204,10 @@ public class MultiAction extends RestBaseController {
             @PathVariable(value = DB_KEY) final String dbName,
             HttpServletRequest request, HttpServletResponse response)
             throws DdlException {
+        if (needRedirect(request.getScheme())) {
+            return redirectToHttps(request);
+        }
+
         try {
             executeCheckPassword(request, response);
             execEnv = ExecuteEnv.getInstance();
@@ -222,6 +242,10 @@ public class MultiAction extends RestBaseController {
             @PathVariable(value = DB_KEY) final String dbName,
             HttpServletRequest request, HttpServletResponse response)
             throws DdlException {
+        if (needRedirect(request.getScheme())) {
+            return redirectToHttps(request);
+        }
+
         try {
             executeCheckPassword(request, response);
             execEnv = ExecuteEnv.getInstance();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/RestBaseController.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/RestBaseController.java
index 1d8a71def3..2bbf914051 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/RestBaseController.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/RestBaseController.java
@@ -20,6 +20,7 @@ package org.apache.doris.httpv2.rest;
 import org.apache.doris.analysis.UserIdentity;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.cluster.ClusterNamespace;
+import org.apache.doris.common.Config;
 import org.apache.doris.httpv2.controller.BaseController;
 import org.apache.doris.httpv2.exception.UnauthorizedException;
 import org.apache.doris.qe.ConnectContext;
@@ -30,6 +31,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
+import org.springframework.http.HttpStatus;
 import org.springframework.web.servlet.view.RedirectView;
 
 import java.io.BufferedInputStream;
@@ -172,4 +174,20 @@ public class RestBaseController extends BaseController {
         }
         return fullDbName;
     }
+
+    public boolean needRedirect(String scheme) {
+        return Config.enable_https && "http".equalsIgnoreCase(scheme);
+    }
+
+    public Object redirectToHttps(HttpServletRequest request) {
+        String serverName = request.getServerName();
+        String uri = request.getRequestURI();
+        String query = request.getQueryString();
+        query = query == null ? "" : query;
+        String newUrl = "https://" + serverName + ":" + Config.https_port + uri + "?" + query;
+        LOG.info("redirect to new url: {}", newUrl);
+        RedirectView redirectView = new RedirectView(newUrl);
+        redirectView.setStatusCode(HttpStatus.TEMPORARY_REDIRECT);
+        return redirectView;
+    }
 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/StmtExecutionAction.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/StmtExecutionAction.java
index 190c5cf82e..8175762ba8 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/StmtExecutionAction.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/StmtExecutionAction.java
@@ -84,6 +84,10 @@ public class StmtExecutionAction extends RestBaseController {
     @RequestMapping(path = "/api/query/{" + NS_KEY + "}/{" + DB_KEY + "}", method = {RequestMethod.POST})
     public Object executeSQL(@PathVariable(value = NS_KEY) String ns, @PathVariable(value = DB_KEY) String dbName,
             HttpServletRequest request, HttpServletResponse response, @RequestBody String body) {
+        if (needRedirect(request.getScheme())) {
+            return redirectToHttps(request);
+        }
+
         ActionAuthorizationInfo authInfo = checkWithCookie(request, response, false);
         String fullDbName = getFullDbName(dbName);
         if (Config.enable_all_http_auth) {
@@ -125,8 +129,12 @@ public class StmtExecutionAction extends RestBaseController {
      * @return plain text of create table stmts
      */
     @RequestMapping(path = "/api/query_schema/{" + NS_KEY + "}/{" + DB_KEY + "}", method = {RequestMethod.POST})
-    public String querySchema(@PathVariable(value = NS_KEY) String ns, @PathVariable(value = DB_KEY) String dbName,
+    public Object querySchema(@PathVariable(value = NS_KEY) String ns, @PathVariable(value = DB_KEY) String dbName,
             HttpServletRequest request, HttpServletResponse response, @RequestBody String sql) {
+        if (needRedirect(request.getScheme())) {
+            return redirectToHttps(request);
+        }
+
         checkWithCookie(request, response, false);
 
         if (ns.equalsIgnoreCase(SystemInfoService.DEFAULT_CLUSTER)) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/TableQueryPlanAction.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/TableQueryPlanAction.java
index fa051b983f..dcae36301e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/TableQueryPlanAction.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/TableQueryPlanAction.java
@@ -84,6 +84,10 @@ public class TableQueryPlanAction extends RestBaseController {
             @PathVariable(value = DB_KEY) final String dbName,
             @PathVariable(value = TABLE_KEY) final String tblName,
             HttpServletRequest request, HttpServletResponse response) {
+        if (needRedirect(request.getScheme())) {
+            return redirectToHttps(request);
+        }
+
         executeCheckPassword(request, response);
         // just allocate 2 slot for top holder map
         Map<String, Object> resultMap = new HashMap<>(4);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/UploadAction.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/UploadAction.java
index 8431bd5195..6b58fcefcf 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/UploadAction.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/UploadAction.java
@@ -75,6 +75,9 @@ public class UploadAction extends RestBaseController {
             @PathVariable(value = TABLE_KEY) String tblName,
             @RequestParam("file") MultipartFile file,
             HttpServletRequest request, HttpServletResponse response) {
+        if (needRedirect(request.getScheme())) {
+            return redirectToHttps(request);
+        }
 
         checkWithCookie(request, response, false);
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/restv2/ImportAction.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/restv2/ImportAction.java
index 11f66a906c..1979a9e983 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/restv2/ImportAction.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/restv2/ImportAction.java
@@ -76,6 +76,10 @@ public class ImportAction extends RestBaseController {
     @RequestMapping(path = "/api/import/file_review", method = RequestMethod.POST)
     public Object fileReview(@RequestBody FileReviewRequestVo body,
             HttpServletRequest request, HttpServletResponse response) {
+        if (needRedirect(request.getScheme())) {
+            return redirectToHttps(request);
+        }
+
         if (Config.enable_all_http_auth) {
             executeCheckPassword(request, response);
         }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org