Skip to content

Commit

Permalink
add fix for multiple set-cookies API Gateway limitation
Browse files Browse the repository at this point in the history
  • Loading branch information
tj committed Jun 7, 2018
1 parent 8360c22 commit 68bdaab
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 0 deletions.
6 changes: 6 additions & 0 deletions http/relay/relay.go
Expand Up @@ -174,6 +174,12 @@ retry:
r.URL.Host = p.target.Host
res, err := DefaultTransport.RoundTrip(r)

// API Gateway does not support multiple set-cookie fields
// so we have to stagger the casing in order to support this.
if err == nil {
util.FixMultipleSetCookie(res.Header)
}

// retries disabled, don't create noise in the logs
if p.maxRetries == 0 {
return res, err
Expand Down
41 changes: 41 additions & 0 deletions internal/util/util.go
Expand Up @@ -490,3 +490,44 @@ func StripLerna(s string) string {

return s
}

// FixMultipleSetCookie staggers the casing of each set-cookie
// value to trick API Gateway into setting multiple in the response.
func FixMultipleSetCookie(h http.Header) {
cookies := h["Set-Cookie"]

if len(cookies) == 0 {
return
}

h.Del("Set-Cookie")

for i, v := range cookies {
h[BinaryCase("set-cookie", i)] = []string{v}
}
}

// BinaryCase ported from https://github.com/Gi60s/binary-case/blob/master/index.js#L86.
func BinaryCase(s string, n int) string {
var res []rune

for _, c := range s {
if c >= 65 && c <= 90 {
if n&1 > 0 {
c += 32
}
res = append(res, c)
n >>= 1
} else if c >= 97 && c <= 122 {
if n&1 > 0 {
c -= 32
}
res = append(res, c)
n >>= 1
} else {
res = append(res, c)
}
}

return string(res)
}
36 changes: 36 additions & 0 deletions internal/util/util_test.go
@@ -1,6 +1,7 @@
package util

import (
"net/http"
"os/exec"
"strings"
"testing"
Expand Down Expand Up @@ -123,3 +124,38 @@ func TestEncodeAlias(t *testing.T) {
func TestDecodeAlias(t *testing.T) {
assert.Equal(t, `v1.2.3-beta`, DecodeAlias(EncodeAlias(`v1.2.3-beta`)))
}

func TestFixMultipleSetCookie(t *testing.T) {
h := http.Header{}
h.Add("Set-Cookie", "first=tj")
h.Add("Set-Cookie", "last=holowaychuk")
h.Add("set-cookie", "pet=tobi")
FixMultipleSetCookie(h)
assert.Len(t, h, 3)
assert.Equal(t, []string{"last=holowaychuk"}, h["Set-cookie"])
assert.Equal(t, []string{"pet=tobi"}, h["sEt-cookie"])
assert.Equal(t, []string{"first=tj"}, h["set-cookie"])
}

func TestBinaryCase(t *testing.T) {
var variations []string

// create variations
for i := 0; i < 50; i++ {
variations = append(variations, BinaryCase("set-cookie", i))
}

// ensure none are malformed
for _, v := range variations {
assert.Equal(t, "set-cookie", strings.ToLower(v))
}

// ensure none are duplicates
for i, a := range variations {
for j, b := range variations {
if i != j {
assert.NotEqual(t, a, b)
}
}
}
}

0 comments on commit 68bdaab

Please sign in to comment.