Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Header getter/setter should be case in-sensitive #331

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions ftwhttp/header.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package ftwhttp
import (
"bytes"
"io"
"net/textproto"
"sort"

"github.com/rs/zerolog/log"
Expand Down Expand Up @@ -34,7 +35,9 @@ func (w stringWriter) WriteString(s string) (n int, err error) {

// Add adds the key, value pair to the header.
// It appends to any existing values associated with key.
// The key is case-insensitive
func (h Header) Add(key, value string) {
theseion marked this conversation as resolved.
Show resolved Hide resolved
key = canonicalKey(key)
theseion marked this conversation as resolved.
Show resolved Hide resolved
if h.Get(key) == "" {
h.Set(key, value)
}
Expand All @@ -43,35 +46,37 @@ func (h Header) Add(key, value string) {
// Set sets the header entries associated with key to
// the single element value. It replaces any existing
// values associated with key.
// The key is case-insensitive
func (h Header) Set(key, value string) {
h[key] = value
h[canonicalKey(key)] = value
}

// Get gets the first value associated with the given key.
// It is case insensitive;
// If there are no values associated with the key, Get returns "".
// The key is case-insensitive
func (h Header) Get(key string) string {
if h == nil {
return ""
}
v := h[key]
v := h[canonicalKey(key)]

return v
}

// Value returns the value associated with the given key.
// It is case insensitive;
// The key is case-insensitive
func (h Header) Value(key string) string {
if h == nil {
return ""
}

return h[key]
return h[canonicalKey(key)]
}

// Del deletes the value associated with key.
// The key is case-insensitive
func (h Header) Del(key string) {
delete(h, key)
delete(h, canonicalKey(key))
}

// Write writes a header in wire format.
Expand Down Expand Up @@ -138,3 +143,8 @@ func (h Header) getSortedHeadersByName() []string {

return keys
}

// canonicalKey transforms given to the canonical form
func canonicalKey(key string) string {
return textproto.CanonicalMIMEHeaderKey(key)
}
51 changes: 49 additions & 2 deletions ftwhttp/header_test.go
theseion marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,54 @@ func (s *headerTestSuite) TestHeaderWriteString() {
}
}

func (s *headerTestSuite) TestHeaderSetGet() {
func (s *headerTestSuite) TestHeaderAdd() {
h := Header{
"Custom": "Value",
}
h.Add("Other", "Value")
value := h.Get("Other")
value := h["Other"]
theseion marked this conversation as resolved.
Show resolved Hide resolved
s.Equalf("Value", value, "got: %s, want: %s\n", value, "Value")
}

func (s *headerTestSuite) TestHeaderAdd_CaseInsensitiveKey() {
h := Header{}

h.Add("camel-Header", "Value")
value := h["Camel-Header"]
s.Equalf("Value", value, "got: %s, want: %s\n", value, "Value")

h.Add("headerwithouthyphens", "Value2")
value = h["headerwithouthyphens"]
s.Equalf("", value, "got: %s, want: %s\n", value, "")
value = h["Headerwithouthyphens"]
s.Equalf("Value2", value, "got: %s, want: %s\n", value, "Value2")
}

func (s *headerTestSuite) TestHeaderGet() {
h := Header{
"Custom": "Value",
}
value := h.Get("Custom")
s.Equalf("Value", value, "got: %s, want: %s\n", value, "Value")
}

func (s *headerTestSuite) TestHeaderGet_CaseInsensitiveKey() {
h := Header{
"Custom": "Value",
"Custom-Header": "Value2",
"case-sensitive-Header-Key": "Value3",
}

value := h.Get("Custom")
s.Equalf("Value", value, "got: %s, want: %s\n", value, "Value")

value = h.Get("Custom-Header")
s.Equalf("Value2", value, "got: %s, want: %s\n", value, "Value2")

value = h.Get("case-sensitive-Header-Key")
s.Equalf("", value, "got: %s, want: %s\n", value, "")
}

func (s *headerTestSuite) TestHeaderDel() {
for i, test := range headerWriteTests {
// we clone it because we are modifying the original
Expand All @@ -126,6 +165,14 @@ func (s *headerTestSuite) TestHeaderDel() {
}
}

theseion marked this conversation as resolved.
Show resolved Hide resolved
func (s *headerTestSuite) TestHeaderDel_CaseInsensitiveKey() {
h := Header{}
h.Add("content-Type", "Value")
h.Del("Content-type")
value := h.Get("Content-Type")
s.Equalf("", value, "#case: got: %s, want: %s\n", value, "")
}

func (s *headerTestSuite) TestHeaderClone() {
h := Header{
"Custom": "Value",
Expand Down