Skip to content

Commit 79f4756

Browse files
Trifonova.AntoniaTrifonova.Antonia
Trifonova.Antonia
authored and
Trifonova.Antonia
committed
Poc Headers improvements
Signed-off-by: Antonia Trifonova [email protected]
1 parent 16a0ee7 commit 79f4756

File tree

3 files changed

+61
-50
lines changed

3 files changed

+61
-50
lines changed

protocol/headers.go

+32-46
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@
1212
package protocol
1313

1414
import (
15+
"encoding/json"
1516
"fmt"
1617
"strconv"
1718
"strings"
1819
"time"
20+
21+
"github.com/google/uuid"
1922
)
2023

2124
const (
@@ -72,15 +75,16 @@ const (
7275
HeaderContentType = "content-type"
7376
)
7477

75-
// Headers represents all Ditto-specific headers along with additional HTTP/etc. headers
78+
// Headers represents all Ditto-specific headers along with additional HTTP/etc. Headers
7679
// that can be applied depending on the transport used.
77-
// For the pre-defined headers, the values are in the row type. The getter methods are provided
78-
// to get the header value in specified type.
80+
//
81+
// The header values in this map should be serialized.
82+
// The provided getter methods returns the header values which is associated with this definition's key.
7983
// See https://www.eclipse.org/ditto/protocol-specification.html
8084
type Headers map[string]interface{}
8185

8286
// CorrelationID returns the 'correlation-id' header value if it is presented.
83-
// If the header value is not presented, the CorrelationID returns empty string.
87+
// If the header value is not presented, the 'correlation-id' header value will be generated in UUID format.
8488
//
8589
// If there are two headers differing only in capitalization CorrelationID returns the first value.
8690
// To use the provided key to get the value, access the map directly.
@@ -90,10 +94,10 @@ func (h Headers) CorrelationID() string {
9094
return v.(string)
9195
}
9296
}
93-
return ""
97+
return uuid.New().String()
9498
}
9599

96-
// Timeout returns the 'timeout' header value if it is presented
100+
// Timeout returns the 'timeout' header value if it is presented.
97101
// The default and maximum value is duration of 60 seconds.
98102
// If the header value is not presented, the Timout returns the default value.
99103
//
@@ -134,7 +138,7 @@ func parseTimeout(timeout string) (time.Duration, error) {
134138
t = time.Duration(i) * time.Second
135139
}
136140
}
137-
if t >= 0 && t < time.Hour {
141+
if t >= 0 && t <= 60*time.Second {
138142
return t, nil
139143
}
140144
}
@@ -284,7 +288,7 @@ func (h Headers) ReplyTo() string {
284288
}
285289

286290
// Version returns the 'version' header value if it is presented.
287-
// If the header value is not presented, the Version returns 0.
291+
// If the header value is not presented, the Version returns 2.
288292
//
289293
// If there are two headers differing only in capitalization, the Version returns the first value.
290294
// To use the provided key to get the value, access the map directly.
@@ -294,7 +298,7 @@ func (h Headers) Version() int64 {
294298
return v.(int64)
295299
}
296300
}
297-
return 0
301+
return 2
298302
}
299303

300304
// ContentType returns the 'content-type' header value if it is presented.
@@ -325,44 +329,26 @@ func (h Headers) Generic(id string) interface{} {
325329
return nil
326330
}
327331

328-
// // MarshalJSON marshels Headers.
329-
// func (h *Headers) MarshalJSON() ([]byte, error) {
330-
// // TODO validation
331-
// // convert - timeout - ditto timeout string
332-
// // error for invalid values
333-
// return json.Marshal(h.Values)
334-
// }
335-
336-
// UnmarshalJSON unmarshels Headers.
337-
// func (h *Headers) UnmarshalJSON(data []byte) error {
338-
// var m map[string]interface{}
339-
340-
// if err := json.Unmarshal(data, &m); err != nil {
341-
// return err
342-
// }
343-
344-
// for k := range m {
345-
// // TODO for all headers
346-
// // error for ivalid values
347-
// if strings.EqualFold(k, HeaderTimeout) && m[k] != nil {
348-
// m[k] = parseTimeout(m[k].(string))
349-
// }
350-
// }
351-
352-
// h.Values = m
353-
354-
// return nil
355-
// }
356-
357332
// UnmarshalJSON unmarshels Headers.
358-
// func (h *Headers) UnmarshalJSON(data []byte) error {
359-
// temp := make(map[string]interface{})
360-
// if err := json.Unmarshal(data, &temp); err != nil {
361-
// return err
362-
// }
363-
// *h = temp
364-
// return nil
365-
// }
333+
//
334+
// The header names are case-insensitive and case-preserving.
335+
// If there is the same header name as the provided and the difference is
336+
// in capitalization the new header name will be set.
337+
func (h *Headers) UnmarshalJSON(data []byte) error {
338+
temp := make(map[string]interface{})
339+
if err := json.Unmarshal(data, &temp); err != nil {
340+
return err
341+
}
342+
for k := range temp {
343+
for k1 := range *h {
344+
if strings.EqualFold(k, k1) {
345+
delete(*h, k1)
346+
}
347+
}
348+
}
349+
*h = temp
350+
return nil
351+
}
366352

367353
// With sets new Headers to the existing.
368354
func (h Headers) With(opts ...HeaderOpt) Headers {

protocol/headers_opts.go

+10
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ package protocol
1313

1414
import (
1515
"strconv"
16+
"strings"
1617
"time"
1718
)
1819

@@ -188,8 +189,17 @@ func WithContentType(contentType string) HeaderOpt {
188189
}
189190

190191
// WithGeneric sets the value of the provided key header.
192+
//
193+
// The header names are case-insensitive and case-preserving.
194+
// If there is the same header name as the provided and the difference is
195+
// in capitalization the new header name will be set.
191196
func WithGeneric(headerID string, value interface{}) HeaderOpt {
192197
return func(headers Headers) error {
198+
for k := range headers {
199+
if strings.EqualFold(k, headerID) {
200+
delete(headers, k)
201+
}
202+
}
193203
headers[headerID] = value
194204
return nil
195205
}

protocol/headers_test.go

+19-4
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@ func TestHeadersCorrelationID(t *testing.T) {
3030
},
3131
"test_without_correlation_id": {
3232
testHeader: Headers{},
33-
want: "",
3433
},
35-
3634
"test_empty_correlation_id": {
3735
testHeader: Headers{HeaderCorrelationID: ""},
3836
want: "",
@@ -42,7 +40,11 @@ func TestHeadersCorrelationID(t *testing.T) {
4240
for testName, testCase := range tests {
4341
t.Run(testName, func(t *testing.T) {
4442
got := testCase.testHeader.CorrelationID()
45-
internal.AssertEqual(t, testCase.want, got)
43+
if testCase.testHeader[HeaderCorrelationID] == nil {
44+
internal.AssertNotNil(t, got)
45+
} else {
46+
internal.AssertEqual(t, testCase.want, got)
47+
}
4648
})
4749
}
4850
}
@@ -367,7 +369,7 @@ func TestHeadersVersion(t *testing.T) {
367369
},
368370
"test_without_version": {
369371
testHeader: Headers{},
370-
want: 0,
372+
want: 2,
371373
},
372374
}
373375

@@ -509,3 +511,16 @@ func TestCaseInsensitiveKey(t *testing.T) {
509511
json.Unmarshal([]byte(data), &envelope.Headers)
510512
internal.AssertEqual(t, "correlation-id-3", envelope.Headers["correlation-iD"])
511513
}
514+
515+
func TestCasePreservedKey(t *testing.T) {
516+
headers := Headers{HeaderCorrelationID: "correlation-id-1"}
517+
518+
data := `{
519+
"correlation-iD":"correlation-id-2"
520+
}`
521+
522+
want := Headers{"correlation-iD": "correlation-id-2"}
523+
524+
headers.UnmarshalJSON([]byte(data))
525+
internal.AssertEqual(t, want, headers)
526+
}

0 commit comments

Comments
 (0)