diff --git a/clients/http/command.go b/clients/http/command.go index 1b54d6bb..128ba559 100644 --- a/clients/http/command.go +++ b/clients/http/command.go @@ -20,15 +20,17 @@ import ( ) type CommandClient struct { - baseUrl string - authInjector interfaces.AuthenticationInjector + baseUrl string + authInjector interfaces.AuthenticationInjector + enableNameFieldEscape bool } // NewCommandClient creates an instance of CommandClient -func NewCommandClient(baseUrl string, authInjector interfaces.AuthenticationInjector) interfaces.CommandClient { +func NewCommandClient(baseUrl string, authInjector interfaces.AuthenticationInjector, enableNameFieldEscape bool) interfaces.CommandClient { return &CommandClient{ - baseUrl: baseUrl, - authInjector: authInjector, + baseUrl: baseUrl, + authInjector: authInjector, + enableNameFieldEscape: enableNameFieldEscape, } } @@ -48,7 +50,8 @@ func (client *CommandClient) AllDeviceCoreCommands(ctx context.Context, offset i // DeviceCoreCommandsByDeviceName returns all commands associated with the specified device name. func (client *CommandClient) DeviceCoreCommandsByDeviceName(ctx context.Context, name string) ( res responses.DeviceCoreCommandResponse, err errors.EdgeX) { - path := utils.EscapeAndJoinPath(common.ApiDeviceRoute, common.Name, name) + path := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiDeviceRoute).SetPath(common.Name).SetNameFieldPath(name).BuildPath() err = utils.GetRequest(ctx, &res, client.baseUrl, path, nil, client.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) @@ -61,7 +64,8 @@ func (client *CommandClient) IssueGetCommandByName(ctx context.Context, deviceNa requestParams := url.Values{} requestParams.Set(common.PushEvent, strconv.FormatBool(dsPushEvent)) requestParams.Set(common.ReturnEvent, strconv.FormatBool(dsReturnEvent)) - requestPath := utils.EscapeAndJoinPath(common.ApiDeviceRoute, common.Name, deviceName, commandName) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiDeviceRoute).SetPath(common.Name).SetNameFieldPath(deviceName).SetNameFieldPath(commandName).BuildPath() err = utils.GetRequest(ctx, &res, client.baseUrl, requestPath, requestParams, client.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) @@ -74,8 +78,8 @@ func (client *CommandClient) IssueGetCommandByNameWithQueryParams(ctx context.Co for k, v := range queryParams { requestParams.Set(k, v) } - - requestPath := utils.EscapeAndJoinPath(common.ApiDeviceRoute, common.Name, deviceName, commandName) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiDeviceRoute).SetPath(common.Name).SetNameFieldPath(deviceName).SetNameFieldPath(commandName).BuildPath() err = utils.GetRequest(ctx, &res, client.baseUrl, requestPath, requestParams, client.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) @@ -85,7 +89,8 @@ func (client *CommandClient) IssueGetCommandByNameWithQueryParams(ctx context.Co // IssueSetCommandByName issues the specified write command referenced by the command name to the device/sensor that is also referenced by name. func (client *CommandClient) IssueSetCommandByName(ctx context.Context, deviceName string, commandName string, settings map[string]string) (res dtoCommon.BaseResponse, err errors.EdgeX) { - requestPath := utils.EscapeAndJoinPath(common.ApiDeviceRoute, common.Name, deviceName, commandName) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiDeviceRoute).SetPath(common.Name).SetNameFieldPath(deviceName).SetNameFieldPath(commandName).BuildPath() err = utils.PutRequest(ctx, &res, client.baseUrl, requestPath, nil, settings, client.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) @@ -95,7 +100,8 @@ func (client *CommandClient) IssueSetCommandByName(ctx context.Context, deviceNa // IssueSetCommandByNameWithObject issues the specified write command and the settings supports object value type func (client *CommandClient) IssueSetCommandByNameWithObject(ctx context.Context, deviceName string, commandName string, settings map[string]interface{}) (res dtoCommon.BaseResponse, err errors.EdgeX) { - requestPath := utils.EscapeAndJoinPath(common.ApiDeviceRoute, common.Name, deviceName, commandName) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiDeviceRoute).SetPath(common.Name).SetNameFieldPath(deviceName).SetNameFieldPath(commandName).BuildPath() err = utils.PutRequest(ctx, &res, client.baseUrl, requestPath, nil, settings, client.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) diff --git a/clients/http/command_test.go b/clients/http/command_test.go index cf57c11a..68c6ff0c 100644 --- a/clients/http/command_test.go +++ b/clients/http/command_test.go @@ -8,7 +8,6 @@ package http import ( "context" "encoding/json" - "github.com/edgexfoundry/go-mod-core-contracts/v3/clients/http/utils" "net/http" "net/http/httptest" "strconv" @@ -24,7 +23,7 @@ import ( func TestQueryDeviceCoreCommands(t *testing.T) { ts := newTestServer(http.MethodGet, common.ApiAllDeviceRoute, responses.MultiDeviceCoreCommandsResponse{}) defer ts.Close() - client := NewCommandClient(ts.URL, NewNullAuthenticationInjector()) + client := NewCommandClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.AllDeviceCoreCommands(context.Background(), 0, 10) require.NoError(t, err) require.IsType(t, responses.MultiDeviceCoreCommandsResponse{}, res) @@ -32,10 +31,11 @@ func TestQueryDeviceCoreCommands(t *testing.T) { func TestQueryDeviceCoreCommandsByDeviceName(t *testing.T) { deviceName := "Simple-Device01" - path := utils.EscapeAndJoinPath(common.ApiDeviceRoute, common.Name, deviceName) + path := common.NewPathBuilder().EnableNameFieldEscape(false). + SetPath(common.ApiDeviceRoute).SetPath(common.Name).SetNameFieldPath(deviceName).BuildPath() ts := newTestServer(http.MethodGet, path, responses.DeviceCoreCommandResponse{}) defer ts.Close() - client := NewCommandClient(ts.URL, NewNullAuthenticationInjector()) + client := NewCommandClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeviceCoreCommandsByDeviceName(context.Background(), deviceName) require.NoError(t, err) require.IsType(t, responses.DeviceCoreCommandResponse{}, res) @@ -44,10 +44,11 @@ func TestQueryDeviceCoreCommandsByDeviceName(t *testing.T) { func TestIssueGetCommandByName(t *testing.T) { deviceName := "Simple-Device01" cmdName := "SwitchButton" - path := utils.EscapeAndJoinPath(common.ApiDeviceRoute, common.Name, deviceName, cmdName) + path := common.NewPathBuilder().EnableNameFieldEscape(false). + SetPath(common.ApiDeviceRoute).SetPath(common.Name).SetNameFieldPath(deviceName).SetNameFieldPath(cmdName).BuildPath() ts := newTestServer(http.MethodGet, path, &responses.EventResponse{}) defer ts.Close() - client := NewCommandClient(ts.URL, NewNullAuthenticationInjector()) + client := NewCommandClient(ts.URL, NewNullAuthenticationInjector(), false) pushEvent, err := strconv.ParseBool(common.ValueTrue) require.NoError(t, err) notReturnEvent, err := strconv.ParseBool(common.ValueFalse) @@ -75,7 +76,7 @@ func TestIssueGetCommandByNameWithQueryParams(t *testing.T) { })) defer ts.Close() - client := NewCommandClient(ts.URL, NewNullAuthenticationInjector()) + client := NewCommandClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.IssueGetCommandByNameWithQueryParams(context.Background(), deviceName, cmdName, testQueryParams) require.NoError(t, err) require.IsType(t, &responses.EventResponse{}, res) @@ -87,10 +88,11 @@ func TestIssueIssueSetCommandByName(t *testing.T) { settings := map[string]string{ "SwitchButton": "true", } - path := utils.EscapeAndJoinPath(common.ApiDeviceRoute, common.Name, deviceName, cmdName) + path := common.NewPathBuilder().EnableNameFieldEscape(false). + SetPath(common.ApiDeviceRoute).SetPath(common.Name).SetNameFieldPath(deviceName).SetNameFieldPath(cmdName).BuildPath() ts := newTestServer(http.MethodPut, path, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewCommandClient(ts.URL, NewNullAuthenticationInjector()) + client := NewCommandClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.IssueSetCommandByName(context.Background(), deviceName, cmdName, settings) require.NoError(t, err) require.IsType(t, dtoCommon.BaseResponse{}, res) @@ -105,10 +107,11 @@ func TestIssueIssueSetCommandByNameWithObject(t *testing.T) { "value": "on", }, } - path := utils.EscapeAndJoinPath(common.ApiDeviceRoute, common.Name, deviceName, cmdName) + path := common.NewPathBuilder().EnableNameFieldEscape(false). + SetPath(common.ApiDeviceRoute).SetPath(common.Name).SetNameFieldPath(deviceName).SetNameFieldPath(cmdName).BuildPath() ts := newTestServer(http.MethodPut, path, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewCommandClient(ts.URL, NewNullAuthenticationInjector()) + client := NewCommandClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.IssueSetCommandByNameWithObject(context.Background(), deviceName, cmdName, settings) require.NoError(t, err) require.IsType(t, dtoCommon.BaseResponse{}, res) diff --git a/clients/http/device.go b/clients/http/device.go index d339a69f..09895737 100644 --- a/clients/http/device.go +++ b/clients/http/device.go @@ -22,15 +22,17 @@ import ( ) type DeviceClient struct { - baseUrl string - authInjector interfaces.AuthenticationInjector + baseUrl string + authInjector interfaces.AuthenticationInjector + enableNameFieldEscape bool } // NewDeviceClient creates an instance of DeviceClient -func NewDeviceClient(baseUrl string, authInjector interfaces.AuthenticationInjector) interfaces.DeviceClient { +func NewDeviceClient(baseUrl string, authInjector interfaces.AuthenticationInjector, enableNameFieldEscape bool) interfaces.DeviceClient { return &DeviceClient{ - baseUrl: baseUrl, - authInjector: authInjector, + baseUrl: baseUrl, + authInjector: authInjector, + enableNameFieldEscape: enableNameFieldEscape, } } @@ -65,7 +67,8 @@ func (dc DeviceClient) AllDevices(ctx context.Context, labels []string, offset i } func (dc DeviceClient) DeviceNameExists(ctx context.Context, name string) (res dtoCommon.BaseResponse, err errors.EdgeX) { - path := utils.EscapeAndJoinPath(common.ApiDeviceRoute, common.Check, common.Name, name) + path := common.NewPathBuilder().EnableNameFieldEscape(dc.enableNameFieldEscape). + SetPath(common.ApiDeviceRoute).SetPath(common.Check).SetPath(common.Name).SetNameFieldPath(name).BuildPath() err = utils.GetRequest(ctx, &res, dc.baseUrl, path, nil, dc.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) @@ -74,7 +77,8 @@ func (dc DeviceClient) DeviceNameExists(ctx context.Context, name string) (res d } func (dc DeviceClient) DeviceByName(ctx context.Context, name string) (res responses.DeviceResponse, err errors.EdgeX) { - path := utils.EscapeAndJoinPath(common.ApiDeviceRoute, common.Name, name) + path := common.NewPathBuilder().EnableNameFieldEscape(dc.enableNameFieldEscape). + SetPath(common.ApiDeviceRoute).SetPath(common.Name).SetNameFieldPath(name).BuildPath() err = utils.GetRequest(ctx, &res, dc.baseUrl, path, nil, dc.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) @@ -83,7 +87,8 @@ func (dc DeviceClient) DeviceByName(ctx context.Context, name string) (res respo } func (dc DeviceClient) DeleteDeviceByName(ctx context.Context, name string) (res dtoCommon.BaseResponse, err errors.EdgeX) { - path := utils.EscapeAndJoinPath(common.ApiDeviceRoute, common.Name, name) + path := common.NewPathBuilder().EnableNameFieldEscape(dc.enableNameFieldEscape). + SetPath(common.ApiDeviceRoute).SetPath(common.Name).SetNameFieldPath(name).BuildPath() err = utils.DeleteRequest(ctx, &res, dc.baseUrl, path, dc.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) @@ -92,7 +97,8 @@ func (dc DeviceClient) DeleteDeviceByName(ctx context.Context, name string) (res } func (dc DeviceClient) DevicesByProfileName(ctx context.Context, name string, offset int, limit int) (res responses.MultiDevicesResponse, err errors.EdgeX) { - requestPath := utils.EscapeAndJoinPath(common.ApiDeviceRoute, common.Profile, common.Name, name) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(dc.enableNameFieldEscape). + SetPath(common.ApiDeviceRoute).SetPath(common.Profile).SetPath(common.Name).SetNameFieldPath(name).BuildPath() requestParams := url.Values{} requestParams.Set(common.Offset, strconv.Itoa(offset)) requestParams.Set(common.Limit, strconv.Itoa(limit)) @@ -104,7 +110,8 @@ func (dc DeviceClient) DevicesByProfileName(ctx context.Context, name string, of } func (dc DeviceClient) DevicesByServiceName(ctx context.Context, name string, offset int, limit int) (res responses.MultiDevicesResponse, err errors.EdgeX) { - requestPath := utils.EscapeAndJoinPath(common.ApiDeviceRoute, common.Service, common.Name, name) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(dc.enableNameFieldEscape). + SetPath(common.ApiDeviceRoute).SetPath(common.Service).SetPath(common.Name).SetNameFieldPath(name).BuildPath() requestParams := url.Values{} requestParams.Set(common.Offset, strconv.Itoa(offset)) requestParams.Set(common.Limit, strconv.Itoa(limit)) diff --git a/clients/http/device_test.go b/clients/http/device_test.go index 0621aa7b..73395831 100644 --- a/clients/http/device_test.go +++ b/clients/http/device_test.go @@ -23,7 +23,7 @@ import ( func TestAddDevices(t *testing.T) { ts := newTestServer(http.MethodPost, common.ApiDeviceRoute, []dtoCommon.BaseWithIdResponse{}) defer ts.Close() - client := NewDeviceClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.Add(context.Background(), []requests.AddDeviceRequest{}) require.NoError(t, err) require.IsType(t, []dtoCommon.BaseWithIdResponse{}, res) @@ -32,7 +32,7 @@ func TestAddDevices(t *testing.T) { func TestPatchDevices(t *testing.T) { ts := newTestServer(http.MethodPatch, common.ApiDeviceRoute, []dtoCommon.BaseResponse{}) defer ts.Close() - client := NewDeviceClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.Update(context.Background(), []requests.UpdateDeviceRequest{}) require.NoError(t, err) require.IsType(t, []dtoCommon.BaseResponse{}, res) @@ -41,7 +41,7 @@ func TestPatchDevices(t *testing.T) { func TestQueryAllDevices(t *testing.T) { ts := newTestServer(http.MethodGet, common.ApiAllDeviceRoute, responses.MultiDevicesResponse{}) defer ts.Close() - client := NewDeviceClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.AllDevices(context.Background(), []string{"label1", "label2"}, 1, 10) require.NoError(t, err) require.IsType(t, responses.MultiDevicesResponse{}, res) @@ -52,7 +52,7 @@ func TestDeviceNameExists(t *testing.T) { path := path.Join(common.ApiDeviceRoute, common.Check, common.Name, deviceName) ts := newTestServer(http.MethodGet, path, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewDeviceClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeviceNameExists(context.Background(), deviceName) require.NoError(t, err) require.IsType(t, dtoCommon.BaseResponse{}, res) @@ -63,7 +63,7 @@ func TestQueryDeviceByName(t *testing.T) { path := path.Join(common.ApiDeviceRoute, common.Name, deviceName) ts := newTestServer(http.MethodGet, path, responses.DeviceResponse{}) defer ts.Close() - client := NewDeviceClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeviceByName(context.Background(), deviceName) require.NoError(t, err) require.IsType(t, responses.DeviceResponse{}, res) @@ -74,7 +74,7 @@ func TestDeleteDeviceByName(t *testing.T) { path := path.Join(common.ApiDeviceRoute, common.Name, deviceName) ts := newTestServer(http.MethodDelete, path, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewDeviceClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeleteDeviceByName(context.Background(), deviceName) require.NoError(t, err) require.IsType(t, dtoCommon.BaseResponse{}, res) @@ -85,7 +85,7 @@ func TestQueryDevicesByProfileName(t *testing.T) { urlPath := path.Join(common.ApiDeviceRoute, common.Profile, common.Name, profileName) ts := newTestServer(http.MethodGet, urlPath, responses.MultiDevicesResponse{}) defer ts.Close() - client := NewDeviceClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DevicesByProfileName(context.Background(), profileName, 1, 10) require.NoError(t, err) require.IsType(t, responses.MultiDevicesResponse{}, res) @@ -96,7 +96,7 @@ func TestQueryDevicesByServiceName(t *testing.T) { urlPath := path.Join(common.ApiDeviceRoute, common.Service, common.Name, serviceName) ts := newTestServer(http.MethodGet, urlPath, responses.MultiDevicesResponse{}) defer ts.Close() - client := NewDeviceClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DevicesByServiceName(context.Background(), serviceName, 1, 10) require.NoError(t, err) require.IsType(t, responses.MultiDevicesResponse{}, res) diff --git a/clients/http/deviceprofile.go b/clients/http/deviceprofile.go index 1836dfb9..d6d51f2d 100644 --- a/clients/http/deviceprofile.go +++ b/clients/http/deviceprofile.go @@ -25,18 +25,20 @@ import ( ) type DeviceProfileClient struct { - baseUrl string - authInjector interfaces.AuthenticationInjector - resourcesCache map[string]responses.DeviceResourceResponse - mux sync.RWMutex + baseUrl string + authInjector interfaces.AuthenticationInjector + resourcesCache map[string]responses.DeviceResourceResponse + mux sync.RWMutex + enableNameFieldEscape bool } // NewDeviceProfileClient creates an instance of DeviceProfileClient -func NewDeviceProfileClient(baseUrl string, authInjector interfaces.AuthenticationInjector) interfaces.DeviceProfileClient { +func NewDeviceProfileClient(baseUrl string, authInjector interfaces.AuthenticationInjector, enableNameFieldEscape bool) interfaces.DeviceProfileClient { return &DeviceProfileClient{ - baseUrl: baseUrl, - authInjector: authInjector, - resourcesCache: make(map[string]responses.DeviceResourceResponse), + baseUrl: baseUrl, + authInjector: authInjector, + resourcesCache: make(map[string]responses.DeviceResourceResponse), + enableNameFieldEscape: enableNameFieldEscape, } } @@ -83,7 +85,8 @@ func (client *DeviceProfileClient) UpdateByYaml(ctx context.Context, yamlFilePat // DeleteByName deletes the device profile by name func (client *DeviceProfileClient) DeleteByName(ctx context.Context, name string) (dtoCommon.BaseResponse, errors.EdgeX) { var response dtoCommon.BaseResponse - requestPath := utils.EscapeAndJoinPath(common.ApiDeviceProfileRoute, common.Name, name) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiDeviceProfileRoute).SetPath(common.Name).SetNameFieldPath(name).BuildPath() err := utils.DeleteRequest(ctx, &response, client.baseUrl, requestPath, client.authInjector) if err != nil { return response, errors.NewCommonEdgeXWrapper(err) @@ -93,7 +96,8 @@ func (client *DeviceProfileClient) DeleteByName(ctx context.Context, name string // DeviceProfileByName queries the device profile by name func (client *DeviceProfileClient) DeviceProfileByName(ctx context.Context, name string) (res responses.DeviceProfileResponse, edgexError errors.EdgeX) { - requestPath := utils.EscapeAndJoinPath(common.ApiDeviceProfileRoute, common.Name, name) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiDeviceProfileRoute).SetPath(common.Name).SetNameFieldPath(name).BuildPath() err := utils.GetRequest(ctx, &res, client.baseUrl, requestPath, nil, client.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) @@ -162,7 +166,8 @@ func (client *DeviceProfileClient) DeviceResourceByProfileNameAndResourceName(ct if exists { return res, nil } - requestPath := utils.EscapeAndJoinPath(common.ApiDeviceResourceRoute, common.Profile, profileName, common.Resource, resourceName) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiDeviceResourceRoute).SetPath(common.Profile).SetNameFieldPath(profileName).SetPath(common.Resource).SetNameFieldPath(resourceName).BuildPath() err := utils.GetRequest(ctx, &res, client.baseUrl, requestPath, nil, client.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) @@ -223,7 +228,8 @@ func (client *DeviceProfileClient) UpdateDeviceProfileResource(ctx context.Conte // DeleteDeviceResourceByName deletes device resource by name func (client *DeviceProfileClient) DeleteDeviceResourceByName(ctx context.Context, profileName string, resourceName string) (dtoCommon.BaseResponse, errors.EdgeX) { var response dtoCommon.BaseResponse - requestPath := utils.EscapeAndJoinPath(common.ApiDeviceProfileRoute, common.Name, profileName, common.Resource, resourceName) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiDeviceProfileRoute).SetPath(common.Name).SetNameFieldPath(profileName).SetPath(common.Resource).SetNameFieldPath(resourceName).BuildPath() err := utils.DeleteRequest(ctx, &response, client.baseUrl, requestPath, client.authInjector) if err != nil { return response, errors.NewCommonEdgeXWrapper(err) @@ -254,7 +260,8 @@ func (client *DeviceProfileClient) UpdateDeviceProfileDeviceCommand(ctx context. // DeleteDeviceCommandByName deletes device command by name func (client *DeviceProfileClient) DeleteDeviceCommandByName(ctx context.Context, profileName string, commandName string) (dtoCommon.BaseResponse, errors.EdgeX) { var response dtoCommon.BaseResponse - requestPath := utils.EscapeAndJoinPath(common.ApiDeviceProfileRoute, common.Name, profileName, common.DeviceCommand, commandName) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiDeviceProfileRoute).SetPath(common.Name).SetNameFieldPath(profileName).SetPath(common.DeviceCommand).SetNameFieldPath(commandName).BuildPath() err := utils.DeleteRequest(ctx, &response, client.baseUrl, requestPath, client.authInjector) if err != nil { return response, errors.NewCommonEdgeXWrapper(err) diff --git a/clients/http/deviceprofile_test.go b/clients/http/deviceprofile_test.go index 99e75ee3..feeaa090 100644 --- a/clients/http/deviceprofile_test.go +++ b/clients/http/deviceprofile_test.go @@ -49,7 +49,7 @@ func TestAddDeviceProfiles(t *testing.T) { })) defer ts.Close() - client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.Add(context.Background(), []requests.DeviceProfileRequest{}) require.NoError(t, err) require.NotNil(t, res) @@ -76,7 +76,7 @@ func TestPutDeviceProfiles(t *testing.T) { })) defer ts.Close() - client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.Update(context.Background(), []requests.DeviceProfileRequest{}) require.NoError(t, err) require.NotNil(t, res) @@ -102,7 +102,7 @@ func TestAddDeviceProfileByYaml(t *testing.T) { _, _ = w.Write(res) })) defer ts.Close() - client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector(), false) _, b, _, _ := runtime.Caller(0) tests := []struct { @@ -147,7 +147,7 @@ func TestUpdateDeviceProfileByYaml(t *testing.T) { _, _ = w.Write(res) })) defer ts.Close() - client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector(), false) _, b, _, _ := runtime.Caller(0) tests := []struct { @@ -179,7 +179,7 @@ func TestDeleteDeviceProfileByName(t *testing.T) { ts := newTestServer(http.MethodDelete, urlPath, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeleteByName(context.Background(), testName) require.NoError(t, err) require.NotNil(t, res) @@ -190,7 +190,7 @@ func TestQueryDeviceProfileByName(t *testing.T) { urlPath := path.Join(common.ApiDeviceProfileRoute, common.Name, testName) ts := newTestServer(http.MethodGet, urlPath, responses.DeviceProfileResponse{}) defer ts.Close() - client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector(), false) _, err := client.DeviceProfileByName(context.Background(), testName) require.NoError(t, err) } @@ -198,7 +198,7 @@ func TestQueryDeviceProfileByName(t *testing.T) { func TestQueryAllDeviceProfiles(t *testing.T) { ts := newTestServer(http.MethodGet, common.ApiAllDeviceProfileRoute, responses.MultiDeviceProfilesResponse{}) defer ts.Close() - client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector(), false) _, err := client.AllDeviceProfiles(context.Background(), []string{"testLabel1", "testLabel2"}, 1, 10) require.NoError(t, err) } @@ -208,7 +208,7 @@ func TestQueryDeviceProfilesByModel(t *testing.T) { urlPath := path.Join(common.ApiDeviceProfileRoute, common.Model, testModel) ts := newTestServer(http.MethodGet, urlPath, responses.MultiDeviceProfilesResponse{}) defer ts.Close() - client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector(), false) _, err := client.DeviceProfilesByModel(context.Background(), testModel, 1, 10) require.NoError(t, err) } @@ -218,7 +218,7 @@ func TestQueryDeviceProfilesByManufacturer(t *testing.T) { urlPath := path.Join(common.ApiDeviceProfileRoute, common.Manufacturer, testManufacturer) ts := newTestServer(http.MethodGet, urlPath, responses.MultiDeviceProfilesResponse{}) defer ts.Close() - client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector(), false) _, err := client.DeviceProfilesByManufacturer(context.Background(), testManufacturer, 1, 10) require.NoError(t, err) } @@ -229,7 +229,7 @@ func TestQueryDeviceProfilesByManufacturerAndModel(t *testing.T) { urlPath := path.Join(common.ApiDeviceProfileRoute, common.Manufacturer, testManufacturer, common.Model, testModel) ts := newTestServer(http.MethodGet, urlPath, responses.MultiDeviceProfilesResponse{}) defer ts.Close() - client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector(), false) _, err := client.DeviceProfilesByManufacturerAndModel(context.Background(), testManufacturer, testModel, 1, 10) require.NoError(t, err) } @@ -240,7 +240,7 @@ func TestDeviceResourceByProfileNameAndResourceName(t *testing.T) { urlPath := path.Join(common.ApiDeviceResourceRoute, common.Profile, profileName, common.Resource, resourceName) ts := newTestServer(http.MethodGet, urlPath, responses.DeviceResourceResponse{}) defer ts.Close() - client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeviceResourceByProfileNameAndResourceName(context.Background(), profileName, resourceName) @@ -252,7 +252,7 @@ func TestUpdateDeviceProfileBasicInfo(t *testing.T) { ts := newTestServer(http.MethodPatch, common.ApiDeviceProfileBasicInfoRoute, []dtoCommon.BaseResponse{}) defer ts.Close() - client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.UpdateDeviceProfileBasicInfo(context.Background(), []requests.DeviceProfileBasicInfoRequest{}) require.NoError(t, err) require.IsType(t, []dtoCommon.BaseResponse{}, res) @@ -262,7 +262,7 @@ func TestAddDeviceProfileResource(t *testing.T) { ts := newTestServer(http.MethodPost, common.ApiDeviceProfileResourceRoute, []dtoCommon.BaseResponse{}) defer ts.Close() - client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.AddDeviceProfileResource(context.Background(), []requests.AddDeviceResourceRequest{}) require.NoError(t, err) @@ -273,7 +273,7 @@ func TestUpdateDeviceProfileResource(t *testing.T) { ts := newTestServer(http.MethodPatch, common.ApiDeviceProfileResourceRoute, []dtoCommon.BaseResponse{}) defer ts.Close() - client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.UpdateDeviceProfileResource(context.Background(), []requests.UpdateDeviceResourceRequest{}) require.NoError(t, err) require.IsType(t, []dtoCommon.BaseResponse{}, res) @@ -286,7 +286,7 @@ func TestDeleteDeviceResourceByName(t *testing.T) { ts := newTestServer(http.MethodDelete, urlPath, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeleteDeviceResourceByName(context.Background(), profileName, resourceName) require.NoError(t, err) require.NotNil(t, res) @@ -296,7 +296,7 @@ func TestAddDeviceProfileDeviceCommand(t *testing.T) { ts := newTestServer(http.MethodPost, common.ApiDeviceProfileDeviceCommandRoute, []dtoCommon.BaseResponse{}) defer ts.Close() - client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.AddDeviceProfileDeviceCommand(context.Background(), []requests.AddDeviceCommandRequest{}) require.NoError(t, err) @@ -307,7 +307,7 @@ func TestUpdateDeviceProfileDeviceCommand(t *testing.T) { ts := newTestServer(http.MethodPatch, common.ApiDeviceProfileDeviceCommandRoute, []dtoCommon.BaseResponse{}) defer ts.Close() - client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.UpdateDeviceProfileDeviceCommand(context.Background(), []requests.UpdateDeviceCommandRequest{}) require.NoError(t, err) require.IsType(t, []dtoCommon.BaseResponse{}, res) @@ -320,7 +320,7 @@ func TestDeleteDeviceCommandByName(t *testing.T) { ts := newTestServer(http.MethodDelete, urlPath, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceProfileClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeleteDeviceCommandByName(context.Background(), profileName, commandName) require.NoError(t, err) require.NotNil(t, res) diff --git a/clients/http/deviceservice.go b/clients/http/deviceservice.go index 2b003212..b646b21b 100644 --- a/clients/http/deviceservice.go +++ b/clients/http/deviceservice.go @@ -22,15 +22,17 @@ import ( ) type DeviceServiceClient struct { - baseUrl string - authInjector interfaces.AuthenticationInjector + baseUrl string + authInjector interfaces.AuthenticationInjector + enableNameFieldEscape bool } // NewDeviceServiceClient creates an instance of DeviceServiceClient -func NewDeviceServiceClient(baseUrl string, authInjector interfaces.AuthenticationInjector) interfaces.DeviceServiceClient { +func NewDeviceServiceClient(baseUrl string, authInjector interfaces.AuthenticationInjector, enableNameFieldEscape bool) interfaces.DeviceServiceClient { return &DeviceServiceClient{ - baseUrl: baseUrl, - authInjector: authInjector, + baseUrl: baseUrl, + authInjector: authInjector, + enableNameFieldEscape: enableNameFieldEscape, } } @@ -69,7 +71,8 @@ func (dsc DeviceServiceClient) AllDeviceServices(ctx context.Context, labels []s func (dsc DeviceServiceClient) DeviceServiceByName(ctx context.Context, name string) ( res responses.DeviceServiceResponse, err errors.EdgeX) { - path := utils.EscapeAndJoinPath(common.ApiDeviceServiceRoute, common.Name, name) + path := common.NewPathBuilder().EnableNameFieldEscape(dsc.enableNameFieldEscape). + SetPath(common.ApiDeviceServiceRoute).SetPath(common.Name).SetNameFieldPath(name).BuildPath() err = utils.GetRequest(ctx, &res, dsc.baseUrl, path, nil, dsc.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) @@ -79,7 +82,8 @@ func (dsc DeviceServiceClient) DeviceServiceByName(ctx context.Context, name str func (dsc DeviceServiceClient) DeleteByName(ctx context.Context, name string) ( res dtoCommon.BaseResponse, err errors.EdgeX) { - path := utils.EscapeAndJoinPath(common.ApiDeviceServiceRoute, common.Name, name) + path := common.NewPathBuilder().EnableNameFieldEscape(dsc.enableNameFieldEscape). + SetPath(common.ApiDeviceServiceRoute).SetPath(common.Name).SetNameFieldPath(name).BuildPath() err = utils.DeleteRequest(ctx, &res, dsc.baseUrl, path, dsc.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) diff --git a/clients/http/deviceservice_test.go b/clients/http/deviceservice_test.go index aba7d5bf..c240fe00 100644 --- a/clients/http/deviceservice_test.go +++ b/clients/http/deviceservice_test.go @@ -25,7 +25,7 @@ func TestAddDeviceServices(t *testing.T) { ts := newTestServer(http.MethodPost, common.ApiDeviceServiceRoute, []dtoCommon.BaseWithIdResponse{}) defer ts.Close() - client := NewDeviceServiceClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceServiceClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.Add(context.Background(), []requests.AddDeviceServiceRequest{}) require.NoError(t, err) @@ -36,7 +36,7 @@ func TestPatchDeviceServices(t *testing.T) { ts := newTestServer(http.MethodPatch, common.ApiDeviceServiceRoute, []dtoCommon.BaseResponse{}) defer ts.Close() - client := NewDeviceServiceClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceServiceClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.Update(context.Background(), []requests.UpdateDeviceServiceRequest{}) require.NoError(t, err) assert.IsType(t, []dtoCommon.BaseResponse{}, res) @@ -46,7 +46,7 @@ func TestQueryAllDeviceServices(t *testing.T) { ts := newTestServer(http.MethodGet, common.ApiAllDeviceServiceRoute, responses.MultiDeviceServicesResponse{}) defer ts.Close() - client := NewDeviceServiceClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceServiceClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.AllDeviceServices(context.Background(), []string{"label1", "label2"}, 1, 10) require.NoError(t, err) assert.IsType(t, responses.MultiDeviceServicesResponse{}, res) @@ -59,7 +59,7 @@ func TestQueryDeviceServiceByName(t *testing.T) { ts := newTestServer(http.MethodGet, path, responses.DeviceResponse{}) defer ts.Close() - client := NewDeviceServiceClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceServiceClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeviceServiceByName(context.Background(), deviceServiceName) require.NoError(t, err) assert.IsType(t, responses.DeviceServiceResponse{}, res) @@ -72,7 +72,7 @@ func TestDeleteDeviceServiceByName(t *testing.T) { ts := newTestServer(http.MethodDelete, path, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewDeviceServiceClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceServiceClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeleteByName(context.Background(), deviceServiceName) require.NoError(t, err) assert.IsType(t, dtoCommon.BaseResponse{}, res) diff --git a/clients/http/deviceservicecallback.go b/clients/http/deviceservicecallback.go index c7d419cd..9d2e18f5 100644 --- a/clients/http/deviceservicecallback.go +++ b/clients/http/deviceservicecallback.go @@ -19,15 +19,17 @@ import ( ) type deviceServiceCallbackClient struct { - baseUrl string - authInjector interfaces.AuthenticationInjector + baseUrl string + authInjector interfaces.AuthenticationInjector + enableNameFieldEscape bool } // NewDeviceServiceCallbackClient creates an instance of deviceServiceCallbackClient -func NewDeviceServiceCallbackClient(baseUrl string, authInjector interfaces.AuthenticationInjector) interfaces.DeviceServiceCallbackClient { +func NewDeviceServiceCallbackClient(baseUrl string, authInjector interfaces.AuthenticationInjector, enableNameFieldEscape bool) interfaces.DeviceServiceCallbackClient { return &deviceServiceCallbackClient{ - baseUrl: baseUrl, - authInjector: authInjector, + baseUrl: baseUrl, + authInjector: authInjector, + enableNameFieldEscape: enableNameFieldEscape, } } @@ -97,7 +99,8 @@ func (client *deviceServiceCallbackClient) UpdateProvisionWatcherCallback(ctx co func (client *deviceServiceCallbackClient) DeleteProvisionWatcherCallback(ctx context.Context, name string) (dtoCommon.BaseResponse, errors.EdgeX) { var response dtoCommon.BaseResponse - requestPath := utils.EscapeAndJoinPath(common.ApiWatcherCallbackRoute, common.Name, name) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiWatcherCallbackRoute).SetPath(common.Name).SetNameFieldPath(name).BuildPath() err := utils.DeleteRequest(ctx, &response, client.baseUrl, requestPath, client.authInjector) if err != nil { return response, errors.NewCommonEdgeXWrapper(err) diff --git a/clients/http/deviceservicecallback_test.go b/clients/http/deviceservicecallback_test.go index b704101d..66c6e8c7 100644 --- a/clients/http/deviceservicecallback_test.go +++ b/clients/http/deviceservicecallback_test.go @@ -27,7 +27,7 @@ func TestAddDeviceCallback(t *testing.T) { ts := newTestServer(http.MethodPost, common.ApiDeviceCallbackRoute, expectedResponse) defer ts.Close() - client := NewDeviceServiceCallbackClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceServiceCallbackClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.AddDeviceCallback(context.Background(), requests.AddDeviceRequest{}) require.NoError(t, err) @@ -40,7 +40,7 @@ func TestValidateDeviceCallback(t *testing.T) { ts := newTestServer(http.MethodPost, common.ApiDeviceValidationRoute, expectedResponse) defer ts.Close() - client := NewDeviceServiceCallbackClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceServiceCallbackClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.ValidateDeviceCallback(context.Background(), requests.AddDeviceRequest{}) require.NoError(t, err) @@ -53,7 +53,7 @@ func TestUpdateDeviceCallback(t *testing.T) { ts := newTestServer(http.MethodPut, common.ApiDeviceCallbackRoute, expectedResponse) defer ts.Close() - client := NewDeviceServiceCallbackClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceServiceCallbackClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.UpdateDeviceCallback(context.Background(), requests.UpdateDeviceRequest{}) require.NoError(t, err) @@ -68,7 +68,7 @@ func TestDeleteDeviceCallback(t *testing.T) { ts := newTestServer(http.MethodDelete, urlPath, expectedResponse) defer ts.Close() - client := NewDeviceServiceCallbackClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceServiceCallbackClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeleteDeviceCallback(context.Background(), testDeviceName) require.NoError(t, err) @@ -81,7 +81,7 @@ func TestUpdateDeviceProfileCallback(t *testing.T) { ts := newTestServer(http.MethodPut, common.ApiProfileCallbackRoute, expectedResponse) defer ts.Close() - client := NewDeviceServiceCallbackClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceServiceCallbackClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.UpdateDeviceProfileCallback(context.Background(), requests.DeviceProfileRequest{}) require.NoError(t, err) @@ -94,7 +94,7 @@ func TestAddProvisionWatcherCallback(t *testing.T) { ts := newTestServer(http.MethodPost, common.ApiWatcherCallbackRoute, expectedResponse) defer ts.Close() - client := NewDeviceServiceCallbackClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceServiceCallbackClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.AddProvisionWatcherCallback(context.Background(), requests.AddProvisionWatcherRequest{}) require.NoError(t, err) @@ -107,7 +107,7 @@ func TestUpdateProvisionWatcherCallback(t *testing.T) { ts := newTestServer(http.MethodPut, common.ApiWatcherCallbackRoute, expectedResponse) defer ts.Close() - client := NewDeviceServiceCallbackClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceServiceCallbackClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.UpdateProvisionWatcherCallback(context.Background(), requests.UpdateProvisionWatcherRequest{}) require.NoError(t, err) @@ -122,7 +122,7 @@ func TestDeleteProvisionWatcherCallback(t *testing.T) { ts := newTestServer(http.MethodDelete, urlPath, expectedResponse) defer ts.Close() - client := NewDeviceServiceCallbackClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceServiceCallbackClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeleteProvisionWatcherCallback(context.Background(), testWatcherName) require.NoError(t, err) @@ -135,7 +135,7 @@ func TestUpdateDeviceServiceCallback(t *testing.T) { ts := newTestServer(http.MethodPut, common.ApiServiceCallbackRoute, expectedResponse) defer ts.Close() - client := NewDeviceServiceCallbackClient(ts.URL, NewNullAuthenticationInjector()) + client := NewDeviceServiceCallbackClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.UpdateDeviceServiceCallback(context.Background(), requests.UpdateDeviceServiceRequest{}) require.NoError(t, err) diff --git a/clients/http/deviceservicecommand.go b/clients/http/deviceservicecommand.go index 48acc002..3bca341e 100644 --- a/clients/http/deviceservicecommand.go +++ b/clients/http/deviceservicecommand.go @@ -22,19 +22,22 @@ import ( ) type deviceServiceCommandClient struct { - authInjector interfaces.AuthenticationInjector + authInjector interfaces.AuthenticationInjector + enableNameFieldEscape bool } // NewDeviceServiceCommandClient creates an instance of deviceServiceCommandClient -func NewDeviceServiceCommandClient(authInjector interfaces.AuthenticationInjector) interfaces.DeviceServiceCommandClient { +func NewDeviceServiceCommandClient(authInjector interfaces.AuthenticationInjector, enableNameFieldEscape bool) interfaces.DeviceServiceCommandClient { return &deviceServiceCommandClient{ - authInjector: authInjector, + authInjector: authInjector, + enableNameFieldEscape: enableNameFieldEscape, } } // GetCommand sends HTTP request to execute the Get command func (client *deviceServiceCommandClient) GetCommand(ctx context.Context, baseUrl string, deviceName string, commandName string, queryParams string) (*responses.EventResponse, errors.EdgeX) { - requestPath := utils.EscapeAndJoinPath(common.ApiDeviceRoute, common.Name, deviceName, commandName) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiDeviceRoute).SetPath(common.Name).SetNameFieldPath(deviceName).SetNameFieldPath(commandName).BuildPath() params, err := url.ParseQuery(queryParams) if err != nil { return nil, errors.NewCommonEdgeXWrapper(err) @@ -64,7 +67,8 @@ func (client *deviceServiceCommandClient) GetCommand(ctx context.Context, baseUr // SetCommand sends HTTP request to execute the Set command func (client *deviceServiceCommandClient) SetCommand(ctx context.Context, baseUrl string, deviceName string, commandName string, queryParams string, settings map[string]string) (dtoCommon.BaseResponse, errors.EdgeX) { var response dtoCommon.BaseResponse - requestPath := utils.EscapeAndJoinPath(common.ApiDeviceRoute, common.Name, deviceName, commandName) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiDeviceRoute).SetPath(common.Name).SetNameFieldPath(deviceName).SetNameFieldPath(commandName).BuildPath() params, err := url.ParseQuery(queryParams) if err != nil { return response, errors.NewCommonEdgeXWrapper(err) @@ -79,7 +83,8 @@ func (client *deviceServiceCommandClient) SetCommand(ctx context.Context, baseUr // SetCommandWithObject invokes device service's set command API and the settings supports object value type func (client *deviceServiceCommandClient) SetCommandWithObject(ctx context.Context, baseUrl string, deviceName string, commandName string, queryParams string, settings map[string]interface{}) (dtoCommon.BaseResponse, errors.EdgeX) { var response dtoCommon.BaseResponse - requestPath := utils.EscapeAndJoinPath(common.ApiDeviceRoute, common.Name, deviceName, commandName) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiDeviceRoute).SetPath(common.Name).SetNameFieldPath(deviceName).SetNameFieldPath(commandName).BuildPath() params, err := url.ParseQuery(queryParams) if err != nil { return response, errors.NewCommonEdgeXWrapper(err) diff --git a/clients/http/deviceservicecommand_test.go b/clients/http/deviceservicecommand_test.go index 437ba30f..40287efe 100644 --- a/clients/http/deviceservicecommand_test.go +++ b/clients/http/deviceservicecommand_test.go @@ -48,7 +48,7 @@ func TestGetCommand(t *testing.T) { ts := newTestServer(http.MethodGet, common.ApiDeviceRoute+"/"+common.Name+"/"+TestDeviceName+"/"+TestCommandName, expectedResponse) defer ts.Close() - client := NewDeviceServiceCommandClient(NewNullAuthenticationInjector()) + client := NewDeviceServiceCommandClient(NewNullAuthenticationInjector(), false) res, err := client.GetCommand(context.Background(), ts.URL, TestDeviceName, TestCommandName, "") require.NoError(t, err) @@ -61,7 +61,7 @@ func TestSetCommand(t *testing.T) { ts := newTestServer(http.MethodPut, common.ApiDeviceRoute+"/"+common.Name+"/"+TestDeviceName+"/"+TestCommandName, expectedResponse) defer ts.Close() - client := NewDeviceServiceCommandClient(NewNullAuthenticationInjector()) + client := NewDeviceServiceCommandClient(NewNullAuthenticationInjector(), false) res, err := client.SetCommand(context.Background(), ts.URL, TestDeviceName, TestCommandName, "", nil) require.NoError(t, err) @@ -80,7 +80,7 @@ func TestSetCommandWithObject(t *testing.T) { }, } - client := NewDeviceServiceCommandClient(NewNullAuthenticationInjector()) + client := NewDeviceServiceCommandClient(NewNullAuthenticationInjector(), false) res, err := client.SetCommandWithObject(context.Background(), ts.URL, TestDeviceName, TestCommandName, "", settings) require.NoError(t, err) diff --git a/clients/http/event.go b/clients/http/event.go index 36b18a33..43626df5 100644 --- a/clients/http/event.go +++ b/clients/http/event.go @@ -22,21 +22,24 @@ import ( ) type eventClient struct { - baseUrl string - authInjector interfaces.AuthenticationInjector + baseUrl string + authInjector interfaces.AuthenticationInjector + enableNameFieldEscape bool } // NewEventClient creates an instance of EventClient -func NewEventClient(baseUrl string, authInjector interfaces.AuthenticationInjector) interfaces.EventClient { +func NewEventClient(baseUrl string, authInjector interfaces.AuthenticationInjector, enableNameFieldEscape bool) interfaces.EventClient { return &eventClient{ - baseUrl: baseUrl, - authInjector: authInjector, + baseUrl: baseUrl, + authInjector: authInjector, + enableNameFieldEscape: enableNameFieldEscape, } } func (ec *eventClient) Add(ctx context.Context, serviceName string, req requests.AddEventRequest) ( dtoCommon.BaseWithIdResponse, errors.EdgeX) { - path := utils.EscapeAndJoinPath(common.ApiEventRoute, serviceName, req.Event.ProfileName, req.Event.DeviceName, req.Event.SourceName) + path := common.NewPathBuilder().EnableNameFieldEscape(ec.enableNameFieldEscape). + SetPath(common.ApiEventRoute).SetNameFieldPath(serviceName).SetNameFieldPath(req.Event.ProfileName).SetNameFieldPath(req.Event.DeviceName).SetNameFieldPath(req.Event.SourceName).BuildPath() var br dtoCommon.BaseWithIdResponse bytes, encoding, err := req.Encode() diff --git a/clients/http/event_test.go b/clients/http/event_test.go index f38c8dde..5740d8f7 100644 --- a/clients/http/event_test.go +++ b/clients/http/event_test.go @@ -25,12 +25,12 @@ import ( func TestAddEvent(t *testing.T) { serviceName := "serviceName" - event := dtos.Event{ProfileName: "profileName", DeviceName: "deviceName"} + event := dtos.Event{ProfileName: "profileName", DeviceName: "deviceName", SourceName: "sourceName"} apiRoute := path.Join(common.ApiEventRoute, serviceName, event.ProfileName, event.DeviceName, event.SourceName) ts := newTestServer(http.MethodPost, apiRoute, dtoCommon.BaseWithIdResponse{}) defer ts.Close() - client := NewEventClient(ts.URL, NewNullAuthenticationInjector()) + client := NewEventClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.Add(context.Background(), serviceName, requests.AddEventRequest{Event: event}) require.NoError(t, err) assert.IsType(t, dtoCommon.BaseWithIdResponse{}, res) @@ -40,7 +40,7 @@ func TestQueryAllEvents(t *testing.T) { ts := newTestServer(http.MethodGet, common.ApiAllEventRoute, responses.MultiEventsResponse{}) defer ts.Close() - client := NewEventClient(ts.URL, NewNullAuthenticationInjector()) + client := NewEventClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.AllEvents(context.Background(), 1, 10) require.NoError(t, err) assert.IsType(t, responses.MultiEventsResponse{}, res) @@ -50,7 +50,7 @@ func TestQueryEventCount(t *testing.T) { ts := newTestServer(http.MethodGet, common.ApiEventCountRoute, dtoCommon.CountResponse{}) defer ts.Close() - client := NewEventClient(ts.URL, NewNullAuthenticationInjector()) + client := NewEventClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.EventCount(context.Background()) require.NoError(t, err) assert.IsType(t, dtoCommon.CountResponse{}, res) @@ -62,7 +62,7 @@ func TestQueryEventCountByDeviceName(t *testing.T) { ts := newTestServer(http.MethodGet, path, dtoCommon.CountResponse{}) defer ts.Close() - client := NewEventClient(ts.URL, NewNullAuthenticationInjector()) + client := NewEventClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.EventCountByDeviceName(context.Background(), deviceName) require.NoError(t, err) require.IsType(t, dtoCommon.CountResponse{}, res) @@ -74,7 +74,7 @@ func TestQueryEventsByDeviceName(t *testing.T) { ts := newTestServer(http.MethodGet, urlPath, responses.MultiEventsResponse{}) defer ts.Close() - client := NewEventClient(ts.URL, NewNullAuthenticationInjector()) + client := NewEventClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.EventsByDeviceName(context.Background(), deviceName, 1, 10) require.NoError(t, err) assert.IsType(t, responses.MultiEventsResponse{}, res) @@ -86,7 +86,7 @@ func TestDeleteEventsByDeviceName(t *testing.T) { ts := newTestServer(http.MethodDelete, path, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewEventClient(ts.URL, NewNullAuthenticationInjector()) + client := NewEventClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeleteByDeviceName(context.Background(), deviceName) require.NoError(t, err) assert.IsType(t, dtoCommon.BaseResponse{}, res) @@ -99,7 +99,7 @@ func TestQueryEventsByTimeRange(t *testing.T) { ts := newTestServer(http.MethodGet, urlPath, responses.MultiEventsResponse{}) defer ts.Close() - client := NewEventClient(ts.URL, NewNullAuthenticationInjector()) + client := NewEventClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.EventsByTimeRange(context.Background(), start, end, 1, 10) require.NoError(t, err) assert.IsType(t, responses.MultiEventsResponse{}, res) @@ -111,7 +111,7 @@ func TestDeleteEventsByAge(t *testing.T) { ts := newTestServer(http.MethodDelete, path, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewEventClient(ts.URL, NewNullAuthenticationInjector()) + client := NewEventClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeleteByAge(context.Background(), age) require.NoError(t, err) assert.IsType(t, dtoCommon.BaseResponse{}, res) diff --git a/clients/http/interval.go b/clients/http/interval.go index 2bd988d6..f4bc6097 100644 --- a/clients/http/interval.go +++ b/clients/http/interval.go @@ -21,15 +21,17 @@ import ( ) type IntervalClient struct { - baseUrl string - authInjector interfaces.AuthenticationInjector + baseUrl string + authInjector interfaces.AuthenticationInjector + enableNameFieldEscape bool } // NewIntervalClient creates an instance of IntervalClient -func NewIntervalClient(baseUrl string, authInjector interfaces.AuthenticationInjector) interfaces.IntervalClient { +func NewIntervalClient(baseUrl string, authInjector interfaces.AuthenticationInjector, enableNameFieldEscape bool) interfaces.IntervalClient { return &IntervalClient{ - baseUrl: baseUrl, - authInjector: authInjector, + baseUrl: baseUrl, + authInjector: authInjector, + enableNameFieldEscape: enableNameFieldEscape, } } @@ -69,7 +71,8 @@ func (client IntervalClient) AllIntervals(ctx context.Context, offset int, limit // IntervalByName query the interval by name func (client IntervalClient) IntervalByName(ctx context.Context, name string) ( res responses.IntervalResponse, err errors.EdgeX) { - path := utils.EscapeAndJoinPath(common.ApiIntervalRoute, common.Name, name) + path := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiIntervalRoute).SetPath(common.Name).SetNameFieldPath(name).BuildPath() err = utils.GetRequest(ctx, &res, client.baseUrl, path, nil, client.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) @@ -80,7 +83,8 @@ func (client IntervalClient) IntervalByName(ctx context.Context, name string) ( // DeleteIntervalByName delete the interval by name func (client IntervalClient) DeleteIntervalByName(ctx context.Context, name string) ( res dtoCommon.BaseResponse, err errors.EdgeX) { - path := utils.EscapeAndJoinPath(common.ApiIntervalRoute, common.Name, name) + path := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiIntervalRoute).SetPath(common.Name).SetNameFieldPath(name).BuildPath() err = utils.DeleteRequest(ctx, &res, client.baseUrl, path, client.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) diff --git a/clients/http/interval_test.go b/clients/http/interval_test.go index e9a31630..732bfcdb 100644 --- a/clients/http/interval_test.go +++ b/clients/http/interval_test.go @@ -27,7 +27,7 @@ func TestAddIntervals(t *testing.T) { defer ts.Close() dto := dtos.NewInterval(TestIntervalName, TestFrequency) request := []requests.AddIntervalRequest{requests.NewAddIntervalRequest(dto)} - client := NewIntervalClient(ts.URL, NewNullAuthenticationInjector()) + client := NewIntervalClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.Add(context.Background(), request) @@ -40,7 +40,7 @@ func TestPatchIntervals(t *testing.T) { defer ts.Close() dto := dtos.NewUpdateInterval(TestIntervalName) request := []requests.UpdateIntervalRequest{requests.NewUpdateIntervalRequest(dto)} - client := NewIntervalClient(ts.URL, NewNullAuthenticationInjector()) + client := NewIntervalClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.Update(context.Background(), request) @@ -51,7 +51,7 @@ func TestPatchIntervals(t *testing.T) { func TestQueryAllIntervals(t *testing.T) { ts := newTestServer(http.MethodGet, common.ApiAllIntervalRoute, responses.MultiIntervalsResponse{}) defer ts.Close() - client := NewIntervalClient(ts.URL, NewNullAuthenticationInjector()) + client := NewIntervalClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.AllIntervals(context.Background(), 0, 10) @@ -64,7 +64,7 @@ func TestQueryIntervalByName(t *testing.T) { ts := newTestServer(http.MethodGet, path, responses.DeviceResponse{}) defer ts.Close() - client := NewIntervalClient(ts.URL, NewNullAuthenticationInjector()) + client := NewIntervalClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.IntervalByName(context.Background(), TestIntervalName) require.NoError(t, err) @@ -75,7 +75,7 @@ func TestDeleteIntervalByName(t *testing.T) { path := path.Join(common.ApiIntervalRoute, common.Name, TestIntervalName) ts := newTestServer(http.MethodDelete, path, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewIntervalClient(ts.URL, NewNullAuthenticationInjector()) + client := NewIntervalClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeleteIntervalByName(context.Background(), TestIntervalName) diff --git a/clients/http/intervalaction.go b/clients/http/intervalaction.go index 9c037769..9a28ec4e 100644 --- a/clients/http/intervalaction.go +++ b/clients/http/intervalaction.go @@ -21,15 +21,17 @@ import ( ) type IntervalActionClient struct { - baseUrl string - authInjector interfaces.AuthenticationInjector + baseUrl string + authInjector interfaces.AuthenticationInjector + enableNameFieldEscape bool } // NewIntervalActionClient creates an instance of IntervalActionClient -func NewIntervalActionClient(baseUrl string, authInjector interfaces.AuthenticationInjector) interfaces.IntervalActionClient { +func NewIntervalActionClient(baseUrl string, authInjector interfaces.AuthenticationInjector, enableNameFieldEscape bool) interfaces.IntervalActionClient { return &IntervalActionClient{ - baseUrl: baseUrl, - authInjector: authInjector, + baseUrl: baseUrl, + authInjector: authInjector, + enableNameFieldEscape: enableNameFieldEscape, } } @@ -69,7 +71,8 @@ func (client IntervalActionClient) AllIntervalActions(ctx context.Context, offse // IntervalActionByName query the intervalAction by name func (client IntervalActionClient) IntervalActionByName(ctx context.Context, name string) ( res responses.IntervalActionResponse, err errors.EdgeX) { - path := utils.EscapeAndJoinPath(common.ApiIntervalActionRoute, common.Name, name) + path := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiIntervalActionRoute).SetPath(common.Name).SetNameFieldPath(name).BuildPath() err = utils.GetRequest(ctx, &res, client.baseUrl, path, nil, client.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) @@ -80,7 +83,8 @@ func (client IntervalActionClient) IntervalActionByName(ctx context.Context, nam // DeleteIntervalActionByName delete the intervalAction by name func (client IntervalActionClient) DeleteIntervalActionByName(ctx context.Context, name string) ( res dtoCommon.BaseResponse, err errors.EdgeX) { - path := utils.EscapeAndJoinPath(common.ApiIntervalActionRoute, common.Name, name) + path := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiIntervalActionRoute).SetPath(common.Name).SetNameFieldPath(name).BuildPath() err = utils.DeleteRequest(ctx, &res, client.baseUrl, path, client.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) diff --git a/clients/http/intervalaction_test.go b/clients/http/intervalaction_test.go index 5de4bc44..52afe8bd 100644 --- a/clients/http/intervalaction_test.go +++ b/clients/http/intervalaction_test.go @@ -27,7 +27,7 @@ func TestAddIntervalActions(t *testing.T) { defer ts.Close() dto := dtos.NewIntervalAction(TestIntervalActionName, TestIntervalName, dtos.NewRESTAddress(TestHost, TestPort, TestHTTPMethod)) request := []requests.AddIntervalActionRequest{requests.NewAddIntervalActionRequest(dto)} - client := NewIntervalActionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewIntervalActionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.Add(context.Background(), request) @@ -40,7 +40,7 @@ func TestPatchIntervalActions(t *testing.T) { defer ts.Close() dto := dtos.NewUpdateIntervalAction(TestIntervalActionName) request := []requests.UpdateIntervalActionRequest{requests.NewUpdateIntervalActionRequest(dto)} - client := NewIntervalActionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewIntervalActionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.Update(context.Background(), request) @@ -51,7 +51,7 @@ func TestPatchIntervalActions(t *testing.T) { func TestQueryAllIntervalActions(t *testing.T) { ts := newTestServer(http.MethodGet, common.ApiAllIntervalActionRoute, responses.MultiIntervalActionsResponse{}) defer ts.Close() - client := NewIntervalActionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewIntervalActionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.AllIntervalActions(context.Background(), 0, 10) @@ -63,7 +63,7 @@ func TestQueryIntervalActionByName(t *testing.T) { path := path.Join(common.ApiIntervalActionRoute, common.Name, TestIntervalActionName) ts := newTestServer(http.MethodGet, path, responses.DeviceResponse{}) defer ts.Close() - client := NewIntervalActionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewIntervalActionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.IntervalActionByName(context.Background(), TestIntervalActionName) @@ -75,7 +75,7 @@ func TestDeleteIntervalActionByName(t *testing.T) { path := path.Join(common.ApiIntervalActionRoute, common.Name, TestIntervalActionName) ts := newTestServer(http.MethodDelete, path, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewIntervalActionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewIntervalActionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeleteIntervalActionByName(context.Background(), TestIntervalActionName) diff --git a/clients/http/notification.go b/clients/http/notification.go index c4752cea..26cac607 100644 --- a/clients/http/notification.go +++ b/clients/http/notification.go @@ -22,15 +22,17 @@ import ( ) type NotificationClient struct { - baseUrl string - authInjector interfaces.AuthenticationInjector + baseUrl string + authInjector interfaces.AuthenticationInjector + enableNameFieldEscape bool } // NewNotificationClient creates an instance of NotificationClient -func NewNotificationClient(baseUrl string, authInjector interfaces.AuthenticationInjector) interfaces.NotificationClient { +func NewNotificationClient(baseUrl string, authInjector interfaces.AuthenticationInjector, enableNameFieldEscape bool) interfaces.NotificationClient { return &NotificationClient{ - baseUrl: baseUrl, - authInjector: authInjector, + baseUrl: baseUrl, + authInjector: authInjector, + enableNameFieldEscape: enableNameFieldEscape, } } diff --git a/clients/http/notification_test.go b/clients/http/notification_test.go index f8f7e234..7f961c22 100644 --- a/clients/http/notification_test.go +++ b/clients/http/notification_test.go @@ -38,7 +38,7 @@ func addNotificationRequest() requests.AddNotificationRequest { func TestNotificationClient_SendNotification(t *testing.T) { ts := newTestServer(http.MethodPost, common.ApiNotificationRoute, []dtoCommon.BaseWithIdResponse{}) defer ts.Close() - client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector()) + client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.SendNotification(context.Background(), []requests.AddNotificationRequest{addNotificationRequest()}) require.NoError(t, err) require.IsType(t, []dtoCommon.BaseWithIdResponse{}, res) @@ -49,7 +49,7 @@ func TestNotificationClient_NotificationById(t *testing.T) { path := path.Join(common.ApiNotificationRoute, common.Id, testId) ts := newTestServer(http.MethodGet, path, responses.NotificationResponse{}) defer ts.Close() - client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector()) + client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.NotificationById(context.Background(), testId) require.NoError(t, err) require.IsType(t, responses.NotificationResponse{}, res) @@ -60,7 +60,7 @@ func TestNotificationClient_NotificationsByCategory(t *testing.T) { urlPath := path.Join(common.ApiNotificationRoute, common.Category, category) ts := newTestServer(http.MethodGet, urlPath, responses.MultiNotificationsResponse{}) defer ts.Close() - client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector()) + client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.NotificationsByCategory(context.Background(), category, 0, 10) require.NoError(t, err) require.IsType(t, responses.MultiNotificationsResponse{}, res) @@ -71,7 +71,7 @@ func TestNotificationClient_NotificationsByLabel(t *testing.T) { urlPath := path.Join(common.ApiNotificationRoute, common.Label, label) ts := newTestServer(http.MethodGet, urlPath, responses.MultiNotificationsResponse{}) defer ts.Close() - client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector()) + client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.NotificationsByLabel(context.Background(), label, 0, 10) require.NoError(t, err) require.IsType(t, responses.MultiNotificationsResponse{}, res) @@ -82,7 +82,7 @@ func TestNotificationClient_NotificationsByStatus(t *testing.T) { urlPath := path.Join(common.ApiNotificationRoute, common.Status, status) ts := newTestServer(http.MethodGet, urlPath, responses.MultiNotificationsResponse{}) defer ts.Close() - client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector()) + client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.NotificationsByStatus(context.Background(), status, 0, 10) require.NoError(t, err) require.IsType(t, responses.MultiNotificationsResponse{}, res) @@ -93,7 +93,7 @@ func TestNotificationClient_NotificationsBySubscriptionName(t *testing.T) { urlPath := path.Join(common.ApiNotificationRoute, common.Subscription, common.Name, subscriptionName) ts := newTestServer(http.MethodGet, urlPath, responses.MultiNotificationsResponse{}) defer ts.Close() - client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector()) + client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.NotificationsBySubscriptionName(context.Background(), subscriptionName, 0, 10) require.NoError(t, err) require.IsType(t, responses.MultiNotificationsResponse{}, res) @@ -105,7 +105,7 @@ func TestNotificationClient_NotificationsByTimeRange(t *testing.T) { urlPath := path.Join(common.ApiNotificationRoute, common.Start, strconv.Itoa(start), common.End, strconv.Itoa(end)) ts := newTestServer(http.MethodGet, urlPath, responses.MultiNotificationsResponse{}) defer ts.Close() - client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector()) + client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.NotificationsByTimeRange(context.Background(), start, end, 0, 10) require.NoError(t, err) require.IsType(t, responses.MultiNotificationsResponse{}, res) @@ -114,7 +114,7 @@ func TestNotificationClient_NotificationsByTimeRange(t *testing.T) { func TestNotificationClient_CleanupNotifications(t *testing.T) { ts := newTestServer(http.MethodDelete, common.ApiNotificationCleanupRoute, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector()) + client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.CleanupNotifications(context.Background()) require.NoError(t, err) require.IsType(t, dtoCommon.BaseResponse{}, res) @@ -125,7 +125,7 @@ func TestNotificationClient_CleanupNotificationsByAge(t *testing.T) { path := path.Join(common.ApiNotificationCleanupRoute, common.Age, strconv.Itoa(age)) ts := newTestServer(http.MethodDelete, path, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector()) + client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.CleanupNotificationsByAge(context.Background(), age) require.NoError(t, err) require.IsType(t, dtoCommon.BaseResponse{}, res) @@ -136,7 +136,7 @@ func TestNotificationClient_DeleteNotificationById(t *testing.T) { path := path.Join(common.ApiNotificationRoute, common.Id, id) ts := newTestServer(http.MethodDelete, path, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector()) + client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeleteNotificationById(context.Background(), id) require.NoError(t, err) require.IsType(t, dtoCommon.BaseResponse{}, res) @@ -147,7 +147,7 @@ func TestNotificationClient_DeleteProcessedNotificationsByAge(t *testing.T) { path := path.Join(common.ApiNotificationRoute, common.Age, strconv.Itoa(age)) ts := newTestServer(http.MethodDelete, path, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector()) + client := NewNotificationClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeleteProcessedNotificationsByAge(context.Background(), age) require.NoError(t, err) require.IsType(t, dtoCommon.BaseResponse{}, res) diff --git a/clients/http/provisionwatcher.go b/clients/http/provisionwatcher.go index 9f56bde2..7cb585e1 100644 --- a/clients/http/provisionwatcher.go +++ b/clients/http/provisionwatcher.go @@ -22,15 +22,17 @@ import ( ) type ProvisionWatcherClient struct { - baseUrl string - authInjector interfaces.AuthenticationInjector + baseUrl string + authInjector interfaces.AuthenticationInjector + enableNameFieldEscape bool } // NewProvisionWatcherClient creates an instance of ProvisionWatcherClient -func NewProvisionWatcherClient(baseUrl string, authInjector interfaces.AuthenticationInjector) interfaces.ProvisionWatcherClient { +func NewProvisionWatcherClient(baseUrl string, authInjector interfaces.AuthenticationInjector, enableNameFieldEscape bool) interfaces.ProvisionWatcherClient { return &ProvisionWatcherClient{ - baseUrl: baseUrl, - authInjector: authInjector, + baseUrl: baseUrl, + authInjector: authInjector, + enableNameFieldEscape: enableNameFieldEscape, } } @@ -68,7 +70,8 @@ func (pwc ProvisionWatcherClient) AllProvisionWatchers(ctx context.Context, labe } func (pwc ProvisionWatcherClient) ProvisionWatcherByName(ctx context.Context, name string) (res responses.ProvisionWatcherResponse, err errors.EdgeX) { - path := utils.EscapeAndJoinPath(common.ApiProvisionWatcherRoute, common.Name, name) + path := common.NewPathBuilder().EnableNameFieldEscape(pwc.enableNameFieldEscape). + SetPath(common.ApiProvisionWatcherRoute).SetPath(common.Name).SetNameFieldPath(name).BuildPath() err = utils.GetRequest(ctx, &res, pwc.baseUrl, path, nil, pwc.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) @@ -78,7 +81,8 @@ func (pwc ProvisionWatcherClient) ProvisionWatcherByName(ctx context.Context, na } func (pwc ProvisionWatcherClient) DeleteProvisionWatcherByName(ctx context.Context, name string) (res dtoCommon.BaseResponse, err errors.EdgeX) { - path := utils.EscapeAndJoinPath(common.ApiProvisionWatcherRoute, common.Name, name) + path := common.NewPathBuilder().EnableNameFieldEscape(pwc.enableNameFieldEscape). + SetPath(common.ApiProvisionWatcherRoute).SetPath(common.Name).SetNameFieldPath(name).BuildPath() err = utils.DeleteRequest(ctx, &res, pwc.baseUrl, path, pwc.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) @@ -88,7 +92,8 @@ func (pwc ProvisionWatcherClient) DeleteProvisionWatcherByName(ctx context.Conte } func (pwc ProvisionWatcherClient) ProvisionWatchersByProfileName(ctx context.Context, name string, offset int, limit int) (res responses.MultiProvisionWatchersResponse, err errors.EdgeX) { - requestPath := utils.EscapeAndJoinPath(common.ApiProvisionWatcherRoute, common.Profile, common.Name, name) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(pwc.enableNameFieldEscape). + SetPath(common.ApiProvisionWatcherRoute).SetPath(common.Profile).SetPath(common.Name).SetNameFieldPath(name).BuildPath() requestParams := url.Values{} requestParams.Set(common.Offset, strconv.Itoa(offset)) requestParams.Set(common.Limit, strconv.Itoa(limit)) @@ -101,7 +106,8 @@ func (pwc ProvisionWatcherClient) ProvisionWatchersByProfileName(ctx context.Con } func (pwc ProvisionWatcherClient) ProvisionWatchersByServiceName(ctx context.Context, name string, offset int, limit int) (res responses.MultiProvisionWatchersResponse, err errors.EdgeX) { - requestPath := utils.EscapeAndJoinPath(common.ApiProvisionWatcherRoute, common.Service, common.Name, name) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(pwc.enableNameFieldEscape). + SetPath(common.ApiProvisionWatcherRoute).SetPath(common.Service).SetPath(common.Name).SetNameFieldPath(name).BuildPath() requestParams := url.Values{} requestParams.Set(common.Offset, strconv.Itoa(offset)) requestParams.Set(common.Limit, strconv.Itoa(limit)) diff --git a/clients/http/provisionwatcher_test.go b/clients/http/provisionwatcher_test.go index 26dbc2eb..0cccabd1 100644 --- a/clients/http/provisionwatcher_test.go +++ b/clients/http/provisionwatcher_test.go @@ -23,7 +23,7 @@ func TestProvisionWatcherClient_Add(t *testing.T) { ts := newTestServer(http.MethodPost, common.ApiProvisionWatcherRoute, []dtoCommon.BaseWithIdResponse{}) defer ts.Close() - client := NewProvisionWatcherClient(ts.URL, NewNullAuthenticationInjector()) + client := NewProvisionWatcherClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.Add(context.Background(), []requests.AddProvisionWatcherRequest{}) require.NoError(t, err) require.IsType(t, []dtoCommon.BaseWithIdResponse{}, res) @@ -33,7 +33,7 @@ func TestProvisionWatcherClient_Update(t *testing.T) { ts := newTestServer(http.MethodPatch, common.ApiProvisionWatcherRoute, []dtoCommon.BaseResponse{}) defer ts.Close() - client := NewProvisionWatcherClient(ts.URL, NewNullAuthenticationInjector()) + client := NewProvisionWatcherClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.Update(context.Background(), []requests.UpdateProvisionWatcherRequest{}) require.NoError(t, err) require.IsType(t, []dtoCommon.BaseResponse{}, res) @@ -43,7 +43,7 @@ func TestProvisionWatcherClient_AllProvisionWatchers(t *testing.T) { ts := newTestServer(http.MethodGet, common.ApiAllProvisionWatcherRoute, responses.MultiProvisionWatchersResponse{}) defer ts.Close() - client := NewProvisionWatcherClient(ts.URL, NewNullAuthenticationInjector()) + client := NewProvisionWatcherClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.AllProvisionWatchers(context.Background(), []string{"label1", "label2"}, 1, 10) require.NoError(t, err) require.IsType(t, responses.MultiProvisionWatchersResponse{}, res) @@ -55,7 +55,7 @@ func TestProvisionWatcherClient_ProvisionWatcherByName(t *testing.T) { ts := newTestServer(http.MethodGet, urlPath, responses.ProvisionWatcherResponse{}) defer ts.Close() - client := NewProvisionWatcherClient(ts.URL, NewNullAuthenticationInjector()) + client := NewProvisionWatcherClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.ProvisionWatcherByName(context.Background(), pwName) require.NoError(t, err) require.IsType(t, responses.ProvisionWatcherResponse{}, res) @@ -67,7 +67,7 @@ func TestProvisionWatcherClient_DeleteProvisionWatcherByName(t *testing.T) { ts := newTestServer(http.MethodDelete, urlPath, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewProvisionWatcherClient(ts.URL, NewNullAuthenticationInjector()) + client := NewProvisionWatcherClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeleteProvisionWatcherByName(context.Background(), pwName) require.NoError(t, err) require.IsType(t, dtoCommon.BaseResponse{}, res) @@ -79,7 +79,7 @@ func TestProvisionWatcherClient_ProvisionWatchersByProfileName(t *testing.T) { ts := newTestServer(http.MethodGet, urlPath, responses.MultiProvisionWatchersResponse{}) defer ts.Close() - client := NewProvisionWatcherClient(ts.URL, NewNullAuthenticationInjector()) + client := NewProvisionWatcherClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.ProvisionWatchersByProfileName(context.Background(), profileName, 1, 10) require.NoError(t, err) require.IsType(t, responses.MultiProvisionWatchersResponse{}, res) @@ -91,7 +91,7 @@ func TestProvisionWatcherClient_ProvisionWatchersByServiceName(t *testing.T) { ts := newTestServer(http.MethodGet, urlPath, responses.MultiProvisionWatchersResponse{}) defer ts.Close() - client := NewProvisionWatcherClient(ts.URL, NewNullAuthenticationInjector()) + client := NewProvisionWatcherClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.ProvisionWatchersByServiceName(context.Background(), serviceName, 1, 10) require.NoError(t, err) require.IsType(t, responses.MultiProvisionWatchersResponse{}, res) diff --git a/clients/http/reading.go b/clients/http/reading.go index 48fb68e8..a56d5ab3 100644 --- a/clients/http/reading.go +++ b/clients/http/reading.go @@ -21,15 +21,17 @@ import ( ) type readingClient struct { - baseUrl string - authInjector interfaces.AuthenticationInjector + baseUrl string + authInjector interfaces.AuthenticationInjector + enableNameFieldEscape bool } // NewReadingClient creates an instance of ReadingClient -func NewReadingClient(baseUrl string, authInjector interfaces.AuthenticationInjector) interfaces.ReadingClient { +func NewReadingClient(baseUrl string, authInjector interfaces.AuthenticationInjector, enableNameFieldEscape bool) interfaces.ReadingClient { return &readingClient{ - baseUrl: baseUrl, - authInjector: authInjector, + baseUrl: baseUrl, + authInjector: authInjector, + enableNameFieldEscape: enableNameFieldEscape, } } @@ -78,7 +80,8 @@ func (rc readingClient) ReadingsByDeviceName(ctx context.Context, name string, o } func (rc readingClient) ReadingsByResourceName(ctx context.Context, name string, offset, limit int) (responses.MultiReadingsResponse, errors.EdgeX) { - requestPath := utils.EscapeAndJoinPath(common.ApiReadingRoute, common.ResourceName, name) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(rc.enableNameFieldEscape). + SetPath(common.ApiReadingRoute).SetPath(common.ResourceName).SetNameFieldPath(name).BuildPath() requestParams := url.Values{} requestParams.Set(common.Offset, strconv.Itoa(offset)) requestParams.Set(common.Limit, strconv.Itoa(limit)) @@ -105,7 +108,8 @@ func (rc readingClient) ReadingsByTimeRange(ctx context.Context, start, end, off // ReadingsByResourceNameAndTimeRange returns readings by resource name and specified time range. Readings are sorted in descending order of origin time. func (rc readingClient) ReadingsByResourceNameAndTimeRange(ctx context.Context, name string, start, end, offset, limit int) (responses.MultiReadingsResponse, errors.EdgeX) { - requestPath := utils.EscapeAndJoinPath(common.ApiReadingRoute, common.ResourceName, name, common.Start, strconv.Itoa(start), common.End, strconv.Itoa(end)) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(rc.enableNameFieldEscape). + SetPath(common.ApiReadingRoute).SetPath(common.ResourceName).SetNameFieldPath(name).SetPath(common.Start).SetPath(strconv.Itoa(start)).SetPath(common.End).SetPath(strconv.Itoa(end)).BuildPath() requestParams := url.Values{} requestParams.Set(common.Offset, strconv.Itoa(offset)) requestParams.Set(common.Limit, strconv.Itoa(limit)) @@ -118,7 +122,8 @@ func (rc readingClient) ReadingsByResourceNameAndTimeRange(ctx context.Context, } func (rc readingClient) ReadingsByDeviceNameAndResourceName(ctx context.Context, deviceName, resourceName string, offset, limit int) (responses.MultiReadingsResponse, errors.EdgeX) { - requestPath := utils.EscapeAndJoinPath(common.ApiReadingRoute, common.Device, common.Name, deviceName, common.ResourceName, resourceName) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(rc.enableNameFieldEscape). + SetPath(common.ApiReadingRoute).SetPath(common.Device).SetPath(common.Name).SetNameFieldPath(deviceName).SetPath(common.ResourceName).SetNameFieldPath(resourceName).BuildPath() requestParams := url.Values{} requestParams.Set(common.Offset, strconv.Itoa(offset)) requestParams.Set(common.Limit, strconv.Itoa(limit)) @@ -132,7 +137,9 @@ func (rc readingClient) ReadingsByDeviceNameAndResourceName(ctx context.Context, } func (rc readingClient) ReadingsByDeviceNameAndResourceNameAndTimeRange(ctx context.Context, deviceName, resourceName string, start, end, offset, limit int) (responses.MultiReadingsResponse, errors.EdgeX) { - requestPath := utils.EscapeAndJoinPath(common.ApiReadingRoute, common.Device, common.Name, deviceName, common.ResourceName, resourceName, common.Start, strconv.Itoa(start), common.End, strconv.Itoa(end)) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(rc.enableNameFieldEscape). + SetPath(common.ApiReadingRoute).SetPath(common.Device).SetPath(common.Name).SetNameFieldPath(deviceName).SetPath(common.ResourceName).SetNameFieldPath(resourceName). + SetPath(common.Start).SetPath(strconv.Itoa(start)).SetPath(common.End).SetPath(strconv.Itoa(end)).BuildPath() requestParams := url.Values{} requestParams.Set(common.Offset, strconv.Itoa(offset)) requestParams.Set(common.Limit, strconv.Itoa(limit)) @@ -145,7 +152,9 @@ func (rc readingClient) ReadingsByDeviceNameAndResourceNameAndTimeRange(ctx cont } func (rc readingClient) ReadingsByDeviceNameAndResourceNamesAndTimeRange(ctx context.Context, deviceName string, resourceNames []string, start, end, offset, limit int) (responses.MultiReadingsResponse, errors.EdgeX) { - requestPath := utils.EscapeAndJoinPath(common.ApiReadingRoute, common.Device, common.Name, deviceName, common.Start, strconv.Itoa(start), common.End, strconv.Itoa(end)) + requestPath := common.NewPathBuilder().EnableNameFieldEscape(rc.enableNameFieldEscape). + SetPath(common.ApiReadingRoute).SetPath(common.Device).SetPath(common.Name).SetNameFieldPath(deviceName). + SetPath(common.Start).SetPath(strconv.Itoa(start)).SetPath(common.End).SetPath(strconv.Itoa(end)).BuildPath() requestParams := url.Values{} requestParams.Set(common.Offset, strconv.Itoa(offset)) requestParams.Set(common.Limit, strconv.Itoa(limit)) diff --git a/clients/http/reading_test.go b/clients/http/reading_test.go index 7d65fa57..e7fc90cd 100644 --- a/clients/http/reading_test.go +++ b/clients/http/reading_test.go @@ -25,7 +25,7 @@ func TestQueryAllReadings(t *testing.T) { ts := newTestServer(http.MethodGet, common.ApiAllReadingRoute, responses.MultiReadingsResponse{}) defer ts.Close() - client := NewReadingClient(ts.URL, NewNullAuthenticationInjector()) + client := NewReadingClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.AllReadings(context.Background(), 1, 10) require.NoError(t, err) assert.IsType(t, responses.MultiReadingsResponse{}, res) @@ -35,7 +35,7 @@ func TestQueryReadingCount(t *testing.T) { ts := newTestServer(http.MethodGet, common.ApiReadingCountRoute, dtoCommon.CountResponse{}) defer ts.Close() - client := NewReadingClient(ts.URL, NewNullAuthenticationInjector()) + client := NewReadingClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.ReadingCount(context.Background()) require.NoError(t, err) assert.IsType(t, dtoCommon.CountResponse{}, res) @@ -47,7 +47,7 @@ func TestQueryReadingCountByDeviceName(t *testing.T) { ts := newTestServer(http.MethodGet, path, dtoCommon.CountResponse{}) defer ts.Close() - client := NewReadingClient(ts.URL, NewNullAuthenticationInjector()) + client := NewReadingClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.ReadingCountByDeviceName(context.Background(), deviceName) require.NoError(t, err) require.IsType(t, dtoCommon.CountResponse{}, res) @@ -59,7 +59,7 @@ func TestQueryReadingsByDeviceName(t *testing.T) { ts := newTestServer(http.MethodGet, urlPath, responses.MultiReadingsResponse{}) defer ts.Close() - client := NewReadingClient(ts.URL, NewNullAuthenticationInjector()) + client := NewReadingClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.ReadingsByDeviceName(context.Background(), deviceName, 1, 10) require.NoError(t, err) assert.IsType(t, responses.MultiReadingsResponse{}, res) @@ -71,7 +71,7 @@ func TestQueryReadingsByResourceName(t *testing.T) { ts := newTestServer(http.MethodGet, urlPath, responses.MultiReadingsResponse{}) defer ts.Close() - client := NewReadingClient(ts.URL, NewNullAuthenticationInjector()) + client := NewReadingClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.ReadingsByResourceName(context.Background(), resourceName, 1, 10) require.NoError(t, err) assert.IsType(t, responses.MultiReadingsResponse{}, res) @@ -84,7 +84,7 @@ func TestQueryReadingsByTimeRange(t *testing.T) { ts := newTestServer(http.MethodGet, urlPath, responses.MultiReadingsResponse{}) defer ts.Close() - client := NewReadingClient(ts.URL, NewNullAuthenticationInjector()) + client := NewReadingClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.ReadingsByTimeRange(context.Background(), start, end, 1, 10) require.NoError(t, err) assert.IsType(t, responses.MultiReadingsResponse{}, res) @@ -98,7 +98,7 @@ func TestQueryReadingsByResourceNameAndTimeRange(t *testing.T) { ts := newTestServer(http.MethodGet, urlPath, responses.MultiReadingsResponse{}) defer ts.Close() - client := NewReadingClient(ts.URL, NewNullAuthenticationInjector()) + client := NewReadingClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.ReadingsByResourceNameAndTimeRange(context.Background(), resourceName, start, end, 1, 10) require.NoError(t, err) assert.IsType(t, responses.MultiReadingsResponse{}, res) @@ -111,7 +111,7 @@ func TestQueryReadingsByDeviceNameAndResourceName(t *testing.T) { ts := newTestServer(http.MethodGet, urlPath, responses.MultiReadingsResponse{}) defer ts.Close() - client := NewReadingClient(ts.URL, NewNullAuthenticationInjector()) + client := NewReadingClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.ReadingsByDeviceNameAndResourceName(context.Background(), deviceName, resourceName, 1, 10) require.NoError(t, err) assert.IsType(t, responses.MultiReadingsResponse{}, res) @@ -126,7 +126,7 @@ func TestQueryReadingsByDeviceNameAndResourceNameAndTimeRange(t *testing.T) { ts := newTestServer(http.MethodGet, urlPath, responses.MultiReadingsResponse{}) defer ts.Close() - client := NewReadingClient(ts.URL, NewNullAuthenticationInjector()) + client := NewReadingClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.ReadingsByDeviceNameAndResourceNameAndTimeRange(context.Background(), deviceName, resourceName, start, end, 1, 10) require.NoError(t, err) assert.IsType(t, responses.MultiReadingsResponse{}, res) @@ -141,7 +141,7 @@ func TestQueryReadingsByDeviceNameAndResourceNamesAndTimeRange(t *testing.T) { ts := newTestServer(http.MethodGet, urlPath, responses.MultiReadingsResponse{}) defer ts.Close() - client := NewReadingClient(ts.URL, NewNullAuthenticationInjector()) + client := NewReadingClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.ReadingsByDeviceNameAndResourceNamesAndTimeRange(context.Background(), deviceName, resourceNames, start, end, 1, 10) require.NoError(t, err) assert.IsType(t, responses.MultiReadingsResponse{}, res) diff --git a/clients/http/subscription.go b/clients/http/subscription.go index 490fb470..c9543aa0 100644 --- a/clients/http/subscription.go +++ b/clients/http/subscription.go @@ -22,15 +22,17 @@ import ( ) type SubscriptionClient struct { - baseUrl string - authInjector interfaces.AuthenticationInjector + baseUrl string + authInjector interfaces.AuthenticationInjector + enableNameFieldEscape bool } // NewSubscriptionClient creates an instance of SubscriptionClient -func NewSubscriptionClient(baseUrl string, authInjector interfaces.AuthenticationInjector) interfaces.SubscriptionClient { +func NewSubscriptionClient(baseUrl string, authInjector interfaces.AuthenticationInjector, enableNameFieldEscape bool) interfaces.SubscriptionClient { return &SubscriptionClient{ - baseUrl: baseUrl, - authInjector: authInjector, + baseUrl: baseUrl, + authInjector: authInjector, + enableNameFieldEscape: enableNameFieldEscape, } } @@ -105,7 +107,8 @@ func (client *SubscriptionClient) SubscriptionsByReceiver(ctx context.Context, r // SubscriptionByName query subscription by name. func (client *SubscriptionClient) SubscriptionByName(ctx context.Context, name string) (res responses.SubscriptionResponse, err errors.EdgeX) { - path := utils.EscapeAndJoinPath(common.ApiSubscriptionRoute, common.Name, name) + path := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiSubscriptionRoute).SetPath(common.Name).SetNameFieldPath(name).BuildPath() err = utils.GetRequest(ctx, &res, client.baseUrl, path, nil, client.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) @@ -115,7 +118,8 @@ func (client *SubscriptionClient) SubscriptionByName(ctx context.Context, name s // DeleteSubscriptionByName deletes a subscription by name. func (client *SubscriptionClient) DeleteSubscriptionByName(ctx context.Context, name string) (res dtoCommon.BaseResponse, err errors.EdgeX) { - path := utils.EscapeAndJoinPath(common.ApiSubscriptionRoute, common.Name, name) + path := common.NewPathBuilder().EnableNameFieldEscape(client.enableNameFieldEscape). + SetPath(common.ApiSubscriptionRoute).SetPath(common.Name).SetNameFieldPath(name).BuildPath() err = utils.DeleteRequest(ctx, &res, client.baseUrl, path, client.authInjector) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) diff --git a/clients/http/subscription_test.go b/clients/http/subscription_test.go index afd37757..cb2a387a 100644 --- a/clients/http/subscription_test.go +++ b/clients/http/subscription_test.go @@ -49,7 +49,7 @@ func updateSubscriptionRequest() requests.UpdateSubscriptionRequest { func TestSubscriptionClient_Add(t *testing.T) { ts := newTestServer(http.MethodPost, common.ApiSubscriptionRoute, []dtoCommon.BaseWithIdResponse{}) defer ts.Close() - client := NewSubscriptionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewSubscriptionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.Add(context.Background(), []requests.AddSubscriptionRequest{addSubscriptionRequest()}) require.NoError(t, err) require.IsType(t, []dtoCommon.BaseWithIdResponse{}, res) @@ -58,7 +58,7 @@ func TestSubscriptionClient_Add(t *testing.T) { func TestSubscriptionClient_Update(t *testing.T) { ts := newTestServer(http.MethodPatch, common.ApiSubscriptionRoute, []dtoCommon.BaseResponse{}) defer ts.Close() - client := NewSubscriptionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewSubscriptionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.Update(context.Background(), []requests.UpdateSubscriptionRequest{updateSubscriptionRequest()}) require.NoError(t, err) require.IsType(t, []dtoCommon.BaseResponse{}, res) @@ -67,7 +67,7 @@ func TestSubscriptionClient_Update(t *testing.T) { func TestSubscriptionClient_AllSubscriptions(t *testing.T) { ts := newTestServer(http.MethodGet, common.ApiAllSubscriptionRoute, responses.MultiSubscriptionsResponse{}) defer ts.Close() - client := NewSubscriptionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewSubscriptionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.AllSubscriptions(context.Background(), 0, 10) require.NoError(t, err) require.IsType(t, responses.MultiSubscriptionsResponse{}, res) @@ -78,7 +78,7 @@ func TestSubscriptionClient_DeleteSubscriptionByName(t *testing.T) { path := path.Join(common.ApiSubscriptionRoute, common.Name, subscriptionName) ts := newTestServer(http.MethodDelete, path, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewSubscriptionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewSubscriptionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeleteSubscriptionByName(context.Background(), subscriptionName) require.NoError(t, err) require.IsType(t, dtoCommon.BaseResponse{}, res) @@ -89,7 +89,7 @@ func TestSubscriptionClient_SubscriptionByName(t *testing.T) { path := path.Join(common.ApiSubscriptionRoute, common.Name, subscriptionName) ts := newTestServer(http.MethodGet, path, responses.SubscriptionResponse{}) defer ts.Close() - client := NewSubscriptionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewSubscriptionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.SubscriptionByName(context.Background(), subscriptionName) require.NoError(t, err) require.IsType(t, responses.SubscriptionResponse{}, res) @@ -100,7 +100,7 @@ func TestSubscriptionClient_SubscriptionsByCategory(t *testing.T) { urlPath := path.Join(common.ApiSubscriptionRoute, common.Category, category) ts := newTestServer(http.MethodGet, urlPath, responses.MultiSubscriptionsResponse{}) defer ts.Close() - client := NewSubscriptionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewSubscriptionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.SubscriptionsByCategory(context.Background(), category, 0, 10) require.NoError(t, err) require.IsType(t, responses.MultiSubscriptionsResponse{}, res) @@ -111,7 +111,7 @@ func TestSubscriptionClient_SubscriptionsByLabel(t *testing.T) { urlPath := path.Join(common.ApiSubscriptionRoute, common.Label, label) ts := newTestServer(http.MethodGet, urlPath, responses.MultiSubscriptionsResponse{}) defer ts.Close() - client := NewSubscriptionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewSubscriptionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.SubscriptionsByLabel(context.Background(), label, 0, 10) require.NoError(t, err) require.IsType(t, responses.MultiSubscriptionsResponse{}, res) @@ -122,7 +122,7 @@ func TestSubscriptionClient_SubscriptionsByReceiver(t *testing.T) { urlPath := path.Join(common.ApiSubscriptionRoute, common.Receiver, receiver) ts := newTestServer(http.MethodGet, urlPath, responses.MultiSubscriptionsResponse{}) defer ts.Close() - client := NewSubscriptionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewSubscriptionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.SubscriptionsByReceiver(context.Background(), receiver, 0, 10) require.NoError(t, err) require.IsType(t, responses.MultiSubscriptionsResponse{}, res) diff --git a/clients/http/transmission.go b/clients/http/transmission.go index a6cf1216..73712356 100644 --- a/clients/http/transmission.go +++ b/clients/http/transmission.go @@ -21,15 +21,17 @@ import ( ) type TransmissionClient struct { - baseUrl string - authInjector interfaces.AuthenticationInjector + baseUrl string + authInjector interfaces.AuthenticationInjector + enableNameFieldEscape bool } // NewTransmissionClient creates an instance of TransmissionClient -func NewTransmissionClient(baseUrl string, authInjector interfaces.AuthenticationInjector) interfaces.TransmissionClient { +func NewTransmissionClient(baseUrl string, authInjector interfaces.AuthenticationInjector, enableNameFieldEscape bool) interfaces.TransmissionClient { return &TransmissionClient{ - baseUrl: baseUrl, - authInjector: authInjector, + baseUrl: baseUrl, + authInjector: authInjector, + enableNameFieldEscape: enableNameFieldEscape, } } diff --git a/clients/http/transmission_test.go b/clients/http/transmission_test.go index 49c8cb45..1c1c7ae8 100644 --- a/clients/http/transmission_test.go +++ b/clients/http/transmission_test.go @@ -24,7 +24,7 @@ import ( func TestTransmissionClient_AllTransmissions(t *testing.T) { ts := newTestServer(http.MethodGet, common.ApiAllTransmissionRoute, responses.MultiTransmissionsResponse{}) defer ts.Close() - client := NewTransmissionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewTransmissionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.AllTransmissions(context.Background(), 0, 10) require.NoError(t, err) require.IsType(t, responses.MultiTransmissionsResponse{}, res) @@ -35,7 +35,7 @@ func TestTransmissionClient_DeleteProcessedTransmissionsByAge(t *testing.T) { path := path.Join(common.ApiTransmissionRoute, common.Age, strconv.Itoa(age)) ts := newTestServer(http.MethodDelete, path, dtoCommon.BaseResponse{}) defer ts.Close() - client := NewTransmissionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewTransmissionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.DeleteProcessedTransmissionsByAge(context.Background(), age) require.NoError(t, err) require.IsType(t, dtoCommon.BaseResponse{}, res) @@ -46,7 +46,7 @@ func TestTransmissionClient_TransmissionById(t *testing.T) { path := path.Join(common.ApiTransmissionRoute, common.Id, testId) ts := newTestServer(http.MethodGet, path, responses.TransmissionResponse{}) defer ts.Close() - client := NewTransmissionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewTransmissionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.TransmissionById(context.Background(), testId) require.NoError(t, err) require.IsType(t, responses.TransmissionResponse{}, res) @@ -57,7 +57,7 @@ func TestTransmissionClient_TransmissionsByStatus(t *testing.T) { urlPath := path.Join(common.ApiTransmissionRoute, common.Status, status) ts := newTestServer(http.MethodGet, urlPath, responses.MultiTransmissionsResponse{}) defer ts.Close() - client := NewTransmissionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewTransmissionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.TransmissionsByStatus(context.Background(), status, 0, 10) require.NoError(t, err) require.IsType(t, responses.MultiTransmissionsResponse{}, res) @@ -68,7 +68,7 @@ func TestTransmissionClient_TransmissionsBySubscriptionName(t *testing.T) { urlPath := path.Join(common.ApiTransmissionRoute, common.Subscription, common.Name, subscriptionName) ts := newTestServer(http.MethodGet, urlPath, responses.MultiTransmissionsResponse{}) defer ts.Close() - client := NewTransmissionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewTransmissionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.TransmissionsBySubscriptionName(context.Background(), subscriptionName, 0, 10) require.NoError(t, err) require.IsType(t, responses.MultiTransmissionsResponse{}, res) @@ -80,7 +80,7 @@ func TestTransmissionClient_TransmissionsByTimeRange(t *testing.T) { urlPath := path.Join(common.ApiTransmissionRoute, common.Start, strconv.Itoa(start), common.End, strconv.Itoa(end)) ts := newTestServer(http.MethodGet, urlPath, responses.MultiTransmissionsResponse{}) defer ts.Close() - client := NewTransmissionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewTransmissionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.TransmissionsByTimeRange(context.Background(), start, end, 0, 10) require.NoError(t, err) require.IsType(t, responses.MultiTransmissionsResponse{}, res) @@ -91,7 +91,7 @@ func TestTransmissionClient_TransmissionsByNotificationId(t *testing.T) { urlPath := path.Join(common.ApiTransmissionRoute, common.Notification, common.Id, notificationId) ts := newTestServer(http.MethodGet, urlPath, responses.MultiTransmissionsResponse{}) defer ts.Close() - client := NewTransmissionClient(ts.URL, NewNullAuthenticationInjector()) + client := NewTransmissionClient(ts.URL, NewNullAuthenticationInjector(), false) res, err := client.TransmissionsByNotificationId(context.Background(), notificationId, 0, 10) require.NoError(t, err) require.IsType(t, responses.MultiTransmissionsResponse{}, res) diff --git a/common/utils.go b/common/utils.go index 3427ea00..6d45cd21 100644 --- a/common/utils.go +++ b/common/utils.go @@ -52,3 +52,35 @@ func URLEncode(s string) string { return res } + +type pathBuilder struct { + sb strings.Builder + enableNameFieldEscape bool +} + +func NewPathBuilder() *pathBuilder { + return &pathBuilder{} +} + +func (b *pathBuilder) EnableNameFieldEscape(enableNameFieldEscape bool) *pathBuilder { + b.enableNameFieldEscape = enableNameFieldEscape + return b +} + +func (b *pathBuilder) SetPath(path string) *pathBuilder { + b.sb.WriteString(path + "/") + return b +} + +// SetNameFieldPath set name path, such as device name, profile name, interval name +func (b *pathBuilder) SetNameFieldPath(namePath string) *pathBuilder { + if b.enableNameFieldEscape { + namePath = URLEncode(namePath) + } + b.sb.WriteString(namePath + "/") + return b +} + +func (b *pathBuilder) BuildPath() string { + return strings.TrimSuffix(b.sb.String(), "/") +} diff --git a/common/utils_test.go b/common/utils_test.go index 4b7cb146..7b8bd5e3 100644 --- a/common/utils_test.go +++ b/common/utils_test.go @@ -33,3 +33,31 @@ func TestURLEncode(t *testing.T) { }) } } + +func TestPathBuild(t *testing.T) { + tests := []struct { + name string + enableNameFieldEscape bool + prefixPath string + deviceServiceName string + deviceName string + expectedPath string + }{ + { + "valid with name filed escape", true, + "edgex/system-events/core-metadata/device/add", "^[this]+{is}?test:string*#", "this-is_test.string~ε“ˆε›‰δΈ–η•Œ< >/!#%^*()+,`@$&", + "edgex/system-events/core-metadata/device/add/%5E%5Bthis%5D%2B%7Bis%7D%3Ftest:string%2A%23/this%2Dis%5Ftest%2Estring%7E%E5%93%88%E5%9B%89%E4%B8%96%E7%95%8C%3C%20%3E%2F%21%23%25%5E%2A%28%29%2B%2C%60@$&", + }, + { + "valid without name filed escape", false, + "edgex/system-events/core-metadata/device/add", "device-onvif-camera", "camera-device", + "edgex/system-events/core-metadata/device/add/device-onvif-camera/camera-device"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res := NewPathBuilder().EnableNameFieldEscape(tt.enableNameFieldEscape). + SetPath(tt.prefixPath).SetNameFieldPath(tt.deviceServiceName).SetNameFieldPath(tt.deviceName).BuildPath() + assert.Equal(t, tt.expectedPath, res) + }) + } +}