diff --git a/proxyd/proxyd/cmd/proxyd/main.go b/proxyd/proxyd/cmd/proxyd/main.go index db3828b..c184a1d 100644 --- a/proxyd/proxyd/cmd/proxyd/main.go +++ b/proxyd/proxyd/cmd/proxyd/main.go @@ -37,6 +37,21 @@ func main() { log.Crit("error reading config file", "err", err) } + // update log level from config + logLevel, err := log.LvlFromString(config.Server.LogLevel) + if err != nil { + logLevel = log.LvlInfo + if config.Server.LogLevel != "" { + log.Warn("invalid server.log_level set: " + config.Server.LogLevel) + } + } + log.Root().SetHandler( + log.LvlFilterHandler( + logLevel, + log.StreamHandler(os.Stdout, log.JSONFormat()), + ), + ) + shutdown, err := proxyd.Start(config) if err != nil { log.Crit("error starting proxyd", "err", err) diff --git a/proxyd/proxyd/config.go b/proxyd/proxyd/config.go index de221d9..ccf050f 100644 --- a/proxyd/proxyd/config.go +++ b/proxyd/proxyd/config.go @@ -14,6 +14,7 @@ type ServerConfig struct { WSPort int `toml:"ws_port"` MaxBodySizeBytes int64 `toml:"max_body_size_bytes"` MaxConcurrentRPCs int64 `toml:"max_concurrent_rpcs"` + LogLevel string `toml:"log_level"` // TimeoutSeconds specifies the maximum time spent serving an HTTP request. Note that isn't used for websocket connections TimeoutSeconds int `toml:"timeout_seconds"` diff --git a/proxyd/proxyd/example.config.toml b/proxyd/proxyd/example.config.toml index 2573910..fb8fea9 100644 --- a/proxyd/proxyd/example.config.toml +++ b/proxyd/proxyd/example.config.toml @@ -19,6 +19,8 @@ ws_port = 8085 # Maximum client body size, in bytes, that the server will accept. max_body_size_bytes = 10485760 max_concurrent_rpcs = 1000 +# Server log level +log_level = "info" [redis] # URL to a Redis instance. diff --git a/proxyd/proxyd/server.go b/proxyd/proxyd/server.go index e86ba4c..1ee10fa 100644 --- a/proxyd/proxyd/server.go +++ b/proxyd/proxyd/server.go @@ -8,6 +8,7 @@ import ( "io" "math" "net/http" + "regexp" "strconv" "strings" "sync" @@ -49,8 +50,8 @@ type Server struct { upgrader *websocket.Upgrader mainLim FrontendRateLimiter overrideLims map[string]FrontendRateLimiter - limExemptOrigins map[string]bool - limExemptUserAgents map[string]bool + limExemptOrigins []*regexp.Regexp + limExemptUserAgents []*regexp.Regexp rpcServer *http.Server wsServer *http.Server cache RPCCache @@ -104,15 +105,23 @@ func NewServer( } var mainLim FrontendRateLimiter - limExemptOrigins := make(map[string]bool) - limExemptUserAgents := make(map[string]bool) + limExemptOrigins := make([]*regexp.Regexp, 0) + limExemptUserAgents := make([]*regexp.Regexp, 0) if rateLimitConfig.BaseRate > 0 { mainLim = limiterFactory(time.Duration(rateLimitConfig.BaseInterval), rateLimitConfig.BaseRate, "main") for _, origin := range rateLimitConfig.ExemptOrigins { - limExemptOrigins[strings.ToLower(origin)] = true + pattern, err := regexp.Compile(origin) + if err != nil { + return nil, err + } + limExemptOrigins = append(limExemptOrigins, pattern) } for _, agent := range rateLimitConfig.ExemptUserAgents { - limExemptUserAgents[strings.ToLower(agent)] = true + pattern, err := regexp.Compile(agent) + if err != nil { + return nil, err + } + limExemptUserAgents = append(limExemptUserAgents, pattern) } } else { mainLim = NoopFrontendRateLimiter @@ -548,11 +557,22 @@ func (s *Server) populateContext(w http.ResponseWriter, r *http.Request) context } func (s *Server) isUnlimitedOrigin(origin string) bool { - return s.limExemptOrigins[strings.ToLower(origin)] + for _, pat := range s.limExemptOrigins { + if pat.MatchString(origin) { + return true + } + } + + return false } func (s *Server) isUnlimitedUserAgent(origin string) bool { - return s.limExemptUserAgents[strings.ToLower(origin)] + for _, pat := range s.limExemptUserAgents { + if pat.MatchString(origin) { + return true + } + } + return false } func setCacheHeader(w http.ResponseWriter, cached bool) {