Skip to content

Commit

Permalink
Fix the Content Header-related issue with CBOR.
Browse files Browse the repository at this point in the history
Signed-off-by: Akram Ahmad <sftwr2020@gmail.com>
  • Loading branch information
akramtexas committed Mar 17, 2020
1 parent 9e6d46c commit 8eaf976
Show file tree
Hide file tree
Showing 7 changed files with 271 additions and 44 deletions.
5 changes: 3 additions & 2 deletions internal/autoevent/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ import (
"sync"
"time"

"github.com/OneOfOne/xxhash"
"github.com/edgexfoundry/device-sdk-go/internal/common"
"github.com/edgexfoundry/device-sdk-go/internal/handler"
dsModels "github.com/edgexfoundry/device-sdk-go/pkg/models"
contract "github.com/edgexfoundry/go-mod-core-contracts/models"

"github.com/OneOfOne/xxhash"
)

type Executor interface {
Expand Down Expand Up @@ -75,7 +76,7 @@ func readResource(e *executor) (*dsModels.Event, common.AppError) {
vars[common.NameVar] = e.deviceName
vars[common.CommandVar] = e.autoEvent.Resource

evt, appErr := handler.CommandHandler(vars, "", common.GetCmdMethod, "")
evt, appErr := handler.CommandHandler(vars, "", nil)
return evt, appErr
}

Expand Down
3 changes: 2 additions & 1 deletion internal/common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import (
// WritableInfo is a struct which contains configuration settings that can be changed in the Registry .
type WritableInfo struct {
// Level is the logging level of writing log message
LogLevel string
LogLevel string
ChecksumAlgo string
}

// ServiceInfo is a struct which contains service related configuration
Expand Down
90 changes: 90 additions & 0 deletions internal/common/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ package common
import (
"bytes"
"context"
"crypto/md5"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"reflect"
"strings"
Expand All @@ -21,6 +26,14 @@ import (
"github.com/edgexfoundry/go-mod-core-contracts/clients"
contract "github.com/edgexfoundry/go-mod-core-contracts/models"
"github.com/google/uuid"

"github.com/OneOfOne/xxhash"
"github.com/ugorji/go/codec"
)

const (
ChecksumAlgoxxHash = "xxHash"
checksumContextKey = "payload-checksum"
)

var (
Expand Down Expand Up @@ -286,3 +299,80 @@ func FilterQueryParams(queryParams string) url.Values {

return m
}

// Read reads and converts the request's JSON event data into an Event struct
func (jsonReader) Read(reader io.Reader, ctx *context.Context) (dsModels.Event, error) {
c := context.WithValue(*ctx, clients.ContentType, clients.ContentTypeJSON)
*ctx = c

event := dsModels.Event{}
err := json.NewDecoder(reader).Decode(&event)
if err != nil {
return event, err
}

return event, nil
}

// Read reads and converts the request's CBOR event data into an Event struct
func (cr cborReader) Read(reader io.Reader, ctx *context.Context) (dsModels.Event, error) {
c := context.WithValue(*ctx, clients.ContentType, clients.ContentTypeCBOR)
event := dsModels.Event{}
bytes, err := ioutil.ReadAll(reader)
if err != nil {
return event, err
}

x := codec.CborHandle{}
err = codec.NewDecoderBytes(bytes, &x).Decode(&event)
if err != nil {
return event, err
}

switch cr.configuration.Writable.ChecksumAlgo {
case ChecksumAlgoxxHash:
event.Checksum = fmt.Sprintf("%x", xxhash.Checksum64(bytes))
default:
event.Checksum = fmt.Sprintf("%x", md5.Sum(bytes))
}
c = context.WithValue(c, checksumContextKey, event.Checksum)
*ctx = c
event.EncodedEvent = bytes

return event, nil
}

// jsonReader handles unmarshaling of a JSON request body payload
type jsonReader struct{}

// NewJsonReader creates a new instance of jsonReader.
func NewJsonReader() jsonReader {
return jsonReader{}
}

// cborReader handles unmarshaling of a CBOR request body payload
type cborReader struct {
configuration *Config
}

// NewCborReader creates a new instance of cborReader.
func NewCborReader(configuration *Config) cborReader {
return cborReader{configuration: configuration}
}

// EventReader unmarshals a request body into an Event type
type EventReader interface {
Read(reader io.Reader, ctx *context.Context) (dsModels.Event, error)
}

// NewRequestReader returns a BodyReader capable of processing the request body
func NewRequestReader(request *http.Request, configuration *Config) EventReader {
contentType := request.Header.Get(clients.ContentType)

switch strings.ToLower(contentType) {
case clients.ContentTypeCBOR:
return NewCborReader(configuration)
default:
return NewJsonReader()
}
}
5 changes: 3 additions & 2 deletions internal/controller/restfuncs.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/edgexfoundry/device-sdk-go/internal/handler/callback"
"github.com/edgexfoundry/go-mod-core-contracts/clients"
contract "github.com/edgexfoundry/go-mod-core-contracts/models"

"github.com/gorilla/mux"
)

Expand Down Expand Up @@ -105,7 +106,7 @@ func commandFunc(w http.ResponseWriter, req *http.Request) {
return
}

event, appErr := handler.CommandHandler(vars, body, req.Method, req.URL.RawQuery)
event, appErr := handler.CommandHandler(vars, body, req)

if appErr != nil {
http.Error(w, fmt.Sprintf("%s %s", appErr.Message(), req.URL.Path), appErr.Code())
Expand Down Expand Up @@ -149,7 +150,7 @@ func commandAllFunc(w http.ResponseWriter, req *http.Request) {
return
}

events, appErr := handler.CommandAllHandler(vars[common.CommandVar], body, req.Method, req.URL.RawQuery)
events, appErr := handler.CommandAllHandler(vars[common.CommandVar], body, req)
if appErr != nil {
http.Error(w, appErr.Message(), appErr.Code())
} else if len(events) > 0 {
Expand Down
Loading

0 comments on commit 8eaf976

Please sign in to comment.