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

Config max request header size #174

Merged
merged 5 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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: 8 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ func setConfigDefaults(v *viper.Viper) {
v.SetDefault("request_limits.max_size_bytes", utils.REQUEST_MAX_SIZE_BYTES)
v.SetDefault("request_limits.max_num_values", utils.REQUEST_MAX_NUM_VALUES)
v.SetDefault("request_limits.max_ttl_seconds", utils.REQUEST_MAX_TTL_SECONDS)
v.SetDefault("request_limits.max_header_size_bytes", 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does 0 = no limit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If zero, the http.Server is created with a the http library's DefaultMaxHeaderBytes constant that equals 1 MB

v.SetDefault("routes.allow_public_write", true)
}

Expand Down Expand Up @@ -179,6 +180,7 @@ type RequestLimits struct {
MaxNumValues int `mapstructure:"max_num_values"`
MaxTTLSeconds int `mapstructure:"max_ttl_seconds"`
AllowSettingKeys bool `mapstructure:"allow_setting_keys"`
MaxHeaderSize int `mapstructure:"max_header_size_bytes"`
}

func (cfg *RequestLimits) validateAndLog() {
Expand All @@ -201,6 +203,12 @@ func (cfg *RequestLimits) validateAndLog() {
} else {
log.Fatalf("invalid config.request_limits.max_num_values: %d. Value cannot be negative.", cfg.MaxNumValues)
}

if cfg.MaxHeaderSize >= 0 {
log.Infof("config.request_limits.max_header_size_bytes: %d", cfg.MaxHeaderSize)
} else {
log.Fatalf("invalid config.request_limits.max_header_size_bytes: %d. Value cannot be negative.", cfg.MaxHeaderSize)
AlexBVolcy marked this conversation as resolved.
Show resolved Hide resolved
}
}

type Compression struct {
Expand Down
14 changes: 14 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,18 @@ func TestRequestLimitsValidateAndLog(t *testing.T) {
},
expectFatal: true,
},
{
description: "Negative max_num_values, expect fatal level log and early exit",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: this comment should reference max_header_size_bytes instead of max_num_values.

inRequestLimitsCfg: &RequestLimits{MaxHeaderSize: -1},
expectedLogInfo: []logComponents{
{msg: `config.request_limits.allow_setting_keys: false`, lvl: logrus.InfoLevel},
{msg: `config.request_limits.max_ttl_seconds: 0`, lvl: logrus.InfoLevel},
{msg: `config.request_limits.max_size_bytes: 0`, lvl: logrus.InfoLevel},
{msg: `config.request_limits.max_num_values: 0`, lvl: logrus.InfoLevel},
{msg: `invalid config.request_limits.max_header_size_bytes: -1. Value cannot be negative.`, lvl: logrus.FatalLevel},
},
expectFatal: true,
},
}

//substitute logger exit function so execution doesn't get interrupted
Expand Down Expand Up @@ -1078,6 +1090,7 @@ func TestConfigurationValidateAndLog(t *testing.T) {
{msg: fmt.Sprintf("config.request_limits.max_ttl_seconds: %d", expectedConfig.RequestLimits.MaxTTLSeconds), lvl: logrus.InfoLevel},
{msg: fmt.Sprintf("config.request_limits.max_size_bytes: %d", expectedConfig.RequestLimits.MaxSize), lvl: logrus.InfoLevel},
{msg: fmt.Sprintf("config.request_limits.max_num_values: %d", expectedConfig.RequestLimits.MaxNumValues), lvl: logrus.InfoLevel},
{msg: fmt.Sprintf("config.request_limits.max_header_size_bytes: %d", expectedConfig.RequestLimits.MaxHeaderSize), lvl: logrus.InfoLevel},
{msg: fmt.Sprintf("config.backend.type: %s", expectedConfig.Backend.Type), lvl: logrus.InfoLevel},
{msg: fmt.Sprintf("config.compression.type: %s", expectedConfig.Compression.Type), lvl: logrus.InfoLevel},
{msg: fmt.Sprintf("Prebid Cache will run without metrics"), lvl: logrus.InfoLevel},
Expand Down Expand Up @@ -1244,6 +1257,7 @@ func getExpectedFullConfigForTestFile() Configuration {
MaxNumValues: 10,
MaxTTLSeconds: 5000,
AllowSettingKeys: true,
MaxHeaderSize: 16384, //16KiB
},
Backend: Backend{
Type: BackendMemory,
Expand Down
1 change: 1 addition & 0 deletions config/configtest/sample_full_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ request_limits:
max_num_values: 10
max_ttl_seconds: 5000
allow_setting_keys: true
max_header_size_bytes: 16384
backend:
type: "memory"
aerospike:
Expand Down
21 changes: 19 additions & 2 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,20 +74,37 @@ func Listen(cfg config.Configuration, publicHandler http.Handler, adminHandler h
return
}

// newAdminServer returns an http.Server with the AdminPort and RequestLimits.MaxHeaderBytes
// from Prebid Cache's config files or environment variables. If RequestLimits.MaxHeaderBytes
// is zero or was not specified, the http library's DefaultMaxHeaderBytes value of 1 MB
// is set instead.
func newAdminServer(cfg config.Configuration, handler http.Handler) *http.Server {
return &http.Server{
server := &http.Server{
Addr: ":" + strconv.Itoa(cfg.AdminPort),
Handler: handler,
}
if cfg.RequestLimits.MaxHeaderSize > 0 {
server.MaxHeaderBytes = cfg.RequestLimits.MaxHeaderSize
}
return server
}

// newMainServer returns an http.Server with the configured Port and
// RequestLimits.MaxHeaderBytes values specified in Prebid Cache's config files
// or environment variables. If RequestLimits.MaxHeaderBytes is zero or was not
// specified, 1 MB, which is the value of the http library's DefaultMaxHeaderBytes,
// is set instead.
func newMainServer(cfg config.Configuration, handler http.Handler) *http.Server {
return &http.Server{
server := &http.Server{
Addr: ":" + strconv.Itoa(cfg.Port),
Handler: handler,
ReadTimeout: 15 * time.Second,
WriteTimeout: 15 * time.Second,
}
if cfg.RequestLimits.MaxHeaderSize > 0 {
server.MaxHeaderBytes = cfg.RequestLimits.MaxHeaderSize
}
return server
}

func runServer(server *http.Server, name string, listener net.Listener) {
Expand Down
Loading