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

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


The following commit(s) were added to refs/heads/master by this push:
     new 6ad064501e0 [Enhancement] (FE) Convert intra FE-to-FE calls to HTTPS 
when enabled (#60921)
6ad064501e0 is described below

commit 6ad064501e0b73d31299cabdb82f0133a1a3c7c1
Author: nsivarajan <[email protected]>
AuthorDate: Tue Jul 7 16:07:34 2026 +0530

    [Enhancement] (FE) Convert intra FE-to-FE calls to HTTPS when enabled 
(#60921)
    
    Problem Summary:
    
    Currently, Doris provides an enable_https switch to enforce HTTPS
    connections. In hardened deployments, HTTP is completely disabled by
    setting http_port = 0. However, intra FE-to-FE communication still
    relies on HTTP, causing failures in edit log and checkpoint
    synchronisation when HTTPS is enabled.
    
    This PR enhances HTTPS support by automatically converting intra
    FE-to-FE communication to HTTPS when enable_https=true, without
    introducing any new configuration, leveraging
    mysql_ssl_default_ca_certificate created for https connection. When
    enable_https=false, behavior remains unchanged. This ensures secure and
    seamless FE-to-FE communication without breaking existing workflows.
    
    
    Co-authored-by: Sivarajan Narayanan <[email protected]>
---
 .../main/java/org/apache/doris/catalog/Env.java    |  21 ++---
 .../org/apache/doris/common/util/HttpURLUtil.java  |  25 ++++++
 .../doris/common/util/InternalHttpsUtils.java      | 100 +++++++++++++++++++++
 .../doris/httpv2/controller/SessionController.java |   5 +-
 .../org/apache/doris/httpv2/meta/MetaService.java  |   5 +-
 .../doris/httpv2/rest/RestBaseController.java      |  30 ++++++-
 .../doris/httpv2/rest/manager/ClusterAction.java   |   4 +-
 .../doris/httpv2/rest/manager/HttpUtils.java       |  20 +++--
 .../doris/httpv2/rest/manager/NodeAction.java      |  15 +++-
 .../httpv2/rest/manager/QueryProfileAction.java    |   4 +-
 .../java/org/apache/doris/master/Checkpoint.java   |  11 ++-
 .../java/org/apache/doris/master/MetaHelper.java   |   8 +-
 .../doris/nereids/minidump/MinidumpUtils.java      |   7 +-
 .../java/org/apache/doris/system/HeartbeatMgr.java |   5 +-
 .../apache/doris/common/util/HttpURLUtilTest.java  |  80 +++++++++++++++++
 .../doris/common/util/InternalHttpsUtilsTest.java  |  64 +++++++++++++
 .../doris/nereids/minidump/MinidumpUtTest.java     |  45 ++++++++++
 .../org/apache/doris/system/HeartbeatMgrTest.java  |  38 ++++++++
 18 files changed, 445 insertions(+), 42 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
index b6de5fa9e06..8ef13b43522 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
@@ -1466,8 +1466,7 @@ public class Env {
                 getClusterIdFromStorage(storage);
                 token = storage.getToken();
                 try {
-                    String url = "http://"; + NetUtils
-                            
.getHostPortInAccessibleFormat(rightHelperNode.getHost(), Config.http_port) + 
"/check";
+                    String url = 
HttpURLUtil.buildInternalFeUrl(rightHelperNode.getHost(), "/check", null);
                     HttpURLConnection conn = 
HttpURLUtil.getConnectionWithNodeIdent(url);
                     conn.setConnectTimeout(2 * 1000);
                     conn.setReadTimeout(2 * 1000);
@@ -1563,9 +1562,8 @@ public class Env {
             try {
                 // For upgrade compatibility, the host parameter name remains 
the same
                 // and the new hostname parameter is added
-                String url = "http://"; + 
NetUtils.getHostPortInAccessibleFormat(helperNode.getHost(), Config.http_port)
-                        + "/role?host=" + selfNode.getHost()
-                        + "&port=" + selfNode.getPort();
+                String queryParams = "host=" + selfNode.getHost() + "&port=" + 
selfNode.getPort();
+                String url = 
HttpURLUtil.buildInternalFeUrl(helperNode.getHost(), "/role", queryParams);
                 HttpURLConnection conn = 
HttpURLUtil.getConnectionWithNodeIdent(url);
                 if (conn.getResponseCode() != 200) {
                     LOG.warn("failed to get fe node type from helper node: {}. 
response code: {}", helperNode,
@@ -1599,7 +1597,8 @@ public class Env {
             }
 
             LOG.info("get fe node type {}, name {} from {}:{}:{}", role, 
nodeName,
-                    helperNode.getHost(), helperNode.getHost(), 
Config.http_port);
+                    helperNode.getHost(), helperNode.getPort(),
+                    HttpURLUtil.getHttpPort());
             rightHelperNode = helperNode;
             break;
         }
@@ -1828,7 +1827,7 @@ public class Env {
 
             toMasterProgress = "log master info";
             this.masterInfo = new 
MasterInfo(Env.getCurrentEnv().getSelfNode().getHost(),
-                    Config.http_port,
+                    HttpURLUtil.getHttpPort(),
                     Config.rpc_port);
             editLog.logMasterInfo(masterInfo);
             LOG.info("logMasterInfo:{}", masterInfo);
@@ -2286,8 +2285,7 @@ public class Env {
 
     protected boolean getVersionFileFromHelper(HostInfo helperNode) throws 
IOException {
         try {
-            String url = "http://"; + 
NetUtils.getHostPortInAccessibleFormat(helperNode.getHost(), Config.http_port)
-                    + "/version";
+            String url = HttpURLUtil.buildInternalFeUrl(helperNode.getHost(), 
"/version", null);
             File dir = new File(this.imageDir);
             MetaHelper.getRemoteFile(url, HTTP_TIMEOUT_SECOND * 1000,
                     MetaHelper.getFile(Storage.VERSION_FILE, dir));
@@ -2306,8 +2304,7 @@ public class Env {
         localImageVersion = storage.getLatestImageSeq();
 
         try {
-            String hostPort = 
NetUtils.getHostPortInAccessibleFormat(helperNode.getHost(), Config.http_port);
-            String infoUrl = "http://"; + hostPort + "/info";
+            String infoUrl = 
HttpURLUtil.buildInternalFeUrl(helperNode.getHost(), "/info", null);
             ResponseBody<StorageInfo> responseBody = MetaHelper
                     .doGet(infoUrl, HTTP_TIMEOUT_SECOND * 1000, 
StorageInfo.class);
             if (responseBody.getCode() != RestApiStatusCode.OK.code) {
@@ -2317,7 +2314,7 @@ public class Env {
             StorageInfo info = responseBody.getData();
             long version = info.getImageSeq();
             if (version > localImageVersion) {
-                String url = "http://"; + hostPort + "/image?version=" + 
version;
+                String url = 
HttpURLUtil.buildInternalFeUrl(helperNode.getHost(), "/image", "version=" + 
version);
                 String filename = Storage.IMAGE + "." + version;
                 File dir = new File(this.imageDir);
                 MetaHelper.getRemoteFile(url, Config.sync_image_timeout_second 
* 1000,
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/common/util/HttpURLUtil.java 
b/fe/fe-core/src/main/java/org/apache/doris/common/util/HttpURLUtil.java
index baafc104bf9..7e590de5a74 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/util/HttpURLUtil.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/HttpURLUtil.java
@@ -23,11 +23,13 @@ import org.apache.doris.common.Config;
 import org.apache.doris.system.SystemInfoService.HostInfo;
 
 import com.google.common.collect.Maps;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
 
 import java.io.IOException;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.util.Map;
+import javax.net.ssl.HttpsURLConnection;
 
 public class HttpURLUtil {
 
@@ -40,6 +42,13 @@ public class HttpURLUtil {
             SecurityChecker.getInstance().startSSRFChecking(request);
             URL url = new URL(request);
             HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+
+            if (conn instanceof HttpsURLConnection && Config.enable_https) {
+                HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
+                
httpsConn.setSSLSocketFactory(InternalHttpsUtils.getSslContext().getSocketFactory());
+                httpsConn.setHostnameVerifier(NoopHostnameVerifier.INSTANCE);
+            }
+
             // Must use Env.getServingEnv() instead of getCurrentEnv(),
             // because here we need to obtain selfNode through the official 
service catalog.
             HostInfo selfNode = Env.getServingEnv().getSelfNode();
@@ -63,4 +72,20 @@ public class HttpURLUtil {
         return headers;
     }
 
+    public static int getHttpPort() {
+        return Config.enable_https ? Config.https_port : Config.http_port;
+    }
+
+    public static String buildInternalFeUrl(String host, String path, String 
queryParams) {
+        String protocol = Config.enable_https ? "https" : "http";
+        int port = getHttpPort();
+
+        String url = protocol + "://" + 
NetUtils.getHostPortInAccessibleFormat(host, port) + path;
+        if (queryParams != null && !queryParams.isEmpty()) {
+            url += "?" + queryParams;
+        }
+
+        return url;
+    }
+
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/common/util/InternalHttpsUtils.java 
b/fe/fe-core/src/main/java/org/apache/doris/common/util/InternalHttpsUtils.java
new file mode 100644
index 00000000000..f0c7f7db7dd
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/common/util/InternalHttpsUtils.java
@@ -0,0 +1,100 @@
+// 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.common.util;
+
+import org.apache.doris.common.Config;
+
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.KeyStore;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+
+/**
+ * Utility for creating SSL-aware HTTP clients for internal FE-to-FE 
communication.
+ *
+ * <p>Builds an {@link SSLContext} from the configured CA truststore once and 
caches it.
+ * Hostname verification is disabled for IP-based intra-cluster connections.
+ * Certificate rotation requires a FE restart.
+ */
+public class InternalHttpsUtils {
+    private static volatile SSLContext cachedSslContext = null;
+
+    private static final Logger LOG = 
LogManager.getLogger(InternalHttpsUtils.class);
+
+    /**
+     * Returns the cached SSLContext, building it from the configured 
truststore on first call.
+     */
+    public static SSLContext getSslContext() {
+        if (cachedSslContext == null) {
+            synchronized (InternalHttpsUtils.class) {
+                if (cachedSslContext == null) {
+                    cachedSslContext = buildSslContext();
+                }
+            }
+        }
+        return cachedSslContext;
+    }
+
+    private static SSLContext buildSslContext() {
+        try {
+            // The same CA signs all Doris TLS certs (FE HTTPS + MySQL SSL), 
so mysql_ssl_default_ca_certificate
+            // is the correct trust anchor for FE-to-FE HTTPS. Hostname 
verification is skipped for IP-based comms.
+            KeyStore trustStore = 
KeyStore.getInstance(Config.ssl_trust_store_type);
+            try (InputStream stream = Files.newInputStream(
+                    Paths.get(Config.mysql_ssl_default_ca_certificate))) {
+                trustStore.load(stream, 
Config.mysql_ssl_default_ca_certificate_password.toCharArray());
+            }
+
+            TrustManagerFactory tmf = TrustManagerFactory.getInstance(
+                    TrustManagerFactory.getDefaultAlgorithm());
+            tmf.init(trustStore);
+
+            SSLContext sslContext = SSLContext.getInstance("TLS");
+            sslContext.init(null, tmf.getTrustManagers(), null);
+            return sslContext;
+        } catch (Exception e) {
+            LOG.error("Failed to build SSLContext from truststore: {}",
+                    Config.mysql_ssl_default_ca_certificate, e);
+            throw new RuntimeException(
+                    "Failed to build SSLContext from truststore: "
+                            + Config.mysql_ssl_default_ca_certificate, e);
+        }
+    }
+
+    /**
+     * Returns an HTTP client configured with the FE CA truststore and 
hostname verification disabled.
+     */
+    public static CloseableHttpClient createValidatedHttpClient() {
+        SSLConnectionSocketFactory sslFactory = new SSLConnectionSocketFactory(
+                getSslContext(),
+                NoopHostnameVerifier.INSTANCE);
+
+        return HttpClients.custom()
+                .setSSLSocketFactory(sslFactory)
+                .build();
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/SessionController.java
 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/SessionController.java
index 94be8e17376..a753305106a 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/SessionController.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/SessionController.java
@@ -20,6 +20,7 @@ package org.apache.doris.httpv2.controller;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.SchemaTable;
 import org.apache.doris.catalog.Table;
+import org.apache.doris.common.util.HttpURLUtil;
 import org.apache.doris.httpv2.entity.ResponseBody;
 import org.apache.doris.httpv2.entity.ResponseEntityBuilder;
 import org.apache.doris.httpv2.rest.RestBaseController;
@@ -118,8 +119,8 @@ public class SessionController extends RestBaseController {
                                                           Frontend frontend) 
throws IOException {
         Map<String, String> header = Maps.newHashMap();
         header.put(NodeAction.AUTHORIZATION, 
request.getHeader(NodeAction.AUTHORIZATION));
-        String res = 
HttpUtils.doGet(String.format("http://%s:%s/rest/v1/session";,
-                frontend.getHost(), Env.getCurrentEnv().getMasterHttpPort()), 
header);
+        String res = HttpUtils.doGet(HttpURLUtil.buildInternalFeUrl(
+                frontend.getHost(), "/rest/v1/session", null), header);
         ObjectMapper objectMapper = new ObjectMapper();
         Map<String, Object> jsonMap = objectMapper.readValue(res,
             new TypeReference<Map<String, Object>>() {});
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/meta/MetaService.java 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/meta/MetaService.java
index 6a8bd71faca..79a34ad4d38 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/meta/MetaService.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/meta/MetaService.java
@@ -163,7 +163,10 @@ public class MetaService extends RestBaseController {
                 clientHost, clientPort, machine, portStr);
 
         clientHost = Strings.isNullOrEmpty(clientHost) ? machine : clientHost;
-        String url = "http://"; + 
NetUtils.getHostPortInAccessibleFormat(clientHost, Integer.valueOf(portStr))
+        // Use the master-supplied port: Checkpoint sends getHttpPort() 
(https_port when
+        // enable_https=true), so scheme and port must stay consistent.
+        String scheme = Config.enable_https ? "https" : "http";
+        String url = scheme + "://" + 
NetUtils.getHostPortInAccessibleFormat(clientHost, port)
                 + "/image?version=" + versionStr;
 
         String filename = Storage.IMAGE + "." + versionStr;
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 c352d46ac6c..249d8d04c5d 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
@@ -22,6 +22,8 @@ import org.apache.doris.catalog.Env;
 import org.apache.doris.common.Config;
 import org.apache.doris.common.FeConstants;
 import org.apache.doris.common.UserException;
+import org.apache.doris.common.util.HttpURLUtil;
+import org.apache.doris.common.util.InternalHttpsUtils;
 import org.apache.doris.common.util.NetUtils;
 import org.apache.doris.httpv2.controller.BaseController;
 import org.apache.doris.httpv2.entity.ResponseEntityBuilder;
@@ -36,6 +38,7 @@ import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import jline.internal.Nullable;
 import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.springframework.http.HttpEntity;
@@ -43,6 +46,7 @@ import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.SimpleClientHttpRequestFactory;
 import org.springframework.web.client.RestTemplate;
 import org.springframework.web.servlet.view.RedirectView;
 
@@ -52,10 +56,12 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.net.HttpURLConnection;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.Collections;
 import java.util.stream.Collectors;
+import javax.net.ssl.HttpsURLConnection;
 
 public class RestBaseController extends BaseController {
 
@@ -271,8 +277,8 @@ public class RestBaseController extends BaseController {
                 redirectUrl =
                         getRedirectUrL(request, new 
TNetworkAddress(request.getServerName(), request.getServerPort()));
             } else {
-                redirectUrl = getRedirectUrL(request,
-                        new TNetworkAddress(env.getMasterHost(), 
env.getMasterHttpPort()));
+                redirectUrl = HttpURLUtil.buildInternalFeUrl(
+                        env.getMasterHost(), request.getRequestURI(), 
request.getQueryString());
             }
             String method = request.getMethod();
 
@@ -292,7 +298,25 @@ public class RestBaseController extends BaseController {
 
             HttpEntity<Object> entity = new HttpEntity<>(body, headers);
 
-            RestTemplate restTemplate = new RestTemplate();
+            RestTemplate restTemplate;
+            if (Config.enable_https) {
+                SimpleClientHttpRequestFactory factory = new 
SimpleClientHttpRequestFactory() {
+                    @Override
+                    protected void prepareConnection(HttpURLConnection conn, 
String httpMethod)
+                            throws IOException {
+                        if (conn instanceof HttpsURLConnection) {
+                            HttpsURLConnection https = (HttpsURLConnection) 
conn;
+                            https.setSSLSocketFactory(
+                                    
InternalHttpsUtils.getSslContext().getSocketFactory());
+                            
https.setHostnameVerifier(NoopHostnameVerifier.INSTANCE);
+                        }
+                        super.prepareConnection(conn, httpMethod);
+                    }
+                };
+                restTemplate = new RestTemplate(factory);
+            } else {
+                restTemplate = new RestTemplate();
+            }
 
             ResponseEntity<Object> responseEntity;
             switch (method) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/ClusterAction.java
 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/ClusterAction.java
index 391d7c85163..2c49a3b7178 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/ClusterAction.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/ClusterAction.java
@@ -20,6 +20,7 @@ package org.apache.doris.httpv2.rest.manager;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.cloud.system.CloudSystemInfoService;
 import org.apache.doris.common.Config;
+import org.apache.doris.common.util.HttpURLUtil;
 import org.apache.doris.common.util.NetUtils;
 import 
org.apache.doris.httpv2.controller.BaseController.ActionAuthorizationInfo;
 import org.apache.doris.httpv2.entity.ResponseEntityBuilder;
@@ -71,7 +72,8 @@ public class ClusterAction extends RestBaseController {
         result.put("mysql", frontends.stream().map(ip -> NetUtils
                 .getHostPortInAccessibleFormat(ip, 
Config.query_port)).collect(Collectors.toList()));
         result.put("http", frontends.stream().map(ip -> NetUtils
-                .getHostPortInAccessibleFormat(ip, 
Config.http_port)).collect(Collectors.toList()));
+                .getHostPortInAccessibleFormat(ip,
+                        
HttpURLUtil.getHttpPort())).collect(Collectors.toList()));
         result.put("arrow flight sql server", frontends.stream().map(
                 ip -> NetUtils.getHostPortInAccessibleFormat(ip, 
Config.arrow_flight_sql_port))
                 .collect(Collectors.toList()));
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/HttpUtils.java 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/HttpUtils.java
index 6cda1ac4f37..25171e3f411 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/HttpUtils.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/HttpUtils.java
@@ -20,6 +20,8 @@ package org.apache.doris.httpv2.rest.manager;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.common.Config;
 import org.apache.doris.common.Pair;
+import org.apache.doris.common.util.HttpURLUtil;
+import org.apache.doris.common.util.InternalHttpsUtils;
 import org.apache.doris.common.util.Util;
 import org.apache.doris.httpv2.entity.ResponseBody;
 import org.apache.doris.persist.gson.GsonUtils;
@@ -51,7 +53,7 @@ import java.util.Objects;
 import java.util.stream.Collectors;
 
 /*
- * used to forward http requests from manager to be.
+ * Used for internal HTTP(S) communication between FE nodes and from manager 
to BE.
  */
 public class HttpUtils {
     private static final Logger LOG = LogManager.getLogger(HttpUtils.class);
@@ -60,18 +62,21 @@ public class HttpUtils {
     static final int DEFAULT_TIME_OUT_MS = 2000;
 
     public static List<Pair<String, Integer>> getFeList() {
+        int port = HttpURLUtil.getHttpPort();
         return Env.getCurrentEnv().getFrontends(null)
-                .stream().filter(Frontend::isAlive).map(fe -> 
Pair.of(fe.getHost(), Config.http_port))
+                .stream().filter(Frontend::isAlive).map(fe -> 
Pair.of(fe.getHost(), port))
                 .collect(Collectors.toList());
     }
 
     static boolean isCurrentFe(String ip, int port) {
         HostInfo hostInfo = Env.getCurrentEnv().getSelfNode();
-        return hostInfo.isSame(new HostInfo(ip, port));
+        // Compare against the actual HTTP/HTTPS port, not the edit_log_port 
held by selfNode.
+        int selfPort = HttpURLUtil.getHttpPort();
+        return hostInfo.getHost().equals(ip) && selfPort == port;
     }
 
     public static String concatUrl(Pair<String, Integer> ipPort, String path, 
Map<String, String> arguments) {
-        StringBuilder url = new StringBuilder("http://";)
+        StringBuilder url = new StringBuilder(Config.enable_https ? "https://"; 
: "http://";)
                 
.append(ipPort.first).append(":").append(ipPort.second).append(path);
         boolean isFirst = true;
         for (Map.Entry<String, String> entry : arguments.entrySet()) {
@@ -130,8 +135,11 @@ public class HttpUtils {
     }
 
     private static String executeRequest(HttpRequestBase request) throws 
IOException {
-        CloseableHttpClient client = getHttpClient();
-        return client.execute(request, httpResponse -> 
EntityUtils.toString(httpResponse.getEntity()));
+        try (CloseableHttpClient client = Config.enable_https
+                ? InternalHttpsUtils.createValidatedHttpClient()
+                : HttpClientBuilder.create().build()) {
+            return client.execute(request, httpResponse -> 
EntityUtils.toString(httpResponse.getEntity()));
+        }
     }
 
     static String parseResponse(String response) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/NodeAction.java 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/NodeAction.java
index 1ad24aaf3d6..3a8dc73bbe2 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/NodeAction.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/NodeAction.java
@@ -27,6 +27,7 @@ import org.apache.doris.common.Pair;
 import org.apache.doris.common.ThreadPoolManager;
 import org.apache.doris.common.proc.ProcResult;
 import org.apache.doris.common.proc.ProcService;
+import org.apache.doris.common.util.HttpURLUtil;
 import org.apache.doris.common.util.NetUtils;
 import org.apache.doris.common.util.PropertyAnalyzer;
 import org.apache.doris.ha.FrontendNodeType;
@@ -240,8 +241,9 @@ public class NodeAction extends RestBaseController {
     }
 
     private static List<String> getFeList() {
+        int port = HttpURLUtil.getHttpPort();
         return Env.getCurrentEnv().getFrontends(null).stream()
-                .map(fe -> 
NetUtils.getHostPortInAccessibleFormat(fe.getHost(), Config.http_port))
+                .map(fe -> 
NetUtils.getHostPortInAccessibleFormat(fe.getHost(), port))
                 .collect(Collectors.toList());
     }
 
@@ -373,7 +375,10 @@ public class NodeAction extends RestBaseController {
             Pair<String, Integer> hostPort = hostPorts.get(i);
             String address = 
NetUtils.getHostPortInAccessibleFormat(hostPort.first, hostPort.second);
             configRequestDoneSignal.addMark(address, -1);
-            String url = "http://"; + address + questPath;
+            // FE nodes use HTTPS when enabled; BE nodes always use plain HTTP
+            // (BEs do not participate in the FE internal HTTPS scheme)
+            String scheme = (Config.enable_https && "FE".equals(nodeType)) ? 
"https://"; : "http://";;
+            String url = scheme + address + questPath;
             httpExecutor.submit(
                     new HttpConfigInfoTask(url, hostPort, authorization, 
nodeType, confNames, configRequestDoneSignal,
                             configInfoTotal.get(i)));
@@ -497,7 +502,8 @@ public class NodeAction extends RestBaseController {
         List<Map<String, String>> failedTotal = Lists.newArrayList();
         List<NodeConfigs> nodeConfigList = parseSetConfigNodes(requestBody, 
failedTotal);
         List<Pair<String, Integer>> aliveFe = 
Env.getCurrentEnv().getFrontends(null).stream().filter(Frontend::isAlive)
-                .map(fe -> Pair.of(fe.getHost(), 
Config.http_port)).collect(Collectors.toList());
+                .map(fe -> Pair.of(fe.getHost(),
+                        
HttpURLUtil.getHttpPort())).collect(Collectors.toList());
         checkNodeIsAlive(nodeConfigList, aliveFe, failedTotal);
 
         Map<String, String> header = Maps.newHashMap();
@@ -569,7 +575,8 @@ public class NodeAction extends RestBaseController {
     private String concatFeSetConfigUrl(NodeConfigs nodeConfigs, boolean 
isPersist) {
         StringBuilder sb = new StringBuilder();
         Pair<String, Integer> hostPort = nodeConfigs.getHostPort();
-        
sb.append("http://";).append(hostPort.first).append(":").append(hostPort.second).append("/api/_set_config");
+        sb.append(Config.enable_https ? "https://"; : "http://";)
+                
.append(hostPort.first).append(":").append(hostPort.second).append("/api/_set_config");
         Map<String, String> configs = nodeConfigs.getConfigs(isPersist);
         boolean addAnd = false;
         for (Map.Entry<String, String> entry : configs.entrySet()) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/QueryProfileAction.java
 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/QueryProfileAction.java
index 27b955522ae..d0aae7d1a0e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/QueryProfileAction.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/QueryProfileAction.java
@@ -20,7 +20,6 @@ package org.apache.doris.httpv2.rest.manager;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.AuthenticationException;
-import org.apache.doris.common.Config;
 import org.apache.doris.common.Pair;
 import org.apache.doris.common.Status;
 import org.apache.doris.common.proc.CurrentQueryStatisticsProcDir;
@@ -28,6 +27,7 @@ import org.apache.doris.common.proc.ProcResult;
 import org.apache.doris.common.profile.ProfileManager;
 import org.apache.doris.common.profile.ProfileManager.ProfileElement;
 import org.apache.doris.common.profile.SummaryProfile;
+import org.apache.doris.common.util.HttpURLUtil;
 import org.apache.doris.common.util.NetUtils;
 import 
org.apache.doris.httpv2.controller.BaseController.ActionAuthorizationInfo;
 import org.apache.doris.httpv2.entity.ResponseEntityBuilder;
@@ -196,7 +196,7 @@ public class QueryProfileAction extends RestBaseController {
         // add node information
         for (List<String> query : queries) {
             query.set(1, 
NetUtils.getHostPortInAccessibleFormat(Env.getCurrentEnv().getSelfNode().getHost(),
-                    Config.http_port));
+                    HttpURLUtil.getHttpPort()));
         }
 
         if (!Strings.isNullOrEmpty(search)) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/master/Checkpoint.java 
b/fe/fe-core/src/main/java/org/apache/doris/master/Checkpoint.java
index b908954541d..2b933034eeb 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/master/Checkpoint.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/master/Checkpoint.java
@@ -32,7 +32,6 @@ import org.apache.doris.common.Config;
 import org.apache.doris.common.FeConstants;
 import org.apache.doris.common.util.HttpURLUtil;
 import org.apache.doris.common.util.MasterDaemon;
-import org.apache.doris.common.util.NetUtils;
 import org.apache.doris.httpv2.entity.ResponseBody;
 import org.apache.doris.httpv2.rest.RestApiStatusCode;
 import org.apache.doris.metric.MetricRepo;
@@ -229,10 +228,10 @@ public class Checkpoint extends MasterDaemon {
                     // skip master itself
                     continue;
                 }
-                int port = Config.http_port;
+                int port = HttpURLUtil.getHttpPort();
 
-                String url = "http://"; + 
NetUtils.getHostPortInAccessibleFormat(host, port) + "/put?version=" + 
replayedJournalId
-                        + "&port=" + port;
+                String queryParams = "version=" + replayedJournalId + "&port=" 
+ port;
+                String url = HttpURLUtil.buildInternalFeUrl(host, "/put", 
queryParams);
                 LOG.info("Put image:{}", url);
 
                 try {
@@ -286,7 +285,6 @@ public class Checkpoint extends MasterDaemon {
                             // skip master itself
                             continue;
                         }
-                        int port = Config.http_port;
                         String idURL;
                         HttpURLConnection conn = null;
                         try {
@@ -296,7 +294,7 @@ public class Checkpoint extends MasterDaemon {
                              * any non-master node's current replayed journal 
id. otherwise,
                              * this lagging node can never get the deleted 
journal.
                              */
-                            idURL = "http://"; + 
NetUtils.getHostPortInAccessibleFormat(host, port) + "/journal_id";
+                            idURL = HttpURLUtil.buildInternalFeUrl(host, 
"/journal_id", null);
                             conn = 
HttpURLUtil.getConnectionWithNodeIdent(idURL);
                             conn.setConnectTimeout(CONNECT_TIMEOUT_SECOND * 
1000);
                             conn.setReadTimeout(READ_TIMEOUT_SECOND * 1000);
@@ -306,6 +304,7 @@ public class Checkpoint extends MasterDaemon {
                                 minOtherNodesJournalId = id;
                             }
                         } catch (Throwable e) {
+                            int port = HttpURLUtil.getHttpPort();
                             throw new 
CheckpointException(String.format("Exception when getting current replayed"
                                     + " journal id. host=%s, port=%d", host, 
port), e);
                         } finally {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/master/MetaHelper.java 
b/fe/fe-core/src/main/java/org/apache/doris/master/MetaHelper.java
index 96e73756791..5acec62ae59 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/master/MetaHelper.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/master/MetaHelper.java
@@ -149,9 +149,13 @@ public class MetaHelper {
 
     public static <T> ResponseBody doGet(String url, int timeout, Class<T> 
clazz) throws IOException {
         Map<String, String> headers = HttpURLUtil.getNodeIdentHeaders();
-        LOG.info("meta helper, url: {}, timeout{}, headers: {}", url, timeout, 
headers);
+        LOG.info("meta helper, url: {}, timeout: {}, headers: {}", url, 
timeout, headers);
         String response = HttpUtils.doGet(url, headers, timeout);
-        return parseResponse(response, clazz);
+        try {
+            return parseResponse(response, clazz);
+        } catch (Exception e) {
+            throw new IOException("Failed to parse response from " + url + ". 
Response: " + response, e);
+        }
     }
 
     // download file from remote node
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/minidump/MinidumpUtils.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/minidump/MinidumpUtils.java
index 7ed1c6a1d77..8469cafff5b 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/minidump/MinidumpUtils.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/minidump/MinidumpUtils.java
@@ -28,6 +28,7 @@ import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.Config;
 import org.apache.doris.common.proc.FrontendsProcNode;
 import org.apache.doris.common.util.DebugUtil;
+import org.apache.doris.common.util.HttpURLUtil;
 import org.apache.doris.nereids.NereidsPlanner;
 import org.apache.doris.nereids.StatementContext;
 import org.apache.doris.nereids.glue.LogicalPlanAdapter;
@@ -106,9 +107,11 @@ public class MinidumpUtils {
     public static void saveMinidumpString(JSONObject minidump, String querId) {
         String dumpPath = MinidumpUtils.DUMP_PATH + File.separator + "_" + 
querId;
         String feAddress = 
FrontendsProcNode.getCurrentFrontendVersion(Env.getCurrentEnv()).getHost();
-        int feHttpPort = Config.http_port;
+        int feHttpPort = HttpURLUtil.getHttpPort();
+        String scheme = Config.enable_https ? "https" : "http";
         MinidumpUtils.DUMP_FILE_FULL_PATH = dumpPath + ".json";
-        MinidumpUtils.HTTP_GET_STRING = "http://"; + feAddress + ":" + 
feHttpPort + "/api/minidump?query_id=" + querId;
+        MinidumpUtils.HTTP_GET_STRING = scheme + "://" + feAddress + ":" + 
feHttpPort
+                + "/api/minidump?query_id=" + querId;
         String jsonMinidump = minidump.toString(4);
         try (FileWriter file = new 
FileWriter(MinidumpUtils.DUMP_FILE_FULL_PATH)) {
             file.write(jsonMinidump);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/system/HeartbeatMgr.java 
b/fe/fe-core/src/main/java/org/apache/doris/system/HeartbeatMgr.java
index a8906e43df1..f23af939399 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/system/HeartbeatMgr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/system/HeartbeatMgr.java
@@ -26,6 +26,7 @@ import org.apache.doris.common.ThreadPoolManager;
 import org.apache.doris.common.UserException;
 import org.apache.doris.common.Version;
 import org.apache.doris.common.util.DebugPointUtil;
+import org.apache.doris.common.util.HttpURLUtil;
 import org.apache.doris.common.util.MasterDaemon;
 import org.apache.doris.persist.HbPackage;
 import org.apache.doris.resource.Tag;
@@ -96,7 +97,9 @@ public class HeartbeatMgr extends MasterDaemon {
         TMasterInfo tMasterInfo = new TMasterInfo(
                 new TNetworkAddress(FrontendOptions.getLocalHostAddress(), 
Config.rpc_port), clusterId, epoch);
         tMasterInfo.setToken(token);
-        tMasterInfo.setHttpPort(Config.http_port);
+        // small_file_mgr at BE downloads from FE using this port,
+        // by trying http then fallback to https(for http_port=0 cases).
+        tMasterInfo.setHttpPort(HttpURLUtil.getHttpPort());
         long flags = heartbeatFlags.getHeartbeatFlags();
         tMasterInfo.setHeartbeatFlags(flags);
         if (Config.isCloudMode()) {
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/common/util/HttpURLUtilTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/common/util/HttpURLUtilTest.java
new file mode 100644
index 00000000000..5bba968b49a
--- /dev/null
+++ b/fe/fe-core/src/test/java/org/apache/doris/common/util/HttpURLUtilTest.java
@@ -0,0 +1,80 @@
+// 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.common.util;
+
+import org.apache.doris.common.Config;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class HttpURLUtilTest {
+
+    @After
+    public void tearDown() {
+        Config.enable_https = false;
+        Config.http_port = 8030;
+        Config.https_port = 8050;
+    }
+
+    @Test
+    public void testBuildInternalFeUrlHttp() {
+        Config.enable_https = false;
+        Config.http_port = 8030;
+
+        String url = HttpURLUtil.buildInternalFeUrl("192.168.1.10", "/put", 
"version=123&port=8030");
+        
Assert.assertEquals("http://192.168.1.10:8030/put?version=123&port=8030";, url);
+    }
+
+    @Test
+    public void testBuildInternalFeUrlHttps() {
+        Config.enable_https = true;
+        Config.https_port = 8050;
+
+        String url = HttpURLUtil.buildInternalFeUrl("192.168.1.10", "/put", 
"version=123&port=8050");
+        
Assert.assertEquals("https://192.168.1.10:8050/put?version=123&port=8050";, url);
+    }
+
+    @Test
+    public void testBuildInternalFeUrlNoQueryParams() {
+        Config.enable_https = false;
+        Config.http_port = 8030;
+
+        String url = HttpURLUtil.buildInternalFeUrl("192.168.1.10", 
"/journal_id", null);
+        Assert.assertEquals("http://192.168.1.10:8030/journal_id";, url);
+    }
+
+    @Test
+    public void testBuildInternalFeUrlEmptyQueryParams() {
+        Config.enable_https = false;
+        Config.http_port = 8030;
+
+        String url = HttpURLUtil.buildInternalFeUrl("192.168.1.10", 
"/version", "");
+        Assert.assertEquals("http://192.168.1.10:8030/version";, url);
+    }
+
+    @Test
+    public void testBuildInternalFeUrlHttpsWithIPv6() {
+        Config.enable_https = true;
+        Config.https_port = 8050;
+
+        String url = HttpURLUtil.buildInternalFeUrl("fe80::1", "/role", 
"host=fe80::2&port=9010");
+        Assert.assertTrue(url.startsWith("https://";));
+        Assert.assertTrue(url.contains("/role?host=fe80::2&port=9010"));
+    }
+}
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/common/util/InternalHttpsUtilsTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/common/util/InternalHttpsUtilsTest.java
new file mode 100644
index 00000000000..47f41c4858d
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/common/util/InternalHttpsUtilsTest.java
@@ -0,0 +1,64 @@
+// 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.common.util;
+
+import org.apache.doris.common.Config;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+
+public class InternalHttpsUtilsTest {
+
+    private String originalCertPath;
+
+    @Before
+    public void setUp() throws Exception {
+        originalCertPath = Config.mysql_ssl_default_ca_certificate;
+        // Reset the cached SSLContext before each test so tests are 
independent.
+        resetCachedSslContext();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        Config.mysql_ssl_default_ca_certificate = originalCertPath;
+        resetCachedSslContext();
+    }
+
+    private void resetCachedSslContext() throws Exception {
+        Field field = 
InternalHttpsUtils.class.getDeclaredField("cachedSslContext");
+        field.setAccessible(true);
+        field.set(null, null);
+    }
+
+    @Test
+    public void testGetSslContextThrowsWhenCertMissing() {
+        Config.mysql_ssl_default_ca_certificate = "/non/existent/path/ca.p12";
+        try {
+            InternalHttpsUtils.getSslContext();
+            Assert.fail("Expected RuntimeException when cert file does not 
exist");
+        } catch (RuntimeException e) {
+            // Error message must mention the cert path so operators know what 
to fix.
+            Assert.assertTrue("Error message should contain cert path",
+                    e.getMessage() != null && 
e.getMessage().contains("/non/existent/path/ca.p12"));
+        }
+    }
+}
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/minidump/MinidumpUtTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/minidump/MinidumpUtTest.java
index 60ff399fa0b..7c01338955c 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/minidump/MinidumpUtTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/minidump/MinidumpUtTest.java
@@ -17,9 +17,17 @@
 
 package org.apache.doris.nereids.minidump;
 
+import org.apache.doris.catalog.Env;
+import org.apache.doris.common.Config;
+import org.apache.doris.common.proc.FrontendsProcNode;
+import org.apache.doris.system.Frontend;
+
 import org.json.JSONObject;
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
 
 /**
  * Used for add unit test of minidump
@@ -46,4 +54,41 @@ class MinidumpUtTest {
         assert (minidump != null);
         assert (resultPlan != null);
     }
+
+    @Test
+    public void testSaveMinidumpStringUsesHttpsWhenEnabled() {
+        Frontend fe = Mockito.mock(Frontend.class);
+        Mockito.when(fe.getHost()).thenReturn("192.168.1.1");
+        Env mockEnv = Mockito.mock(Env.class);
+
+        boolean originalEnableHttps = Config.enable_https;
+        int originalHttpPort = Config.http_port;
+        int originalHttpsPort = Config.https_port;
+        try (MockedStatic<Env> envStatic = Mockito.mockStatic(Env.class);
+                MockedStatic<FrontendsProcNode> procStatic = 
Mockito.mockStatic(FrontendsProcNode.class)) {
+            envStatic.when(Env::getCurrentEnv).thenReturn(mockEnv);
+            procStatic.when(() -> 
FrontendsProcNode.getCurrentFrontendVersion(mockEnv)).thenReturn(fe);
+
+            // enable_https=true: URL must use https scheme and https_port
+            Config.enable_https = true;
+            Config.https_port = 8050;
+            Config.http_port = 0;
+            MinidumpUtils.saveMinidumpString(new JSONObject(), "query-001");
+            String url = MinidumpUtils.getHttpGetString();
+            Assertions.assertTrue(url.startsWith("https://";), "Expected https 
scheme but got: " + url);
+            Assertions.assertTrue(url.contains(":8050/"), "Expected https_port 
8050 but got: " + url);
+
+            // enable_https=false: URL must use http scheme and http_port
+            Config.enable_https = false;
+            Config.http_port = 8030;
+            MinidumpUtils.saveMinidumpString(new JSONObject(), "query-002");
+            url = MinidumpUtils.getHttpGetString();
+            Assertions.assertTrue(url.startsWith("http://";), "Expected http 
scheme but got: " + url);
+            Assertions.assertTrue(url.contains(":8030/"), "Expected http_port 
8030 but got: " + url);
+        } finally {
+            Config.enable_https = originalEnableHttps;
+            Config.http_port = originalHttpPort;
+            Config.https_port = originalHttpsPort;
+        }
+    }
 }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/system/HeartbeatMgrTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/system/HeartbeatMgrTest.java
index 6ef64b1bbe9..8e9120ba276 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/system/HeartbeatMgrTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/system/HeartbeatMgrTest.java
@@ -20,6 +20,7 @@ package org.apache.doris.system;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.FsBroker;
 import org.apache.doris.common.ClientPool;
+import org.apache.doris.common.Config;
 import org.apache.doris.common.GenericPool;
 import org.apache.doris.ha.FrontendNodeType;
 import org.apache.doris.system.HeartbeatMgr.BrokerHeartbeatHandler;
@@ -33,6 +34,7 @@ import org.apache.doris.thrift.TBrokerPingBrokerRequest;
 import org.apache.doris.thrift.TFrontendPingFrontendRequest;
 import org.apache.doris.thrift.TFrontendPingFrontendResult;
 import org.apache.doris.thrift.TFrontendPingFrontendStatusCode;
+import org.apache.doris.thrift.TMasterInfo;
 import org.apache.doris.thrift.TNetworkAddress;
 import org.apache.doris.thrift.TPaloBrokerService;
 
@@ -43,6 +45,9 @@ import org.junit.Test;
 import org.mockito.MockedStatic;
 import org.mockito.Mockito;
 
+import java.lang.reflect.Field;
+import java.util.concurrent.atomic.AtomicReference;
+
 public class HeartbeatMgrTest {
 
     private Env env = Mockito.mock(Env.class);
@@ -122,6 +127,39 @@ public class HeartbeatMgrTest {
         }
     }
 
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testSetMasterHttpPort() throws Exception {
+        int originalHttpPort = Config.http_port;
+        int originalHttpsPort = Config.https_port;
+        boolean originalEnableHttps = Config.enable_https;
+
+        try {
+            HeartbeatMgr mgr = new HeartbeatMgr(null, false);
+            Field masterInfoField = 
HeartbeatMgr.class.getDeclaredField("masterInfo");
+            masterInfoField.setAccessible(true);
+
+            // enable_https=false: must send http_port to BEs
+            Config.enable_https = false;
+            Config.http_port = 8030;
+            Config.https_port = 8050;
+            mgr.setMaster(1, "token", 1L);
+            AtomicReference<TMasterInfo> masterInfo =
+                    (AtomicReference<TMasterInfo>) masterInfoField.get(null);
+            Assert.assertEquals(8030, masterInfo.get().getHttpPort());
+
+            // enable_https=true: must send https_port to BEs so 
small_file_mgr can connect
+            Config.enable_https = true;
+            mgr.setMaster(1, "token", 1L);
+            masterInfo = (AtomicReference<TMasterInfo>) 
masterInfoField.get(null);
+            Assert.assertEquals(8050, masterInfo.get().getHttpPort());
+        } finally {
+            Config.http_port = originalHttpPort;
+            Config.https_port = originalHttpsPort;
+            Config.enable_https = originalEnableHttps;
+        }
+    }
+
     @SuppressWarnings("unchecked")
     @Test
     public void testBrokerHbHandler() throws Exception {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to