From 8690ef6f077aa4f09e1c290a800e35321f54b9f1 Mon Sep 17 00:00:00 2001 From: Bruce Huang Date: Thu, 14 Sep 2023 16:50:51 +0800 Subject: [PATCH] feat: Allow name field escape configurable (#4674) * feat: Allow name field escape configurable Add config and modify topic build logic to allow name field escape configurable. Close #4673 Signed-off-by: bruce * build: Upgrade dependency libs Upgrade go-mod-bootstrap and go-mod-core-contracts. Close #4673 Signed-off-by: bruce --------- Signed-off-by: bruce --- .../res/configuration.yaml | 1 + go.mod | 4 +-- go.sum | 8 +++--- .../command/controller/messaging/external.go | 26 +++++++++---------- .../controller/messaging/external_test.go | 12 ++++----- .../command/controller/messaging/internal.go | 19 +++++++------- .../controller/messaging/internal_test.go | 9 +++++-- internal/core/command/init.go | 7 ++--- internal/core/data/application/event.go | 3 ++- internal/core/metadata/application/notify.go | 23 +++++++--------- .../core/metadata/application/notify_test.go | 3 ++- 11 files changed, 60 insertions(+), 55 deletions(-) diff --git a/cmd/core-common-config-bootstrapper/res/configuration.yaml b/cmd/core-common-config-bootstrapper/res/configuration.yaml index 7310e05033..fb940b6dbc 100644 --- a/cmd/core-common-config-bootstrapper/res/configuration.yaml +++ b/cmd/core-common-config-bootstrapper/res/configuration.yaml @@ -26,6 +26,7 @@ all-services: MaxResultCount: 1024 MaxRequestSize: 0 # Not currently used. Defines the maximum size of http request body in bytes RequestTimeout: "5s" + EnableNameFieldEscape: false # The name field escape could allow the system to use special or Chinese characters in the different name fields, including device, profile, and so on. If the EnableNameFieldEscape is false, some special characters might cause system error. TODO: This is set to false by default to avoid breaking change and will be removed in EdgeX 4.0 CORSConfiguration: EnableCORS: false CORSAllowCredentials: false diff --git a/go.mod b/go.mod index 75734066e1..0448af8bff 100644 --- a/go.mod +++ b/go.mod @@ -4,9 +4,9 @@ go 1.21 require ( github.com/eclipse/paho.mqtt.golang v1.4.3 - github.com/edgexfoundry/go-mod-bootstrap/v3 v3.1.0-dev.33 + github.com/edgexfoundry/go-mod-bootstrap/v3 v3.1.0-dev.36 github.com/edgexfoundry/go-mod-configuration/v3 v3.1.0-dev.5 - github.com/edgexfoundry/go-mod-core-contracts/v3 v3.1.0-dev.9 + github.com/edgexfoundry/go-mod-core-contracts/v3 v3.1.0-dev.13 github.com/edgexfoundry/go-mod-messaging/v3 v3.1.0-dev.20 github.com/edgexfoundry/go-mod-secrets/v3 v3.1.0-dev.6 github.com/fxamacker/cbor/v2 v2.5.0 diff --git a/go.sum b/go.sum index c8438b74f9..9549d5e6bc 100644 --- a/go.sum +++ b/go.sum @@ -26,12 +26,12 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/eclipse/paho.mqtt.golang v1.4.3 h1:2kwcUGn8seMUfWndX0hGbvH8r7crgcJguQNCyp70xik= github.com/eclipse/paho.mqtt.golang v1.4.3/go.mod h1:CSYvoAlsMkhYOXh/oKyxa8EcBci6dVkLCbo5tTC1RIE= -github.com/edgexfoundry/go-mod-bootstrap/v3 v3.1.0-dev.33 h1:9vlPLEucmj0R7y8L4cggujqLz4MiUu43zjDjRzAhpRc= -github.com/edgexfoundry/go-mod-bootstrap/v3 v3.1.0-dev.33/go.mod h1:RTiszbfiWOsmzVVQ15irWLl2+N9uXd/dmK/RanrJn3c= +github.com/edgexfoundry/go-mod-bootstrap/v3 v3.1.0-dev.36 h1:zCdZFPSArKhTKGHWDpDPzLLRIpDfTPA1N3NsE/gjKTU= +github.com/edgexfoundry/go-mod-bootstrap/v3 v3.1.0-dev.36/go.mod h1:k/dJYGezHt13V2IUvuX9uubgsz+zyFITLQ/3Hs+rs+w= github.com/edgexfoundry/go-mod-configuration/v3 v3.1.0-dev.5 h1:wTs2qOG/RHeizCHcPp8KOQcSzGrvNOhVQnK+JdAHJNs= github.com/edgexfoundry/go-mod-configuration/v3 v3.1.0-dev.5/go.mod h1:mZyBGQ7eX+K63b46/K/OdiWSHtYbl/TK2GTfc0eOM6Q= -github.com/edgexfoundry/go-mod-core-contracts/v3 v3.1.0-dev.9 h1:ZvCeuB1CXzNzg2WhpLCEKhkPSZpS0Geoh0AqTbj08X4= -github.com/edgexfoundry/go-mod-core-contracts/v3 v3.1.0-dev.9/go.mod h1:L7i97+A+bMpvXFo1M6t0WHeRrsSocTgDEl3ayfVxCmo= +github.com/edgexfoundry/go-mod-core-contracts/v3 v3.1.0-dev.13 h1:guSGxvTDHc7SUjoOgRAUnXpsU60OwQZCbh1RAjjcQBY= +github.com/edgexfoundry/go-mod-core-contracts/v3 v3.1.0-dev.13/go.mod h1:MztlrH+8hPRX6XNZrbdvbV0RNgkoAN1etcvAtgSHeuQ= github.com/edgexfoundry/go-mod-messaging/v3 v3.1.0-dev.20 h1:iKhaDrfN0plO95MjPmrOEhfiUrE9gMD9Os7odtOrM10= github.com/edgexfoundry/go-mod-messaging/v3 v3.1.0-dev.20/go.mod h1:cD3WRffguDrR/G7dIyzYewfoOk44VlJfGSkgbuUzvYM= github.com/edgexfoundry/go-mod-registry/v3 v3.1.0-dev.5 h1:Xu1Jxk8gjMGMROqOf2C5pLY6lx1nWNYSDife2d623UE= diff --git a/internal/core/command/controller/messaging/external.go b/internal/core/command/controller/messaging/external.go index 2b5140b296..a0a2bf0018 100644 --- a/internal/core/command/controller/messaging/external.go +++ b/internal/core/command/controller/messaging/external.go @@ -60,7 +60,7 @@ func commandQueryHandler(dic *di.Container) mqtt.MessageHandler { } externalMQTTInfo := container.ConfigurationFrom(dic.Get).ExternalMQTT - responseTopic := externalMQTTInfo.Topics[common.ExternalCommandQueryResponseTopicKey] + responseTopic := externalMQTTInfo.Topics[common.CommandQueryResponseTopicKey] if responseTopic == "" { lc.Error("QueryResponseTopic not provided in External.Topics") lc.Warn("Not publishing error message back due to insufficient information on response topic") @@ -95,6 +95,7 @@ func commandQueryHandler(dic *di.Container) mqtt.MessageHandler { func commandRequestHandler(requestTimeout time.Duration, dic *di.Container) mqtt.MessageHandler { return func(client mqtt.Client, message mqtt.Message) { lc := bootstrapContainer.LoggingClientFrom(dic.Get) + config := container.ConfigurationFrom(dic.Get) lc.Debugf("Received command request from external message broker on topic '%s' with %d bytes", message.Topic(), len(message.Payload())) externalMQTTInfo := container.ConfigurationFrom(dic.Get).ExternalMQTT @@ -117,17 +118,15 @@ func commandRequestHandler(requestTimeout time.Duration, dic *di.Container) mqtt } // expected external command request/response topic scheme: #/// - deviceName := topicLevels[length-3] - unescapedDeviceName, err := url.PathUnescape(deviceName) + deviceName, err := url.PathUnescape(topicLevels[length-3]) if err != nil { - lc.Errorf("Failed to unescape device name '%s': %s", deviceName, err.Error()) + lc.Errorf("Failed to unescape device name from '%s': %s", topicLevels[length-3], err.Error()) lc.Warn("Not publishing error message back due to insufficient information on response topic") return } - commandName := topicLevels[length-2] - unescapedCommandName, err := url.PathUnescape(commandName) + commandName, err := url.PathUnescape(topicLevels[length-2]) if err != nil { - lc.Errorf("Failed to unescape command name '%s': %s", commandName, err.Error()) + lc.Errorf("Failed to unescape command name from '%s': %s", topicLevels[length-2], err.Error()) lc.Warn("Not publishing error message back due to insufficient information on response topic") return } @@ -138,12 +137,12 @@ func commandRequestHandler(requestTimeout time.Duration, dic *di.Container) mqtt return } - externalResponseTopic := common.BuildTopic(externalMQTTInfo.Topics[common.ExternalCommandResponseTopicPrefixKey], deviceName, commandName, method) + externalResponseTopic := common.BuildTopic(externalMQTTInfo.Topics[common.CommandResponseTopicPrefixKey], deviceName, commandName, method) - internalBaseTopic := container.ConfigurationFrom(dic.Get).MessageBus.GetBaseTopicPrefix() + internalBaseTopic := config.MessageBus.GetBaseTopicPrefix() topicPrefix := common.BuildTopic(internalBaseTopic, common.CoreCommandDeviceRequestPublishTopic) - deviceServiceName, err := retrieveServiceNameByDevice(unescapedDeviceName, dic) + deviceServiceName, err := retrieveServiceNameByDevice(deviceName, dic) if err != nil { responseEnvelope := types.NewMessageEnvelopeWithError(requestEnvelope.RequestID, err.Error()) publishMessage(client, externalResponseTopic, qos, retain, responseEnvelope, lc) @@ -157,9 +156,10 @@ func commandRequestHandler(requestTimeout time.Duration, dic *di.Container) mqtt return } - // escape again to ensure that the topic is valid in the internal message bus - deviceRequestTopic := common.BuildTopic(topicPrefix, common.URLEncode(deviceServiceName), common.URLEncode(unescapedDeviceName), common.URLEncode(unescapedCommandName), method) - deviceResponseTopicPrefix := common.BuildTopic(internalBaseTopic, common.ResponseTopic, common.URLEncode(deviceServiceName)) + deviceRequestTopic := common.NewPathBuilder().EnableNameFieldEscape(config.Service.EnableNameFieldEscape). + SetPath(topicPrefix).SetNameFieldPath(deviceServiceName).SetNameFieldPath(deviceName).SetNameFieldPath(commandName).SetPath(method).BuildPath() + deviceResponseTopicPrefix := common.NewPathBuilder().EnableNameFieldEscape(config.Service.EnableNameFieldEscape). + SetPath(internalBaseTopic).SetPath(common.ResponseTopic).SetNameFieldPath(deviceServiceName).BuildPath() lc.Debugf("Sending Command request to internal MessageBus. Topic: %s, Request-id: %s Correlation-id: %s", deviceRequestTopic, requestEnvelope.RequestID, requestEnvelope.CorrelationID) lc.Debugf("Expecting response on topic: %s/%s", deviceResponseTopicPrefix, requestEnvelope.RequestID) diff --git a/internal/core/command/controller/messaging/external_test.go b/internal/core/command/controller/messaging/external_test.go index 535e7a68ab..0f9f4a9a4b 100644 --- a/internal/core/command/controller/messaging/external_test.go +++ b/internal/core/command/controller/messaging/external_test.go @@ -65,10 +65,10 @@ func TestOnConnectHandler(t *testing.T) { return &config.ConfigurationStruct{ ExternalMQTT: bootstrapConfig.ExternalMQTTInfo{ Topics: map[string]string{ - common.CommandRequestTopicKey: testExternalCommandRequestTopic, - common.ExternalCommandResponseTopicPrefixKey: testExternalCommandResponseTopicPrefix, - common.CommandQueryRequestTopicKey: testQueryRequestTopic, - common.ExternalCommandQueryResponseTopicKey: testQueryResponseTopic, + common.CommandRequestTopicKey: testExternalCommandRequestTopic, + common.CommandResponseTopicPrefixKey: testExternalCommandResponseTopicPrefix, + common.CommandQueryRequestTopicKey: testQueryRequestTopic, + common.CommandQueryResponseTopicKey: testQueryResponseTopic, }, QoS: 0, Retain: true, @@ -171,7 +171,7 @@ func Test_commandQueryHandler(t *testing.T) { QoS: 0, Retain: true, Topics: map[string]string{ - common.ExternalCommandQueryResponseTopicKey: testQueryResponseTopic, + common.CommandQueryResponseTopicKey: testQueryResponseTopic, }, }, } @@ -298,7 +298,7 @@ func Test_commandRequestHandler(t *testing.T) { QoS: 0, Retain: true, Topics: map[string]string{ - common.ExternalCommandResponseTopicPrefixKey: testExternalCommandResponseTopicPrefix, + common.CommandResponseTopicPrefixKey: testExternalCommandResponseTopicPrefix, }, }, } diff --git a/internal/core/command/controller/messaging/internal.go b/internal/core/command/controller/messaging/internal.go index e18abac4a0..6f400f6e52 100644 --- a/internal/core/command/controller/messaging/internal.go +++ b/internal/core/command/controller/messaging/internal.go @@ -73,6 +73,7 @@ func processDeviceCommandRequest( lc logger.LoggingClient, dic *di.Container) { var err error + config := container.ConfigurationFrom(dic.Get) lc.Debugf("Command device request received on internal MessageBus. Topic: %s, Request-id: %s, Correlation-id: %s", requestEnvelope.ReceivedTopic, requestEnvelope.RequestID, requestEnvelope.CorrelationID) @@ -98,17 +99,15 @@ func processDeviceCommandRequest( } // expected internal command request/response topic scheme: #/// - deviceName := topicLevels[length-3] - unescapedDeviceName, err := url.PathUnescape(deviceName) + deviceName, err := url.PathUnescape(topicLevels[length-3]) if err != nil { - lc.Errorf("Failed to unescape device name '%s': %s", deviceName, err.Error()) + lc.Errorf("Failed to unescape device name from '%s': %s", topicLevels[length-3], err.Error()) lc.Warn("Not publishing error message back due to insufficient information on response topic") return } - commandName := topicLevels[length-2] - unescapedCommandName, err := url.PathUnescape(commandName) + commandName, err := url.PathUnescape(topicLevels[length-2]) if err != nil { - err = fmt.Errorf("failed to unescape command name '%s': %s", commandName, err.Error()) + err = fmt.Errorf("failed to unescape command name from '%s': %s", topicLevels[length-2], err.Error()) lc.Error(err.Error()) responseEnvelope := types.NewMessageEnvelopeWithError(requestEnvelope.RequestID, err.Error()) err = messageBus.Publish(responseEnvelope, internalResponseTopic) @@ -131,7 +130,7 @@ func processDeviceCommandRequest( topicPrefix := common.BuildTopic(baseTopic, common.CoreCommandDeviceRequestPublishTopic) // internal command request topic scheme: //// - deviceServiceName, err := retrieveServiceNameByDevice(unescapedDeviceName, dic) + deviceServiceName, err := retrieveServiceNameByDevice(deviceName, dic) if err != nil { err = fmt.Errorf("invalid request topic: %s", err.Error()) lc.Error(err.Error()) @@ -154,8 +153,10 @@ func processDeviceCommandRequest( return } - deviceRequestTopic := common.BuildTopic(topicPrefix, common.URLEncode(deviceServiceName), common.URLEncode(unescapedDeviceName), common.URLEncode(unescapedCommandName), method) - deviceResponseTopicPrefix := common.BuildTopic(baseTopic, common.ResponseTopic, common.URLEncode(deviceServiceName)) + deviceRequestTopic := common.NewPathBuilder().EnableNameFieldEscape(config.Service.EnableNameFieldEscape). + SetPath(topicPrefix).SetNameFieldPath(deviceServiceName).SetNameFieldPath(deviceName).SetNameFieldPath(commandName).SetPath(method).BuildPath() + deviceResponseTopicPrefix := common.NewPathBuilder().EnableNameFieldEscape(config.Service.EnableNameFieldEscape). + SetPath(baseTopic).SetPath(common.ResponseTopic).SetNameFieldPath(deviceServiceName).BuildPath() lc.Debugf("Sending Command Device Request to internal MessageBus. Topic: %s, Correlation-id: %s", deviceRequestTopic, requestEnvelope.CorrelationID) lc.Debugf("Expecting response on topic: %s/%s", deviceResponseTopicPrefix, requestEnvelope.RequestID) diff --git a/internal/core/command/controller/messaging/internal_test.go b/internal/core/command/controller/messaging/internal_test.go index 160196c7bb..2f5fa51bbb 100644 --- a/internal/core/command/controller/messaging/internal_test.go +++ b/internal/core/command/controller/messaging/internal_test.go @@ -42,12 +42,12 @@ func TestSubscribeCommandRequests(t *testing.T) { expectedDevice := "device1" expectedResource := "resource" expectedMethod := "get" - expectedDeviceResponseTopicPrefix := strings.Join([]string{expectedResponseTopicPrefix, common.URLEncode(expectedServiceName)}, "/") + expectedDeviceResponseTopicPrefix := strings.Join([]string{expectedResponseTopicPrefix, expectedServiceName}, "/") expectedCommandResponseTopic := strings.Join([]string{expectedResponseTopicPrefix, common.CoreCommandServiceKey, expectedRequestId}, "/") expectedCommandRequestSubscribeTopic := common.BuildTopic(baseTopic, common.CoreCommandRequestSubscribeTopic) expectedCommandRequestReceivedTopic := common.BuildTopic(strings.Replace(expectedCommandRequestSubscribeTopic, "/#", "", 1), expectedServiceName, expectedDevice, expectedResource, expectedMethod) - expectedDeviceCommandRequestRequestTopic := common.BuildTopic(baseTopic, common.CoreCommandDeviceRequestPublishTopic, common.URLEncode(expectedServiceName), common.URLEncode(expectedDevice), common.URLEncode(expectedResource), expectedMethod) + expectedDeviceCommandRequestRequestTopic := common.BuildTopic(baseTopic, common.CoreCommandDeviceRequestPublishTopic, expectedServiceName, expectedDevice, expectedResource, expectedMethod) mockLogger := &lcMocks.LoggingClient{} mockDeviceClient := &mocks2.DeviceClient{} mockDeviceProfileClient := &mocks2.DeviceProfileClient{} @@ -128,6 +128,11 @@ func TestSubscribeCommandRequests(t *testing.T) { bootstrapContainer.DeviceServiceClientName: func(get di.Get) interface{} { return mockDeviceServiceClient }, + bootstrapContainer.ConfigurationInterfaceName: func(get di.Get) interface{} { + return &config.ConfigurationStruct{ + Service: config2.ServiceInfo{EnableNameFieldEscape: false}, + } + }, }) err := SubscribeCommandRequests(context.Background(), time.Second*5, dic) diff --git a/internal/core/command/init.go b/internal/core/command/init.go index 31cc0f5837..ba9edba9e4 100644 --- a/internal/core/command/init.go +++ b/internal/core/command/init.go @@ -20,7 +20,7 @@ import ( "context" "sync" - "github.com/edgexfoundry/go-mod-bootstrap/v3/bootstrap/container" + "github.com/edgexfoundry/edgex-go/internal/core/command/container" bootstrapContainer "github.com/edgexfoundry/go-mod-bootstrap/v3/bootstrap/container" "github.com/edgexfoundry/go-mod-bootstrap/v3/bootstrap/secret" "github.com/edgexfoundry/go-mod-bootstrap/v3/bootstrap/startup" @@ -47,12 +47,13 @@ func NewBootstrap(router *echo.Echo, serviceName string) *Bootstrap { // BootstrapHandler fulfills the BootstrapHandler contract and performs initialization needed by the command service. func (b *Bootstrap) BootstrapHandler(ctx context.Context, wg *sync.WaitGroup, _ startup.Timer, dic *di.Container) bool { LoadRestRoutes(b.router, dic, b.serviceName) + config := container.ConfigurationFrom(dic.Get) // DeviceServiceCommandClient is not part of the common clients handled by the NewClientsBootstrap handler dic.Update(di.ServiceConstructorMap{ bootstrapContainer.DeviceServiceCommandClientName: func(get di.Get) interface{} { // add API DeviceServiceCommandClient - jwtSecretProvider := secret.NewJWTSecretProvider(container.SecretProviderExtFrom(get)) - return clients.NewDeviceServiceCommandClient(jwtSecretProvider) + jwtSecretProvider := secret.NewJWTSecretProvider(bootstrapContainer.SecretProviderExtFrom(get)) + return clients.NewDeviceServiceCommandClient(jwtSecretProvider, config.Service.EnableNameFieldEscape) }, }) diff --git a/internal/core/data/application/event.go b/internal/core/data/application/event.go index d86c74bf21..2ee18464d7 100644 --- a/internal/core/data/application/event.go +++ b/internal/core/data/application/event.go @@ -82,7 +82,8 @@ func (a *CoreDataApp) PublishEvent(data []byte, serviceName string, profileName correlationId := correlation.FromContext(ctx) basePrefix := configuration.MessageBus.GetBaseTopicPrefix() - publishTopic := common.BuildTopic(basePrefix, common.EventsPublishTopic, CoreDataEventTopicPrefix, common.URLEncode(serviceName), common.URLEncode(profileName), common.URLEncode(deviceName), common.URLEncode(sourceName)) + publishTopic := common.NewPathBuilder().EnableNameFieldEscape(configuration.Service.EnableNameFieldEscape). + SetPath(basePrefix).SetPath(common.EventsPublishTopic).SetPath(CoreDataEventTopicPrefix).SetNameFieldPath(serviceName).SetNameFieldPath(profileName).SetNameFieldPath(deviceName).SetNameFieldPath(sourceName).BuildPath() lc.Debugf("Publishing AddEventRequest to MessageBus. Topic: %s; %s: %s", publishTopic, common.CorrelationHeader, correlationId) msgEnvelope := msgTypes.NewMessageEnvelope(data, ctx) diff --git a/internal/core/metadata/application/notify.go b/internal/core/metadata/application/notify.go index 6a79ed4beb..4771156322 100644 --- a/internal/core/metadata/application/notify.go +++ b/internal/core/metadata/application/notify.go @@ -42,8 +42,10 @@ func validateDeviceCallback(device dtos.Device, dic *di.Container) errors.EdgeX } baseTopic := configuration.MessageBus.GetBaseTopicPrefix() - requestTopic := common.BuildTopic(baseTopic, common.URLEncode(device.ServiceName), common.ValidateDeviceSubscribeTopic) - responseTopicPrefix := common.BuildTopic(baseTopic, common.ResponseTopic, common.URLEncode(device.ServiceName)) + requestTopic := common.NewPathBuilder().EnableNameFieldEscape(configuration.Service.EnableNameFieldEscape). + SetPath(baseTopic).SetNameFieldPath(device.ServiceName).SetPath(common.ValidateDeviceSubscribeTopic).BuildPath() + responseTopicPrefix := common.NewPathBuilder().EnableNameFieldEscape(configuration.Service.EnableNameFieldEscape). + SetPath(baseTopic).SetPath(common.ResponseTopic).SetNameFieldPath(device.ServiceName).BuildPath() requestEnvelope := types.NewMessageEnvelopeForRequest(requestBytes, nil) lc.Debugf("Sending Device Validation request for device=%s, CorrelationId=%s to topic: %s", device.Name, requestEnvelope.CorrelationID, requestTopic) @@ -86,6 +88,7 @@ func publishUpdateDeviceProfileSystemEvent(profileDTO dtos.DeviceProfile, ctx co func publishSystemEvent(eventType, action, owner string, dto any, ctx context.Context, dic *di.Container) { lc := bootstrapContainer.LoggingClientFrom(dic.Get) + config := container.ConfigurationFrom(dic.Get) systemEvent := dtos.NewSystemEvent(eventType, action, common.CoreMetaDataServiceKey, owner, nil, dto) messagingClient := bootstrapContainer.MessagingClientFrom(dic.Get) if messagingClient == nil { @@ -130,20 +133,12 @@ func publishSystemEvent(eventType, action, owner string, dto any, ctx context.Co return } - publishTopic := common.BuildTopic( - container.ConfigurationFrom(dic.Get).MessageBus.GetBaseTopicPrefix(), - common.SystemEventPublishTopic, - systemEvent.Source, - systemEvent.Type, - systemEvent.Action, - common.URLEncode(systemEvent.Owner), - ) + topicPathBuilder := common.NewPathBuilder().EnableNameFieldEscape(config.Service.EnableNameFieldEscape) + publishTopic := topicPathBuilder.SetPath(config.MessageBus.GetBaseTopicPrefix()).SetPath(common.SystemEventPublishTopic). + SetPath(systemEvent.Source).SetPath(systemEvent.Type).SetPath(systemEvent.Action).SetNameFieldPath(systemEvent.Owner).BuildPath() if profileName != "" { - publishTopic = common.BuildTopic( - publishTopic, - common.URLEncode(profileName), - ) + publishTopic = topicPathBuilder.SetNameFieldPath(profileName).BuildPath() } payload, _ := json.Marshal(systemEvent) diff --git a/internal/core/metadata/application/notify_test.go b/internal/core/metadata/application/notify_test.go index bdce0efd9c..e8c21f87f3 100644 --- a/internal/core/metadata/application/notify_test.go +++ b/internal/core/metadata/application/notify_test.go @@ -15,6 +15,7 @@ import ( "github.com/edgexfoundry/edgex-go/internal/core/metadata/config" "github.com/edgexfoundry/edgex-go/internal/core/metadata/container" + bootstrapConfig "github.com/edgexfoundry/go-mod-bootstrap/v3/config" mocks2 "github.com/edgexfoundry/go-mod-core-contracts/v3/clients/logger/mocks" "github.com/edgexfoundry/go-mod-core-contracts/v3/common" "github.com/edgexfoundry/go-mod-core-contracts/v3/dtos" @@ -75,7 +76,7 @@ func TestPublishSystemEvent(t *testing.T) { dic := di.NewContainer(di.ServiceConstructorMap{ container.ConfigurationName: func(get di.Get) interface{} { - return &config.ConfigurationStruct{} + return &config.ConfigurationStruct{Service: bootstrapConfig.ServiceInfo{EnableNameFieldEscape: true}} }, bootstrapContainer.LoggingClientInterfaceName: func(get di.Get) interface{} { return mockLogger