Skip to content
Permalink
Browse files

fix multiple set-cookie API Gateway limitation

for real this time
  • Loading branch information...
tj committed Jun 8, 2018
1 parent 7fb1278 commit 200cb924571604bb9e35c0076144c9398da352ff
Showing with 83 additions and 0 deletions.
  1. +6 −0 internal/proxy/response.go
  2. +41 −0 internal/util/util.go
  3. +36 −0 internal/util/util_test.go
@@ -6,6 +6,8 @@ import (
"mime"
"net/http"
"strings"

"github.com/apex/up/internal/util"
)

// ResponseWriter implements the http.ResponseWriter interface
@@ -56,6 +58,10 @@ func (w *ResponseWriter) WriteHeader(status int) {

h := make(map[string]string)

// API Gateway does not support multiple set-cookie fields
// so we have to stagger the casing in order to support this.
util.FixMultipleSetCookie(w.Header())

for k, v := range w.Header() {
if len(v) > 0 {
h[k] = v[len(v)-1]
@@ -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)
}
@@ -1,6 +1,7 @@
package util

import (
"net/http"
"os/exec"
"strings"
"testing"
@@ -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 200cb92

Please sign in to comment.
You can’t perform that action at this time.