Skip to content

Commit 8b345a6

Browse files
authored
feat: added serializable http.Header type (#321)
1 parent c16d77d commit 8b345a6

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed

util/headers.go

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package util
2+
3+
import (
4+
"encoding/json"
5+
"net/http"
6+
)
7+
8+
// Headers is a serializable version of http.Header it supports both yaml & json formats.
9+
// Headers expects the yaml/json representation to be a map[string]string.
10+
type Headers struct {
11+
http.Header
12+
}
13+
14+
func (h Headers) MarshalYAML() (interface{}, error) {
15+
return h.Header, nil
16+
}
17+
18+
func (h Headers) MarshalJSON() ([]byte, error) {
19+
return json.Marshal(h.Header)
20+
}
21+
22+
func (h *Headers) UnmarshalYAML(unmarshal func(interface{}) error) error {
23+
var headers map[string]string
24+
if err := unmarshal(&headers); err != nil {
25+
return err
26+
}
27+
28+
h.Header = http.Header{}
29+
for k, v := range headers {
30+
h.Add(k, v)
31+
}
32+
33+
return nil
34+
}
35+
36+
func (h *Headers) UnmarshalJSON(b []byte) error {
37+
var headers map[string]string
38+
if err := json.Unmarshal(b, &headers); err != nil {
39+
return err
40+
}
41+
42+
h.Header = http.Header{}
43+
for k, v := range headers {
44+
h.Add(k, v)
45+
}
46+
47+
return nil
48+
}

util/headers_test.go

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package util
2+
3+
import (
4+
"encoding/json"
5+
"net/http"
6+
"testing"
7+
8+
"github.com/stretchr/testify/assert"
9+
"github.com/stretchr/testify/require"
10+
"gopkg.in/yaml.v3"
11+
)
12+
13+
func TestHeaders_Unmarshal(t *testing.T) {
14+
testCases := []struct {
15+
name string
16+
url string
17+
expected http.Header
18+
errCheck require.ErrorAssertionFunc
19+
unmarshal func([]byte, interface{}) error
20+
}{
21+
{"invalid-json", `{"h": "<>:hey>"}`, nil, require.Error, json.Unmarshal},
22+
{"null-json", `{"h": null}`, http.Header{}, require.NoError, json.Unmarshal},
23+
{"empty-json", `{"h": {}}`, http.Header{}, require.NoError, json.Unmarshal},
24+
{
25+
"valid-json",
26+
`{"h": {"X-NF-TEST-A": "aAa", "x-nf-test-b": "bBb"}}`,
27+
http.Header{"X-Nf-Test-A": {"aAa"}, "X-Nf-Test-B": {"bBb"}},
28+
require.NoError,
29+
json.Unmarshal,
30+
},
31+
{
32+
"duplicate-json",
33+
`{"h": {"X-NF-TEST-A": "aAa", "X-Nf-Test-A": "bBb", "x-nf-test-a": "cCc"}}`,
34+
http.Header{"X-Nf-Test-A": {"aAa", "bBb", "cCc"}},
35+
require.NoError,
36+
json.Unmarshal,
37+
},
38+
39+
{"invalid-yaml", `h: ""`, nil, require.Error, yaml.Unmarshal},
40+
{"null-yaml", `h: null`, http.Header{}, require.NoError, yaml.Unmarshal},
41+
{"empty-yaml", `h: {}`, http.Header{}, require.NoError, yaml.Unmarshal},
42+
{
43+
"valid-yaml",
44+
`h: {"X-NF-TEST-A": "aAa", "x-nf-test-b": "bBb"}`,
45+
http.Header{"X-Nf-Test-A": {"aAa"}, "X-Nf-Test-B": {"bBb"}},
46+
require.NoError,
47+
yaml.Unmarshal,
48+
},
49+
{
50+
"duplicate-yaml",
51+
`h: {"X-NF-TEST-A": "aAa", "X-Nf-Test-A": "bBb", "x-nf-test-a": "cCc"}`,
52+
http.Header{"X-Nf-Test-A": {"aAa", "bBb", "cCc"}},
53+
require.NoError,
54+
yaml.Unmarshal,
55+
},
56+
}
57+
58+
for _, tc := range testCases {
59+
t.Run(tc.name, func(t *testing.T) {
60+
var s struct {
61+
H Headers `json:"h"`
62+
}
63+
tc.errCheck(t, tc.unmarshal([]byte(tc.url), &s))
64+
assert.ObjectsAreEqualValues(tc.expected, s.H.Header)
65+
})
66+
}
67+
}
68+
69+
func TestHeaders_Marshal(t *testing.T) {
70+
testCases := []struct {
71+
name string
72+
marshal func(interface{}) ([]byte, error)
73+
expected string
74+
}{
75+
{"json", json.Marshal, `{"h":{"X-Nf-Test-A":["aAa","bBb"]}}`},
76+
{"yaml", yaml.Marshal, "h:\n X-Nf-Test-A:\n - aAa\n - bBb\n"},
77+
}
78+
79+
for _, tc := range testCases {
80+
t.Run(tc.name, func(t *testing.T) {
81+
h := struct {
82+
H Headers `json:"h" yaml:"h"`
83+
}{H: Headers{http.Header{"X-Nf-Test-A": {"aAa", "bBb"}}}}
84+
85+
serialized, err := tc.marshal(h)
86+
require.NoError(t, err)
87+
assert.Equal(t, tc.expected, string(serialized))
88+
})
89+
}
90+
}

0 commit comments

Comments
 (0)