Skip to content

Commit

Permalink
Helper function to create event from HTTP Request or Response (#799)
Browse files Browse the repository at this point in the history
* Helper function to create event from HTTP Request or Response

* Add missing use of encoding options and remove redundant function call

Signed-off-by: Adam Ross <adamross@google.com>

* Update v2/protocol/http/utility.go

Co-authored-by: Scott Nichols <n3wscott@tableflip.dev>

* Update v2/protocol/http/utility.go

Co-authored-by: Scott Nichols <n3wscott@tableflip.dev>

* Update v2/protocol/http/utility.go

Co-authored-by: Scott Nichols <n3wscott@tableflip.dev>

* Update v2/protocol/http/utility.go

Co-authored-by: Scott Nichols <n3wscott@tableflip.dev>

* capitalize HTTP and WIP clean-up

Signed-off-by: Adam Ross <adamross@google.com>

Signed-off-by: Adam Ross <adamross@google.com>
Co-authored-by: Scott Nichols <n3wscott@tableflip.dev>
  • Loading branch information
grayside and n3wscott committed Sep 21, 2022
1 parent c623f8b commit a718752
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 0 deletions.
13 changes: 13 additions & 0 deletions README.md
Expand Up @@ -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:
Expand Down
13 changes: 13 additions & 0 deletions docs/index.md
Expand Up @@ -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:
Expand Down
4 changes: 4 additions & 0 deletions v2/alias.go
Expand Up @@ -134,6 +134,10 @@ var (

ToMessage = binding.ToMessage

// Event Creation
NewEventFromHTTPRequest = http.NewEventFromHTTPRequest
NewEventFromHTTPResponse = http.NewEventFromHTTPResponse

// HTTP Messages

WriteHTTPRequest = http.WriteRequest
Expand Down
26 changes: 26 additions & 0 deletions v2/protocol/http/utility.go
@@ -0,0 +1,26 @@
/*
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)
}

// NewEventFromHTTPResponse returns an Event.
func NewEventFromHTTPResponse(resp *nethttp.Response) (*event.Event, error) {
msg := NewMessageFromHttpResponse(resp)
return binding.ToEvent(context.Background(), msg)
}
91 changes: 91 additions & 0 deletions v2/protocol/http/utility_test.go
@@ -0,0 +1,91 @@
/*
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.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))

got, err := NewEventFromHTTPRequest(req)
require.NoError(t, err)
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())
})
}
}

0 comments on commit a718752

Please sign in to comment.