Skip to content

Commit

Permalink
feature(query-params): Pass QueryParams through EdgeX to Device Servi…
Browse files Browse the repository at this point in the history
…ces (#1571)

Fix #1564

This pull request is an example/POC that @lenny-intel and I put together of how #1564 could be accomplished. This is only 1/2 of the equation as the device-sdk would need to be updated to handle the query parameters. The good thing with this is that it wouldn't be a breaking change as the device-sdk would simply ignore the query parameters that are sent on.

Signed-off-by: Mike Johanson <[email protected]>
  • Loading branch information
rsdmike authored and tsconn23 committed Aug 6, 2019
1 parent 1ae3ef6 commit 4d7ed08
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 19 deletions.
13 changes: 7 additions & 6 deletions internal/core/command/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
contract "github.com/edgexfoundry/go-mod-core-contracts/models"
)

func commandByDeviceID(deviceID string, commandID string, body string, isPutCommand bool, ctx context.Context) (string, int) {
func commandByDeviceID(deviceID string, commandID string, body string, queryParams string, isPutCommand bool, ctx context.Context) (string, int) {
d, err := mdc.Device(deviceID, ctx)
if err != nil {
LoggingClient.Error(err.Error())
Expand Down Expand Up @@ -66,10 +66,10 @@ func commandByDeviceID(deviceID string, commandID string, body string, isPutComm
return errMsg, http.StatusNotFound
}

return commandByDevice(d, c, body, isPutCommand, ctx)
return commandByDevice(d, c, body, queryParams, isPutCommand, ctx)
}

func commandByNames(dn string, cn string, body string, isPutCommand bool, ctx context.Context) (string, int) {
func commandByNames(dn string, cn string, body string, queryParams string, isPutCommand bool, ctx context.Context) (string, int) {
d, err := mdc.DeviceForName(dn, ctx)
if err != nil {
LoggingClient.Error(err.Error())
Expand All @@ -89,16 +89,17 @@ func commandByNames(dn string, cn string, body string, isPutCommand bool, ctx co
return err.Error(), http.StatusInternalServerError
}
}
return commandByDevice(d, command, body, isPutCommand, ctx)

return commandByDevice(d, command, body, queryParams, isPutCommand, ctx)
}

func commandByDevice(device contract.Device, command contract.Command, body string, isPutCommand bool, ctx context.Context) (string, int) {
func commandByDevice(device contract.Device, command contract.Command, body string, queryParams string, isPutCommand bool, ctx context.Context) (string, int) {
var ex Executor
var err error
if isPutCommand {
ex, err = NewPutCommand(device, command, body, ctx, &http.Client{})
} else {
ex, err = NewGetCommand(device, command, ctx, &http.Client{})
ex, err = NewGetCommand(device, command, queryParams, ctx, &http.Client{})
}

if err != nil {
Expand Down
16 changes: 11 additions & 5 deletions internal/core/command/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,23 @@ package command

import (
"context"
"net/http"
"net/url"
"strings"

"github.com/edgexfoundry/edgex-go/internal"
"github.com/edgexfoundry/go-mod-core-contracts/clients"
contract "github.com/edgexfoundry/go-mod-core-contracts/models"
"net/http"
"strings"
)

// NewGetCommand creates and Executor which can be used to execute the GET related command.
func NewGetCommand(device contract.Device, command contract.Command, context context.Context, httpCaller internal.HttpCaller) (Executor, error) {
url := device.Service.Addressable.GetBaseURL() + strings.Replace(command.Get.Action.Path, DEVICEIDURLPARAM, device.Id, -1)
request, err := http.NewRequest(http.MethodGet, url, nil)
func NewGetCommand(device contract.Device, command contract.Command, queryParams string, context context.Context, httpCaller internal.HttpCaller) (Executor, error) {
urlResult := device.Service.Addressable.GetBaseURL() + strings.Replace(command.Get.Action.Path, DEVICEIDURLPARAM, device.Id, -1) + "?" + queryParams
validURL, err := url.ParseRequestURI(urlResult)
if err != nil {
return serviceCommand{}, err
}
request, err := http.NewRequest(http.MethodGet, validURL.String(), nil)
if err != nil {
return serviceCommand{}, err
}
Expand Down
39 changes: 33 additions & 6 deletions internal/core/command/get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ package command

import (
"context"
"strconv"
"testing"

"github.com/edgexfoundry/go-mod-core-contracts/clients"
contract "github.com/edgexfoundry/go-mod-core-contracts/models"
"testing"
)

const (
Expand Down Expand Up @@ -58,7 +60,7 @@ var testCommand = contract.Command{
func TestNewGetCommandWithCorrelationId(t *testing.T) {
expectedCorrelationIDHeaderValue := "Testing"
testContext := context.WithValue(context.Background(), clients.CorrelationHeader, expectedCorrelationIDHeaderValue)
getCommand, _ := NewGetCommand(testDevice, testCommand, testContext, nil)
getCommand, _ := NewGetCommand(testDevice, testCommand, "", testContext, nil)
actualCorrelationIDHeaderValue := getCommand.(serviceCommand).Request.Header.Get(clients.CorrelationHeader)
if actualCorrelationIDHeaderValue == "" {
t.Errorf("The populated GetCommand's request should contain a correlation ID header value")
Expand All @@ -69,8 +71,33 @@ func TestNewGetCommandWithCorrelationId(t *testing.T) {
}
}

func TestNewGetCommandWithQueryParams(t *testing.T) {
queryParams := "test=value1&test2=value2"
getCommand, _ := NewGetCommand(testDevice, testCommand, queryParams, context.Background(), nil)
req := getCommand.(serviceCommand).Request.URL
if req.Scheme != TestProtocol {
t.Errorf("Unexpected protocol")
}
expectedHost := TestAddress + ":" + strconv.Itoa(TestPort)
if req.Host != expectedHost {
t.Errorf("Unexpected host address and port")
}
if req.Path != testCommand.Get.Action.Path {
t.Errorf("Unexpected path")
}
if req.RawQuery != queryParams {
t.Errorf("Unexpected Raw Query Value")
}
}
func TestNewGetCommandWithMalformedQueryParams(t *testing.T) {
queryParams := "!@#$%"
_, err := NewGetCommand(testDevice, testCommand, queryParams, context.Background(), nil)
if err == nil {
t.Errorf("Expected error for malformed query parameters")
}
}
func TestNewGetCommandNoCorrelationIDInContext(t *testing.T) {
getCommand, _ := NewGetCommand(testDevice, testCommand, context.Background(), nil)
getCommand, _ := NewGetCommand(testDevice, testCommand, "", context.Background(), nil)
actualCorrelationIDHeaderValue := getCommand.(serviceCommand).Request.Header.Get(clients.CorrelationHeader)
if actualCorrelationIDHeaderValue != "" {
t.Errorf("No correlation ID should be specified")
Expand All @@ -80,8 +107,8 @@ func TestNewGetCommandNoCorrelationIDInContext(t *testing.T) {
func TestNewGetCommandInvalidBaseUrl(t *testing.T) {
device := testDevice
device.Service.Addressable.Address = "!@#$"
_, err := NewGetCommand(device, testCommand, context.Background(), nil)
if err != nil {
t.Errorf("The invalid URL error was not properly propegated to the caller")
_, err := NewGetCommand(device, testCommand, "", context.Background(), nil)
if err == nil {
t.Errorf("The invalid URL error was not properly propagated to the caller")
}
}
4 changes: 2 additions & 2 deletions internal/core/command/restDevice.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func issueDeviceCommand(w http.ResponseWriter, r *http.Request, isPutCommand boo
}

ctx := r.Context()
body, status := commandByDeviceID(did, cid, string(b), isPutCommand, ctx)
body, status := commandByDeviceID(did, cid, string(b), r.URL.RawQuery, isPutCommand, ctx)
if status != http.StatusOK {
http.Error(w, body, status)
} else {
Expand Down Expand Up @@ -75,7 +75,7 @@ func issueDeviceCommandByNames(w http.ResponseWriter, r *http.Request, isPutComm
LoggingClient.Error(err.Error())
return
}
body, status := commandByNames(dn, cn, string(b), isPutCommand, ctx)
body, status := commandByNames(dn, cn, string(b), r.URL.RawQuery, isPutCommand, ctx)

if status != http.StatusOK {
http.Error(w, body, status)
Expand Down

0 comments on commit 4d7ed08

Please sign in to comment.