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

alexstocks pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git


The following commit(s) were added to refs/heads/develop by this push:
     new f7323d7cf feat: TLS new API design and replace the TLSconfig of config 
package (#2891)
f7323d7cf is described below

commit f7323d7cf52ce241b4b1b896544e3b868b7752b7
Author: marsevilspirit <[email protected]>
AuthorDate: Sun Jun 8 16:58:29 2025 +0800

    feat: TLS new API design and replace the TLSconfig of config package (#2891)
    
    * move TLSOption to tls dir
    
    * rename tls option function
    
    * server TLSOption implement
    
    * rename something and pass TLSConfig to url
    
    * add tls config parser
    
    * change to global TLSConfig
    
    * support global TLSConfig in client side
    
    * rename variables for better readability
    
    * Preparing to replace all TLSConfig with the TLSConfig in the global 
package.
    
    * fix golanglint-ci error
    
    * fix dubbo.load with register can't use tls bug
    
    * rename TLSOption API
    
    * Optimize TLS Options
    
    * import format
    
    * fix non-tls mode also use TLSConfig bug
    
    * add tls helper to help we judge the valid of the TLSConfig
    
    * add some todo
    
    * fix comment
    
    * fix ci error
    
    * Update protocol/triple/server.go
    
    Co-authored-by: Copilot <[email protected]>
    
    * rename
    
    * add some comments
    
    ---------
    
    Co-authored-by: Copilot <[email protected]>
---
 client/action.go                               |   1 +
 client/client.go                               |   1 +
 client/options.go                              |  76 ++++++++++++------
 common/constant/key.go                         |   1 +
 compat.go                                      |  26 ------
 dubbo.go                                       |   8 ++
 global/tls_config.go                           |  29 +------
 loader.go                                      |   2 -
 options.go                                     |  21 ++---
 protocol/dubbo3/dubbo3_invoker.go              |  24 +++++-
 protocol/dubbo3/dubbo3_protocol.go             |  22 ++++-
 protocol/grpc/client.go                        |  28 ++++++-
 protocol/grpc/server.go                        |  27 ++++++-
 protocol/triple/client.go                      |  44 +++++-----
 protocol/triple/dubbo3_invoker.go              |  24 +++++-
 protocol/triple/health/healthServer.go         |   2 +-
 protocol/triple/reflection/serverreflection.go |   2 +-
 protocol/triple/server.go                      |  37 ++++-----
 remoting/getty/getty_client.go                 |  27 ++++++-
 remoting/getty/getty_client_test.go            |   4 +-
 remoting/getty/getty_server.go                 |  27 ++++++-
 remoting/getty/getty_server_test.go            |   5 +-
 server/action.go                               |  84 ++++++++++----------
 server/options.go                              |  43 ++++++++--
 server/server.go                               |   7 +-
 tls/helper.go                                  | 106 +++++++++++++++++++++++++
 tls/helper_test.go                             | 103 ++++++++++++++++++++++++
 tls/options.go                                 |  70 ++++++++++++++++
 28 files changed, 650 insertions(+), 201 deletions(-)

diff --git a/client/action.go b/client/action.go
index 0b650ae20..4c437c42d 100644
--- a/client/action.go
+++ b/client/action.go
@@ -134,6 +134,7 @@ func (refOpts *ReferenceOptions) refer(srv 
common.RPCService, info *ClientInfo)
                common.WithParamsValue(constant.TimeoutKey, 
refOpts.Consumer.RequestTimeout),
                common.WithParamsValue(constant.KeepAliveInterval, 
ref.KeepAliveInterval),
                common.WithParamsValue(constant.KeepAliveTimeout, 
ref.KeepAliveTimeout),
+               common.WithAttribute(constant.TLSConfigKey, refOpts.TLS),
                // for new triple non-IDL mode
                // TODO: remove ISIDL after old triple removed
                common.WithParamsValue(constant.IDLMode, ref.IDLMode),
diff --git a/client/client.go b/client/client.go
index 069fdced1..096b2a54c 100644
--- a/client/client.go
+++ b/client/client.go
@@ -168,6 +168,7 @@ func (cli *Client) dial(interfaceName string, info 
*ClientInfo, srv any, opts ..
                setConsumer(cli.cliOpts.Consumer),
                setMetrics(cli.cliOpts.Metrics),
                setOtel(cli.cliOpts.Otel),
+               setTLS(cli.cliOpts.TLS),
                // this config must be set after Reference initialized
                setInterfaceName(interfaceName),
        }
diff --git a/client/options.go b/client/options.go
index 64a8ef3eb..cdc389cc3 100644
--- a/client/options.go
+++ b/client/options.go
@@ -36,6 +36,7 @@ import (
        "dubbo.apache.org/dubbo-go/v3/protocol/base"
        "dubbo.apache.org/dubbo-go/v3/proxy"
        "dubbo.apache.org/dubbo-go/v3/registry"
+       "dubbo.apache.org/dubbo-go/v3/tls"
 )
 
 type ReferenceOptions struct {
@@ -43,6 +44,7 @@ type ReferenceOptions struct {
        Consumer  *global.ConsumerConfig
        Metrics   *global.MetricsConfig
        Otel      *global.OtelConfig
+       TLS       *global.TLSConfig
 
        pxy          *proxy.Proxy
        id           string
@@ -61,6 +63,7 @@ func defaultReferenceOptions() *ReferenceOptions {
                Reference: global.DefaultReferenceConfig(),
                Metrics:   global.DefaultMetricsConfig(),
                Otel:      global.DefaultOtelConfig(),
+               TLS:       global.DefaultTLSConfig(),
        }
 }
 
@@ -72,21 +75,21 @@ func (refOpts *ReferenceOptions) init(opts 
...ReferenceOption) error {
                return err
        }
 
-       ref := refOpts.Reference
+       refConf := refOpts.Reference
 
        app := refOpts.applicationCompat
        if app != nil {
                refOpts.metaDataType = app.MetadataType
-               if ref.Group == "" {
-                       ref.Group = app.Group
+               if refConf.Group == "" {
+                       refConf.Group = app.Group
                }
-               if ref.Version == "" {
-                       ref.Version = app.Version
+               if refConf.Version == "" {
+                       refConf.Version = app.Version
                }
        }
 
        // init method
-       methods := ref.Methods
+       methods := refConf.Methods
        if length := len(methods); length > 0 {
                refOpts.methodsCompat = make([]*config.MethodConfig, length)
                for i, method := range methods {
@@ -99,23 +102,23 @@ func (refOpts *ReferenceOptions) init(opts 
...ReferenceOption) error {
 
        // init cluster
        // TODO: use constant replace failover
-       if ref.Cluster == "" {
-               ref.Cluster = "failover"
+       if refConf.Cluster == "" {
+               refConf.Cluster = "failover"
        }
 
        // init registries
        if len(refOpts.registriesCompat) > 0 {
                regs := refOpts.registriesCompat
-               if len(ref.RegistryIDs) <= 0 {
-                       ref.RegistryIDs = make([]string, len(regs))
+               if len(refConf.RegistryIDs) <= 0 {
+                       refConf.RegistryIDs = make([]string, len(regs))
                        for key := range regs {
-                               ref.RegistryIDs = append(ref.RegistryIDs, key)
+                               refConf.RegistryIDs = 
append(refConf.RegistryIDs, key)
                        }
                }
-               ref.RegistryIDs = commonCfg.TranslateIds(ref.RegistryIDs)
+               refConf.RegistryIDs = 
commonCfg.TranslateIds(refConf.RegistryIDs)
 
                newRegs := make(map[string]*config.RegistryConfig)
-               for _, id := range ref.RegistryIDs {
+               for _, id := range refConf.RegistryIDs {
                        if reg, ok := regs[id]; ok {
                                newRegs[id] = reg
                        }
@@ -124,16 +127,16 @@ func (refOpts *ReferenceOptions) init(opts 
...ReferenceOption) error {
        }
 
        // init protocol
-       if ref.Protocol == "" {
-               ref.Protocol = constant.TriProtocol
+       if refConf.Protocol == "" {
+               refConf.Protocol = constant.TriProtocol
                if refOpts.Consumer != nil && refOpts.Consumer.Protocol != "" {
-                       ref.Protocol = refOpts.Consumer.Protocol
+                       refConf.Protocol = refOpts.Consumer.Protocol
                }
        }
 
        // init serialization
-       if ref.Serialization == "" {
-               ref.Serialization = constant.ProtobufSerialization
+       if refConf.Serialization == "" {
+               refConf.Serialization = constant.ProtobufSerialization
        }
 
        return commonCfg.Verify(refOpts)
@@ -449,6 +452,12 @@ func setOtel(oc *global.OtelConfig) ReferenceOption {
        }
 }
 
+func setTLS(tls *global.TLSConfig) ReferenceOption {
+       return func(opts *ReferenceOptions) {
+               opts.TLS = tls
+       }
+}
+
 type ClientOptions struct {
        Consumer    *global.ConsumerConfig
        Application *global.ApplicationConfig
@@ -456,6 +465,7 @@ type ClientOptions struct {
        Shutdown    *global.ShutdownConfig
        Metrics     *global.MetricsConfig
        Otel        *global.OtelConfig
+       TLS         *global.TLSConfig
 
        overallReference  *global.ReferenceConfig
        applicationCompat *config.ApplicationConfig
@@ -470,6 +480,7 @@ func defaultClientOptions() *ClientOptions {
                Shutdown:         global.DefaultShutdownConfig(),
                Metrics:          global.DefaultMetricsConfig(),
                Otel:             global.DefaultOtelConfig(),
+               TLS:              global.DefaultTLSConfig(),
                overallReference: global.DefaultReferenceConfig(),
        }
 }
@@ -482,7 +493,7 @@ func (cliOpts *ClientOptions) init(opts ...ClientOption) 
error {
                return err
        }
 
-       con := cliOpts.Consumer
+       consumerConf := cliOpts.Consumer
 
        // init application
        application := cliOpts.Application
@@ -497,15 +508,15 @@ func (cliOpts *ClientOptions) init(opts ...ClientOption) 
error {
        regs := cliOpts.Registries
        if regs != nil {
                cliOpts.registriesCompat = 
make(map[string]*config.RegistryConfig)
-               if len(con.RegistryIDs) <= 0 {
-                       con.RegistryIDs = make([]string, len(regs))
+               if len(consumerConf.RegistryIDs) <= 0 {
+                       consumerConf.RegistryIDs = make([]string, len(regs))
                        for key := range regs {
-                               con.RegistryIDs = append(con.RegistryIDs, key)
+                               consumerConf.RegistryIDs = 
append(consumerConf.RegistryIDs, key)
                        }
                }
-               con.RegistryIDs = commonCfg.TranslateIds(con.RegistryIDs)
+               consumerConf.RegistryIDs = 
commonCfg.TranslateIds(consumerConf.RegistryIDs)
 
-               for _, id := range con.RegistryIDs {
+               for _, id := range consumerConf.RegistryIDs {
                        if reg, ok := regs[id]; ok {
                                cliOpts.registriesCompat[id] = 
compatRegistryConfig(reg)
                                if err := cliOpts.registriesCompat[id].Init(); 
err != nil {
@@ -583,6 +594,17 @@ func WithClientShutdown(opts ...graceful_shutdown.Option) 
ClientOption {
        }
 }
 
+func WithClientTLSOption(opts ...tls.Option) ClientOption {
+       tlsOpts := tls.NewOptions(opts...)
+
+       return func(cliOpts *ClientOptions) {
+               if cliOpts.TLS == nil {
+                       cliOpts.TLS = new(global.TLSConfig)
+               }
+               cliOpts.TLS = tlsOpts.TLSConf
+       }
+}
+
 // ========== Cluster Strategy ==========
 
 func WithClientClusterAvailable() ClientOption {
@@ -862,6 +884,12 @@ func SetClientOtel(otel *global.OtelConfig) ClientOption {
        }
 }
 
+func SetClientTLS(tls *global.TLSConfig) ClientOption {
+       return func(opts *ClientOptions) {
+               opts.TLS = tls
+       }
+}
+
 // todo: need to be consistent with MethodConfig
 type CallOptions struct {
        RequestTimeout string
diff --git a/common/constant/key.go b/common/constant/key.go
index b95b20196..2694d25fa 100644
--- a/common/constant/key.go
+++ b/common/constant/key.go
@@ -160,6 +160,7 @@ const (
        ServiceInfoKey                     = "service-info"
        RpcServiceKey                      = "rpc-service"
        ClientInfoKey                      = "client-info"
+       TLSConfigKey                       = "tls-config"
 )
 
 const (
diff --git a/compat.go b/compat.go
index 572099c4d..ef31c2350 100644
--- a/compat.go
+++ b/compat.go
@@ -56,7 +56,6 @@ func compatRootConfig(c *InstanceOptions) *config.RootConfig {
                CacheFile:           c.CacheFile,
                Custom:              compatCustomConfig(c.Custom),
                Profiles:            compatProfilesConfig(c.Profiles),
-               TLSConfig:           compatTLSConfig(c.TLSConfig),
        }
 }
 
@@ -361,18 +360,6 @@ func compatProfilesConfig(c *global.ProfilesConfig) 
*config.ProfilesConfig {
        }
 }
 
-func compatTLSConfig(c *global.TLSConfig) *config.TLSConfig {
-       if c == nil {
-               return nil
-       }
-       return &config.TLSConfig{
-               CACertFile:    c.CACertFile,
-               TLSCertFile:   c.TLSCertFile,
-               TLSKeyFile:    c.TLSKeyFile,
-               TLSServerName: c.TLSServerName,
-       }
-}
-
 func compatMetricAggregationConfig(a *global.AggregateConfig) 
*config.AggregateConfig {
        if a == nil {
                return nil
@@ -446,7 +433,6 @@ func compatInstanceOptions(cr *config.RootConfig, rc 
*InstanceOptions) {
        rc.CacheFile = cr.CacheFile
        rc.Custom = compatGlobalCustomConfig(cr.Custom)
        rc.Profiles = compatGlobalProfilesConfig(cr.Profiles)
-       rc.TLSConfig = compatGlobalTLSConfig(cr.TLSConfig)
 }
 
 func compatGlobalProtocolConfig(c *config.ProtocolConfig) 
*global.ProtocolConfig {
@@ -847,15 +833,3 @@ func compatGlobalProfilesConfig(c *config.ProfilesConfig) 
*global.ProfilesConfig
                Active: c.Active,
        }
 }
-
-func compatGlobalTLSConfig(c *config.TLSConfig) *global.TLSConfig {
-       if c == nil {
-               return nil
-       }
-       return &global.TLSConfig{
-               CACertFile:    c.CACertFile,
-               TLSCertFile:   c.TLSCertFile,
-               TLSKeyFile:    c.TLSKeyFile,
-               TLSServerName: c.TLSServerName,
-       }
-}
diff --git a/dubbo.go b/dubbo.go
index d4d3c5358..da3231b39 100644
--- a/dubbo.go
+++ b/dubbo.go
@@ -75,6 +75,7 @@ func (ins *Instance) NewClient(opts ...client.ClientOption) 
(*client.Client, err
        sdCfg := ins.insOpts.CloneShutdown()
        metricsCfg := ins.insOpts.CloneMetrics()
        otelCfg := ins.insOpts.CloneOtel()
+       tlsCfg := ins.insOpts.CloneTLSConfig()
 
        if conCfg != nil {
                if !conCfg.Check {
@@ -105,6 +106,9 @@ func (ins *Instance) NewClient(opts ...client.ClientOption) 
(*client.Client, err
        if otelCfg != nil {
                cliOpts = append(cliOpts, client.SetClientOtel(otelCfg))
        }
+       if tlsCfg != nil {
+               cliOpts = append(cliOpts, client.SetClientTLS(tlsCfg))
+       }
 
        // options passed by users has higher priority
        cliOpts = append(cliOpts, opts...)
@@ -130,6 +134,7 @@ func (ins *Instance) NewServer(opts ...server.ServerOption) 
(*server.Server, err
        sdCfg := ins.insOpts.CloneShutdown()
        metricsCfg := ins.insOpts.CloneMetrics()
        otelCfg := ins.insOpts.CloneOtel()
+       tlsCfg := ins.insOpts.CloneTLSConfig()
 
        if appCfg != nil {
                srvOpts = append(srvOpts,
@@ -159,6 +164,9 @@ func (ins *Instance) NewServer(opts ...server.ServerOption) 
(*server.Server, err
        if otelCfg != nil {
                srvOpts = append(srvOpts, server.SetServerOtel(otelCfg))
        }
+       if tlsCfg != nil {
+               srvOpts = append(srvOpts, server.SetServerTLS(tlsCfg))
+       }
 
        // options passed by users have higher priority
        srvOpts = append(srvOpts, opts...)
diff --git a/global/tls_config.go b/global/tls_config.go
index 862d9b408..3830b3bba 100644
--- a/global/tls_config.go
+++ b/global/tls_config.go
@@ -31,8 +31,7 @@ type TLSConfig struct {
 }
 
 func DefaultTLSConfig() *TLSConfig {
-       // please refer to /config/tls_config.go NewTLSConfigBuilder
-       return nil
+       return &TLSConfig{}
 }
 
 // Clone a new TLSConfig
@@ -48,29 +47,3 @@ func (c *TLSConfig) Clone() *TLSConfig {
                TLSServerName: c.TLSServerName,
        }
 }
-
-type TLSOption func(*TLSConfig)
-
-func WithTLS_CACertFile(file string) TLSOption {
-       return func(cfg *TLSConfig) {
-               cfg.CACertFile = file
-       }
-}
-
-func WithTLS_TLSCertFile(file string) TLSOption {
-       return func(cfg *TLSConfig) {
-               cfg.TLSCertFile = file
-       }
-}
-
-func WithTLS_TLSKeyFile(file string) TLSOption {
-       return func(cfg *TLSConfig) {
-               cfg.TLSKeyFile = file
-       }
-}
-
-func WithTLS_TLSServerName(name string) TLSOption {
-       return func(cfg *TLSConfig) {
-               cfg.TLSServerName = name
-       }
-}
diff --git a/loader.go b/loader.go
index 3537f8ae6..fa5cf5ab6 100644
--- a/loader.go
+++ b/loader.go
@@ -47,7 +47,6 @@ var (
 )
 
 func Load(opts ...LoaderConfOption) error {
-       // conf
        conf := NewLoaderConf(opts...)
        if conf.opts == nil {
                koan := GetConfigResolver(conf)
@@ -170,7 +169,6 @@ func WithBytes(bytes []byte) LoaderConfOption {
 
 // absolutePath get absolut path
 func absolutePath(inPath string) string {
-
        if inPath == "$HOME" || strings.HasPrefix(inPath, 
"$HOME"+string(os.PathSeparator)) {
                inPath = userHomeDir() + inPath[5:]
        }
diff --git a/options.go b/options.go
index 4242a62e3..b8c5f6ff3 100644
--- a/options.go
+++ b/options.go
@@ -38,6 +38,7 @@ import (
        "dubbo.apache.org/dubbo-go/v3/otel/trace"
        "dubbo.apache.org/dubbo-go/v3/protocol"
        "dubbo.apache.org/dubbo-go/v3/registry"
+       "dubbo.apache.org/dubbo-go/v3/tls"
 )
 
 type InstanceOptions struct {
@@ -484,13 +485,13 @@ func WithShutdown(opts ...graceful_shutdown.Option) 
InstanceOption {
 //     }
 //}
 
-//func WithTLS(opts ...global.TLSOption) InstanceOption {
-//     tlsCfg := new(global.TLSConfig)
-//     for _, opt := range opts {
-//             opt(tlsCfg)
-//     }
-//
-//     return func(cfg *InstanceOptions) {
-//             cfg.TLSConfig = tlsCfg
-//     }
-//}
+func WithTLS(opts ...tls.Option) InstanceOption {
+       tlsOpts := tls.NewOptions(opts...)
+
+       return func(insOpts *InstanceOptions) {
+               if insOpts.TLSConfig == nil {
+                       insOpts.TLSConfig = new(global.TLSConfig)
+               }
+               insOpts.TLSConfig = tlsOpts.TLSConf
+       }
+}
diff --git a/protocol/dubbo3/dubbo3_invoker.go 
b/protocol/dubbo3/dubbo3_invoker.go
index 54bdfd26c..8c5ac5cfc 100644
--- a/protocol/dubbo3/dubbo3_invoker.go
+++ b/protocol/dubbo3/dubbo3_invoker.go
@@ -19,6 +19,7 @@ package dubbo3
 
 import (
        "context"
+       "errors"
        "reflect"
        "strconv"
        "strings"
@@ -42,9 +43,11 @@ import (
        "dubbo.apache.org/dubbo-go/v3/common"
        "dubbo.apache.org/dubbo-go/v3/common/constant"
        "dubbo.apache.org/dubbo-go/v3/config"
+       "dubbo.apache.org/dubbo-go/v3/global"
        "dubbo.apache.org/dubbo-go/v3/protocol/base"
        "dubbo.apache.org/dubbo-go/v3/protocol/invocation"
        "dubbo.apache.org/dubbo-go/v3/protocol/result"
+       dubbotls "dubbo.apache.org/dubbo-go/v3/tls"
 )
 
 // same as dubbo_invoker.go attachmentKey
@@ -118,13 +121,30 @@ func NewDubboInvoker(url *common.URL) (*DubboInvoker, 
error) {
        }
 
        triOption := triConfig.NewTripleOption(opts...)
+
+       // TODO: remove config TLSConfig
+       // delete this branch
        tlsConfig := config.GetRootConfig().TLSConfig
        if tlsConfig != nil {
+               triOption.CACertFile = tlsConfig.CACertFile
                triOption.TLSCertFile = tlsConfig.TLSCertFile
                triOption.TLSKeyFile = tlsConfig.TLSKeyFile
-               triOption.CACertFile = tlsConfig.CACertFile
                triOption.TLSServerName = tlsConfig.TLSServerName
-               logger.Infof("Triple Client initialized the TLSConfig 
configuration")
+               logger.Infof("DUBBO3 Client initialized the TLSConfig 
configuration")
+       } else if tlsConfRaw, ok := url.GetAttribute(constant.TLSConfigKey); ok 
{
+               // use global TLSConfig handle tls
+               tlsConf, ok := tlsConfRaw.(*global.TLSConfig)
+               if !ok {
+                       logger.Errorf("DUBBO3 Client initialized the TLSConfig 
configuration failed")
+                       return nil, errors.New("DUBBO3 Client initialized the 
TLSConfig configuration failed")
+               }
+               if dubbotls.IsClientTLSValid(tlsConf) {
+                       triOption.CACertFile = tlsConf.CACertFile
+                       triOption.TLSCertFile = tlsConf.TLSCertFile
+                       triOption.TLSKeyFile = tlsConf.TLSKeyFile
+                       triOption.TLSServerName = tlsConf.TLSServerName
+                       logger.Infof("DUBBO3 Server initialized the TLSConfig 
configuration")
+               }
        }
        client, err := triple.NewTripleClient(consumerService, triOption)
 
diff --git a/protocol/dubbo3/dubbo3_protocol.go 
b/protocol/dubbo3/dubbo3_protocol.go
index 37da7009e..b8ee4aeeb 100644
--- a/protocol/dubbo3/dubbo3_protocol.go
+++ b/protocol/dubbo3/dubbo3_protocol.go
@@ -41,8 +41,10 @@ import (
        "dubbo.apache.org/dubbo-go/v3/common"
        "dubbo.apache.org/dubbo-go/v3/common/constant"
        "dubbo.apache.org/dubbo-go/v3/config"
+       "dubbo.apache.org/dubbo-go/v3/global"
        "dubbo.apache.org/dubbo-go/v3/protocol/base"
        "dubbo.apache.org/dubbo-go/v3/protocol/invocation"
+       dubbotls "dubbo.apache.org/dubbo-go/v3/tls"
 )
 
 var protocolOnce sync.Once
@@ -256,13 +258,29 @@ func (dp *DubboProtocol) openServer(url *common.URL, 
tripleCodecType tripleConst
 
        triOption := triConfig.NewTripleOption(opts...)
 
+       // TODO: remove config TLSConfig
+       // delete this branch
        tlsConfig := config.GetRootConfig().TLSConfig
        if tlsConfig != nil {
+               triOption.CACertFile = tlsConfig.CACertFile
                triOption.TLSCertFile = tlsConfig.TLSCertFile
                triOption.TLSKeyFile = tlsConfig.TLSKeyFile
-               triOption.CACertFile = tlsConfig.CACertFile
                triOption.TLSServerName = tlsConfig.TLSServerName
-               logger.Infof("Triple Server initialized the TLSConfig 
configuration")
+               logger.Infof("DUBBO3 Server initialized the TLSConfig 
configuration")
+       } else if tlsConfRaw, tlsOk := url.GetAttribute(constant.TLSConfigKey); 
tlsOk {
+               // use global TLSConfig handle tls
+               tlsConf, RawOk := tlsConfRaw.(*global.TLSConfig)
+               if !RawOk {
+                       logger.Errorf("DUBBO3 Server initialized the TLSConfig 
configuration failed")
+                       return
+               }
+               if dubbotls.IsServerTLSValid(tlsConf) {
+                       triOption.CACertFile = tlsConf.CACertFile
+                       triOption.TLSCertFile = tlsConf.TLSCertFile
+                       triOption.TLSKeyFile = tlsConf.TLSKeyFile
+                       triOption.TLSServerName = tlsConf.TLSServerName
+                       logger.Infof("DUBBO3 Server initialized the TLSConfig 
configuration")
+               }
        }
 
        _, ok = dp.ExporterMap().Load(url.ServiceKey())
diff --git a/protocol/grpc/client.go b/protocol/grpc/client.go
index fa96a02b0..c6b389d6e 100644
--- a/protocol/grpc/client.go
+++ b/protocol/grpc/client.go
@@ -18,6 +18,7 @@
 package grpc
 
 import (
+       "errors"
        "reflect"
        "sync"
        "time"
@@ -43,6 +44,8 @@ import (
        "dubbo.apache.org/dubbo-go/v3/common"
        "dubbo.apache.org/dubbo-go/v3/common/constant"
        "dubbo.apache.org/dubbo-go/v3/config"
+       "dubbo.apache.org/dubbo-go/v3/global"
+       dubbotls "dubbo.apache.org/dubbo-go/v3/tls"
 )
 
 var clientConf *ClientConfig
@@ -88,8 +91,10 @@ func NewClient(url *common.URL) (*Client, error) {
                        grpc.MaxCallSendMsgSize(maxCallSendMsgSize),
                ),
        )
-       tlsConfig := config.GetRootConfig().TLSConfig
 
+       // TODO: remove config TLSConfig
+       // delete this branch
+       tlsConfig := config.GetRootConfig().TLSConfig
        if tlsConfig != nil {
                cfg, err := config.GetClientTlsConfig(&config.TLSConfig{
                        CACertFile:    tlsConfig.CACertFile,
@@ -102,7 +107,28 @@ func NewClient(url *common.URL) (*Client, error) {
                        return nil, err
                }
                dialOpts = append(dialOpts, 
grpc.WithTransportCredentials(credentials.NewTLS(cfg)))
+       } else if tlsConfRaw, ok := url.GetAttribute(constant.TLSConfigKey); ok 
{
+               // use global TLSConfig handle tls
+               tlsConf, ok := tlsConfRaw.(*global.TLSConfig)
+               if !ok {
+                       logger.Errorf("Grpc Client initialized the TLSConfig 
configuration failed")
+                       return nil, errors.New("DUBBO3 Client initialized the 
TLSConfig configuration failed")
+               }
+
+               if dubbotls.IsClientTLSValid(tlsConf) {
+                       cfg, err := dubbotls.GetClientTlSConfig(tlsConf)
+                       if err != nil {
+                               return nil, err
+                       }
+                       if cfg != nil {
+                               logger.Infof("Grpc Client initialized the 
TLSConfig configuration")
+                               dialOpts = append(dialOpts, 
grpc.WithTransportCredentials(credentials.NewTLS(cfg)))
+                       }
+               } else {
+                       dialOpts = append(dialOpts, 
grpc.WithTransportCredentials(insecure.NewCredentials()))
+               }
        } else {
+               // TODO: remove this else
                dialOpts = append(dialOpts, 
grpc.WithTransportCredentials(insecure.NewCredentials()))
        }
 
diff --git a/protocol/grpc/server.go b/protocol/grpc/server.go
index 9df4083f7..7cab2ff76 100644
--- a/protocol/grpc/server.go
+++ b/protocol/grpc/server.go
@@ -44,7 +44,9 @@ import (
        "dubbo.apache.org/dubbo-go/v3/common"
        "dubbo.apache.org/dubbo-go/v3/common/constant"
        "dubbo.apache.org/dubbo-go/v3/config"
+       "dubbo.apache.org/dubbo-go/v3/global"
        "dubbo.apache.org/dubbo-go/v3/protocol/base"
+       dubbotls "dubbo.apache.org/dubbo-go/v3/tls"
 )
 
 // DubboGrpcService is gRPC service
@@ -104,6 +106,8 @@ func (s *Server) Start(url *common.URL) {
                grpc.MaxSendMsgSize(maxServerSendMsgSize),
        )
 
+       // TODO: remove config TLSConfig
+       // delete this branch
        tlsConfig := config.GetRootConfig().TLSConfig
        if tlsConfig != nil {
                var cfg *tls.Config
@@ -116,11 +120,32 @@ func (s *Server) Start(url *common.URL) {
                if err != nil {
                        return
                }
-               logger.Infof("Grpc Server initialized the TLSConfig 
configuration")
+               logger.Infof("gRPC Server initialized the TLSConfig 
configuration")
                serverOpts = append(serverOpts, 
grpc.Creds(credentials.NewTLS(cfg)))
+       } else if tlsConfRaw, ok := url.GetAttribute(constant.TLSConfigKey); ok 
{
+               // use global TLSConfig handle tls
+               tlsConf, ok := tlsConfRaw.(*global.TLSConfig)
+               if !ok {
+                       logger.Errorf("gRPC Server initialized the TLSConfig 
configuration failed")
+                       return
+               }
+               if dubbotls.IsServerTLSValid(tlsConf) {
+                       cfg, tlsErr := dubbotls.GetServerTlSConfig(tlsConf)
+                       if tlsErr != nil {
+                               return
+                       }
+                       if cfg != nil {
+                               logger.Infof("gRPC Server initialized the 
TLSConfig configuration")
+                               serverOpts = append(serverOpts, 
grpc.Creds(credentials.NewTLS(cfg)))
+                       }
+               } else {
+                       serverOpts = append(serverOpts, 
grpc.Creds(insecure.NewCredentials()))
+               }
        } else {
+               // TODO: remove this else
                serverOpts = append(serverOpts, 
grpc.Creds(insecure.NewCredentials()))
        }
+
        server := grpc.NewServer(serverOpts...)
        s.grpcServer = server
 
diff --git a/protocol/triple/client.go b/protocol/triple/client.go
index 29d3c97f1..ad70e86cb 100644
--- a/protocol/triple/client.go
+++ b/protocol/triple/client.go
@@ -20,6 +20,7 @@ package triple
 import (
        "context"
        "crypto/tls"
+       "errors"
        "fmt"
        "net"
        "net/http"
@@ -38,8 +39,9 @@ import (
 import (
        "dubbo.apache.org/dubbo-go/v3/common"
        "dubbo.apache.org/dubbo-go/v3/common/constant"
-       "dubbo.apache.org/dubbo-go/v3/config"
+       "dubbo.apache.org/dubbo-go/v3/global"
        tri "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+       dubbotls "dubbo.apache.org/dubbo-go/v3/tls"
 )
 
 const (
@@ -180,30 +182,30 @@ func newClientManager(url *common.URL) (*clientManager, 
error) {
 
        // todo(DMwangnima): support opentracing
 
-       // todo(DMwangnima): support TLS in an ideal way
-       var cfg *tls.Config
-       var tlsFlag bool
-       var err error
+       // handle tls
+       var (
+               tlsFlag bool
+               tlsConf *global.TLSConfig
+               cfg     *tls.Config
+               err     error
+       )
 
-       // handle tls config
-       // TODO: think about a more elegant way to configure tls,
-       // Maybe we can try to create a ClientOptions for unified settings,
-       // after this function becomes bloated.
-
-       // TODO: Once the global replacement of the config is completed,
-       // replace config with global.
-       if tlsConfig := config.GetRootConfig().TLSConfig; tlsConfig != nil {
-               cfg, err = config.GetClientTlsConfig(&config.TLSConfig{
-                       CACertFile:    tlsConfig.CACertFile,
-                       TLSCertFile:   tlsConfig.TLSCertFile,
-                       TLSKeyFile:    tlsConfig.TLSKeyFile,
-                       TLSServerName: tlsConfig.TLSServerName,
-               })
+       tlsConfRaw, ok := url.GetAttribute(constant.TLSConfigKey)
+       if ok {
+               tlsConf, ok = tlsConfRaw.(*global.TLSConfig)
+               if !ok {
+                       return nil, errors.New("TRIPLE clientManager 
initialized the TLSConfig configuration failed")
+               }
+       }
+       if dubbotls.IsClientTLSValid(tlsConf) {
+               cfg, err = dubbotls.GetClientTlSConfig(tlsConf)
                if err != nil {
                        return nil, err
                }
-               logger.Infof("TRIPLE clientManager initialized the TLSConfig 
configuration")
-               tlsFlag = true
+               if cfg != nil {
+                       logger.Infof("TRIPLE clientManager initialized the 
TLSConfig configuration")
+                       tlsFlag = true
+               }
        }
 
        var transport http.RoundTripper
diff --git a/protocol/triple/dubbo3_invoker.go 
b/protocol/triple/dubbo3_invoker.go
index 9173b6efc..627833351 100644
--- a/protocol/triple/dubbo3_invoker.go
+++ b/protocol/triple/dubbo3_invoker.go
@@ -19,6 +19,7 @@ package triple
 
 import (
        "context"
+       "errors"
        "reflect"
        "strconv"
        "strings"
@@ -42,9 +43,11 @@ import (
        "dubbo.apache.org/dubbo-go/v3/common"
        "dubbo.apache.org/dubbo-go/v3/common/constant"
        "dubbo.apache.org/dubbo-go/v3/config"
+       "dubbo.apache.org/dubbo-go/v3/global"
        "dubbo.apache.org/dubbo-go/v3/protocol/base"
        "dubbo.apache.org/dubbo-go/v3/protocol/invocation"
        "dubbo.apache.org/dubbo-go/v3/protocol/result"
+       dubbotls "dubbo.apache.org/dubbo-go/v3/tls"
 )
 
 // same as dubbo_invoker.go attachmentKey
@@ -123,14 +126,31 @@ func NewDubbo3Invoker(url *common.URL) (*DubboInvoker, 
error) {
        }
 
        triOption := triConfig.NewTripleOption(opts...)
+
+       // TODO: remove config TLSConfig
+       // delete this branch
        tlsConfig := config.GetRootConfig().TLSConfig
        if tlsConfig != nil {
+               triOption.CACertFile = tlsConfig.CACertFile
                triOption.TLSCertFile = tlsConfig.TLSCertFile
                triOption.TLSKeyFile = tlsConfig.TLSKeyFile
-               triOption.CACertFile = tlsConfig.CACertFile
                triOption.TLSServerName = tlsConfig.TLSServerName
-               logger.Infof("Triple Client initialized the TLSConfig 
configuration")
+               logger.Infof("DUBBO3 Client initialized the TLSConfig 
configuration")
+       } else if tlsConfRaw, ok := url.GetAttribute(constant.TLSConfigKey); ok 
{
+               // use global TLSConfig handle tls
+               tlsConf, ok := tlsConfRaw.(*global.TLSConfig)
+               if !ok {
+                       return nil, errors.New("DUBBO3 Client initialized the 
TLSConfig configuration failed")
+               }
+               if dubbotls.IsClientTLSValid(tlsConf) {
+                       triOption.CACertFile = tlsConf.CACertFile
+                       triOption.TLSCertFile = tlsConf.TLSCertFile
+                       triOption.TLSKeyFile = tlsConf.TLSKeyFile
+                       triOption.TLSServerName = tlsConf.TLSServerName
+                       logger.Infof("DUBBO3 Client initialized the TLSConfig 
configuration")
+               }
        }
+
        client, err := triple.NewTripleClient(consumerService, triOption)
 
        if err != nil {
diff --git a/protocol/triple/health/healthServer.go 
b/protocol/triple/health/healthServer.go
index fbd4694c4..4b1d551b5 100644
--- a/protocol/triple/health/healthServer.go
+++ b/protocol/triple/health/healthServer.go
@@ -173,7 +173,7 @@ func (srv *HealthTripleServer) Resume() {
 func init() {
        healthServer = NewServer()
        internal.HealthSetServingStatusServing = SetServingStatusServing
-       server.SetProServices(&server.InternalService{
+       server.SetProviderServices(&server.InternalService{
                Name: "healthCheck",
                Init: func(options *server.ServiceOptions) 
(*server.ServiceDefinition, bool) {
                        return &server.ServiceDefinition{
diff --git a/protocol/triple/reflection/serverreflection.go 
b/protocol/triple/reflection/serverreflection.go
index 234e1aeb7..63a514b4a 100644
--- a/protocol/triple/reflection/serverreflection.go
+++ b/protocol/triple/reflection/serverreflection.go
@@ -266,7 +266,7 @@ var reflectionServer *ReflectionServer
 func init() {
        reflectionServer = NewServer()
        internal.ReflectionRegister = Register
-       server.SetProServices(&server.InternalService{
+       server.SetProviderServices(&server.InternalService{
                Name: "reflection",
                Init: func(options *server.ServiceOptions) 
(*server.ServiceDefinition, bool) {
                        return &server.ServiceDefinition{
diff --git a/protocol/triple/server.go b/protocol/triple/server.go
index 5f7060e0c..f9282614b 100644
--- a/protocol/triple/server.go
+++ b/protocol/triple/server.go
@@ -19,7 +19,6 @@ package triple
 
 import (
        "context"
-       "crypto/tls"
        "fmt"
        "net/http"
        "reflect"
@@ -43,10 +42,13 @@ import (
        "dubbo.apache.org/dubbo-go/v3/common"
        "dubbo.apache.org/dubbo-go/v3/common/constant"
        "dubbo.apache.org/dubbo-go/v3/config"
+       "dubbo.apache.org/dubbo-go/v3/global"
        "dubbo.apache.org/dubbo-go/v3/internal"
        "dubbo.apache.org/dubbo-go/v3/protocol/base"
        "dubbo.apache.org/dubbo-go/v3/protocol/dubbo3"
        "dubbo.apache.org/dubbo-go/v3/protocol/invocation"
+       dubbotls "dubbo.apache.org/dubbo-go/v3/tls"
+
        tri "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
 )
 
@@ -88,24 +90,23 @@ func (s *Server) Start(invoker base.Invoker, info 
*common.ServiceInfo) {
        }
        // todo: support opentracing interceptor
 
-       var cfg *tls.Config
-       var err error
-       // handle tls config
-       // TODO: think about a more elegant way to configure tls,
-       // Maybe we can try to create a ServerOptions for unified settings,
-       // after this function becomes bloated.
-
-       // TODO: Once the global replacement of the config is completed,
-       // replace config with global.
-       tlsConfig := config.GetRootConfig().TLSConfig
-       if tlsConfig != nil {
-               cfg, err = config.GetServerTlsConfig(&config.TLSConfig{
-                       CACertFile:    tlsConfig.CACertFile,
-                       TLSCertFile:   tlsConfig.TLSCertFile,
-                       TLSKeyFile:    tlsConfig.TLSKeyFile,
-                       TLSServerName: tlsConfig.TLSServerName,
-               })
+       // TODO: move tls config to handleService
+
+       var tlsConf *global.TLSConfig
+
+       // handle tls
+       tlsConfRaw, ok := URL.GetAttribute(constant.TLSConfigKey)
+       if ok {
+               tlsConf, ok = tlsConfRaw.(*global.TLSConfig)
+               if !ok {
+                       logger.Errorf("TRIPLE Server initialized the TLSConfig 
configuration failed")
+                       return
+               }
+       }
+       if dubbotls.IsServerTLSValid(tlsConf) {
+               cfg, err := dubbotls.GetServerTlSConfig(tlsConf)
                if err != nil {
+                       logger.Errorf("TRIPLE Server initialized the TLSConfig 
configuration failed. err: %v", err)
                        return
                }
                s.triServer.SetTLSConfig(cfg)
diff --git a/remoting/getty/getty_client.go b/remoting/getty/getty_client.go
index a117a2a2e..9fe25b748 100644
--- a/remoting/getty/getty_client.go
+++ b/remoting/getty/getty_client.go
@@ -39,8 +39,11 @@ import (
 
 import (
        "dubbo.apache.org/dubbo-go/v3/common"
+       "dubbo.apache.org/dubbo-go/v3/common/constant"
        "dubbo.apache.org/dubbo-go/v3/config"
+       "dubbo.apache.org/dubbo-go/v3/global"
        "dubbo.apache.org/dubbo-go/v3/remoting"
+       dubbotls "dubbo.apache.org/dubbo-go/v3/tls"
 )
 
 var (
@@ -54,8 +57,8 @@ var (
 )
 
 // it is init client for single protocol.
-func initClient(protocol string) {
-       if protocol == "" {
+func initClient(url *common.URL) {
+       if url.Protocol == "" {
                return
        }
 
@@ -68,7 +71,7 @@ func initClient(protocol string) {
                return
        }
 
-       protocolConf := config.GetRootConfig().Protocols[protocol]
+       protocolConf := config.GetRootConfig().Protocols[url.Protocol]
        if protocolConf == nil {
                logger.Info("use default getty client config")
                return
@@ -82,6 +85,22 @@ func initClient(protocol string) {
                                ClientPrivateKeyPath:          
tlsConfig.TLSKeyFile,
                                ClientTrustCertCollectionPath: 
tlsConfig.CACertFile,
                        }
+               } else if tlsConfRaw, ok := 
url.GetAttribute(constant.TLSConfigKey); ok {
+                       // use global TLSConfig handle tls
+                       tlsConf, ok := tlsConfRaw.(*global.TLSConfig)
+                       if !ok {
+                               logger.Errorf("Getty client initialized the 
TLSConfig configuration failed")
+                               return
+                       }
+                       if dubbotls.IsClientTLSValid(tlsConf) {
+                               srvConf.SSLEnabled = true
+                               srvConf.TLSBuilder = 
&getty.ClientTlsConfigBuilder{
+                                       ClientKeyCertChainPath:        
tlsConf.TLSCertFile,
+                                       ClientPrivateKeyPath:          
tlsConf.TLSKeyFile,
+                                       ClientTrustCertCollectionPath: 
tlsConf.CACertFile,
+                               }
+                               logger.Infof("Getty client initialized the 
TLSConfig configuration")
+                       }
                }
                //getty params
                gettyClientConfig := protocolConf.Params
@@ -165,7 +184,7 @@ func (c *Client) SetExchangeClient(client 
*remoting.ExchangeClient) {
 
 // Connect init client and try to connection.
 func (c *Client) Connect(url *common.URL) error {
-       initClient(url.Protocol)
+       initClient(url)
        c.conf = *clientConf
        c.sslEnabled = c.conf.SSLEnabled
        // codec
diff --git a/remoting/getty/getty_client_test.go 
b/remoting/getty/getty_client_test.go
index 702ceea04..1265d5940 100644
--- a/remoting/getty/getty_client_test.go
+++ b/remoting/getty/getty_client_test.go
@@ -491,7 +491,9 @@ func TestInitClient(t *testing.T) {
                },
        }
        config.SetRootConfig(rootConf)
-       initServer("dubbo")
+       url, err := common.NewURL("dubbo://127.0.0.1:20003/test")
+       assert.Nil(t, err)
+       initServer(url)
        config.SetRootConfig(*originRootConf)
        assert.NotNil(t, srvConf)
 }
diff --git a/remoting/getty/getty_server.go b/remoting/getty/getty_server.go
index 568930e4c..85df629e9 100644
--- a/remoting/getty/getty_server.go
+++ b/remoting/getty/getty_server.go
@@ -36,18 +36,21 @@ import (
 
 import (
        "dubbo.apache.org/dubbo-go/v3/common"
+       "dubbo.apache.org/dubbo-go/v3/common/constant"
        "dubbo.apache.org/dubbo-go/v3/config"
+       "dubbo.apache.org/dubbo-go/v3/global"
        "dubbo.apache.org/dubbo-go/v3/protocol/invocation"
        "dubbo.apache.org/dubbo-go/v3/protocol/result"
        "dubbo.apache.org/dubbo-go/v3/remoting"
+       dubbotls "dubbo.apache.org/dubbo-go/v3/tls"
 )
 
 var (
        srvConf = GetDefaultServerConfig()
 )
 
-func initServer(protocol string) {
-       if protocol == "" {
+func initServer(url *common.URL) {
+       if url.Protocol == "" {
                return
        }
 
@@ -60,7 +63,7 @@ func initServer(protocol string) {
                return
        }
 
-       protocolConf := config.GetRootConfig().Protocols[protocol]
+       protocolConf := config.GetRootConfig().Protocols[url.Protocol]
        if protocolConf == nil {
                logger.Debug("use default getty server config")
                return
@@ -75,6 +78,22 @@ func initServer(protocol string) {
                                ServerTrustCertCollectionPath: 
tlsConfig.CACertFile,
                        }
                        logger.Infof("Getty Server initialized the TLSConfig 
configuration")
+               } else if tlsConfRaw, ok := 
url.GetAttribute(constant.TLSConfigKey); ok {
+                       // use global TLSConfig handle tls
+                       tlsConf, ok := tlsConfRaw.(*global.TLSConfig)
+                       if !ok {
+                               logger.Errorf("Getty Server initialized the 
TLSConfig configuration failed")
+                               return
+                       }
+                       if dubbotls.IsServerTLSValid(tlsConf) {
+                               srvConf.SSLEnabled = true
+                               srvConf.TLSBuilder = 
&getty.ServerTlsConfigBuilder{
+                                       ServerKeyCertChainPath:        
tlsConf.TLSCertFile,
+                                       ServerPrivateKeyPath:          
tlsConf.TLSKeyFile,
+                                       ServerTrustCertCollectionPath: 
tlsConf.CACertFile,
+                               }
+                               logger.Infof("Getty Server initialized the 
TLSConfig configuration")
+                       }
                }
                //getty params
                gettyServerConfig := protocolConf.Params
@@ -126,7 +145,7 @@ type Server struct {
 // NewServer create a new Server
 func NewServer(url *common.URL, handlers func(*invocation.RPCInvocation) 
result.RPCResult) *Server {
        // init
-       initServer(url.Protocol)
+       initServer(url)
        s := &Server{
                conf:           *srvConf,
                addr:           url.Location,
diff --git a/remoting/getty/getty_server_test.go 
b/remoting/getty/getty_server_test.go
index 09db5eeaf..d51da99a7 100644
--- a/remoting/getty/getty_server_test.go
+++ b/remoting/getty/getty_server_test.go
@@ -26,6 +26,7 @@ import (
 )
 
 import (
+       "dubbo.apache.org/dubbo-go/v3/common"
        "dubbo.apache.org/dubbo-go/v3/config"
 )
 
@@ -41,7 +42,9 @@ func TestInitServer(t *testing.T) {
                },
        }
        config.SetRootConfig(rootConf)
-       initServer("dubbo")
+       url, err := common.NewURL("dubbo://127.0.0.1:20003/test")
+       assert.Nil(t, err)
+       initServer(url)
        config.SetRootConfig(*originRootConf)
        assert.NotNil(t, srvConf)
 }
diff --git a/server/action.go b/server/action.go
index 79b03c475..4a44b9a8f 100644
--- a/server/action.go
+++ b/server/action.go
@@ -133,11 +133,11 @@ func (svcOpts *ServiceOptions) ExportWithInfo(info 
*common.ServiceInfo) error {
 }
 
 func (svcOpts *ServiceOptions) export(info *common.ServiceInfo) error {
-       svc := svcOpts.Service
+       svcConf := svcOpts.Service
 
        if info != nil {
-               if svc.Interface == "" {
-                       svc.Interface = info.InterfaceName
+               if svcConf.Interface == "" {
+                       svcConf.Interface = info.InterfaceName
                }
                svcOpts.info = info
        }
@@ -146,24 +146,24 @@ func (svcOpts *ServiceOptions) export(info 
*common.ServiceInfo) error {
 
        // TODO: delay needExport
        if svcOpts.unexported != nil && svcOpts.unexported.Load() {
-               err := perrors.Errorf("The service %v has already unexported!", 
svc.Interface)
+               err := perrors.Errorf("The service %v has already unexported!", 
svcConf.Interface)
                logger.Errorf(err.Error())
                return err
        }
        if svcOpts.exported != nil && svcOpts.exported.Load() {
-               logger.Warnf("The service %v has already exported!", 
svc.Interface)
+               logger.Warnf("The service %v has already exported!", 
svcConf.Interface)
                return nil
        }
 
        regUrls := make([]*common.URL, 0)
-       if !svc.NotRegister {
-               regUrls = config.LoadRegistries(svc.RegistryIDs, 
svcOpts.registriesCompat, common.PROVIDER)
+       if !svcConf.NotRegister {
+               regUrls = config.LoadRegistries(svcConf.RegistryIDs, 
svcOpts.registriesCompat, common.PROVIDER)
        }
 
        urlMap := svcOpts.getUrlMap()
-       protocolConfigs := loadProtocol(svc.ProtocolIDs, svcOpts.Protocols)
+       protocolConfigs := loadProtocol(svcConf.ProtocolIDs, svcOpts.Protocols)
        if len(protocolConfigs) == 0 {
-               logger.Warnf("The service %v'svcOpts '%v' protocols don't has 
right protocolConfigs, Please check your configuration center and transfer 
protocol ", svc.Interface, svc.ProtocolIDs)
+               logger.Warnf("The service %v'svcOpts '%v' protocols don't has 
right protocolConfigs, Please check your configuration center and transfer 
protocol ", svcConf.Interface, svcConf.ProtocolIDs)
                return nil
        }
 
@@ -176,10 +176,10 @@ func (svcOpts *ServiceOptions) export(info 
*common.ServiceInfo) error {
                // todo(DMwangnimg): finish replacing procedure
 
                // registry the service reflect
-               methods, err := common.ServiceMap.Register(svc.Interface, 
protocolConf.Name, svc.Group, svc.Version, svcOpts.rpcService)
+               methods, err := common.ServiceMap.Register(svcConf.Interface, 
protocolConf.Name, svcConf.Group, svcConf.Version, svcOpts.rpcService)
                if err != nil {
                        formatErr := perrors.Errorf("The service %v needExport 
the protocol %v error! Error message is %v.",
-                               svc.Interface, protocolConf.Name, err.Error())
+                               svcConf.Interface, protocolConf.Name, 
err.Error())
                        logger.Errorf(formatErr.Error())
                        return formatErr
                }
@@ -197,7 +197,7 @@ func (svcOpts *ServiceOptions) export(info 
*common.ServiceInfo) error {
                }
 
                ivkURL := common.NewURLWithOptions(
-                       common.WithPath(svc.Interface),
+                       common.WithPath(svcConf.Interface),
                        common.WithProtocol(protocolConf.Name),
                        common.WithIp(protocolConf.Ip),
                        common.WithPort(port),
@@ -206,8 +206,10 @@ func (svcOpts *ServiceOptions) export(info 
*common.ServiceInfo) error {
                        common.WithParamsValue(constant.ApplicationTagKey, 
svcOpts.Application.Tag),
                        //common.WithParamsValue(constant.SslEnabledKey, 
strconv.FormatBool(config.GetSslEnabled())),
                        common.WithMethods(strings.Split(methods, ",")),
+                       // TLSConifg
+                       common.WithAttribute(constant.TLSConfigKey, 
svcOpts.srvOpts.TLS),
                        common.WithAttribute(constant.RpcServiceKey, 
svcOpts.rpcService),
-                       common.WithToken(svc.Token),
+                       common.WithToken(svcConf.Token),
                        common.WithParamsValue(constant.MetadataTypeKey, 
svcOpts.metadataType),
                        // fix https://github.com/apache/dubbo-go/issues/2176
                        common.WithParamsValue(constant.MaxServerSendMsgSize, 
protocolConf.MaxServerSendMsgSize),
@@ -219,8 +221,8 @@ func (svcOpts *ServiceOptions) export(info 
*common.ServiceInfo) error {
                        ivkURL.SetAttribute(constant.ServiceInfoKey, info)
                }
 
-               if len(svc.Tag) > 0 {
-                       ivkURL.AddParam(constant.Tagkey, svc.Tag)
+               if len(svcConf.Tag) > 0 {
+                       ivkURL.AddParam(constant.Tagkey, svcConf.Tag)
                }
 
                // post process the URL to be exported
@@ -321,33 +323,33 @@ func (svcOpts *ServiceOptions) Implement(rpcService 
common.RPCService) {
 }
 
 func (svcOpts *ServiceOptions) getUrlMap() url.Values {
-       srv := svcOpts.Service
+       svcConf := svcOpts.Service
        app := svcOpts.applicationCompat
        metrics := svcOpts.srvOpts.Metrics
        tracing := svcOpts.srvOpts.Otel.TracingConfig
 
        urlMap := url.Values{}
        // first set user params
-       for k, v := range srv.Params {
+       for k, v := range svcConf.Params {
                urlMap.Set(k, v)
        }
-       urlMap.Set(constant.InterfaceKey, srv.Interface)
+       urlMap.Set(constant.InterfaceKey, svcConf.Interface)
        urlMap.Set(constant.TimestampKey, strconv.FormatInt(time.Now().Unix(), 
10))
-       urlMap.Set(constant.ClusterKey, srv.Cluster)
-       urlMap.Set(constant.LoadbalanceKey, srv.Loadbalance)
-       urlMap.Set(constant.WarmupKey, srv.Warmup)
-       urlMap.Set(constant.RetriesKey, srv.Retries)
-       if srv.Group != "" {
-               urlMap.Set(constant.GroupKey, srv.Group)
+       urlMap.Set(constant.ClusterKey, svcConf.Cluster)
+       urlMap.Set(constant.LoadbalanceKey, svcConf.Loadbalance)
+       urlMap.Set(constant.WarmupKey, svcConf.Warmup)
+       urlMap.Set(constant.RetriesKey, svcConf.Retries)
+       if svcConf.Group != "" {
+               urlMap.Set(constant.GroupKey, svcConf.Group)
        }
-       if srv.Version != "" {
-               urlMap.Set(constant.VersionKey, srv.Version)
+       if svcConf.Version != "" {
+               urlMap.Set(constant.VersionKey, svcConf.Version)
        }
        urlMap.Set(constant.RegistryRoleKey, strconv.Itoa(common.PROVIDER))
        urlMap.Set(constant.ReleaseKey, "dubbo-golang-"+constant.Version)
        urlMap.Set(constant.SideKey, (common.RoleType(common.PROVIDER)).Role())
        // todo: move
-       urlMap.Set(constant.SerializationKey, srv.Serialization)
+       urlMap.Set(constant.SerializationKey, svcConf.Serialization)
        // application config info
        urlMap.Set(constant.ApplicationKey, app.Name)
        urlMap.Set(constant.OrganizationKey, app.Organization)
@@ -359,10 +361,10 @@ func (svcOpts *ServiceOptions) getUrlMap() url.Values {
 
        //filter
        var filters string
-       if srv.Filter == "" {
+       if svcConf.Filter == "" {
                filters = constant.DefaultServiceFilters
        } else {
-               filters = srv.Filter
+               filters = svcConf.Filter
        }
        if svcOpts.adaptiveService {
                filters += fmt.Sprintf(",%s", 
constant.AdaptiveServiceProviderFilterKey)
@@ -376,28 +378,28 @@ func (svcOpts *ServiceOptions) getUrlMap() url.Values {
        urlMap.Set(constant.ServiceFilterKey, filters)
 
        // filter special config
-       urlMap.Set(constant.AccessLogFilterKey, srv.AccessLog)
+       urlMap.Set(constant.AccessLogFilterKey, svcConf.AccessLog)
        // tps limiter
-       urlMap.Set(constant.TPSLimitStrategyKey, srv.TpsLimitStrategy)
-       urlMap.Set(constant.TPSLimitIntervalKey, srv.TpsLimitInterval)
-       urlMap.Set(constant.TPSLimitRateKey, srv.TpsLimitRate)
-       urlMap.Set(constant.TPSLimiterKey, srv.TpsLimiter)
-       urlMap.Set(constant.TPSRejectedExecutionHandlerKey, 
srv.TpsLimitRejectedHandler)
-       urlMap.Set(constant.TracingConfigKey, srv.TracingKey)
+       urlMap.Set(constant.TPSLimitStrategyKey, svcConf.TpsLimitStrategy)
+       urlMap.Set(constant.TPSLimitIntervalKey, svcConf.TpsLimitInterval)
+       urlMap.Set(constant.TPSLimitRateKey, svcConf.TpsLimitRate)
+       urlMap.Set(constant.TPSLimiterKey, svcConf.TpsLimiter)
+       urlMap.Set(constant.TPSRejectedExecutionHandlerKey, 
svcConf.TpsLimitRejectedHandler)
+       urlMap.Set(constant.TracingConfigKey, svcConf.TracingKey)
 
        // execute limit filter
-       urlMap.Set(constant.ExecuteLimitKey, srv.ExecuteLimit)
-       urlMap.Set(constant.ExecuteRejectedExecutionHandlerKey, 
srv.ExecuteLimitRejectedHandler)
+       urlMap.Set(constant.ExecuteLimitKey, svcConf.ExecuteLimit)
+       urlMap.Set(constant.ExecuteRejectedExecutionHandlerKey, 
svcConf.ExecuteLimitRejectedHandler)
 
        // auth filter
-       urlMap.Set(constant.ServiceAuthKey, srv.Auth)
-       urlMap.Set(constant.ParameterSignatureEnableKey, srv.ParamSign)
+       urlMap.Set(constant.ServiceAuthKey, svcConf.Auth)
+       urlMap.Set(constant.ParameterSignatureEnableKey, svcConf.ParamSign)
 
        // whether to needExport or not
        urlMap.Set(constant.ExportKey, strconv.FormatBool(svcOpts.needExport))
        urlMap.Set(constant.PIDKey, fmt.Sprintf("%d", os.Getpid()))
 
-       for _, v := range srv.Methods {
+       for _, v := range svcConf.Methods {
                prefix := "methods." + v.Name + "."
                urlMap.Set(prefix+constant.LoadbalanceKey, v.LoadBalance)
                urlMap.Set(prefix+constant.RetriesKey, v.Retries)
diff --git a/server/options.go b/server/options.go
index ae64fba34..6a97eac1f 100644
--- a/server/options.go
+++ b/server/options.go
@@ -46,6 +46,7 @@ import (
        "dubbo.apache.org/dubbo-go/v3/protocol"
        "dubbo.apache.org/dubbo-go/v3/protocol/base"
        "dubbo.apache.org/dubbo-go/v3/registry"
+       "dubbo.apache.org/dubbo-go/v3/tls"
 )
 
 type ServerOptions struct {
@@ -56,6 +57,7 @@ type ServerOptions struct {
        Shutdown    *global.ShutdownConfig
        Metrics     *global.MetricsConfig
        Otel        *global.OtelConfig
+       TLS         *global.TLSConfig
 
        providerCompat *config.ProviderConfig
 }
@@ -67,6 +69,7 @@ func defaultServerOptions() *ServerOptions {
                Shutdown:    global.DefaultShutdownConfig(),
                Metrics:     global.DefaultMetricsConfig(),
                Otel:        global.DefaultOtelConfig(),
+               TLS:         global.DefaultTLSConfig(),
        }
 }
 
@@ -75,26 +78,27 @@ func (srvOpts *ServerOptions) init(opts ...ServerOption) 
error {
        for _, opt := range opts {
                opt(srvOpts)
        }
+
        if err := defaults.Set(srvOpts); err != nil {
                return err
        }
 
-       prov := srvOpts.Provider
+       providerConf := srvOpts.Provider
 
-       prov.RegistryIDs = commonCfg.TranslateIds(prov.RegistryIDs)
-       if len(prov.RegistryIDs) <= 0 {
-               prov.RegistryIDs = getRegistryIds(srvOpts.Registries)
+       providerConf.RegistryIDs = 
commonCfg.TranslateIds(providerConf.RegistryIDs)
+       if len(providerConf.RegistryIDs) <= 0 {
+               providerConf.RegistryIDs = getRegistryIds(srvOpts.Registries)
        }
 
-       prov.ProtocolIDs = commonCfg.TranslateIds(prov.ProtocolIDs)
+       providerConf.ProtocolIDs = 
commonCfg.TranslateIds(providerConf.ProtocolIDs)
 
-       if err := commonCfg.Verify(prov); err != nil {
+       if err := commonCfg.Verify(providerConf); err != nil {
                return err
        }
 
        // enable adaptive service verbose
-       if prov.AdaptiveServiceVerbose {
-               if !prov.AdaptiveService {
+       if providerConf.AdaptiveServiceVerbose {
+               if !providerConf.AdaptiveService {
                        return perrors.Errorf("The adaptive service is 
disabled, " +
                                "adaptive service verbose should be disabled 
either.")
                }
@@ -402,6 +406,20 @@ func WithServerAdaptiveServiceVerbose() ServerOption {
        }
 }
 
+// WithServerTLSOption applies TLS options to the server configuration.
+// It iterates over the provided tls.
+// TLSOption and applies them to the ServerOptions.TLS field.
+func WithServerTLSOption(opts ...tls.Option) ServerOption {
+       tlsOpts := tls.NewOptions(opts...)
+
+       return func(srvOpts *ServerOptions) {
+               if srvOpts.TLS == nil {
+                       srvOpts.TLS = new(global.TLSConfig)
+               }
+               srvOpts.TLS = tlsOpts.TLSConf
+       }
+}
+
 // ========== For framework ==========
 // These functions should not be invoked by users
 
@@ -441,12 +459,21 @@ func SetServerOtel(otel *global.OtelConfig) ServerOption {
        }
 }
 
+func SetServerTLS(tls *global.TLSConfig) ServerOption {
+       return func(opts *ServerOptions) {
+               opts.TLS = tls
+       }
+}
+
 func SetServerProvider(provider *global.ProviderConfig) ServerOption {
        return func(opts *ServerOptions) {
                opts.Provider = provider
        }
 }
 
+// FIXME: ServiceOptions contains ServerOptions?
+// Not ServerOptions contains ServiceOptions?
+// we need to find a way to fix it.
 type ServiceOptions struct {
        Application *global.ApplicationConfig
        Provider    *global.ProviderConfig
diff --git a/server/server.go b/server/server.go
index d86666cc0..1dbc97545 100644
--- a/server/server.go
+++ b/server/server.go
@@ -168,15 +168,16 @@ func (s *Server) Serve() error {
        if err := metadata.InitRegistryMetadataReport(s.cfg.Registries); err != 
nil {
                return err
        }
-       opts := metadata.NewOptions(
+       metadataOpts := metadata.NewOptions(
                metadata.WithAppName(s.cfg.Application.Name),
                metadata.WithMetadataType(s.cfg.Application.MetadataType),
                metadata.WithPort(getMetadataPort(s.cfg)),
                
metadata.WithMetadataProtocol(s.cfg.Application.MetadataServiceProtocol),
        )
-       if err := opts.Init(); err != nil {
+       if err := metadataOpts.Init(); err != nil {
                return err
        }
+
        if err := s.exportServices(); err != nil {
                return err
        }
@@ -294,7 +295,7 @@ func NewServer(opts ...ServerOption) (*Server, error) {
        return srv, nil
 }
 
-func SetProServices(sd *InternalService) {
+func SetProviderServices(sd *InternalService) {
        if sd.Name == "" {
                logger.Warnf("[internal service]internal name is empty, please 
set internal name")
                return
diff --git a/tls/helper.go b/tls/helper.go
new file mode 100644
index 000000000..253ef163b
--- /dev/null
+++ b/tls/helper.go
@@ -0,0 +1,106 @@
+/*
+ * 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 tls
+
+import (
+       "crypto/tls"
+       "crypto/x509"
+       "errors"
+       "os"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3/global"
+)
+
+func IsServerTLSValid(tlsConf *global.TLSConfig) bool {
+       if tlsConf == nil {
+               return false
+       }
+       return tlsConf.TLSCertFile != "" && tlsConf.TLSKeyFile != ""
+}
+
+func IsClientTLSValid(tlsConf *global.TLSConfig) bool {
+       if tlsConf == nil {
+               return false
+       }
+       return tlsConf.CACertFile != ""
+}
+
+// GetServerTlSConfig build server tls config from TLSConfig
+func GetServerTlSConfig(tlsConf *global.TLSConfig) (*tls.Config, error) {
+       //no TLS
+       if tlsConf.TLSCertFile == "" || tlsConf.TLSKeyFile == "" {
+               return nil, nil
+       }
+
+       var ca *x509.CertPool
+       cfg := &tls.Config{}
+       //need mTLS
+       if tlsConf.CACertFile != "" {
+               ca = x509.NewCertPool()
+               caBytes, err := os.ReadFile(tlsConf.CACertFile)
+               if err != nil {
+                       return nil, err
+               }
+               if ok := ca.AppendCertsFromPEM(caBytes); !ok {
+                       return nil, errors.New("failed to parse root 
certificate")
+               }
+               cfg.ClientAuth = tls.RequireAndVerifyClientCert
+               cfg.ClientCAs = ca
+       }
+       cert, err := tls.LoadX509KeyPair(tlsConf.TLSCertFile, 
tlsConf.TLSKeyFile)
+       if err != nil {
+               return nil, err
+       }
+       cfg.Certificates = []tls.Certificate{cert}
+       cfg.ServerName = tlsConf.TLSServerName
+
+       return cfg, nil
+}
+
+// GetClientTlSConfig build client tls config from TLSConfig
+func GetClientTlSConfig(tlsConf *global.TLSConfig) (*tls.Config, error) {
+       //no TLS
+       if tlsConf.CACertFile == "" {
+               return nil, nil
+       }
+
+       cfg := &tls.Config{
+               ServerName: tlsConf.TLSServerName,
+       }
+       ca := x509.NewCertPool()
+       caBytes, err := os.ReadFile(tlsConf.CACertFile)
+       if err != nil {
+               return nil, err
+       }
+       if ok := ca.AppendCertsFromPEM(caBytes); !ok {
+               return nil, errors.New("failed to parse root certificate")
+       }
+       cfg.RootCAs = ca
+       //need mTls
+       if tlsConf.TLSCertFile != "" {
+               var cert tls.Certificate
+               cert, err = tls.LoadX509KeyPair(tlsConf.TLSCertFile, 
tlsConf.TLSKeyFile)
+               if err != nil {
+                       return nil, err
+               }
+               cfg.Certificates = []tls.Certificate{cert}
+       }
+       return cfg, err
+}
diff --git a/tls/helper_test.go b/tls/helper_test.go
new file mode 100644
index 000000000..d62f4f2ef
--- /dev/null
+++ b/tls/helper_test.go
@@ -0,0 +1,103 @@
+/*
+ * 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 tls
+
+import (
+       "testing"
+
+       "dubbo.apache.org/dubbo-go/v3/global"
+       "github.com/stretchr/testify/assert"
+)
+
+func TestIsServerTLSValid(t *testing.T) {
+       tests := []struct {
+               name     string
+               tlsConf  *global.TLSConfig
+               expected bool
+       }{
+               {
+                       name: "Valid TLSConfig with cert and key",
+                       tlsConf: &global.TLSConfig{
+                               TLSCertFile: "cert.pem",
+                               TLSKeyFile:  "key.pem",
+                       },
+                       expected: true,
+               },
+               {
+                       name: "Invalid TLSConfig with empty cert and key",
+                       tlsConf: &global.TLSConfig{
+                               TLSCertFile: "",
+                               TLSKeyFile:  "",
+                       },
+                       expected: false,
+               },
+               {
+                       name: "Invalid TLSConfig with only cert",
+                       tlsConf: &global.TLSConfig{
+                               TLSCertFile: "cert.pem",
+                               TLSKeyFile:  "",
+                       },
+                       expected: false,
+               },
+               {
+                       name: "Invalid TLSConfig with only key",
+                       tlsConf: &global.TLSConfig{
+                               TLSCertFile: "",
+                               TLSKeyFile:  "key.pem",
+                       },
+                       expected: false,
+               },
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       result := IsServerTLSValid(tt.tlsConf)
+                       assert.Equal(t, tt.expected, result, "Test case %s 
failed", tt.name)
+               })
+       }
+}
+
+func TestIsClientTLSValid(t *testing.T) {
+       tests := []struct {
+               name     string
+               tlsConf  *global.TLSConfig
+               expected bool
+       }{
+               {
+                       name: "Valid Client TLSConfig with CA cert",
+                       tlsConf: &global.TLSConfig{
+                               CACertFile: "ca.pem",
+                       },
+                       expected: true,
+               },
+               {
+                       name: "Invalid Client TLSConfig with empty CA cert",
+                       tlsConf: &global.TLSConfig{
+                               CACertFile: "",
+                       },
+                       expected: false,
+               },
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       result := IsClientTLSValid(tt.tlsConf)
+                       assert.Equal(t, tt.expected, result, "Test case %s 
failed", tt.name)
+               })
+       }
+}
diff --git a/tls/options.go b/tls/options.go
new file mode 100644
index 000000000..b716416f6
--- /dev/null
+++ b/tls/options.go
@@ -0,0 +1,70 @@
+/*
+ * 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 tls
+
+import (
+       "dubbo.apache.org/dubbo-go/v3/global"
+)
+
+// The consideration of not placing TLSOption in the global package is
+// to prevent users from directly using the global package, so I created
+// a new tls directory to allow users to establish config through the tls 
package.
+
+type Options struct {
+       TLSConf *global.TLSConfig
+}
+
+func defaultOptions() *Options {
+       return &Options{TLSConf: global.DefaultTLSConfig()}
+}
+
+func NewOptions(opts ...Option) *Options {
+       defOpts := defaultOptions()
+       for _, opt := range opts {
+               opt(defOpts)
+       }
+       return defOpts
+}
+
+type Option func(*Options)
+
+// ---------- For user ----------
+
+func WithCACertFile(file string) Option {
+       return func(opts *Options) {
+               opts.TLSConf.CACertFile = file
+       }
+}
+
+func WithCertFile(file string) Option {
+       return func(opts *Options) {
+               opts.TLSConf.TLSCertFile = file
+       }
+}
+
+func WithKeyFile(file string) Option {
+       return func(opts *Options) {
+               opts.TLSConf.TLSKeyFile = file
+       }
+}
+
+func WithServerName(name string) Option {
+       return func(opts *Options) {
+               opts.TLSConf.TLSServerName = name
+       }
+}

Reply via email to