Skip to content

Commit 8028515

Browse files
authored
feat: add headers config (#40)
* feat: add headers config * fix: cache test
1 parent ab7a00c commit 8028515

File tree

5 files changed

+379
-56
lines changed

5 files changed

+379
-56
lines changed

config/config.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ type CacheConfig struct {
3737
IgnorePaths []string
3838
ShouldHashQuery bool
3939
HashQueryIgnore map[string]bool
40+
HashHeaders []string
4041
}
42+
4143
type Config struct {
4244
ServerConfig ServerConfig
4345
CacheConfig CacheConfig
@@ -48,7 +50,7 @@ func New() Config {
4850
serverConfig := ServerConfig{
4951
Port: getEnv("SERVER_PORT", "8000"),
5052
GracePeriod: getEnvAsInt("SHUTDOWN_GRACE_PERIOD", "30"),
51-
LogLevel: getEnvAsLogLevel("SERVER_LOG_LEVEL"),
53+
LogLevel: getEnvAsLogLevel("LOG_LEVEL"),
5254
Storage: getEnv("SERVER_STORAGE", ""),
5355
}
5456

@@ -57,9 +59,10 @@ func New() Config {
5759
DownstreamHost: getEnvAsURL("DOWNSTREAM_HOST", ""),
5860
Size: getEnvAsFloat("CACHE_SIZE_MB", "10"),
5961
IgnorePaths: getEnvAsSlice("CACHE_IGNORE_ENDPOINTS"),
60-
StaleInSeconds: getEnvAsInt("CACHE_STALE_WHILE_REVALIDATE_SEC", "5"),
62+
StaleInSeconds: getEnvAsInt("CACHE_STALE_WHILE_REVALIDATE_SEC", "60"),
6163
ShouldHashQuery: getEnvAsBool("CACHE_SHOULD_HASH_QUERY", "true"),
6264
HashQueryIgnore: hashQueryIgnoreMap(getEnvAsSlice("CACHE_HASH_QUERY_IGNORE")),
65+
HashHeaders: getEnvAsSlice("CACHE_HASH_HEADERS"),
6366
}
6467

6568
if strings.ToLower(serverConfig.Storage) == "memory" {

config/config_test.go

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
func TestConfig(t *testing.T) {
1010
t.Run("inMemory config", func(t *testing.T) {
1111
defer setupEnv(t, "SERVER_STORAGE", "memory")()
12+
defer setupEnv(t, "CACHE_STRATEGY", "memory")()
13+
defer setupEnv(t, "DOWNSTREAM_HOST", "http://localhost:8080")()
1214
config := New()
1315

1416
assert.NotNil(t, config)
@@ -17,9 +19,132 @@ func TestConfig(t *testing.T) {
1719
t.Run("redis config", func(t *testing.T) {
1820
defer setupEnv(t, "SERVER_STORAGE", "redis")()
1921
defer setupEnv(t, "REDIS_CONNECTION_STRING", "redis")()
22+
defer setupEnv(t, "CACHE_STRATEGY", "redis")()
23+
defer setupEnv(t, "DOWNSTREAM_HOST", "http://localhost:8080")()
2024
config := New()
2125

2226
assert.NotNil(t, config)
2327
assert.Equal(t, "redis", config.RedisConfig.ConnectionString)
2428
})
29+
30+
t.Run("header configuration", func(t *testing.T) {
31+
tests := []struct {
32+
name string
33+
hashHeaders string
34+
hashHeadersIgnore string
35+
wantHeaders []string
36+
}{
37+
{
38+
name: "empty headers",
39+
hashHeaders: "",
40+
hashHeadersIgnore: "",
41+
wantHeaders: []string{},
42+
},
43+
{
44+
name: "single header",
45+
hashHeaders: "Authorization",
46+
hashHeadersIgnore: "",
47+
wantHeaders: []string{"Authorization"},
48+
},
49+
{
50+
name: "multiple headers",
51+
hashHeaders: "Authorization,X-User-ID,Accept",
52+
hashHeadersIgnore: "",
53+
wantHeaders: []string{"Authorization", "X-User-ID", "Accept"},
54+
},
55+
{
56+
name: "headers with ignore",
57+
hashHeaders: "Authorization,X-User-ID,Accept",
58+
hashHeadersIgnore: "X-User-ID",
59+
wantHeaders: []string{"Authorization", "X-User-ID", "Accept"},
60+
},
61+
{
62+
name: "case insensitive headers",
63+
hashHeaders: "AUTHORIZATION,x-user-id,accept",
64+
hashHeadersIgnore: "X-USER-ID",
65+
wantHeaders: []string{"AUTHORIZATION", "x-user-id", "accept"},
66+
},
67+
{
68+
name: "whitespace in headers",
69+
hashHeaders: " Authorization , X-User-ID , Accept ",
70+
hashHeadersIgnore: " X-User-ID ",
71+
wantHeaders: []string{"Authorization", "X-User-ID", "Accept"},
72+
},
73+
{
74+
name: "duplicate headers",
75+
hashHeaders: "Authorization,Authorization,X-User-ID",
76+
hashHeadersIgnore: "",
77+
wantHeaders: []string{"Authorization", "Authorization", "X-User-ID"},
78+
},
79+
}
80+
81+
for _, tt := range tests {
82+
t.Run(tt.name, func(t *testing.T) {
83+
defer setupEnv(t, "CACHE_HASH_HEADERS", tt.hashHeaders)()
84+
defer setupEnv(t, "CACHE_HASH_HEADERS_IGNORE", tt.hashHeadersIgnore)()
85+
86+
config := New()
87+
88+
assert.Equal(t, tt.wantHeaders, config.CacheConfig.HashHeaders)
89+
})
90+
}
91+
})
92+
93+
t.Run("query configuration", func(t *testing.T) {
94+
tests := []struct {
95+
name string
96+
shouldHashQuery string
97+
queryIgnore string
98+
wantHashQuery bool
99+
wantIgnore map[string]bool
100+
}{
101+
{
102+
name: "default query hashing",
103+
shouldHashQuery: "",
104+
queryIgnore: "",
105+
wantHashQuery: true,
106+
wantIgnore: map[string]bool{},
107+
},
108+
{
109+
name: "disabled query hashing",
110+
shouldHashQuery: "false",
111+
queryIgnore: "",
112+
wantHashQuery: false,
113+
wantIgnore: map[string]bool{},
114+
},
115+
{
116+
name: "query ignore parameters",
117+
shouldHashQuery: "true",
118+
queryIgnore: "timestamp,request_id",
119+
wantHashQuery: true,
120+
wantIgnore: map[string]bool{"timestamp": true, "request_id": true},
121+
},
122+
{
123+
name: "whitespace in query ignore",
124+
shouldHashQuery: "true",
125+
queryIgnore: " timestamp , request_id ",
126+
wantHashQuery: true,
127+
wantIgnore: map[string]bool{"timestamp": true, "request_id": true},
128+
},
129+
{
130+
name: "case sensitive query ignore",
131+
shouldHashQuery: "true",
132+
queryIgnore: "Timestamp,Request_ID",
133+
wantHashQuery: true,
134+
wantIgnore: map[string]bool{"timestamp": true, "request_id": true},
135+
},
136+
}
137+
138+
for _, tt := range tests {
139+
t.Run(tt.name, func(t *testing.T) {
140+
defer setupEnv(t, "CACHE_SHOULD_HASH_QUERY", tt.shouldHashQuery)()
141+
defer setupEnv(t, "CACHE_HASH_QUERY_IGNORE", tt.queryIgnore)()
142+
143+
config := New()
144+
145+
assert.Equal(t, tt.wantHashQuery, config.CacheConfig.ShouldHashQuery)
146+
assert.Equal(t, tt.wantIgnore, config.CacheConfig.HashQueryIgnore)
147+
})
148+
}
149+
})
25150
}

config/helpers.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,9 @@ import (
1212

1313
func hashQueryIgnoreMap(queryIgnore []string) map[string]bool {
1414
hashQueryIgnoreMap := make(map[string]bool)
15-
16-
for i := 0; i < len(queryIgnore); i++ {
17-
hashQueryIgnoreMap[queryIgnore[i]] = true
15+
for _, q := range queryIgnore {
16+
hashQueryIgnoreMap[strings.ToLower(strings.TrimSpace(q))] = true
1817
}
19-
2018
return hashQueryIgnoreMap
2119
}
2220

@@ -55,8 +53,11 @@ func getEnvAsSlice(key string) []string {
5553
if strSlice == "" {
5654
return []string{}
5755
}
58-
59-
return strings.Split(strSlice, ",")
56+
parts := strings.Split(strSlice, ",")
57+
for i, p := range parts {
58+
parts[i] = strings.TrimSpace(p)
59+
}
60+
return parts
6061
}
6162

6263
func getEnvAsInt(key, defaultVal string) int {

0 commit comments

Comments
 (0)