Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions v2/extensions/dataref_extension.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
Copyright 2024 The CloudEvents Authors
SPDX-License-Identifier: Apache-2.0
*/

package extensions

import (
"github.com/cloudevents/sdk-go/v2/event"
"net/url"
)

const DataRefExtensionKey = "dataref"

// DataRefExtension represents the CloudEvents Dataref (claim check pattern)
// extension for cloudevents contexts,
// See https://github.com/cloudevents/spec/blob/main/cloudevents/extensions/dataref.md
// for more info
type DataRefExtension struct {
DataRef string `json:"dataref"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that it matters much but I'm curious why it's a struct instead of just a string? Are you leaving the option open that one day we may need to include extra metadata along with the URL?

}

// AddDataRefExtension adds the dataref attribute to the cloudevents context
func AddDataRefExtension(e *event.Event, dataRef string) error {
if _, err := url.Parse(dataRef); err != nil {
return err
}
e.SetExtension(DataRefExtensionKey, dataRef)
return nil
}

// GetDataRefExtension returns any dataref attribute present in the
// cloudevent event/context and a bool to indicate if it was found.
// If not found, the DataRefExtension.DataRef value will be ""
func GetDataRefExtension(e event.Event) (DataRefExtension, bool) {
if dataRefValue, ok := e.Extensions()[DataRefExtensionKey]; ok {
dataRefStr, _ := dataRefValue.(string)
return DataRefExtension{DataRef: dataRefStr}, true
}
return DataRefExtension{}, false
}
69 changes: 69 additions & 0 deletions v2/extensions/dataref_extension_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
Copyright 2024 The CloudEvents Authors
SPDX-License-Identifier: Apache-2.0
*/

package extensions

import (
"testing"

"github.com/cloudevents/sdk-go/v2/event"
)

func TestAddDataRefExtension(t *testing.T) {
// MUST HAVE AT LEAST ONE FAILING TEST as that'll also test to make sure
// that the failed add() call won't actually set anything

tests := []struct {
dataref string
pass bool
}{
{"https://example.com/data", true},
{"://invalid-url", false},
}

for _, test := range tests {
e := event.New()
err := AddDataRefExtension(&e, test.dataref)

// Make sure adding it passed/fails appropriately
if test.pass && err != nil {
t.Fatalf("Failed to add DataRefExtension with valid URL(%s): %s",
test.dataref, err)
}
if !test.pass && err == nil {
t.Fatalf("Expected not to find DataRefExtension (%s), but did",
test.dataref)
}

// Now make sure it's actually there in the 'pass' cases, but
// missing in the failed cases.
dr, ok := GetDataRefExtension(e)
if test.pass {
if !ok || dr.DataRef == "" {
t.Fatalf("Dataref (%s) is missing after being set",
test.dataref)
}
if dr.DataRef != test.dataref {
t.Fatalf("Retrieved dataref(%v) doesn't match set value(%s)",
dr, test.dataref)
}
} else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think it's safe to remove the else and directly jump to the next if without changing test semantics?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need it because we only want to fail when the dataref is set on the "failed" case, not when the pass is expected to pass.

if ok || dr.DataRef != "" {
t.Fatalf("Expected not to find DataRefExtension, but did(%s)",
test.dataref)
}
}
}
}

func TestGetDataRefExtensionNotFound(t *testing.T) {
e := event.New()

// Make sure there's no dataref by default
dr, ok := GetDataRefExtension(e)
if ok || dr.DataRef != "" {
t.Fatal("Expected not to find DataRefExtension, but did")
}
}