Skip to content

Commit 542b5be

Browse files
committed
Implement message attribute parsing for PublishBatch
Factor out attribute parsing for SendMessage, SendMessageBatch, and Publish in the process. I believe this change is adequately covered by the smoke tests, but am happy to be convinced otherwise
1 parent b7de554 commit 542b5be

File tree

3 files changed

+110
-86
lines changed

3 files changed

+110
-86
lines changed

app/models/requests.go

Lines changed: 29 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"fmt"
66
"net/url"
77
"strconv"
8-
"strings"
98

109
"golang.org/x/text/cases"
1110
"golang.org/x/text/language"
@@ -189,30 +188,41 @@ type SendMessageRequest struct {
189188
QueueUrl string `json:"QueueUrl" schema:"QueueUrl"`
190189
}
191190

192-
func (r *SendMessageRequest) SetAttributesFromForm(values url.Values) {
191+
func parseMessageAttributes(values url.Values, keyPrefix string) map[string]MessageAttribute {
192+
result := map[string]MessageAttribute{}
193+
193194
for i := 1; true; i++ {
194-
nameKey := fmt.Sprintf("MessageAttribute.%d.Name", i)
195+
nameKey := fmt.Sprintf("%s.%d.Name", keyPrefix, i)
195196
name := values.Get(nameKey)
196197
if name == "" {
197198
break
198199
}
199200

200-
dataTypeKey := fmt.Sprintf("MessageAttribute.%d.Value.DataType", i)
201+
dataTypeKey := fmt.Sprintf("%s.%d.Value.DataType", keyPrefix, i)
201202
dataType := values.Get(dataTypeKey)
202203
if dataType == "" {
203-
log.Warnf("DataType of MessageAttribute %s is missing, MD5 checksum will most probably be wrong!\n", name)
204+
log.Warnf("DataType of message attribute %s is missing, MD5 checksum will most probably be wrong!\n", name)
204205
continue
205206
}
206207

207-
stringValue := values.Get(fmt.Sprintf("MessageAttribute.%d.Value.StringValue", i))
208-
binaryValue := values.Get(fmt.Sprintf("MessageAttribute.%d.Value.BinaryValue", i))
208+
stringValue := values.Get(fmt.Sprintf("%s.%d.Value.StringValue", keyPrefix, i))
209+
binaryValue := values.Get(fmt.Sprintf("%s.%d.Value.BinaryValue", keyPrefix, i))
209210

210-
r.MessageAttributes[name] = MessageAttribute{
211+
result[name] = MessageAttribute{
211212
DataType: dataType,
212213
StringValue: stringValue,
213214
BinaryValue: []byte(binaryValue),
214215
}
215216
}
217+
218+
if len(result) > 0 {
219+
return result
220+
}
221+
return nil
222+
}
223+
224+
func (r *SendMessageRequest) SetAttributesFromForm(values url.Values) {
225+
r.MessageAttributes = parseMessageAttributes(values, "MessageAttribute")
216226
}
217227

218228
func NewSendMessageBatchRequest() *SendMessageBatchRequest {
@@ -225,53 +235,8 @@ type SendMessageBatchRequest struct {
225235
}
226236

227237
func (r *SendMessageBatchRequest) SetAttributesFromForm(values url.Values) {
228-
for key := range values {
229-
230-
keySegments := strings.Split(key, ".")
231-
//If index value size is 3 or less, there is no attribute value
232-
if len(keySegments) <= 3 {
233-
continue
234-
}
235-
236-
// Both patterns below are supported here.
237-
// strconv.Atoi(keySegments[1] - targets the index value in pattern: `Entries.1.MessageBody`
238-
// strconv.Atoi(keySegments[3] - targets the index value in pattern: `Entries.1.MessageAttributes.1.Name`
239-
entryIndex, err1 := strconv.Atoi(keySegments[1])
240-
attributeIndex, err2 := strconv.Atoi(keySegments[3])
241-
242-
// If the entry index and attribute index cannot be obtained, the attribute will not be set, so skip
243-
if err1 != nil || err2 != nil {
244-
continue
245-
}
246-
247-
nameKey := fmt.Sprintf("Entries.%d.MessageAttributes.%d.Name", entryIndex, attributeIndex)
248-
if key != nameKey {
249-
continue
250-
}
251-
name := values.Get(nameKey)
252-
dataTypeKey := fmt.Sprintf("Entries.%d.MessageAttributes.%d.Value.DataType", entryIndex, attributeIndex)
253-
dataType := values.Get(dataTypeKey)
254-
if dataType == "" {
255-
log.Warnf("DataType of MessageAttribute %s is missing, MD5 checksum will most probably be wrong!\n", name)
256-
continue
257-
}
258-
259-
stringValue := values.Get(fmt.Sprintf("Entries.%d.MessageAttributes.%d.Value.StringValue", entryIndex, attributeIndex))
260-
binaryValue := values.Get(fmt.Sprintf("Entries.%d.MessageAttributes.%d.Value.BinaryValue", entryIndex, attributeIndex))
261-
262-
if r.Entries[entryIndex].MessageAttributes == nil {
263-
r.Entries[entryIndex].MessageAttributes = make(map[string]MessageAttribute)
264-
}
265-
266-
r.Entries[entryIndex].MessageAttributes[name] = MessageAttribute{
267-
DataType: dataType,
268-
StringValue: stringValue,
269-
BinaryValue: []byte(binaryValue),
270-
}
271-
272-
if _, ok := r.Entries[entryIndex].MessageAttributes[name]; !ok {
273-
log.Warnf("StringValue or BinaryValue of MessageAttribute %s is missing, MD5 checksum will most probably be wrong!\n", name)
274-
}
238+
for entryIndex := range r.Entries {
239+
r.Entries[entryIndex].MessageAttributes = parseMessageAttributes(values, fmt.Sprintf("Entries.%d.MessageAttributes", entryIndex))
275240
}
276241
}
277242

@@ -744,34 +709,7 @@ type PublishRequest struct {
744709
}
745710

746711
func (r *PublishRequest) SetAttributesFromForm(values url.Values) {
747-
attributes := map[string]MessageAttribute{}
748-
for i := 1; true; i++ {
749-
nameKey := fmt.Sprintf("MessageAttributes.entry.%d.Name", i)
750-
name := values.Get(nameKey)
751-
if name == "" {
752-
break
753-
}
754-
755-
dataTypeKey := fmt.Sprintf("MessageAttributes.entry.%d.Value.DataType", i)
756-
dataType := values.Get(dataTypeKey)
757-
if dataType == "" {
758-
log.Warnf("DataType of MessageAttribute %s is missing, MD5 checksum will most probably be wrong!\n", name)
759-
continue
760-
}
761-
762-
stringValue := values.Get(fmt.Sprintf("MessageAttributes.entry.%d.Value.StringValue", i))
763-
binaryValue := values.Get(fmt.Sprintf("MessageAttributes.entry.%d.Value.BinaryValue", i))
764-
765-
if r.MessageAttributes == nil {
766-
r.MessageAttributes = make(map[string]MessageAttribute)
767-
}
768-
attributes[name] = MessageAttribute{
769-
DataType: caser.String(dataType), // capitalize
770-
StringValue: stringValue,
771-
BinaryValue: []byte(binaryValue),
772-
}
773-
}
774-
r.MessageAttributes = attributes
712+
r.MessageAttributes = parseMessageAttributes(values, "MessageAttributes.entry")
775713
}
776714

777715
// Satisfy the AbstractPublishEntry interface
@@ -890,7 +828,14 @@ type PublishBatchRequest struct {
890828
}
891829

892830
func (r *PublishBatchRequest) SetAttributesFromForm(values url.Values) {
893-
// TAG - Implement me
831+
for entryIndex, entry := range r.PublishBatchRequestEntries.Member {
832+
if entry == nil {
833+
// The form values are 1-indexed; at the point that this is called, the first element in the
834+
// list of requests will be nil.
835+
continue
836+
}
837+
entry.MessageAttributes = parseMessageAttributes(values, fmt.Sprintf("PublishBatchRequestEntries.member.%d.MessageAttributes.entry", entryIndex))
838+
}
894839
}
895840

896841
type PublishBatchRequestEntries struct {

app/models/requests_test.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,3 +621,81 @@ func Test_DeleteMessageBatchRequest_SetAttributesFromForm_stops_at_invalid_keys(
621621
assert.Equal(t, "message-id-1", dmbr.Entries[0].Id)
622622
assert.Equal(t, "receipt-handle-1", dmbr.Entries[0].ReceiptHandle)
623623
}
624+
625+
func TestParseMessageAttributes(t *testing.T) {
626+
for _, tc := range []struct {
627+
description string
628+
values url.Values
629+
keyPrefix string
630+
want map[string]MessageAttribute
631+
}{
632+
{
633+
description: "empty",
634+
values: url.Values{},
635+
keyPrefix: "foo",
636+
want: nil,
637+
},
638+
{
639+
description: "simple",
640+
values: url.Values{
641+
"MessageAttribute.1.Name": []string{"Attr1"},
642+
"MessageAttribute.1.Value.DataType": []string{"String"},
643+
"MessageAttribute.1.Value.StringValue": []string{"Value1"},
644+
"MessageAttribute.2.Name": []string{"Attr2"},
645+
"MessageAttribute.2.Value.DataType": []string{"Binary"},
646+
"MessageAttribute.2.Value.BinaryValue": []string{"VmFsdWUy"},
647+
},
648+
keyPrefix: "MessageAttribute",
649+
want: map[string]MessageAttribute{
650+
"Attr1": {
651+
DataType: "String",
652+
StringValue: "Value1",
653+
BinaryValue: []byte{},
654+
},
655+
"Attr2": {
656+
DataType: "Binary",
657+
BinaryValue: []byte("VmFsdWUy"),
658+
},
659+
},
660+
},
661+
{
662+
description: "attributes after empty name ignored",
663+
values: url.Values{
664+
"MessageAttribute.1.Name": []string{""},
665+
"MessageAttribute.1.Value.DataType": []string{"String"},
666+
"MessageAttribute.1.Value.StringValue": []string{"Value4"},
667+
"MessageAttribute.2.Name": []string{"Attr2"},
668+
"MessageAttribute.2.Value.DataType": []string{"Binary"},
669+
"MessageAttribute.2.Value.BinaryValue": []string{"VmFsdWUy"},
670+
},
671+
keyPrefix: "MessageAttribute",
672+
want: nil,
673+
},
674+
{
675+
description: "attributes after missing number ignored",
676+
values: url.Values{
677+
// Note starting from 2
678+
"MessageAttribute.2.Name": []string{"Attr2"},
679+
"MessageAttribute.2.Value.DataType": []string{"Binary"},
680+
"MessageAttribute.2.Value.BinaryValue": []string{"VmFsdWUy"},
681+
},
682+
keyPrefix: "MessageAttribute",
683+
want: nil,
684+
},
685+
{
686+
description: "empty DataType ignored",
687+
values: url.Values{
688+
"MessageAttribute.1.Name": []string{"Attr4"},
689+
"MessageAttribute.1.Value.DataType": []string{""},
690+
"MessageAttribute.1.Value.StringValue": []string{"Value4"},
691+
},
692+
keyPrefix: "MessageAttribute",
693+
want: nil,
694+
},
695+
} {
696+
t.Run(tc.description, func(t *testing.T) {
697+
got := parseMessageAttributes(tc.values, tc.keyPrefix)
698+
assert.Equal(t, tc.want, got)
699+
})
700+
}
701+
}

smoke_tests/sns_publish_batch_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,9 @@ func Test_Publish_batch_sqs_json_raw_with_optional_fields(t *testing.T) {
277277

278278
assert.Equal(t, message, *receivedMessage.Messages[0].Body)
279279
assert.Equal(t, "649b2c548f103e499304eda4d6d4c5a2", *receivedMessage.Messages[0].MD5OfBody)
280-
assert.Equal(t, "d41d8cd98f00b204e9800998ecf8427e", *receivedMessage.Messages[0].MD5OfMessageAttributes)
281-
assert.Len(t, receivedMessage.Messages[0].MessageAttributes, 0)
280+
assert.Equal(t, "45a48b32ccd821cc81a8c28fbac4cd97", *receivedMessage.Messages[0].MD5OfMessageAttributes)
281+
assert.Equal(t, *receivedMessage.Messages[0].MessageAttributes["test"].DataType, "String")
282+
assert.Equal(t, *receivedMessage.Messages[0].MessageAttributes["test"].StringValue, "string-value")
282283
assert.NotNil(t, receivedMessage.Messages[0].MessageId)
283284
assert.NotNil(t, receivedMessage.Messages[0].ReceiptHandle)
284285

0 commit comments

Comments
 (0)