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

feat: add cors support #72

Merged
merged 28 commits into from
Sep 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
2ea53de
feat: added handlers dependency for cors management
punit-kulal Aug 28, 2023
6615184
feat: added cors config
punit-kulal Aug 28, 2023
66023ad
feat: load cors middleware
punit-kulal Aug 28, 2023
9e8f253
use cors middle ware in service
punit-kulal Aug 28, 2023
2f838aa
feat: make raccoon depend on cors env instead of ws specific env
punit-kulal Aug 29, 2023
433dcfc
fix: correct env variable name
punit-kulal Aug 29, 2023
26bf5be
feat: added default values for CORS changes
punit-kulal Aug 29, 2023
cd2902d
feat: update .env.test files
punit-kulal Aug 29, 2023
4ae95b8
add default Cors function
punit-kulal Aug 29, 2023
4a85bf6
feat: add default headers used by raccoon
punit-kulal Aug 30, 2023
bdec19a
fix: update env variables
punit-kulal Aug 30, 2023
3dd3755
fix: added debug cache files to gitignore
punit-kulal Aug 30, 2023
d0df9c1
feat: added integration test to check cors headers
punit-kulal Aug 30, 2023
51fa4ce
refactor: change to have standard middleware apply/hook layer
punit-kulal Aug 30, 2023
e8a89aa
fix: test names for CORS feature
punit-kulal Aug 30, 2023
48dfa49
refactor: remove unwanted viper.SetDefault call in setAllowedHeaders
punit-kulal Aug 31, 2023
546e6ff
refactor: remove deprecated env variable
punit-kulal Aug 31, 2023
5d5126f
feat: use cors enabled config in upgrader config init
punit-kulal Sep 4, 2023
16f706e
refactor: move middleware apply layer to service
punit-kulal Sep 4, 2023
6ab5f90
feat: added integration tests for preflight options request with corr…
punit-kulal Sep 4, 2023
4a309ef
feat: improve allowed headers fetching logic
punit-kulal Sep 4, 2023
44838cc
feat: update to more sensible defaults
punit-kulal Sep 4, 2023
acb9d09
docs: add documentation for cors configs
punit-kulal Sep 4, 2023
0d470b2
revert changes to introduce `SERVER_WEBSOCKET_CHECK_ORIGIN`
punit-kulal Sep 5, 2023
1642496
fix: uncomment commented integration test
punit-kulal Sep 5, 2023
df2b25f
refactor: fix formatting of the docs
punit-kulal Sep 5, 2023
473821f
fix: incorrect logic for deduplication in cors headers config
punit-kulal Sep 5, 2023
41d8d8a
feat: updated the config docs
punit-kulal Sep 5, 2023
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
8 changes: 7 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
SERVER_WEBSOCKET_PORT="8080"
SERVER_WEBSOCKET_CHECK_ORIGIN="true"
SERVER_WEBSOCKET_MAX_CONN="30000"
SERVER_WEBSOCKET_READ_BUFFER_SIZE="10240"
SERVER_WEBSOCKET_WRITE_BUFFER_SIZE="10240"
Expand All @@ -8,6 +7,13 @@ SERVER_WEBSOCKET_PING_INTERVAL_MS=30000
SERVER_WEBSOCKET_PONG_WAIT_INTERVAL_MS=60000
SERVER_WEBSOCKET_WRITE_WAIT_INTERVAL_MS=5000
SERVER_WEBSOCKET_PINGER_SIZE=1
SERVER_WEBSOCKET_CHECK_ORIGIN="true"

SERVER_CORS_ENABLED="true"
SERVER_CORS_ALLOWED_ORIGIN="http://localhost:3000 http://localhost:8080"
prakharmathur82 marked this conversation as resolved.
Show resolved Hide resolved
SERVER_CORS_ALLOWED_METHODS="GET HEAD POST OPTIONS"
SERVER_CORS_PREFLIGHT_MAX_AGE_SECONDS=60
SERVER_CORS_ALLOWED_HEADERS=""

SERVER_GRPC_PORT=8081

Expand Down
8 changes: 7 additions & 1 deletion .env.test
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
SERVER_WEBSOCKET_PORT="8080"
SERVER_WEBSOCKET_CHECK_ORIGIN="true"
SERVER_WEBSOCKET_MAX_CONN="30000"
SERVER_WEBSOCKET_READ_BUFFER_SIZE="10240"
SERVER_WEBSOCKET_WRITE_BUFFER_SIZE="10240"
Expand All @@ -9,9 +8,16 @@ SERVER_WEBSOCKET_PING_INTERVAL_MS=10000
SERVER_WEBSOCKET_PONG_WAIT_INTERVAL_MS=10000
SERVER_WEBSOCKET_WRITE_WAIT_INTERVAL_MS=1000
SERVER_WEBSOCKET_PINGER_SIZE=1
SERVER_WEBSOCKET_CHECK_ORIGIN="true"

SERVER_GRPC_PORT=8081


SERVER_CORS_ENABLED="true"
SERVER_CORS_ALLOWED_ORIGIN="http://localhost:3000 http://localhost:8080"
SERVER_CORS_ALLOWED_METHODS="GET HEAD POST OPTIONS"
SERVER_CORS_PREFLIGHT_MAX_AGE_SECONDS=60

WORKER_BUFFER_CHANNEL_SIZE=5
WORKER_BUFFER_FLUSH_TIMEOUT_MS=5000
WORKER_POOL_SIZE=5
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ coverage
*.idea/
raccoon
.temp
__debug.*
1 change: 1 addition & 0 deletions config/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func Load() {
serverConfigLoader()
serverWsConfigLoader()
serverGRPCConfigLoader()
serverCorsConfigLoader()
workerConfigLoader()
metricStatsdConfigLoader()
eventDistributionConfigLoader()
Expand Down
53 changes: 50 additions & 3 deletions config/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
var Server server
var ServerWs serverWs
var ServerGRPC serverGRPC
var ServerCors serverCors

type server struct {
DedupEnabled bool
Expand All @@ -20,33 +21,79 @@ type serverWs struct {
ServerMaxConn int
ReadBufferSize int
WriteBufferSize int
CheckOrigin bool
PingInterval time.Duration
PongWaitInterval time.Duration
WriteWaitInterval time.Duration
PingerSize int
ConnIDHeader string
ConnGroupHeader string
ConnGroupDefault string
CheckOrigin bool
}

type serverGRPC struct {
Port string
}

type serverCors struct {
Enabled bool
AllowedOrigin []string
AllowedMethods []string
AllowedHeaders []string
AllowCredentials bool
MaxAge int
}

func serverConfigLoader() {
viper.SetDefault("SERVER_BATCH_DEDUP_IN_CONNECTION_ENABLED", "false")
Server = server{
DedupEnabled: util.MustGetBool("SERVER_BATCH_DEDUP_IN_CONNECTION_ENABLED"),
}
}

func serverCorsConfigLoader() {
viper.SetDefault("SERVER_CORS_ENABLED", false)
viper.SetDefault("SERVER_CORS_ALLOWED_ORIGIN", "")
viper.SetDefault("SERVER_CORS_ALLOWED_METHODS", []string{"GET", "HEAD", "POST", "OPTIONS"})
viper.SetDefault("SERVER_CORS_ALLOWED_HEADERS", "")
viper.SetDefault("SERVER_CORS_ALLOW_CREDENTIALS", false)
viper.SetDefault("SERVER_CORS_PREFLIGHT_MAX_AGE_SECONDS", 0)
ServerCors = serverCors{
Enabled: util.MustGetBool("SERVER_CORS_ENABLED"),
AllowedOrigin: viper.GetStringSlice("SERVER_CORS_ALLOWED_ORIGIN"),
AllowedMethods: viper.GetStringSlice("SERVER_CORS_ALLOWED_METHODS"),
AllowCredentials: util.MustGetBool("SERVER_CORS_ALLOW_CREDENTIALS"),
AllowedHeaders: getAllowedHeaders(),
MaxAge: util.MustGetInt("SERVER_CORS_PREFLIGHT_MAX_AGE_SECONDS"),
}
}

func getAllowedHeaders() []string {
allowedHeaders := []string{"Content-Type"}
allowedHeaders = setAllowedHeaders(allowedHeaders, "SERVER_WEBSOCKET_CONN_GROUP_HEADER")
allowedHeaders = setAllowedHeaders(allowedHeaders, "SERVER_WEBSOCKET_CONN_ID_HEADER")
inputHeaders := viper.GetStringSlice("SERVER_CORS_ALLOWED_HEADERS")
for _, input := range inputHeaders {
if input != "" && !util.Contains(input, allowedHeaders) {
allowedHeaders = append(allowedHeaders, input)
}
}
return allowedHeaders
}

func setAllowedHeaders(allowedHeaders []string, envKey string) []string {
if header := viper.GetString(envKey); header != "" {
allowedHeaders = append(allowedHeaders, header)
}
return allowedHeaders
}

func serverWsConfigLoader() {
viper.SetDefault("SERVER_WEBSOCKET_CHECK_ORIGIN", true)
viper.SetDefault("SERVER_WEBSOCKET_PORT", "8080")
viper.SetDefault("SERVER_WEBSOCKET_MAX_CONN", 30000)
viper.SetDefault("SERVER_WEBSOCKET_READ_BUFFER_SIZE", 10240)
viper.SetDefault("SERVER_WEBSOCKET_WRITE_BUFFER_SIZE", 10240)
viper.SetDefault("SERVER_WEBSOCKET_CHECK_ORIGIN", true)
viper.SetDefault("SERVER_WEBSOCKET_PING_INTERVAL_MS", "30000")
viper.SetDefault("SERVER_WEBSOCKET_PONG_WAIT_INTERVAL_MS", "60000") //should be more than the ping period
viper.SetDefault("SERVER_WEBSOCKET_WRITE_WAIT_INTERVAL_MS", "5000")
Expand All @@ -59,14 +106,14 @@ func serverWsConfigLoader() {
ServerMaxConn: util.MustGetInt("SERVER_WEBSOCKET_MAX_CONN"),
ReadBufferSize: util.MustGetInt("SERVER_WEBSOCKET_READ_BUFFER_SIZE"),
WriteBufferSize: util.MustGetInt("SERVER_WEBSOCKET_WRITE_BUFFER_SIZE"),
CheckOrigin: util.MustGetBool("SERVER_WEBSOCKET_CHECK_ORIGIN"),
PingInterval: util.MustGetDuration("SERVER_WEBSOCKET_PING_INTERVAL_MS", time.Millisecond),
PongWaitInterval: util.MustGetDuration("SERVER_WEBSOCKET_PONG_WAIT_INTERVAL_MS", time.Millisecond),
WriteWaitInterval: util.MustGetDuration("SERVER_WEBSOCKET_WRITE_WAIT_INTERVAL_MS", time.Millisecond),
PingerSize: util.MustGetInt("SERVER_WEBSOCKET_PINGER_SIZE"),
ConnIDHeader: util.MustGetString("SERVER_WEBSOCKET_CONN_ID_HEADER"),
ConnGroupHeader: util.MustGetString("SERVER_WEBSOCKET_CONN_GROUP_HEADER"),
ConnGroupDefault: util.MustGetString("SERVER_WEBSOCKET_CONN_GROUP_DEFAULT"),
CheckOrigin: util.MustGetBool("SERVER_WEBSOCKET_CHECK_ORIGIN"),
}
}

Expand Down
11 changes: 11 additions & 0 deletions config/util/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,14 @@ func mustHave(key string) {
panic(fmt.Sprintf("key %s is not set", key))
}
}

func Contains(key string, slice []string) bool {
for _, v := range slice {
if v == key {
return true
}
}

return false

}
42 changes: 42 additions & 0 deletions docs/docs/reference/configurations.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,48 @@ Toggle CORS check function. Set `true` to check each request origin. Set `false`
- Type: `Optional`
- Default value: `true`

### `SERVER_CORS_ENABLED`

The config decides whether to enable the cors middleware and thus allow CORS requests. This config only enables CORS for rest services. For websocket, refer `SERVER_WEBSOCKET_CHECK_ORIGIN`

- Type `Optional`
- Default value: `false`

### `SERVER_CORS_ALLOWED_ORIGIN`

The server decides which origin to allow. The configuration is expected to space separated. Multiple values are supported. The value requies `SERVER_CORS_ENABLED` to be true to take effect. If you want to allow all host headers. You can pass `*` as the value.

- Type `Optional`
- Default Value ``

### `SERVER_CORS_ALLOWED_METHODS`

The http methods allowed when it's a cross origin request. The http methods are expected to be space separated.

- Type `Optional`
- Default Value `GET HEAD POST OPTIONS`

### `SERVER_CORS_ALLOWED_HEADERS`

The http request headers which are allowed when request is cross origin. The input expects to add any additional headers which is going to be sent by the client ex: `Authorization`. Headers which are essential for the functioning of Raccoon like Content-Type, Connection-Id & Group headers are added by default and need not be passed as configuration.

- Type `Optional`
- Default Value ``

### `SERVER_CORS_ALLOW_CREDENTIALS`

AllowCredentials can be used to specify that the user agent may pass authentication details along with the request.

- Type `Optional`
- Default Value `false`

### `SERVER_CORS_PREFLIGHT_MAX_AGE_SECONDS`

Replies with a header for clients on how long to cache the response of the preflight request. It's not enforceable. The max value is 600s

- Type `Optional`
- Default Value `0`

### `SERVER_BATCH_DEDUP_IN_CONNECTION_ENABLED`

The server decides whether or not to handle duplicate batches for the active connection. If a batch is sent with a duplicate ReqGUID, the server uses best attempts to discard the duplicate batches. Set `true` to enable the setting.
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.14

require (
github.com/confluentinc/confluent-kafka-go v1.9.3-RC3
github.com/gorilla/handlers v1.5.1
github.com/gorilla/mux v1.7.4
github.com/gorilla/websocket v1.4.2
github.com/sirupsen/logrus v1.6.0
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/frankban/quicktest v1.2.2/go.mod h1:Qh/WofXFeiAFII1aEBu529AtJo6Zg2VHscnEsbBnJ20=
github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o=
github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y=
Expand Down Expand Up @@ -122,6 +124,8 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
Expand Down
Loading
Loading