Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fdcb2d2

Browse files
authored
mqtt protocol binding (#910)
* add receiver and opener for mqtt broker Signed-off-by: myan <[email protected]> add protocol and sample files Signed-off-by: myan <[email protected]> rollback samples to go1.17 Signed-off-by: myan <[email protected]> move the protocol to go1.17 Signed-off-by: myan <[email protected]> add message test Signed-off-by: myan <[email protected]> trigger to run the integration test Signed-off-by: myan <[email protected]> fixed go mod issue Signed-off-by: myan <[email protected]> resolve the review issue Signed-off-by: myan <[email protected]> remove the useless comment Signed-off-by: myan <[email protected]> add ut for writeMessage Signed-off-by: myan <[email protected]> go mod tidy Signed-off-by: myan <[email protected]> add intergration test Signed-off-by: myan <[email protected]> solve the uncheck error Signed-off-by: myan <[email protected]> fix the integration error Signed-off-by: myan <[email protected]> fix the integration error Signed-off-by: myan <[email protected]> reply the review Signed-off-by: myan <[email protected]> simpler tests Signed-off-by: myan <[email protected]> remove the nesting Signed-off-by: myan <[email protected]> refactor the recevier logic Signed-off-by: myan <[email protected]> add a timer for assert loop Signed-off-by: myan <[email protected]> * add copyright Signed-off-by: myan <[email protected]> --------- Signed-off-by: myan <[email protected]>
1 parent f681ac6 commit fdcb2d2

File tree

18 files changed

+1093
-0
lines changed

18 files changed

+1093
-0
lines changed

.github/workflows/integration.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ jobs:
5454
}
5555
ports:
5656
- 5672:5672
57+
58+
mqtt:
59+
image: eclipse-mosquitto:1.6
60+
ports:
61+
- 1883:1883
5762

5863
steps:
5964
- name: Checkout code

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ test/benchmark/e2e/http/results/
3535
tmp/
3636
test/coverage.tmp
3737

38+
vendor/

protocol/mqtt_paho/v2/go.mod

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
module github.com/cloudevents/sdk-go/protocol/mqtt_paho/v2
2+
3+
go 1.17
4+
5+
replace github.com/cloudevents/sdk-go/v2 => ../../../v2
6+
7+
require (
8+
github.com/cloudevents/sdk-go/v2 v2.5.0
9+
github.com/eclipse/paho.golang v0.11.0
10+
github.com/stretchr/testify v1.8.0
11+
)
12+
13+
require (
14+
github.com/davecgh/go-spew v1.1.1 // indirect
15+
github.com/google/go-cmp v0.5.5 // indirect
16+
github.com/json-iterator/go v1.1.10 // indirect
17+
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
18+
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
19+
github.com/pmezard/go-difflib v1.0.0 // indirect
20+
go.uber.org/atomic v1.4.0 // indirect
21+
go.uber.org/multierr v1.1.0 // indirect
22+
go.uber.org/zap v1.10.0 // indirect
23+
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
24+
gopkg.in/yaml.v3 v3.0.1 // indirect
25+
)

protocol/mqtt_paho/v2/go.sum

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
2+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
4+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5+
github.com/eclipse/paho.golang v0.11.0 h1:6Avu5dkkCfcB61/y1vx+XrPQ0oAl4TPYtY0uw3HbQdM=
6+
github.com/eclipse/paho.golang v0.11.0/go.mod h1:rhrV37IEwauUyx8FHrvmXOKo+QRKng5ncoN1vJiJMcs=
7+
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
8+
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
9+
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
10+
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
11+
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
12+
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
13+
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
14+
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
15+
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
16+
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
17+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
18+
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
19+
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
20+
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
21+
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
22+
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
23+
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
24+
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
25+
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
26+
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
27+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
28+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
29+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
30+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
31+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
32+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
33+
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
34+
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
35+
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
36+
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
37+
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
38+
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
39+
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
40+
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
41+
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
42+
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
43+
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
44+
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
45+
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
46+
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
47+
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
48+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
49+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
50+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
51+
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
52+
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
53+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
54+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
55+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

protocol/mqtt_paho/v2/message.go

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
Copyright 2023 The CloudEvents Authors
3+
SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package mqtt_paho
7+
8+
import (
9+
"bytes"
10+
"context"
11+
"strings"
12+
13+
"github.com/cloudevents/sdk-go/v2/binding"
14+
"github.com/cloudevents/sdk-go/v2/binding/format"
15+
"github.com/cloudevents/sdk-go/v2/binding/spec"
16+
"github.com/eclipse/paho.golang/paho"
17+
)
18+
19+
const (
20+
prefix = "ce-"
21+
contentType = "Content-Type"
22+
)
23+
24+
var specs = spec.WithPrefix(prefix)
25+
26+
// Message represents a MQTT message.
27+
// This message *can* be read several times safely
28+
type Message struct {
29+
internal *paho.Publish
30+
version spec.Version
31+
format format.Format
32+
}
33+
34+
// Check if Message implements binding.Message
35+
var (
36+
_ binding.Message = (*Message)(nil)
37+
_ binding.MessageMetadataReader = (*Message)(nil)
38+
)
39+
40+
func NewMessage(msg *paho.Publish) *Message {
41+
var f format.Format
42+
var v spec.Version
43+
if msg.Properties != nil {
44+
// Use properties.User["Content-type"] to determine if message is structured
45+
if s := msg.Properties.User.Get(contentType); format.IsFormat(s) {
46+
f = format.Lookup(s)
47+
} else if s := msg.Properties.User.Get(specs.PrefixedSpecVersionName()); s != "" {
48+
v = specs.Version(s)
49+
}
50+
}
51+
return &Message{
52+
internal: msg,
53+
version: v,
54+
format: f,
55+
}
56+
}
57+
58+
func (m *Message) ReadEncoding() binding.Encoding {
59+
if m.version != nil {
60+
return binding.EncodingBinary
61+
}
62+
if m.format != nil {
63+
return binding.EncodingStructured
64+
}
65+
return binding.EncodingUnknown
66+
}
67+
68+
func (m *Message) ReadStructured(ctx context.Context, encoder binding.StructuredWriter) error {
69+
if m.version != nil {
70+
return binding.ErrNotStructured
71+
}
72+
if m.format == nil {
73+
return binding.ErrNotStructured
74+
}
75+
return encoder.SetStructuredEvent(ctx, m.format, bytes.NewReader(m.internal.Payload))
76+
}
77+
78+
func (m *Message) ReadBinary(ctx context.Context, encoder binding.BinaryWriter) (err error) {
79+
if m.format != nil {
80+
return binding.ErrNotBinary
81+
}
82+
83+
for _, userProperty := range m.internal.Properties.User {
84+
if strings.HasPrefix(userProperty.Key, prefix) {
85+
attr := m.version.Attribute(userProperty.Key)
86+
if attr != nil {
87+
err = encoder.SetAttribute(attr, userProperty.Value)
88+
} else {
89+
err = encoder.SetExtension(strings.TrimPrefix(userProperty.Key, prefix), userProperty.Value)
90+
}
91+
} else if userProperty.Key == contentType {
92+
err = encoder.SetAttribute(m.version.AttributeFromKind(spec.DataContentType), string(userProperty.Value))
93+
}
94+
if err != nil {
95+
return
96+
}
97+
}
98+
99+
if m.internal.Payload != nil {
100+
return encoder.SetData(bytes.NewBuffer(m.internal.Payload))
101+
}
102+
return nil
103+
}
104+
105+
func (m *Message) Finish(error) error {
106+
return nil
107+
}
108+
109+
func (m *Message) GetAttribute(k spec.Kind) (spec.Attribute, interface{}) {
110+
attr := m.version.AttributeFromKind(k)
111+
if attr != nil {
112+
return attr, m.internal.Properties.User.Get(prefix + attr.Name())
113+
}
114+
return nil, nil
115+
}
116+
117+
func (m *Message) GetExtension(name string) interface{} {
118+
return m.internal.Properties.User.Get(prefix + name)
119+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
Copyright 2023 The CloudEvents Authors
3+
SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package mqtt_paho
7+
8+
import (
9+
"context"
10+
"testing"
11+
12+
"github.com/cloudevents/sdk-go/v2/binding"
13+
"github.com/cloudevents/sdk-go/v2/event"
14+
"github.com/eclipse/paho.golang/paho"
15+
)
16+
17+
func TestReadStructured(t *testing.T) {
18+
tests := []struct {
19+
name string
20+
msg *paho.Publish
21+
wantErr error
22+
}{
23+
{
24+
name: "nil format",
25+
msg: &paho.Publish{
26+
Payload: []byte(""),
27+
},
28+
wantErr: binding.ErrNotStructured,
29+
},
30+
{
31+
name: "json format",
32+
msg: &paho.Publish{
33+
Payload: []byte(""),
34+
Properties: &paho.PublishProperties{
35+
User: []paho.UserProperty{{Key: contentType, Value: event.ApplicationCloudEventsJSON}},
36+
},
37+
},
38+
},
39+
}
40+
for _, tc := range tests {
41+
t.Run(tc.name, func(t *testing.T) {
42+
msg := NewMessage(tc.msg)
43+
err := msg.ReadStructured(context.Background(), (*pubMessageWriter)(tc.msg))
44+
if err != tc.wantErr {
45+
t.Errorf("Error unexpected. got: %v, want: %v", err, tc.wantErr)
46+
}
47+
})
48+
}
49+
}
50+
51+
func TestReadBinary(t *testing.T) {
52+
msg := &paho.Publish{
53+
Payload: []byte("{hello:world}"),
54+
Properties: &paho.PublishProperties{
55+
User: []paho.UserProperty{
56+
{Key: "ce-specversion", Value: "1.0"},
57+
{Key: "ce-type", Value: "binary.test"},
58+
{Key: "ce-source", Value: "test-source"},
59+
{Key: "ce-id", Value: "ABC-123"},
60+
},
61+
},
62+
}
63+
64+
message := NewMessage(msg)
65+
err := message.ReadBinary(context.Background(), (*pubMessageWriter)(msg))
66+
if err != nil {
67+
t.Errorf("Error unexpected. got: %v", err)
68+
}
69+
}

0 commit comments

Comments
 (0)