From df1aaf7ba0f938ef7d861d503af6f2b6c174e50d Mon Sep 17 00:00:00 2001 From: Adam Ross Date: Tue, 6 Sep 2022 14:11:18 -0700 Subject: [PATCH 1/7] Helper function to create event from HTTP Request or Response --- README.md | 13 +++++ docs/index.md | 13 +++++ v2/alias.go | 4 ++ v2/protocol/http/utility.go | 31 +++++++++++ v2/protocol/http/utility_test.go | 92 ++++++++++++++++++++++++++++++++ 5 files changed, 153 insertions(+) create mode 100644 v2/protocol/http/utility.go create mode 100644 v2/protocol/http/utility_test.go diff --git a/README.md b/README.md index 0be83aaee..2c34b551d 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,19 @@ func main() { } ``` +## Create a CloudEvent from an HTTP Request + +```go +func handler(w http.ResponseWriter, r *http.Request) { + event, err := cloudevents.NewCloudEventFromHttpRequest(r) + if err != nil { + log.Print("failed to parse CloudEvent from request: %v", err) + http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) + } + w.Write([]byte(*event.String())) +} +``` + ## Serialize/Deserialize a CloudEvent To marshal a CloudEvent into JSON: diff --git a/docs/index.md b/docs/index.md index 3b821970d..d0afe01f2 100644 --- a/docs/index.md +++ b/docs/index.md @@ -81,6 +81,19 @@ func main() { } ``` +## Create a CloudEvent from an HTTP Request + +```go +func handler(w http.ResponseWriter, r *http.Request) { + event, err := cloudevents.NewCloudEventFromHttpRequest(r) + if err != nil { + log.Print("failed to parse CloudEvent from request: %v", err) + http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) + } + w.Write([]byte(*event.String())) +} +``` + ## Serialize/Deserialize a CloudEvent To marshal a CloudEvent into JSON: diff --git a/v2/alias.go b/v2/alias.go index e7ed3a357..c096e0dc3 100644 --- a/v2/alias.go +++ b/v2/alias.go @@ -134,6 +134,10 @@ var ( ToMessage = binding.ToMessage + // Event Creation + NewEventFromHttpRequest = http.NewEventFromHttpRequest + NewEventFromHttpResponse = http.NewEventFromHttpResponse + // HTTP Messages WriteHTTPRequest = http.WriteRequest diff --git a/v2/protocol/http/utility.go b/v2/protocol/http/utility.go new file mode 100644 index 000000000..8941d7ee2 --- /dev/null +++ b/v2/protocol/http/utility.go @@ -0,0 +1,31 @@ +/* + Copyright 2022 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +package http + +import ( + "context" + nethttp "net/http" + + "github.com/cloudevents/sdk-go/v2/binding" + "github.com/cloudevents/sdk-go/v2/event" +) + +// NewEventFromHttpRequest returns an Event. +func NewEventFromHttpRequest(req *nethttp.Request) (*event.Event, error) { + msg := NewMessageFromHttpRequest(req) + return binding.ToEvent(context.Background(), msg, nil) +} + +// NewEventFromHttpResponse returns an Event. +func NewEventFromHttpResponse(resp *nethttp.Response) (*event.Event, error) { + msg := NewMessageFromHttpResponse(resp) + return binding.ToEvent(context.Background(), msg, nil) +} + +// Write tests +// Add to pkg docs +// Add to SDK site +// Move code to preferred home. diff --git a/v2/protocol/http/utility_test.go b/v2/protocol/http/utility_test.go new file mode 100644 index 000000000..d48d247e4 --- /dev/null +++ b/v2/protocol/http/utility_test.go @@ -0,0 +1,92 @@ +/* + Copyright 2022 The CloudEvents Authors + SPDX-License-Identifier: Apache-2.0 +*/ + +package http + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cloudevents/sdk-go/v2/binding" + "github.com/cloudevents/sdk-go/v2/event" + "github.com/cloudevents/sdk-go/v2/test" +) + +func TestNewEventFromHttpRequest(t *testing.T) { + tests := []struct { + name string + encoding binding.Encoding + }{{ + name: "Structured encoding", + encoding: binding.EncodingStructured, + }, { + name: "Binary encoding", + encoding: binding.EncodingBinary, + }} + + for _, tt := range tests { + test.EachEvent(t, test.Events(), func(t *testing.T, eventIn event.Event) { + t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() + req := httptest.NewRequest("POST", "http://localhost", nil) + require.NoError(t, WriteRequest(ctx, (*binding.EventMessage)(&eventIn), req)) + + NewEventFromHttpRequest(req) + got, err := NewEventFromHttpRequest(req) + require.NoError(t, err) + // Equals fails with diff like: + // - "exbinary": []uint8{0x00, 0x01, 0x02, 0x03}, + // + "exbinary": string("AAECAw=="), + // - "exint": int32(42), + // + "exint": string("42"), + // test.AssertEventEquals(t, eventIn, *got) + test.AssertEvent(t, *got, test.IsValid()) + }) + }) + } +} + +func TestNewEventFromHttpResponse(t *testing.T) { + tests := []struct { + name string + resp *http.Response + }{{ + name: "Structured encoding", + resp: &http.Response{ + Header: http.Header{ + "Content-Type": {event.ApplicationCloudEventsJSON}, + }, + Body: ioutil.NopCloser(bytes.NewReader([]byte(`{"data":"foo","datacontenttype":"application/json","id":"id","source":"source","specversion":"1.0","type":"type"}`))), + ContentLength: 113, + }, + }, { + name: "Binary encoding", + resp: &http.Response{ + Header: func() http.Header { + h := http.Header{} + h.Set("ce-specversion", "1.0") + h.Set("ce-source", "unittest") + h.Set("ce-type", "unittest") + h.Set("ce-id", "unittest") + h.Set("Content-Type", "application/json") + return h + }(), + }, + }} + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := NewEventFromHttpResponse(tt.resp) + require.NoError(t, err) + test.AssertEvent(t, *got, test.IsValid()) + }) + } +} From b916b0b1aa2ca0d8a49799700b502f13e97465c8 Mon Sep 17 00:00:00 2001 From: Adam Ross Date: Fri, 9 Sep 2022 09:12:58 -0700 Subject: [PATCH 2/7] Add missing use of encoding options and remove redundant function call Signed-off-by: Adam Ross --- v2/protocol/http/utility_test.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/v2/protocol/http/utility_test.go b/v2/protocol/http/utility_test.go index d48d247e4..5e99a4eb4 100644 --- a/v2/protocol/http/utility_test.go +++ b/v2/protocol/http/utility_test.go @@ -35,11 +35,16 @@ func TestNewEventFromHttpRequest(t *testing.T) { for _, tt := range tests { test.EachEvent(t, test.Events(), func(t *testing.T, eventIn event.Event) { t.Run(tt.name, func(t *testing.T) { - ctx := context.Background() + ctx := context.TODO() + if tt.encoding == binding.EncodingStructured { + ctx = binding.WithForceStructured(ctx) + } else if tt.encoding == binding.EncodingBinary { + ctx = binding.WithForceBinary(ctx) + } + req := httptest.NewRequest("POST", "http://localhost", nil) require.NoError(t, WriteRequest(ctx, (*binding.EventMessage)(&eventIn), req)) - NewEventFromHttpRequest(req) got, err := NewEventFromHttpRequest(req) require.NoError(t, err) // Equals fails with diff like: From 14d864018681d4dbafe471c230a2b88839826748 Mon Sep 17 00:00:00 2001 From: Adam Ross Date: Thu, 15 Sep 2022 10:10:11 -0700 Subject: [PATCH 3/7] Update v2/protocol/http/utility.go Co-authored-by: Scott Nichols --- v2/protocol/http/utility.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2/protocol/http/utility.go b/v2/protocol/http/utility.go index 8941d7ee2..a84dbd03b 100644 --- a/v2/protocol/http/utility.go +++ b/v2/protocol/http/utility.go @@ -14,7 +14,7 @@ import ( ) // NewEventFromHttpRequest returns an Event. -func NewEventFromHttpRequest(req *nethttp.Request) (*event.Event, error) { +func NewEventFromHTTPRequest(req *nethttp.Request) (*event.Event, error) { msg := NewMessageFromHttpRequest(req) return binding.ToEvent(context.Background(), msg, nil) } From f7293812bb604412ef718830ef0bec5f6dddf3cb Mon Sep 17 00:00:00 2001 From: Adam Ross Date: Thu, 15 Sep 2022 10:10:59 -0700 Subject: [PATCH 4/7] Update v2/protocol/http/utility.go Co-authored-by: Scott Nichols --- v2/protocol/http/utility.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2/protocol/http/utility.go b/v2/protocol/http/utility.go index a84dbd03b..715d7d110 100644 --- a/v2/protocol/http/utility.go +++ b/v2/protocol/http/utility.go @@ -20,7 +20,7 @@ func NewEventFromHTTPRequest(req *nethttp.Request) (*event.Event, error) { } // NewEventFromHttpResponse returns an Event. -func NewEventFromHttpResponse(resp *nethttp.Response) (*event.Event, error) { +func NewEventFromHTTPResponse(resp *nethttp.Response) (*event.Event, error) { msg := NewMessageFromHttpResponse(resp) return binding.ToEvent(context.Background(), msg, nil) } From 6ec3a27f9f2dbf3fa204db54752324e44bf8385c Mon Sep 17 00:00:00 2001 From: Adam Ross Date: Thu, 15 Sep 2022 10:11:07 -0700 Subject: [PATCH 5/7] Update v2/protocol/http/utility.go Co-authored-by: Scott Nichols --- v2/protocol/http/utility.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2/protocol/http/utility.go b/v2/protocol/http/utility.go index 715d7d110..78d010fd1 100644 --- a/v2/protocol/http/utility.go +++ b/v2/protocol/http/utility.go @@ -21,7 +21,7 @@ func NewEventFromHTTPRequest(req *nethttp.Request) (*event.Event, error) { // NewEventFromHttpResponse returns an Event. func NewEventFromHTTPResponse(resp *nethttp.Response) (*event.Event, error) { - msg := NewMessageFromHttpResponse(resp) + msg := NewMessageFromHTTPResponse(resp) return binding.ToEvent(context.Background(), msg, nil) } From 3de37fb3be06329f330cdcc8cb93963adffe0a92 Mon Sep 17 00:00:00 2001 From: Adam Ross Date: Thu, 15 Sep 2022 10:12:17 -0700 Subject: [PATCH 6/7] Update v2/protocol/http/utility.go Co-authored-by: Scott Nichols --- v2/protocol/http/utility.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2/protocol/http/utility.go b/v2/protocol/http/utility.go index 78d010fd1..4d4db8f29 100644 --- a/v2/protocol/http/utility.go +++ b/v2/protocol/http/utility.go @@ -16,7 +16,7 @@ import ( // NewEventFromHttpRequest returns an Event. func NewEventFromHTTPRequest(req *nethttp.Request) (*event.Event, error) { msg := NewMessageFromHttpRequest(req) - return binding.ToEvent(context.Background(), msg, nil) + return binding.ToEvent(context.Background(), msg) } // NewEventFromHttpResponse returns an Event. From 6098325bf4f8eefeed7b3f3dcba89631e102b1b5 Mon Sep 17 00:00:00 2001 From: Adam Ross Date: Thu, 15 Sep 2022 10:25:22 -0700 Subject: [PATCH 7/7] capitalize HTTP and WIP clean-up Signed-off-by: Adam Ross --- README.md | 2 +- docs/index.md | 2 +- v2/alias.go | 4 ++-- v2/protocol/http/utility.go | 13 ++++--------- v2/protocol/http/utility_test.go | 10 ++-------- 5 files changed, 10 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 2c34b551d..f57940893 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ func main() { ```go func handler(w http.ResponseWriter, r *http.Request) { - event, err := cloudevents.NewCloudEventFromHttpRequest(r) + event, err := cloudevents.NewCloudEventFromHTTPRequest(r) if err != nil { log.Print("failed to parse CloudEvent from request: %v", err) http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) diff --git a/docs/index.md b/docs/index.md index d0afe01f2..082d00b1b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -85,7 +85,7 @@ func main() { ```go func handler(w http.ResponseWriter, r *http.Request) { - event, err := cloudevents.NewCloudEventFromHttpRequest(r) + event, err := cloudevents.NewCloudEventFromHTTPRequest(r) if err != nil { log.Print("failed to parse CloudEvent from request: %v", err) http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) diff --git a/v2/alias.go b/v2/alias.go index c096e0dc3..a30980a4b 100644 --- a/v2/alias.go +++ b/v2/alias.go @@ -135,8 +135,8 @@ var ( ToMessage = binding.ToMessage // Event Creation - NewEventFromHttpRequest = http.NewEventFromHttpRequest - NewEventFromHttpResponse = http.NewEventFromHttpResponse + NewEventFromHTTPRequest = http.NewEventFromHTTPRequest + NewEventFromHTTPResponse = http.NewEventFromHTTPResponse // HTTP Messages diff --git a/v2/protocol/http/utility.go b/v2/protocol/http/utility.go index 4d4db8f29..d46a33461 100644 --- a/v2/protocol/http/utility.go +++ b/v2/protocol/http/utility.go @@ -13,19 +13,14 @@ import ( "github.com/cloudevents/sdk-go/v2/event" ) -// NewEventFromHttpRequest returns an Event. +// NewEventFromHTTPRequest returns an Event. func NewEventFromHTTPRequest(req *nethttp.Request) (*event.Event, error) { msg := NewMessageFromHttpRequest(req) return binding.ToEvent(context.Background(), msg) } -// NewEventFromHttpResponse returns an Event. +// NewEventFromHTTPResponse returns an Event. func NewEventFromHTTPResponse(resp *nethttp.Response) (*event.Event, error) { - msg := NewMessageFromHTTPResponse(resp) - return binding.ToEvent(context.Background(), msg, nil) + msg := NewMessageFromHttpResponse(resp) + return binding.ToEvent(context.Background(), msg) } - -// Write tests -// Add to pkg docs -// Add to SDK site -// Move code to preferred home. diff --git a/v2/protocol/http/utility_test.go b/v2/protocol/http/utility_test.go index 5e99a4eb4..992751cb4 100644 --- a/v2/protocol/http/utility_test.go +++ b/v2/protocol/http/utility_test.go @@ -45,14 +45,8 @@ func TestNewEventFromHttpRequest(t *testing.T) { req := httptest.NewRequest("POST", "http://localhost", nil) require.NoError(t, WriteRequest(ctx, (*binding.EventMessage)(&eventIn), req)) - got, err := NewEventFromHttpRequest(req) + got, err := NewEventFromHTTPRequest(req) require.NoError(t, err) - // Equals fails with diff like: - // - "exbinary": []uint8{0x00, 0x01, 0x02, 0x03}, - // + "exbinary": string("AAECAw=="), - // - "exint": int32(42), - // + "exint": string("42"), - // test.AssertEventEquals(t, eventIn, *got) test.AssertEvent(t, *got, test.IsValid()) }) }) @@ -89,7 +83,7 @@ func TestNewEventFromHttpResponse(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := NewEventFromHttpResponse(tt.resp) + got, err := NewEventFromHTTPResponse(tt.resp) require.NoError(t, err) test.AssertEvent(t, *got, test.IsValid()) })