github.com/prebid/prebid-server/v2@v2.18.0/config/config.go (about)

     1  package config
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"net/url"
     8  	"reflect"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/golang/glog"
    13  	"github.com/prebid/go-gdpr/consentconstants"
    14  	"github.com/prebid/openrtb/v20/openrtb2"
    15  	"github.com/prebid/prebid-server/v2/errortypes"
    16  	"github.com/prebid/prebid-server/v2/openrtb_ext"
    17  	"github.com/prebid/prebid-server/v2/util/jsonutil"
    18  	"github.com/spf13/viper"
    19  )
    20  
    21  // Configuration specifies the static application config.
    22  type Configuration struct {
    23  	ExternalURL      string      `mapstructure:"external_url"`
    24  	Host             string      `mapstructure:"host"`
    25  	Port             int         `mapstructure:"port"`
    26  	UnixSocketEnable bool        `mapstructure:"unix_socket_enable"`
    27  	UnixSocketName   string      `mapstructure:"unix_socket_name"`
    28  	Client           HTTPClient  `mapstructure:"http_client"`
    29  	CacheClient      HTTPClient  `mapstructure:"http_client_cache"`
    30  	Admin            Admin       `mapstructure:"admin"`
    31  	AdminPort        int         `mapstructure:"admin_port"`
    32  	Compression      Compression `mapstructure:"compression"`
    33  	// GarbageCollectorThreshold allocates virtual memory (in bytes) which is not used by PBS but
    34  	// serves as a hack to trigger the garbage collector only when the heap reaches at least this size.
    35  	// More info: https://github.com/golang/go/issues/48409
    36  	GarbageCollectorThreshold int `mapstructure:"garbage_collector_threshold"`
    37  	// StatusResponse is the string which will be returned by the /status endpoint when things are OK.
    38  	// If empty, it will return a 204 with no content.
    39  	StatusResponse    string          `mapstructure:"status_response"`
    40  	AuctionTimeouts   AuctionTimeouts `mapstructure:"auction_timeouts_ms"`
    41  	TmaxAdjustments   TmaxAdjustments `mapstructure:"tmax_adjustments"`
    42  	CacheURL          Cache           `mapstructure:"cache"`
    43  	ExtCacheURL       ExternalCache   `mapstructure:"external_cache"`
    44  	RecaptchaSecret   string          `mapstructure:"recaptcha_secret"`
    45  	HostCookie        HostCookie      `mapstructure:"host_cookie"`
    46  	Metrics           Metrics         `mapstructure:"metrics"`
    47  	StoredRequests    StoredRequests  `mapstructure:"stored_requests"`
    48  	StoredRequestsAMP StoredRequests  `mapstructure:"stored_amp_req"`
    49  	CategoryMapping   StoredRequests  `mapstructure:"category_mapping"`
    50  	VTrack            VTrack          `mapstructure:"vtrack"`
    51  	Event             Event           `mapstructure:"event"`
    52  	Accounts          StoredRequests  `mapstructure:"accounts"`
    53  	UserSync          UserSync        `mapstructure:"user_sync"`
    54  	// Note that StoredVideo refers to stored video requests, and has nothing to do with caching video creatives.
    55  	StoredVideo     StoredRequests `mapstructure:"stored_video_req"`
    56  	StoredResponses StoredRequests `mapstructure:"stored_responses"`
    57  	// StoredRequestsTimeout defines the number of milliseconds before a timeout occurs with stored requests fetch
    58  	StoredRequestsTimeout int `mapstructure:"stored_requests_timeout_ms"`
    59  
    60  	MaxRequestSize       int64             `mapstructure:"max_request_size"`
    61  	Analytics            Analytics         `mapstructure:"analytics"`
    62  	AMPTimeoutAdjustment int64             `mapstructure:"amp_timeout_adjustment_ms"`
    63  	GDPR                 GDPR              `mapstructure:"gdpr"`
    64  	CCPA                 CCPA              `mapstructure:"ccpa"`
    65  	LMT                  LMT               `mapstructure:"lmt"`
    66  	CurrencyConverter    CurrencyConverter `mapstructure:"currency_converter"`
    67  	DefReqConfig         DefReqConfig      `mapstructure:"default_request"`
    68  
    69  	VideoStoredRequestRequired bool `mapstructure:"video_stored_request_required"`
    70  
    71  	// Array of blacklisted apps that is used to create the hash table BlacklistedAppMap so App.ID's can be instantly accessed.
    72  	BlacklistedApps   []string `mapstructure:"blacklisted_apps,flow"`
    73  	BlacklistedAppMap map[string]bool
    74  	// Is publisher/account ID required to be submitted in the OpenRTB2 request
    75  	AccountRequired bool `mapstructure:"account_required"`
    76  	// AccountDefaults defines default settings for valid accounts that are partially defined
    77  	// and provides a way to set global settings that can be overridden at account level.
    78  	AccountDefaults Account `mapstructure:"account_defaults"`
    79  	// accountDefaultsJSON is the internal serialized form of AccountDefaults used for json merge
    80  	accountDefaultsJSON json.RawMessage
    81  	// Local private file containing SSL certificates
    82  	PemCertsFile string `mapstructure:"certificates_file"`
    83  	// Custom headers to handle request timeouts from queueing infrastructure
    84  	RequestTimeoutHeaders RequestTimeoutHeaders `mapstructure:"request_timeout_headers"`
    85  	// Debug/logging flags go here
    86  	Debug Debug `mapstructure:"debug"`
    87  	// RequestValidation specifies the request validation options.
    88  	RequestValidation RequestValidation `mapstructure:"request_validation"`
    89  	// When true, PBS will assign a randomly generated UUID to req.Source.TID if it is empty
    90  	AutoGenSourceTID bool `mapstructure:"auto_gen_source_tid"`
    91  	//When true, new bid id will be generated in seatbid[].bid[].ext.prebid.bidid and used in event urls instead
    92  	GenerateBidID bool `mapstructure:"generate_bid_id"`
    93  	// GenerateRequestID overrides the bidrequest.id in an AMP Request or an App Stored Request with a generated UUID if set to true. The default is false.
    94  	GenerateRequestID bool                      `mapstructure:"generate_request_id"`
    95  	HostSChainNode    *openrtb2.SupplyChainNode `mapstructure:"host_schain_node"`
    96  	// Experiment configures non-production ready features.
    97  	Experiment Experiment `mapstructure:"experiment"`
    98  	DataCenter string     `mapstructure:"datacenter"`
    99  	// BidderInfos supports adapter overrides in extra configs like pbs.json, pbs.yaml, etc.
   100  	// Refers to main.go `configFileName` constant
   101  	BidderInfos BidderInfos `mapstructure:"adapters"`
   102  	// Hooks provides a way to specify hook execution plan for specific endpoints and stages
   103  	Hooks       Hooks       `mapstructure:"hooks"`
   104  	Validations Validations `mapstructure:"validations"`
   105  	PriceFloors PriceFloors `mapstructure:"price_floors"`
   106  }
   107  
   108  type Admin struct {
   109  	Enabled bool `mapstructure:"enabled"`
   110  }
   111  type PriceFloors struct {
   112  	Enabled bool              `mapstructure:"enabled"`
   113  	Fetcher PriceFloorFetcher `mapstructure:"fetcher"`
   114  }
   115  
   116  type PriceFloorFetcher struct {
   117  	HttpClient HTTPClient `mapstructure:"http_client"`
   118  	CacheSize  int        `mapstructure:"cache_size_mb"`
   119  	Worker     int        `mapstructure:"worker"`
   120  	Capacity   int        `mapstructure:"capacity"`
   121  	MaxRetries int        `mapstructure:"max_retries"`
   122  }
   123  
   124  const MIN_COOKIE_SIZE_BYTES = 500
   125  
   126  type HTTPClient struct {
   127  	MaxConnsPerHost     int `mapstructure:"max_connections_per_host"`
   128  	MaxIdleConns        int `mapstructure:"max_idle_connections"`
   129  	MaxIdleConnsPerHost int `mapstructure:"max_idle_connections_per_host"`
   130  	IdleConnTimeout     int `mapstructure:"idle_connection_timeout_seconds"`
   131  }
   132  
   133  func (cfg *Configuration) validate(v *viper.Viper) []error {
   134  	var errs []error
   135  	errs = cfg.AuctionTimeouts.validate(errs)
   136  	errs = cfg.StoredRequests.validate(errs)
   137  	if cfg.StoredRequestsTimeout <= 0 {
   138  		errs = append(errs, fmt.Errorf("cfg.stored_requests_timeout_ms must be > 0. Got %d", cfg.StoredRequestsTimeout))
   139  	}
   140  	errs = cfg.StoredRequestsAMP.validate(errs)
   141  	errs = cfg.Accounts.validate(errs)
   142  	errs = cfg.CategoryMapping.validate(errs)
   143  	errs = cfg.StoredVideo.validate(errs)
   144  	errs = cfg.Metrics.validate(errs)
   145  	if cfg.MaxRequestSize < 0 {
   146  		errs = append(errs, fmt.Errorf("cfg.max_request_size must be >= 0. Got %d", cfg.MaxRequestSize))
   147  	}
   148  	errs = cfg.GDPR.validate(v, errs)
   149  	errs = cfg.CurrencyConverter.validate(errs)
   150  	errs = cfg.Debug.validate(errs)
   151  	errs = cfg.ExtCacheURL.validate(errs)
   152  	errs = cfg.AccountDefaults.PriceFloors.validate(errs)
   153  	if cfg.AccountDefaults.Disabled {
   154  		glog.Warning(`With account_defaults.disabled=true, host-defined accounts must exist and have "disabled":false. All other requests will be rejected.`)
   155  	}
   156  
   157  	if cfg.AccountDefaults.Events.Enabled {
   158  		glog.Warning(`account_defaults.events has no effect as the feature is under development.`)
   159  	}
   160  
   161  	errs = cfg.Experiment.validate(errs)
   162  	errs = cfg.BidderInfos.validate(errs)
   163  	errs = cfg.AccountDefaults.Privacy.IPv6Config.Validate(errs)
   164  	errs = cfg.AccountDefaults.Privacy.IPv4Config.Validate(errs)
   165  
   166  	return errs
   167  }
   168  
   169  type AuctionTimeouts struct {
   170  	// The default timeout is used if the user's request didn't define one. Use 0 if there's no default.
   171  	Default uint64 `mapstructure:"default"`
   172  	// The max timeout is used as an absolute cap, to prevent excessively long ones. Use 0 for no cap
   173  	Max uint64 `mapstructure:"max"`
   174  }
   175  
   176  func (cfg *AuctionTimeouts) validate(errs []error) []error {
   177  	if cfg.Max < cfg.Default {
   178  		errs = append(errs, fmt.Errorf("auction_timeouts_ms.max cannot be less than auction_timeouts_ms.default. max=%d, default=%d", cfg.Max, cfg.Default))
   179  	}
   180  	return errs
   181  }
   182  
   183  func (data *ExternalCache) validate(errs []error) []error {
   184  	if data.Host == "" && data.Path == "" {
   185  		// Both host and path can be blank. No further validation needed
   186  		return errs
   187  	}
   188  
   189  	if data.Scheme != "" && data.Scheme != "http" && data.Scheme != "https" {
   190  		return append(errs, errors.New("External cache Scheme must be http or https if specified"))
   191  	}
   192  
   193  	// Either host or path or both not empty, validate.
   194  	if data.Host == "" && data.Path != "" || data.Host != "" && data.Path == "" {
   195  		return append(errs, errors.New("external cache Host and Path must both be specified"))
   196  	}
   197  	if strings.HasSuffix(data.Host, "/") {
   198  		return append(errs, fmt.Errorf("external cache Host '%s' must not end with a path separator", data.Host))
   199  	}
   200  	if strings.Contains(data.Host, "://") {
   201  		return append(errs, fmt.Errorf("external cache Host must not specify a protocol. '%s'", data.Host))
   202  	}
   203  	if !strings.HasPrefix(data.Path, "/") {
   204  		return append(errs, fmt.Errorf("external cache Path '%s' must begin with a path separator", data.Path))
   205  	}
   206  
   207  	urlObj, err := url.Parse("https://" + data.Host + data.Path)
   208  	if err != nil {
   209  		return append(errs, fmt.Errorf("external cache Path validation error: %s ", err.Error()))
   210  	}
   211  	if urlObj.Host != data.Host {
   212  		return append(errs, fmt.Errorf("external cache Host '%s' is invalid", data.Host))
   213  	}
   214  	if urlObj.Path != data.Path {
   215  		return append(errs, fmt.Errorf("external cache Path is invalid"))
   216  	}
   217  
   218  	return errs
   219  }
   220  
   221  // LimitAuctionTimeout returns the min of requested or cfg.MaxAuctionTimeout.
   222  // Both values treat "0" as "infinite".
   223  func (cfg *AuctionTimeouts) LimitAuctionTimeout(requested time.Duration) time.Duration {
   224  	if requested == 0 && cfg.Default != 0 {
   225  		return time.Duration(cfg.Default) * time.Millisecond
   226  	}
   227  	if cfg.Max > 0 {
   228  		maxTimeout := time.Duration(cfg.Max) * time.Millisecond
   229  		if requested == 0 || requested > maxTimeout {
   230  			return maxTimeout
   231  		}
   232  	}
   233  	return requested
   234  }
   235  
   236  // Privacy is a grouping of privacy related configs to assist in dependency injection.
   237  type Privacy struct {
   238  	CCPA CCPA
   239  	GDPR GDPR
   240  	LMT  LMT
   241  }
   242  
   243  type GDPR struct {
   244  	Enabled                 bool         `mapstructure:"enabled"`
   245  	HostVendorID            int          `mapstructure:"host_vendor_id"`
   246  	DefaultValue            string       `mapstructure:"default_value"`
   247  	Timeouts                GDPRTimeouts `mapstructure:"timeouts_ms"`
   248  	NonStandardPublishers   []string     `mapstructure:"non_standard_publishers,flow"`
   249  	NonStandardPublisherMap map[string]struct{}
   250  	TCF2                    TCF2 `mapstructure:"tcf2"`
   251  	AMPException            bool `mapstructure:"amp_exception"` // Deprecated: Use account-level GDPR settings (gdpr.integration_enabled.amp) instead
   252  	// EEACountries (EEA = European Economic Area) are a list of countries where we should assume GDPR applies.
   253  	// If the gdpr flag is unset in a request, but geo.country is set, we will assume GDPR applies if and only
   254  	// if the country matches one on this list. If both the GDPR flag and country are not set, we default
   255  	// to DefaultValue
   256  	EEACountries    []string `mapstructure:"eea_countries"`
   257  	EEACountriesMap map[string]struct{}
   258  }
   259  
   260  func (cfg *GDPR) validate(v *viper.Viper, errs []error) []error {
   261  	if !v.IsSet("gdpr.default_value") {
   262  		errs = append(errs, fmt.Errorf("gdpr.default_value is required and must be specified"))
   263  	} else if cfg.DefaultValue != "0" && cfg.DefaultValue != "1" {
   264  		errs = append(errs, fmt.Errorf("gdpr.default_value must be 0 or 1"))
   265  	}
   266  	if cfg.HostVendorID < 0 || cfg.HostVendorID > 0xffff {
   267  		errs = append(errs, fmt.Errorf("gdpr.host_vendor_id must be in the range [0, %d]. Got %d", 0xffff, cfg.HostVendorID))
   268  	}
   269  	if cfg.HostVendorID == 0 {
   270  		glog.Warning("gdpr.host_vendor_id was not specified. Host company GDPR checks will be skipped.")
   271  	}
   272  	if cfg.AMPException {
   273  		errs = append(errs, fmt.Errorf("gdpr.amp_exception has been discontinued and must be removed from your config. If you need to disable GDPR for AMP, you may do so per-account (gdpr.integration_enabled.amp) or at the host level for the default account (account_defaults.gdpr.integration_enabled.amp)"))
   274  	}
   275  	return cfg.validatePurposes(errs)
   276  }
   277  
   278  func (cfg *GDPR) validatePurposes(errs []error) []error {
   279  	purposeConfigs := []TCF2Purpose{
   280  		cfg.TCF2.Purpose1,
   281  		cfg.TCF2.Purpose2,
   282  		cfg.TCF2.Purpose3,
   283  		cfg.TCF2.Purpose4,
   284  		cfg.TCF2.Purpose5,
   285  		cfg.TCF2.Purpose6,
   286  		cfg.TCF2.Purpose7,
   287  		cfg.TCF2.Purpose8,
   288  		cfg.TCF2.Purpose9,
   289  		cfg.TCF2.Purpose10,
   290  	}
   291  
   292  	for i := 0; i < len(purposeConfigs); i++ {
   293  		enforceAlgoValue := purposeConfigs[i].EnforceAlgo
   294  		enforceAlgoField := fmt.Sprintf("gdpr.tcf2.purpose%d.enforce_algo", (i + 1))
   295  
   296  		if enforceAlgoValue != TCF2EnforceAlgoFull && enforceAlgoValue != TCF2EnforceAlgoBasic {
   297  			errs = append(errs, fmt.Errorf("%s must be \"basic\" or \"full\". Got %s", enforceAlgoField, enforceAlgoValue))
   298  		}
   299  	}
   300  	return errs
   301  }
   302  
   303  type GDPRTimeouts struct {
   304  	InitVendorlistFetch   int `mapstructure:"init_vendorlist_fetches"`
   305  	ActiveVendorlistFetch int `mapstructure:"active_vendorlist_fetch"`
   306  }
   307  
   308  func (t *GDPRTimeouts) InitTimeout() time.Duration {
   309  	return time.Duration(t.InitVendorlistFetch) * time.Millisecond
   310  }
   311  
   312  func (t *GDPRTimeouts) ActiveTimeout() time.Duration {
   313  	return time.Duration(t.ActiveVendorlistFetch) * time.Millisecond
   314  }
   315  
   316  const (
   317  	TCF2EnforceAlgoBasic = "basic"
   318  	TCF2EnforceAlgoFull  = "full"
   319  )
   320  
   321  type TCF2EnforcementAlgo int
   322  
   323  const (
   324  	TCF2UndefinedEnforcement TCF2EnforcementAlgo = iota
   325  	TCF2BasicEnforcement
   326  	TCF2FullEnforcement
   327  )
   328  
   329  // TCF2 defines the TCF2 specific configurations for GDPR
   330  type TCF2 struct {
   331  	Enabled   bool        `mapstructure:"enabled"`
   332  	Purpose1  TCF2Purpose `mapstructure:"purpose1"`
   333  	Purpose2  TCF2Purpose `mapstructure:"purpose2"`
   334  	Purpose3  TCF2Purpose `mapstructure:"purpose3"`
   335  	Purpose4  TCF2Purpose `mapstructure:"purpose4"`
   336  	Purpose5  TCF2Purpose `mapstructure:"purpose5"`
   337  	Purpose6  TCF2Purpose `mapstructure:"purpose6"`
   338  	Purpose7  TCF2Purpose `mapstructure:"purpose7"`
   339  	Purpose8  TCF2Purpose `mapstructure:"purpose8"`
   340  	Purpose9  TCF2Purpose `mapstructure:"purpose9"`
   341  	Purpose10 TCF2Purpose `mapstructure:"purpose10"`
   342  	// Map of purpose configs for easy purpose lookup
   343  	PurposeConfigs      map[consentconstants.Purpose]*TCF2Purpose
   344  	SpecialFeature1     TCF2SpecialFeature      `mapstructure:"special_feature1"`
   345  	PurposeOneTreatment TCF2PurposeOneTreatment `mapstructure:"purpose_one_treatment"`
   346  }
   347  
   348  // ChannelEnabled checks if a given channel type is enabled. All channel types are considered either
   349  // enabled or disabled based on the Enabled flag.
   350  func (t *TCF2) ChannelEnabled(channelType ChannelType) bool {
   351  	return t.Enabled
   352  }
   353  
   354  // IsEnabled indicates if TCF2 is enabled
   355  func (t *TCF2) IsEnabled() bool {
   356  	return t.Enabled
   357  }
   358  
   359  // PurposeEnforced checks if full enforcement is turned on for a given purpose. With full enforcement enabled, the
   360  // GDPR full enforcement algorithm will execute for that purpose determining legal basis; otherwise it's skipped.
   361  func (t *TCF2) PurposeEnforced(purpose consentconstants.Purpose) (enforce bool) {
   362  	if t.PurposeConfigs[purpose] == nil {
   363  		return false
   364  	}
   365  	return t.PurposeConfigs[purpose].EnforcePurpose
   366  }
   367  
   368  // PurposeEnforcementAlgo returns the default enforcement algorithm for a given purpose
   369  func (t *TCF2) PurposeEnforcementAlgo(purpose consentconstants.Purpose) (enforcement TCF2EnforcementAlgo) {
   370  	if c, exists := t.PurposeConfigs[purpose]; exists {
   371  		return c.EnforceAlgoID
   372  	}
   373  	return TCF2FullEnforcement
   374  }
   375  
   376  // PurposeEnforcingVendors checks if enforcing vendors is turned on for a given purpose. With enforcing vendors
   377  // enabled, the GDPR full enforcement algorithm considers the GVL when determining legal basis; otherwise it's skipped.
   378  func (t *TCF2) PurposeEnforcingVendors(purpose consentconstants.Purpose) (enforce bool) {
   379  	if t.PurposeConfigs[purpose] == nil {
   380  		return false
   381  	}
   382  	return t.PurposeConfigs[purpose].EnforceVendors
   383  }
   384  
   385  // PurposeVendorExceptions returns the vendor exception map for a given purpose if it exists, otherwise it returns
   386  // an empty map of vendor exceptions
   387  func (t *TCF2) PurposeVendorExceptions(purpose consentconstants.Purpose) (vendorExceptions map[string]struct{}) {
   388  	c, exists := t.PurposeConfigs[purpose]
   389  
   390  	if exists && c.VendorExceptionMap != nil {
   391  		return c.VendorExceptionMap
   392  	}
   393  	return make(map[string]struct{}, 0)
   394  }
   395  
   396  // FeatureOneEnforced checks if special feature one is enforced. If it is enforced, PBS will determine whether geo
   397  // information may be passed through in the bid request.
   398  func (t *TCF2) FeatureOneEnforced() bool {
   399  	return t.SpecialFeature1.Enforce
   400  }
   401  
   402  // FeatureOneVendorException checks if the specified bidder is considered a vendor exception for special feature one.
   403  // If a bidder is a vendor exception, PBS will bypass the pass geo calculation passing the geo information in the bid request.
   404  func (t *TCF2) FeatureOneVendorException(bidder openrtb_ext.BidderName) bool {
   405  	if _, ok := t.SpecialFeature1.VendorExceptionMap[bidder]; ok {
   406  		return true
   407  	}
   408  	return false
   409  }
   410  
   411  // PurposeOneTreatmentEnabled checks if purpose one treatment is enabled.
   412  func (t *TCF2) PurposeOneTreatmentEnabled() bool {
   413  	return t.PurposeOneTreatment.Enabled
   414  }
   415  
   416  // PurposeOneTreatmentAccessAllowed checks if purpose one treatment access is allowed.
   417  func (t *TCF2) PurposeOneTreatmentAccessAllowed() bool {
   418  	return t.PurposeOneTreatment.AccessAllowed
   419  }
   420  
   421  // Making a purpose struct so purpose specific details can be added later.
   422  type TCF2Purpose struct {
   423  	EnforceAlgo string `mapstructure:"enforce_algo"`
   424  	// Integer representation of enforcement algo for performance improvement on compares
   425  	EnforceAlgoID  TCF2EnforcementAlgo
   426  	EnforcePurpose bool `mapstructure:"enforce_purpose"`
   427  	EnforceVendors bool `mapstructure:"enforce_vendors"`
   428  	// Array of vendor exceptions that is used to create the hash table VendorExceptionMap so vendor names can be instantly accessed
   429  	VendorExceptions   []string `mapstructure:"vendor_exceptions"`
   430  	VendorExceptionMap map[string]struct{}
   431  }
   432  
   433  type TCF2SpecialFeature struct {
   434  	Enforce bool `mapstructure:"enforce"`
   435  	// Array of vendor exceptions that is used to create the hash table VendorExceptionMap so vendor names can be instantly accessed
   436  	VendorExceptions   []openrtb_ext.BidderName `mapstructure:"vendor_exceptions"`
   437  	VendorExceptionMap map[openrtb_ext.BidderName]struct{}
   438  }
   439  
   440  type TCF2PurposeOneTreatment struct {
   441  	Enabled       bool `mapstructure:"enabled"`
   442  	AccessAllowed bool `mapstructure:"access_allowed"`
   443  }
   444  
   445  type CCPA struct {
   446  	Enforce bool `mapstructure:"enforce"`
   447  }
   448  
   449  type LMT struct {
   450  	Enforce bool `mapstructure:"enforce"`
   451  }
   452  
   453  type Analytics struct {
   454  	File     FileLogs      `mapstructure:"file"`
   455  	Agma     AgmaAnalytics `mapstructure:"agma"`
   456  	Pubstack Pubstack      `mapstructure:"pubstack"`
   457  }
   458  
   459  type CurrencyConverter struct {
   460  	FetchURL             string `mapstructure:"fetch_url"`
   461  	FetchIntervalSeconds int    `mapstructure:"fetch_interval_seconds"`
   462  	StaleRatesSeconds    int    `mapstructure:"stale_rates_seconds"`
   463  }
   464  
   465  func (cfg *CurrencyConverter) validate(errs []error) []error {
   466  	if cfg.FetchIntervalSeconds < 0 {
   467  		errs = append(errs, fmt.Errorf("currency_converter.fetch_interval_seconds must be in the range [0, %d]. Got %d", 0xffff, cfg.FetchIntervalSeconds))
   468  	}
   469  	return errs
   470  }
   471  
   472  type AgmaAnalytics struct {
   473  	Enabled  bool                      `mapstructure:"enabled"`
   474  	Endpoint AgmaAnalyticsHttpEndpoint `mapstructure:"endpoint"`
   475  	Buffers  AgmaAnalyticsBuffer       `mapstructure:"buffers"`
   476  	Accounts []AgmaAnalyticsAccount    `mapstructure:"accounts"`
   477  }
   478  
   479  type AgmaAnalyticsHttpEndpoint struct {
   480  	Url     string `mapstructure:"url"`
   481  	Timeout string `mapstructure:"timeout"`
   482  	Gzip    bool   `mapstructure:"gzip"`
   483  }
   484  
   485  type AgmaAnalyticsBuffer struct {
   486  	BufferSize string `mapstructure:"size"`
   487  	EventCount int    `mapstructure:"count"`
   488  	Timeout    string `mapstructure:"timeout"`
   489  }
   490  
   491  type AgmaAnalyticsAccount struct {
   492  	Code        string `mapstructure:"code"`
   493  	PublisherId string `mapstructure:"publisher_id"`
   494  	SiteAppId   string `mapstructure:"site_app_id"`
   495  }
   496  
   497  // FileLogs Corresponding config for FileLogger as a PBS Analytics Module
   498  type FileLogs struct {
   499  	Filename string `mapstructure:"filename"`
   500  }
   501  
   502  type Pubstack struct {
   503  	Enabled     bool           `mapstructure:"enabled"`
   504  	ScopeId     string         `mapstructure:"scopeid"`
   505  	IntakeUrl   string         `mapstructure:"endpoint"`
   506  	Buffers     PubstackBuffer `mapstructure:"buffers"`
   507  	ConfRefresh string         `mapstructure:"configuration_refresh_delay"`
   508  }
   509  
   510  type PubstackBuffer struct {
   511  	BufferSize string `mapstructure:"size"`
   512  	EventCount int    `mapstructure:"count"`
   513  	Timeout    string `mapstructure:"timeout"`
   514  }
   515  
   516  type VTrack struct {
   517  	TimeoutMS          int64 `mapstructure:"timeout_ms"`
   518  	AllowUnknownBidder bool  `mapstructure:"allow_unknown_bidder"`
   519  	Enabled            bool  `mapstructure:"enabled"`
   520  }
   521  
   522  type Event struct {
   523  	TimeoutMS int64 `mapstructure:"timeout_ms"`
   524  }
   525  
   526  type HostCookie struct {
   527  	Domain             string `mapstructure:"domain"`
   528  	Family             string `mapstructure:"family"`
   529  	CookieName         string `mapstructure:"cookie_name"`
   530  	OptOutURL          string `mapstructure:"opt_out_url"`
   531  	OptInURL           string `mapstructure:"opt_in_url"`
   532  	MaxCookieSizeBytes int    `mapstructure:"max_cookie_size_bytes"`
   533  	OptOutCookie       Cookie `mapstructure:"optout_cookie"`
   534  	// Cookie timeout in days
   535  	TTL int64 `mapstructure:"ttl_days"`
   536  }
   537  
   538  func (cfg *HostCookie) TTLDuration() time.Duration {
   539  	return time.Duration(cfg.TTL) * time.Hour * 24
   540  }
   541  
   542  type RequestTimeoutHeaders struct {
   543  	RequestTimeInQueue    string `mapstructure:"request_time_in_queue"`
   544  	RequestTimeoutInQueue string `mapstructure:"request_timeout_in_queue"`
   545  }
   546  
   547  type Metrics struct {
   548  	Influxdb   InfluxMetrics     `mapstructure:"influxdb"`
   549  	Prometheus PrometheusMetrics `mapstructure:"prometheus"`
   550  	Disabled   DisabledMetrics   `mapstructure:"disabled_metrics"`
   551  }
   552  
   553  type DisabledMetrics struct {
   554  	// True if we want to stop collecting account-to-adapter metrics
   555  	AccountAdapterDetails bool `mapstructure:"account_adapter_details"`
   556  
   557  	// True if we want to stop collecting account debug request metrics
   558  	AccountDebug bool `mapstructure:"account_debug"`
   559  
   560  	// True if we want to stop collecting account stored respponses metrics
   561  	AccountStoredResponses bool `mapstructure:"account_stored_responses"`
   562  
   563  	// True if we don't want to collect metrics about the connections prebid
   564  	// server establishes with bidder servers such as the number of connections
   565  	// that were created or reused.
   566  	AdapterConnectionMetrics bool `mapstructure:"adapter_connections_metrics"`
   567  
   568  	// True if we don't want to collect the per adapter buyer UID scrubbed metric
   569  	AdapterBuyerUIDScrubbed bool `mapstructure:"adapter_buyeruid_scrubbed"`
   570  
   571  	// True if we don't want to collect the per adapter GDPR request blocked metric
   572  	AdapterGDPRRequestBlocked bool `mapstructure:"adapter_gdpr_request_blocked"`
   573  
   574  	// True if we want to stop collecting account modules metrics
   575  	AccountModulesMetrics bool `mapstructure:"account_modules_metrics"`
   576  }
   577  
   578  func (cfg *Metrics) validate(errs []error) []error {
   579  	return cfg.Prometheus.validate(errs)
   580  }
   581  
   582  type InfluxMetrics struct {
   583  	Host               string `mapstructure:"host"`
   584  	Database           string `mapstructure:"database"`
   585  	Measurement        string `mapstructure:"measurement"`
   586  	Username           string `mapstructure:"username"`
   587  	Password           string `mapstructure:"password"`
   588  	AlignTimestamps    bool   `mapstructure:"align_timestamps"`
   589  	MetricSendInterval int    `mapstructure:"metric_send_interval"`
   590  }
   591  
   592  type PrometheusMetrics struct {
   593  	Port             int    `mapstructure:"port"`
   594  	Namespace        string `mapstructure:"namespace"`
   595  	Subsystem        string `mapstructure:"subsystem"`
   596  	TimeoutMillisRaw int    `mapstructure:"timeout_ms"`
   597  }
   598  
   599  func (cfg *PrometheusMetrics) validate(errs []error) []error {
   600  	if cfg.Port > 0 && cfg.TimeoutMillisRaw <= 0 {
   601  		errs = append(errs, fmt.Errorf("metrics.prometheus.timeout_ms must be positive if metrics.prometheus.port is defined. Got timeout=%d and port=%d", cfg.TimeoutMillisRaw, cfg.Port))
   602  	}
   603  	return errs
   604  }
   605  
   606  func (m *PrometheusMetrics) Timeout() time.Duration {
   607  	return time.Duration(m.TimeoutMillisRaw) * time.Millisecond
   608  }
   609  
   610  // ExternalCache configures the externally accessible cache url.
   611  type ExternalCache struct {
   612  	Scheme string `mapstructure:"scheme"`
   613  	Host   string `mapstructure:"host"`
   614  	Path   string `mapstructure:"path"`
   615  }
   616  
   617  // Cache configures the url used internally by Prebid Server to communicate with Prebid Cache.
   618  type Cache struct {
   619  	Scheme string `mapstructure:"scheme"`
   620  	Host   string `mapstructure:"host"`
   621  	Query  string `mapstructure:"query"`
   622  
   623  	// A static timeout here is not ideal. This is a hack because we have some aggressive timelines for OpenRTB support.
   624  	// This value specifies how much time the prebid server host expects a call to prebid cache to take.
   625  	//
   626  	// OpenRTB allows the caller to specify the auction timeout. Prebid Server will subtract _this_ amount of time
   627  	// from the timeout it gives demand sources to respond.
   628  	//
   629  	// In reality, the cache response time will probably fluctuate with the traffic over time. Someday,
   630  	// this should be replaced by code which tracks the response time of recent cache calls and
   631  	// adjusts the time dynamically.
   632  	ExpectedTimeMillis int `mapstructure:"expected_millis"`
   633  
   634  	DefaultTTLs DefaultTTLs `mapstructure:"default_ttl_seconds"`
   635  }
   636  
   637  // Default TTLs to use to cache bids for different types of imps.
   638  type DefaultTTLs struct {
   639  	Banner int `mapstructure:"banner"`
   640  	Video  int `mapstructure:"video"`
   641  	Native int `mapstructure:"native"`
   642  	Audio  int `mapstructure:"audio"`
   643  }
   644  
   645  type Cookie struct {
   646  	Name  string `mapstructure:"name"`
   647  	Value string `mapstructure:"value"`
   648  }
   649  
   650  // AliasConfig will define the various source(s) or the default aliases
   651  // Currently only filesystem is supported, but keeping the config structure
   652  type DefReqConfig struct {
   653  	Type       string      `mapstructure:"type"`
   654  	FileSystem DefReqFiles `mapstructure:"file"`
   655  	AliasInfo  bool        `mapstructure:"alias_info"`
   656  }
   657  
   658  type DefReqFiles struct {
   659  	FileName string `mapstructure:"name"`
   660  }
   661  
   662  type Debug struct {
   663  	TimeoutNotification TimeoutNotification `mapstructure:"timeout_notification"`
   664  	OverrideToken       string              `mapstructure:"override_token"`
   665  }
   666  
   667  type Server struct {
   668  	ExternalUrl string
   669  	GvlID       int
   670  	DataCenter  string
   671  }
   672  
   673  func (server *Server) Empty() bool {
   674  	return server == nil || (server.DataCenter == "" && server.ExternalUrl == "" && server.GvlID == 0)
   675  }
   676  
   677  func (cfg *Debug) validate(errs []error) []error {
   678  	return cfg.TimeoutNotification.validate(errs)
   679  }
   680  
   681  type TimeoutNotification struct {
   682  	// Log timeout notifications in the application log
   683  	Log bool `mapstructure:"log"`
   684  	// Fraction of notifications to log
   685  	SamplingRate float32 `mapstructure:"sampling_rate"`
   686  	// Only log failures
   687  	FailOnly bool `mapstructure:"fail_only"`
   688  }
   689  
   690  type Validations struct {
   691  	BannerCreativeMaxSize string `mapstructure:"banner_creative_max_size" json:"banner_creative_max_size"`
   692  	SecureMarkup          string `mapstructure:"secure_markup" json:"secure_markup"`
   693  	MaxCreativeWidth      int64  `mapstructure:"max_creative_width" json:"max_creative_width"`
   694  	MaxCreativeHeight     int64  `mapstructure:"max_creative_height" json:"max_creative_height"`
   695  }
   696  
   697  const (
   698  	ValidationEnforce string = "enforce"
   699  	ValidationWarn    string = "warn"
   700  	ValidationSkip    string = "skip"
   701  )
   702  
   703  func (host *Validations) SetBannerCreativeMaxSize(account Validations) {
   704  	if len(account.BannerCreativeMaxSize) > 0 {
   705  		host.BannerCreativeMaxSize = account.BannerCreativeMaxSize
   706  	}
   707  }
   708  
   709  func (cfg *TimeoutNotification) validate(errs []error) []error {
   710  	if cfg.SamplingRate < 0.0 || cfg.SamplingRate > 1.0 {
   711  		errs = append(errs, fmt.Errorf("debug.timeout_notification.sampling_rate must be positive and not greater than 1.0. Got %f", cfg.SamplingRate))
   712  	}
   713  	return errs
   714  }
   715  
   716  // New uses viper to get our server configurations.
   717  func New(v *viper.Viper, bidderInfos BidderInfos, normalizeBidderName func(string) (openrtb_ext.BidderName, bool)) (*Configuration, error) {
   718  	var c Configuration
   719  	if err := v.Unmarshal(&c); err != nil {
   720  		return nil, fmt.Errorf("viper failed to unmarshal app config: %v", err)
   721  	}
   722  
   723  	if err := c.RequestValidation.Parse(); err != nil {
   724  		return nil, err
   725  	}
   726  
   727  	if err := isValidCookieSize(c.HostCookie.MaxCookieSizeBytes); err != nil {
   728  		glog.Fatal(fmt.Printf("Max cookie size %d cannot be less than %d \n", c.HostCookie.MaxCookieSizeBytes, MIN_COOKIE_SIZE_BYTES))
   729  		return nil, err
   730  	}
   731  
   732  	if err := UnpackDSADefault(c.AccountDefaults.Privacy.DSA); err != nil {
   733  		return nil, fmt.Errorf("invalid default account DSA: %v", err)
   734  	}
   735  
   736  	// Update account defaults and generate base json for patch
   737  	c.AccountDefaults.CacheTTL = c.CacheURL.DefaultTTLs // comment this out to set explicitly in config
   738  
   739  	if err := c.MarshalAccountDefaults(); err != nil {
   740  		return nil, err
   741  	}
   742  
   743  	// To look for a request's publisher_id in the NonStandardPublishers list in
   744  	// O(1) time, we fill this hash table located in the NonStandardPublisherMap field of GDPR
   745  	var s struct{}
   746  	c.GDPR.NonStandardPublisherMap = make(map[string]struct{})
   747  	for i := 0; i < len(c.GDPR.NonStandardPublishers); i++ {
   748  		c.GDPR.NonStandardPublisherMap[c.GDPR.NonStandardPublishers[i]] = s
   749  	}
   750  
   751  	c.GDPR.EEACountriesMap = make(map[string]struct{}, len(c.GDPR.EEACountries))
   752  	for _, v := range c.GDPR.EEACountries {
   753  		c.GDPR.EEACountriesMap[v] = s
   754  	}
   755  
   756  	// for each purpose we capture a reference to the purpose config in a map for easy purpose config lookup
   757  	c.GDPR.TCF2.PurposeConfigs = map[consentconstants.Purpose]*TCF2Purpose{
   758  		1:  &c.GDPR.TCF2.Purpose1,
   759  		2:  &c.GDPR.TCF2.Purpose2,
   760  		3:  &c.GDPR.TCF2.Purpose3,
   761  		4:  &c.GDPR.TCF2.Purpose4,
   762  		5:  &c.GDPR.TCF2.Purpose5,
   763  		6:  &c.GDPR.TCF2.Purpose6,
   764  		7:  &c.GDPR.TCF2.Purpose7,
   765  		8:  &c.GDPR.TCF2.Purpose8,
   766  		9:  &c.GDPR.TCF2.Purpose9,
   767  		10: &c.GDPR.TCF2.Purpose10,
   768  	}
   769  
   770  	// As an alternative to performing several string compares per request, we set the integer representation of
   771  	// the enforcement algorithm on each purpose config
   772  	for _, pc := range c.GDPR.TCF2.PurposeConfigs {
   773  		if pc.EnforceAlgo == TCF2EnforceAlgoBasic {
   774  			pc.EnforceAlgoID = TCF2BasicEnforcement
   775  		} else {
   776  			pc.EnforceAlgoID = TCF2FullEnforcement
   777  		}
   778  	}
   779  
   780  	// To look for a purpose's vendor exceptions in O(1) time, for each purpose we fill this hash table with bidders/analytics
   781  	// adapters located in the VendorExceptions field of the GDPR.TCF2.PurposeX struct defined in this file
   782  	for _, pc := range c.GDPR.TCF2.PurposeConfigs {
   783  		pc.VendorExceptionMap = make(map[string]struct{})
   784  		for v := 0; v < len(pc.VendorExceptions); v++ {
   785  			adapterName := pc.VendorExceptions[v]
   786  			pc.VendorExceptionMap[adapterName] = struct{}{}
   787  		}
   788  	}
   789  
   790  	// To look for a special feature's vendor exceptions in O(1) time, we fill this hash table with bidders located in the
   791  	// VendorExceptions field of the GDPR.TCF2.SpecialFeature1 struct defined in this file
   792  	c.GDPR.TCF2.SpecialFeature1.VendorExceptionMap = make(map[openrtb_ext.BidderName]struct{})
   793  	for v := 0; v < len(c.GDPR.TCF2.SpecialFeature1.VendorExceptions); v++ {
   794  		bidderName := c.GDPR.TCF2.SpecialFeature1.VendorExceptions[v]
   795  		c.GDPR.TCF2.SpecialFeature1.VendorExceptionMap[bidderName] = struct{}{}
   796  	}
   797  
   798  	// To look for a request's app_id in O(1) time, we fill this hash table located in the
   799  	// the BlacklistedApps field of the Configuration struct defined in this file
   800  	c.BlacklistedAppMap = make(map[string]bool)
   801  	for i := 0; i < len(c.BlacklistedApps); i++ {
   802  		c.BlacklistedAppMap[c.BlacklistedApps[i]] = true
   803  	}
   804  
   805  	// Migrate combo stored request config to separate stored_reqs and amp stored_reqs configs.
   806  	resolvedStoredRequestsConfig(&c)
   807  
   808  	configBidderInfosWithNillableFields, err := setConfigBidderInfoNillableFields(v, c.BidderInfos)
   809  	if err != nil {
   810  		return nil, err
   811  	}
   812  	mergedBidderInfos, err := applyBidderInfoConfigOverrides(configBidderInfosWithNillableFields, bidderInfos, normalizeBidderName)
   813  	if err != nil {
   814  		return nil, err
   815  	}
   816  	c.BidderInfos = mergedBidderInfos
   817  
   818  	glog.Info("Logging the resolved configuration:")
   819  	logGeneral(reflect.ValueOf(c), "  \t")
   820  	if errs := c.validate(v); len(errs) > 0 {
   821  		return &c, errortypes.NewAggregateError("validation errors", errs)
   822  	}
   823  
   824  	return &c, nil
   825  }
   826  
   827  type bidderInfoNillableFields struct {
   828  	Disabled                *bool `yaml:"disabled" mapstructure:"disabled"`
   829  	ModifyingVastXmlAllowed *bool `yaml:"modifyingVastXmlAllowed" mapstructure:"modifyingVastXmlAllowed"`
   830  }
   831  type nillableFieldBidderInfos map[string]nillableFieldBidderInfo
   832  type nillableFieldBidderInfo struct {
   833  	nillableFields bidderInfoNillableFields
   834  	bidderInfo     BidderInfo
   835  }
   836  
   837  func setConfigBidderInfoNillableFields(v *viper.Viper, bidderInfos BidderInfos) (nillableFieldBidderInfos, error) {
   838  	if len(bidderInfos) == 0 || v == nil {
   839  		return nil, nil
   840  	}
   841  	infos := make(nillableFieldBidderInfos, len(bidderInfos))
   842  
   843  	for bidderName, bidderInfo := range bidderInfos {
   844  		info := nillableFieldBidderInfo{bidderInfo: bidderInfo}
   845  
   846  		if err := v.UnmarshalKey("adapters."+bidderName+".disabled", &info.nillableFields.Disabled); err != nil {
   847  			return nil, fmt.Errorf("viper failed to unmarshal bidder config disabled: %v", err)
   848  		}
   849  		if err := v.UnmarshalKey("adapters."+bidderName+".modifyingvastxmlallowed", &info.nillableFields.ModifyingVastXmlAllowed); err != nil {
   850  			return nil, fmt.Errorf("viper failed to unmarshal bidder config modifyingvastxmlallowed: %v", err)
   851  		}
   852  		infos[bidderName] = info
   853  	}
   854  	return infos, nil
   855  }
   856  
   857  // MarshalAccountDefaults compiles AccountDefaults into the JSON format used for merge patch
   858  func (cfg *Configuration) MarshalAccountDefaults() error {
   859  	var err error
   860  	if cfg.accountDefaultsJSON, err = jsonutil.Marshal(cfg.AccountDefaults); err != nil {
   861  		glog.Warningf("converting %+v to json: %v", cfg.AccountDefaults, err)
   862  	}
   863  	return err
   864  }
   865  
   866  // UnpackDSADefault validates the JSON DSA default object string by unmarshaling and maps it to a struct
   867  func UnpackDSADefault(dsa *AccountDSA) error {
   868  	if dsa == nil || len(dsa.Default) == 0 {
   869  		return nil
   870  	}
   871  	return jsonutil.Unmarshal([]byte(dsa.Default), &dsa.DefaultUnpacked)
   872  }
   873  
   874  // AccountDefaultsJSON returns the precompiled JSON form of account_defaults
   875  func (cfg *Configuration) AccountDefaultsJSON() json.RawMessage {
   876  	return cfg.accountDefaultsJSON
   877  }
   878  
   879  // GetBaseURL allows for protocol relative URL if scheme is empty
   880  func (cfg *Cache) GetBaseURL() string {
   881  	cfg.Scheme = strings.ToLower(cfg.Scheme)
   882  	if strings.Contains(cfg.Scheme, "https") {
   883  		return fmt.Sprintf("https://%s", cfg.Host)
   884  	}
   885  	if strings.Contains(cfg.Scheme, "http") {
   886  		return fmt.Sprintf("http://%s", cfg.Host)
   887  	}
   888  	return fmt.Sprintf("//%s", cfg.Host)
   889  }
   890  
   891  func (cfg *Configuration) GetCachedAssetURL(uuid string) string {
   892  	return fmt.Sprintf("%s/cache?%s", cfg.CacheURL.GetBaseURL(), strings.Replace(cfg.CacheURL.Query, "%PBS_CACHE_UUID%", uuid, 1))
   893  }
   894  
   895  // Set the default config values for the viper object we are using.
   896  func SetupViper(v *viper.Viper, filename string, bidderInfos BidderInfos) {
   897  	if filename != "" {
   898  		v.SetConfigName(filename)
   899  		v.AddConfigPath(".")
   900  		v.AddConfigPath("/etc/config")
   901  	}
   902  
   903  	// Fixes #475: Some defaults will be set just so they are accessible via environment variables
   904  	// (basically so viper knows they exist)
   905  	v.SetDefault("external_url", "http://localhost:8000")
   906  	v.SetDefault("host", "")
   907  	v.SetDefault("port", 8000)
   908  	v.SetDefault("unix_socket_enable", false)              // boolean which decide if the socket-server will be started.
   909  	v.SetDefault("unix_socket_name", "prebid-server.sock") // path of the socket's file which must be listened.
   910  	v.SetDefault("admin_port", 6060)
   911  	v.SetDefault("admin.enabled", true) // boolean to determine if admin listener will be started.
   912  	v.SetDefault("garbage_collector_threshold", 0)
   913  	v.SetDefault("status_response", "")
   914  	v.SetDefault("datacenter", "")
   915  	v.SetDefault("auction_timeouts_ms.default", 0)
   916  	v.SetDefault("auction_timeouts_ms.max", 0)
   917  	v.SetDefault("cache.scheme", "")
   918  	v.SetDefault("cache.host", "")
   919  	v.SetDefault("cache.query", "")
   920  	v.SetDefault("cache.expected_millis", 10)
   921  	v.SetDefault("cache.default_ttl_seconds.banner", 0)
   922  	v.SetDefault("cache.default_ttl_seconds.video", 0)
   923  	v.SetDefault("cache.default_ttl_seconds.native", 0)
   924  	v.SetDefault("cache.default_ttl_seconds.audio", 0)
   925  	v.SetDefault("external_cache.scheme", "")
   926  	v.SetDefault("external_cache.host", "")
   927  	v.SetDefault("external_cache.path", "")
   928  	v.SetDefault("recaptcha_secret", "")
   929  	v.SetDefault("host_cookie.domain", "")
   930  	v.SetDefault("host_cookie.family", "")
   931  	v.SetDefault("host_cookie.cookie_name", "")
   932  	v.SetDefault("host_cookie.opt_out_url", "")
   933  	v.SetDefault("host_cookie.opt_in_url", "")
   934  	v.SetDefault("host_cookie.optout_cookie.name", "")
   935  	v.SetDefault("host_cookie.value", "")
   936  	v.SetDefault("host_cookie.ttl_days", 90)
   937  	v.SetDefault("host_cookie.max_cookie_size_bytes", 0)
   938  	v.SetDefault("host_schain_node", nil)
   939  	v.SetDefault("validations.banner_creative_max_size", ValidationSkip)
   940  	v.SetDefault("validations.secure_markup", ValidationSkip)
   941  	v.SetDefault("validations.max_creative_size.height", 0)
   942  	v.SetDefault("validations.max_creative_size.width", 0)
   943  	v.SetDefault("http_client.max_connections_per_host", 0) // unlimited
   944  	v.SetDefault("http_client.max_idle_connections", 400)
   945  	v.SetDefault("http_client.max_idle_connections_per_host", 10)
   946  	v.SetDefault("http_client.idle_connection_timeout_seconds", 60)
   947  	v.SetDefault("http_client_cache.max_connections_per_host", 0) // unlimited
   948  	v.SetDefault("http_client_cache.max_idle_connections", 10)
   949  	v.SetDefault("http_client_cache.max_idle_connections_per_host", 2)
   950  	v.SetDefault("http_client_cache.idle_connection_timeout_seconds", 60)
   951  	// no metrics configured by default (metrics{host|database|username|password})
   952  	v.SetDefault("metrics.disabled_metrics.account_adapter_details", false)
   953  	v.SetDefault("metrics.disabled_metrics.account_debug", true)
   954  	v.SetDefault("metrics.disabled_metrics.account_stored_responses", true)
   955  	v.SetDefault("metrics.disabled_metrics.adapter_connections_metrics", true)
   956  	v.SetDefault("metrics.disabled_metrics.adapter_buyeruid_scrubbed", true)
   957  	v.SetDefault("metrics.disabled_metrics.adapter_gdpr_request_blocked", false)
   958  	v.SetDefault("metrics.influxdb.host", "")
   959  	v.SetDefault("metrics.influxdb.database", "")
   960  	v.SetDefault("metrics.influxdb.measurement", "")
   961  	v.SetDefault("metrics.influxdb.username", "")
   962  	v.SetDefault("metrics.influxdb.password", "")
   963  	v.SetDefault("metrics.influxdb.align_timestamps", false)
   964  	v.SetDefault("metrics.influxdb.metric_send_interval", 20)
   965  	v.SetDefault("metrics.prometheus.port", 0)
   966  	v.SetDefault("metrics.prometheus.namespace", "")
   967  	v.SetDefault("metrics.prometheus.subsystem", "")
   968  	v.SetDefault("metrics.prometheus.timeout_ms", 10000)
   969  	v.SetDefault("category_mapping.filesystem.enabled", true)
   970  	v.SetDefault("category_mapping.filesystem.directorypath", "./static/category-mapping")
   971  	v.SetDefault("category_mapping.http.endpoint", "")
   972  	v.SetDefault("stored_requests_timeout_ms", 50)
   973  	v.SetDefault("stored_requests.database.connection.driver", "")
   974  	v.SetDefault("stored_requests.database.connection.dbname", "")
   975  	v.SetDefault("stored_requests.database.connection.host", "")
   976  	v.SetDefault("stored_requests.database.connection.port", 0)
   977  	v.SetDefault("stored_requests.database.connection.user", "")
   978  	v.SetDefault("stored_requests.database.connection.password", "")
   979  	v.SetDefault("stored_requests.database.connection.query_string", "")
   980  	v.SetDefault("stored_requests.database.connection.tls.root_cert", "")
   981  	v.SetDefault("stored_requests.database.connection.tls.client_cert", "")
   982  	v.SetDefault("stored_requests.database.connection.tls.client_key", "")
   983  	v.SetDefault("stored_requests.database.fetcher.query", "")
   984  	v.SetDefault("stored_requests.database.fetcher.amp_query", "")
   985  	v.SetDefault("stored_requests.database.initialize_caches.timeout_ms", 0)
   986  	v.SetDefault("stored_requests.database.initialize_caches.query", "")
   987  	v.SetDefault("stored_requests.database.initialize_caches.amp_query", "")
   988  	v.SetDefault("stored_requests.database.poll_for_updates.refresh_rate_seconds", 0)
   989  	v.SetDefault("stored_requests.database.poll_for_updates.timeout_ms", 0)
   990  	v.SetDefault("stored_requests.database.poll_for_updates.query", "")
   991  	v.SetDefault("stored_requests.database.poll_for_updates.amp_query", "")
   992  	v.SetDefault("stored_requests.filesystem.enabled", false)
   993  	v.SetDefault("stored_requests.filesystem.directorypath", "./stored_requests/data/by_id")
   994  	v.SetDefault("stored_requests.directorypath", "./stored_requests/data/by_id")
   995  	v.SetDefault("stored_requests.http.endpoint", "")
   996  	v.SetDefault("stored_requests.http.amp_endpoint", "")
   997  	v.SetDefault("stored_requests.in_memory_cache.type", "none")
   998  	v.SetDefault("stored_requests.in_memory_cache.ttl_seconds", 0)
   999  	v.SetDefault("stored_requests.in_memory_cache.request_cache_size_bytes", 0)
  1000  	v.SetDefault("stored_requests.in_memory_cache.imp_cache_size_bytes", 0)
  1001  	v.SetDefault("stored_requests.in_memory_cache.resp_cache_size_bytes", 0)
  1002  	v.SetDefault("stored_requests.cache_events_api", false)
  1003  	v.SetDefault("stored_requests.http_events.endpoint", "")
  1004  	v.SetDefault("stored_requests.http_events.amp_endpoint", "")
  1005  	v.SetDefault("stored_requests.http_events.refresh_rate_seconds", 0)
  1006  	v.SetDefault("stored_requests.http_events.timeout_ms", 0)
  1007  	// stored_video is short for stored_video_requests.
  1008  	// PBS is not in the business of storing video content beyond the normal prebid cache system.
  1009  	v.SetDefault("stored_video_req.database.connection.driver", "")
  1010  	v.SetDefault("stored_video_req.database.connection.dbname", "")
  1011  	v.SetDefault("stored_video_req.database.connection.host", "")
  1012  	v.SetDefault("stored_video_req.database.connection.port", 0)
  1013  	v.SetDefault("stored_video_req.database.connection.user", "")
  1014  	v.SetDefault("stored_video_req.database.connection.password", "")
  1015  	v.SetDefault("stored_video_req.database.connection.query_string", "")
  1016  	v.SetDefault("stored_video_req.database.connection.tls.root_cert", "")
  1017  	v.SetDefault("stored_video_req.database.connection.tls.client_cert", "")
  1018  	v.SetDefault("stored_video_req.database.connection.tls.client_key", "")
  1019  	v.SetDefault("stored_video_req.database.fetcher.query", "")
  1020  	v.SetDefault("stored_video_req.database.fetcher.amp_query", "")
  1021  	v.SetDefault("stored_video_req.database.initialize_caches.timeout_ms", 0)
  1022  	v.SetDefault("stored_video_req.database.initialize_caches.query", "")
  1023  	v.SetDefault("stored_video_req.database.initialize_caches.amp_query", "")
  1024  	v.SetDefault("stored_video_req.database.poll_for_updates.refresh_rate_seconds", 0)
  1025  	v.SetDefault("stored_video_req.database.poll_for_updates.timeout_ms", 0)
  1026  	v.SetDefault("stored_video_req.database.poll_for_updates.query", "")
  1027  	v.SetDefault("stored_video_req.database.poll_for_updates.amp_query", "")
  1028  	v.SetDefault("stored_video_req.filesystem.enabled", false)
  1029  	v.SetDefault("stored_video_req.filesystem.directorypath", "")
  1030  	v.SetDefault("stored_video_req.http.endpoint", "")
  1031  	v.SetDefault("stored_video_req.in_memory_cache.type", "none")
  1032  	v.SetDefault("stored_video_req.in_memory_cache.ttl_seconds", 0)
  1033  	v.SetDefault("stored_video_req.in_memory_cache.request_cache_size_bytes", 0)
  1034  	v.SetDefault("stored_video_req.in_memory_cache.imp_cache_size_bytes", 0)
  1035  	v.SetDefault("stored_video_req.in_memory_cache.resp_cache_size_bytes", 0)
  1036  	v.SetDefault("stored_video_req.cache_events.enabled", false)
  1037  	v.SetDefault("stored_video_req.cache_events.endpoint", "")
  1038  	v.SetDefault("stored_video_req.http_events.endpoint", "")
  1039  	v.SetDefault("stored_video_req.http_events.refresh_rate_seconds", 0)
  1040  	v.SetDefault("stored_video_req.http_events.timeout_ms", 0)
  1041  	v.SetDefault("stored_responses.database.connection.driver", "")
  1042  	v.SetDefault("stored_responses.database.connection.dbname", "")
  1043  	v.SetDefault("stored_responses.database.connection.host", "")
  1044  	v.SetDefault("stored_responses.database.connection.port", 0)
  1045  	v.SetDefault("stored_responses.database.connection.user", "")
  1046  	v.SetDefault("stored_responses.database.connection.password", "")
  1047  	v.SetDefault("stored_responses.database.connection.query_string", "")
  1048  	v.SetDefault("stored_responses.database.connection.tls.root_cert", "")
  1049  	v.SetDefault("stored_responses.database.connection.tls.client_cert", "")
  1050  	v.SetDefault("stored_responses.database.connection.tls.client_key", "")
  1051  	v.SetDefault("stored_responses.database.fetcher.query", "")
  1052  	v.SetDefault("stored_responses.database.fetcher.amp_query", "")
  1053  	v.SetDefault("stored_responses.database.initialize_caches.timeout_ms", 0)
  1054  	v.SetDefault("stored_responses.database.initialize_caches.query", "")
  1055  	v.SetDefault("stored_responses.database.initialize_caches.amp_query", "")
  1056  	v.SetDefault("stored_responses.database.poll_for_updates.refresh_rate_seconds", 0)
  1057  	v.SetDefault("stored_responses.database.poll_for_updates.timeout_ms", 0)
  1058  	v.SetDefault("stored_responses.database.poll_for_updates.query", "")
  1059  	v.SetDefault("stored_responses.database.poll_for_updates.amp_query", "")
  1060  	v.SetDefault("stored_responses.filesystem.enabled", false)
  1061  	v.SetDefault("stored_responses.filesystem.directorypath", "")
  1062  	v.SetDefault("stored_responses.http.endpoint", "")
  1063  	v.SetDefault("stored_responses.in_memory_cache.type", "none")
  1064  	v.SetDefault("stored_responses.in_memory_cache.ttl_seconds", 0)
  1065  	v.SetDefault("stored_responses.in_memory_cache.request_cache_size_bytes", 0)
  1066  	v.SetDefault("stored_responses.in_memory_cache.imp_cache_size_bytes", 0)
  1067  	v.SetDefault("stored_responses.in_memory_cache.resp_cache_size_bytes", 0)
  1068  	v.SetDefault("stored_responses.cache_events.enabled", false)
  1069  	v.SetDefault("stored_responses.cache_events.endpoint", "")
  1070  	v.SetDefault("stored_responses.http_events.endpoint", "")
  1071  	v.SetDefault("stored_responses.http_events.refresh_rate_seconds", 0)
  1072  	v.SetDefault("stored_responses.http_events.timeout_ms", 0)
  1073  
  1074  	v.SetDefault("vtrack.timeout_ms", 2000)
  1075  	v.SetDefault("vtrack.allow_unknown_bidder", true)
  1076  	v.SetDefault("vtrack.enabled", true)
  1077  
  1078  	v.SetDefault("event.timeout_ms", 1000)
  1079  
  1080  	v.SetDefault("user_sync.priority_groups", [][]string{})
  1081  
  1082  	v.SetDefault("accounts.filesystem.enabled", false)
  1083  	v.SetDefault("accounts.filesystem.directorypath", "./stored_requests/data/by_id")
  1084  	v.SetDefault("accounts.in_memory_cache.type", "none")
  1085  
  1086  	v.BindEnv("user_sync.external_url")
  1087  	v.BindEnv("user_sync.coop_sync.default")
  1088  
  1089  	// some adapters append the user id to the end of the redirect url instead of using
  1090  	// macro substitution. it is important for the uid to be the last query parameter.
  1091  	v.SetDefault("user_sync.redirect_url", "{{.ExternalURL}}/setuid?bidder={{.SyncerKey}}&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&f={{.SyncType}}&uid={{.UserMacro}}")
  1092  
  1093  	v.SetDefault("max_request_size", 1024*256)
  1094  	v.SetDefault("analytics.file.filename", "")
  1095  	v.SetDefault("analytics.pubstack.endpoint", "https://s2s.pbstck.com/v1")
  1096  	v.SetDefault("analytics.pubstack.scopeid", "change-me")
  1097  	v.SetDefault("analytics.pubstack.enabled", false)
  1098  	v.SetDefault("analytics.pubstack.configuration_refresh_delay", "2h")
  1099  	v.SetDefault("analytics.pubstack.buffers.size", "2MB")
  1100  	v.SetDefault("analytics.pubstack.buffers.count", 100)
  1101  	v.SetDefault("analytics.pubstack.buffers.timeout", "900s")
  1102  	v.SetDefault("analytics.agma.enabled", false)
  1103  	v.SetDefault("analytics.agma.endpoint.url", "https://go.pbs.agma-analytics.de/v1/prebid-server")
  1104  	v.SetDefault("analytics.agma.endpoint.timeout", "2s")
  1105  	v.SetDefault("analytics.agma.endpoint.gzip", false)
  1106  	v.SetDefault("analytics.agma.buffers.size", "2MB")
  1107  	v.SetDefault("analytics.agma.buffers.count", 100)
  1108  	v.SetDefault("analytics.agma.buffers.timeout", "15m")
  1109  	v.SetDefault("analytics.agma.accounts", []AgmaAnalyticsAccount{})
  1110  	v.SetDefault("amp_timeout_adjustment_ms", 0)
  1111  	v.BindEnv("gdpr.default_value")
  1112  	v.SetDefault("gdpr.enabled", true)
  1113  	v.SetDefault("gdpr.host_vendor_id", 0)
  1114  	v.SetDefault("gdpr.timeouts_ms.init_vendorlist_fetches", 0)
  1115  	v.SetDefault("gdpr.timeouts_ms.active_vendorlist_fetch", 0)
  1116  	v.SetDefault("gdpr.non_standard_publishers", []string{""})
  1117  	v.SetDefault("gdpr.tcf2.enabled", true)
  1118  	v.SetDefault("gdpr.tcf2.purpose1.enforce_vendors", true)
  1119  	v.SetDefault("gdpr.tcf2.purpose2.enforce_vendors", true)
  1120  	v.SetDefault("gdpr.tcf2.purpose3.enforce_vendors", true)
  1121  	v.SetDefault("gdpr.tcf2.purpose4.enforce_vendors", true)
  1122  	v.SetDefault("gdpr.tcf2.purpose5.enforce_vendors", true)
  1123  	v.SetDefault("gdpr.tcf2.purpose6.enforce_vendors", true)
  1124  	v.SetDefault("gdpr.tcf2.purpose7.enforce_vendors", true)
  1125  	v.SetDefault("gdpr.tcf2.purpose8.enforce_vendors", true)
  1126  	v.SetDefault("gdpr.tcf2.purpose9.enforce_vendors", true)
  1127  	v.SetDefault("gdpr.tcf2.purpose10.enforce_vendors", true)
  1128  	v.SetDefault("gdpr.tcf2.purpose1.vendor_exceptions", []string{})
  1129  	v.SetDefault("gdpr.tcf2.purpose2.vendor_exceptions", []string{})
  1130  	v.SetDefault("gdpr.tcf2.purpose3.vendor_exceptions", []string{})
  1131  	v.SetDefault("gdpr.tcf2.purpose4.vendor_exceptions", []string{})
  1132  	v.SetDefault("gdpr.tcf2.purpose5.vendor_exceptions", []string{})
  1133  	v.SetDefault("gdpr.tcf2.purpose6.vendor_exceptions", []string{})
  1134  	v.SetDefault("gdpr.tcf2.purpose7.vendor_exceptions", []string{})
  1135  	v.SetDefault("gdpr.tcf2.purpose8.vendor_exceptions", []string{})
  1136  	v.SetDefault("gdpr.tcf2.purpose9.vendor_exceptions", []string{})
  1137  	v.SetDefault("gdpr.tcf2.purpose10.vendor_exceptions", []string{})
  1138  	v.SetDefault("gdpr.amp_exception", false)
  1139  	v.SetDefault("gdpr.eea_countries", []string{"ALA", "AUT", "BEL", "BGR", "HRV", "CYP", "CZE", "DNK", "EST",
  1140  		"FIN", "FRA", "GUF", "DEU", "GIB", "GRC", "GLP", "GGY", "HUN", "ISL", "IRL", "IMN", "ITA", "JEY", "LVA",
  1141  		"LIE", "LTU", "LUX", "MLT", "MTQ", "MYT", "NLD", "NOR", "POL", "PRT", "REU", "ROU", "BLM", "MAF", "SPM",
  1142  		"SVK", "SVN", "ESP", "SWE", "GBR"})
  1143  	v.SetDefault("ccpa.enforce", false)
  1144  	v.SetDefault("lmt.enforce", true)
  1145  	v.SetDefault("currency_converter.fetch_url", "https://cdn.jsdelivr.net/gh/prebid/currency-file@1/latest.json")
  1146  	v.SetDefault("currency_converter.fetch_interval_seconds", 1800) // fetch currency rates every 30 minutes
  1147  	v.SetDefault("currency_converter.stale_rates_seconds", 0)
  1148  	v.SetDefault("default_request.type", "")
  1149  	v.SetDefault("default_request.file.name", "")
  1150  	v.SetDefault("default_request.alias_info", false)
  1151  	v.SetDefault("blacklisted_apps", []string{""})
  1152  	v.SetDefault("blacklisted_accts", []string{""})
  1153  	v.SetDefault("account_required", false)
  1154  	v.SetDefault("account_defaults.disabled", false)
  1155  	v.SetDefault("account_defaults.debug_allow", true)
  1156  	v.SetDefault("account_defaults.price_floors.enabled", false)
  1157  	v.SetDefault("account_defaults.price_floors.enforce_floors_rate", 100)
  1158  	v.SetDefault("account_defaults.price_floors.adjust_for_bid_adjustment", true)
  1159  	v.SetDefault("account_defaults.price_floors.enforce_deal_floors", false)
  1160  	v.SetDefault("account_defaults.price_floors.use_dynamic_data", false)
  1161  	v.SetDefault("account_defaults.price_floors.max_rules", 100)
  1162  	v.SetDefault("account_defaults.price_floors.max_schema_dims", 3)
  1163  	v.SetDefault("account_defaults.price_floors.fetch.enabled", false)
  1164  	v.SetDefault("account_defaults.price_floors.fetch.url", "")
  1165  	v.SetDefault("account_defaults.price_floors.fetch.timeout_ms", 3000)
  1166  	v.SetDefault("account_defaults.price_floors.fetch.max_file_size_kb", 100)
  1167  	v.SetDefault("account_defaults.price_floors.fetch.max_rules", 1000)
  1168  	v.SetDefault("account_defaults.price_floors.fetch.max_age_sec", 86400)
  1169  	v.SetDefault("account_defaults.price_floors.fetch.period_sec", 3600)
  1170  	v.SetDefault("account_defaults.price_floors.fetch.max_schema_dims", 0)
  1171  	v.SetDefault("account_defaults.privacy.privacysandbox.topicsdomain", "")
  1172  	v.SetDefault("account_defaults.privacy.privacysandbox.cookiedeprecation.enabled", false)
  1173  	v.SetDefault("account_defaults.privacy.privacysandbox.cookiedeprecation.ttl_sec", 604800)
  1174  
  1175  	v.SetDefault("account_defaults.events_enabled", false)
  1176  	v.BindEnv("account_defaults.privacy.dsa.default")
  1177  	v.BindEnv("account_defaults.privacy.dsa.gdpr_only")
  1178  	v.SetDefault("account_defaults.privacy.ipv6.anon_keep_bits", 56)
  1179  	v.SetDefault("account_defaults.privacy.ipv4.anon_keep_bits", 24)
  1180  
  1181  	//Defaults for Price floor fetcher
  1182  	v.SetDefault("price_floors.fetcher.worker", 20)
  1183  	v.SetDefault("price_floors.fetcher.capacity", 20000)
  1184  	v.SetDefault("price_floors.fetcher.cache_size_mb", 64)
  1185  	v.SetDefault("price_floors.fetcher.http_client.max_connections_per_host", 0) // unlimited
  1186  	v.SetDefault("price_floors.fetcher.http_client.max_idle_connections", 40)
  1187  	v.SetDefault("price_floors.fetcher.http_client.max_idle_connections_per_host", 2)
  1188  	v.SetDefault("price_floors.fetcher.http_client.idle_connection_timeout_seconds", 60)
  1189  	v.SetDefault("price_floors.fetcher.max_retries", 10)
  1190  
  1191  	v.SetDefault("account_defaults.events_enabled", false)
  1192  	v.SetDefault("compression.response.enable_gzip", false)
  1193  	v.SetDefault("compression.request.enable_gzip", false)
  1194  
  1195  	v.SetDefault("certificates_file", "")
  1196  	v.SetDefault("auto_gen_source_tid", true)
  1197  	v.SetDefault("generate_bid_id", false)
  1198  	v.SetDefault("generate_request_id", false)
  1199  
  1200  	v.SetDefault("request_timeout_headers.request_time_in_queue", "")
  1201  	v.SetDefault("request_timeout_headers.request_timeout_in_queue", "")
  1202  
  1203  	v.SetDefault("debug.timeout_notification.log", false)
  1204  	v.SetDefault("debug.timeout_notification.sampling_rate", 0.0)
  1205  	v.SetDefault("debug.timeout_notification.fail_only", false)
  1206  	v.SetDefault("debug.override_token", "")
  1207  
  1208  	v.SetDefault("tmax_adjustments.enabled", false)
  1209  	v.SetDefault("tmax_adjustments.bidder_response_duration_min_ms", 0)
  1210  	v.SetDefault("tmax_adjustments.bidder_network_latency_buffer_ms", 0)
  1211  	v.SetDefault("tmax_adjustments.pbs_response_preparation_duration_ms", 0)
  1212  
  1213  	/* IPv4
  1214  	/*  Site Local: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
  1215  	/*  Link Local: 169.254.0.0/16
  1216  	/*  Loopback:   127.0.0.0/8
  1217  	/*
  1218  	/* IPv6
  1219  	/*  Loopback:      ::1/128
  1220  	/*  Documentation: 2001:db8::/32
  1221  	/*  Unique Local:  fc00::/7
  1222  	/*  Link Local:    fe80::/10
  1223  	/*  Multicast:     ff00::/8
  1224  	*/
  1225  	v.SetDefault("request_validation.ipv4_private_networks", []string{"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "169.254.0.0/16", "127.0.0.0/8"})
  1226  	v.SetDefault("request_validation.ipv6_private_networks", []string{"::1/128", "fc00::/7", "fe80::/10", "ff00::/8", "2001:db8::/32"})
  1227  
  1228  	// Set environment variable support:
  1229  	v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
  1230  	v.SetTypeByDefaultValue(true)
  1231  	v.SetEnvPrefix("PBS")
  1232  	v.AutomaticEnv()
  1233  	v.ReadInConfig()
  1234  
  1235  	// These defaults must be set after the migrate functions because those functions look for the presence of these
  1236  	// config fields and there isn't a way to detect presence of a config field using the viper package if a default
  1237  	// is set. Viper IsSet and Get functions consider default values.
  1238  	v.SetDefault("gdpr.tcf2.purpose1.enforce_algo", TCF2EnforceAlgoFull)
  1239  	v.SetDefault("gdpr.tcf2.purpose2.enforce_algo", TCF2EnforceAlgoFull)
  1240  	v.SetDefault("gdpr.tcf2.purpose3.enforce_algo", TCF2EnforceAlgoFull)
  1241  	v.SetDefault("gdpr.tcf2.purpose4.enforce_algo", TCF2EnforceAlgoFull)
  1242  	v.SetDefault("gdpr.tcf2.purpose5.enforce_algo", TCF2EnforceAlgoFull)
  1243  	v.SetDefault("gdpr.tcf2.purpose6.enforce_algo", TCF2EnforceAlgoFull)
  1244  	v.SetDefault("gdpr.tcf2.purpose7.enforce_algo", TCF2EnforceAlgoFull)
  1245  	v.SetDefault("gdpr.tcf2.purpose8.enforce_algo", TCF2EnforceAlgoFull)
  1246  	v.SetDefault("gdpr.tcf2.purpose9.enforce_algo", TCF2EnforceAlgoFull)
  1247  	v.SetDefault("gdpr.tcf2.purpose10.enforce_algo", TCF2EnforceAlgoFull)
  1248  	v.SetDefault("gdpr.tcf2.purpose1.enforce_purpose", true)
  1249  	v.SetDefault("gdpr.tcf2.purpose2.enforce_purpose", true)
  1250  	v.SetDefault("gdpr.tcf2.purpose3.enforce_purpose", true)
  1251  	v.SetDefault("gdpr.tcf2.purpose4.enforce_purpose", true)
  1252  	v.SetDefault("gdpr.tcf2.purpose5.enforce_purpose", true)
  1253  	v.SetDefault("gdpr.tcf2.purpose6.enforce_purpose", true)
  1254  	v.SetDefault("gdpr.tcf2.purpose7.enforce_purpose", true)
  1255  	v.SetDefault("gdpr.tcf2.purpose8.enforce_purpose", true)
  1256  	v.SetDefault("gdpr.tcf2.purpose9.enforce_purpose", true)
  1257  	v.SetDefault("gdpr.tcf2.purpose10.enforce_purpose", true)
  1258  	v.SetDefault("gdpr.tcf2.purpose_one_treatment.enabled", true)
  1259  	v.SetDefault("gdpr.tcf2.purpose_one_treatment.access_allowed", true)
  1260  	v.SetDefault("gdpr.tcf2.special_feature1.enforce", true)
  1261  	v.SetDefault("gdpr.tcf2.special_feature1.vendor_exceptions", []openrtb_ext.BidderName{})
  1262  	v.SetDefault("price_floors.enabled", false)
  1263  
  1264  	// Defaults for account_defaults.events.default_url
  1265  	v.SetDefault("account_defaults.events.default_url", "https://PBS_HOST/event?t=##PBS-EVENTTYPE##&vtype=##PBS-VASTEVENT##&b=##PBS-BIDID##&f=i&a=##PBS-ACCOUNTID##&ts=##PBS-TIMESTAMP##&bidder=##PBS-BIDDER##&int=##PBS-INTEGRATION##&mt=##PBS-MEDIATYPE##&ch=##PBS-CHANNEL##&aid=##PBS-AUCTIONID##&l=##PBS-LINEID##")
  1266  	v.SetDefault("account_defaults.events.enabled", false)
  1267  
  1268  	v.SetDefault("experiment.adscert.mode", "off")
  1269  	v.SetDefault("experiment.adscert.inprocess.origin", "")
  1270  	v.SetDefault("experiment.adscert.inprocess.key", "")
  1271  	v.SetDefault("experiment.adscert.inprocess.domain_check_interval_seconds", 30)
  1272  	v.SetDefault("experiment.adscert.inprocess.domain_renewal_interval_seconds", 30)
  1273  	v.SetDefault("experiment.adscert.remote.url", "")
  1274  	v.SetDefault("experiment.adscert.remote.signing_timeout_ms", 5)
  1275  
  1276  	v.SetDefault("hooks.enabled", false)
  1277  
  1278  	for bidderName := range bidderInfos {
  1279  		setBidderDefaults(v, strings.ToLower(bidderName))
  1280  	}
  1281  }
  1282  
  1283  func isConfigInfoPresent(v *viper.Viper, prefix string, fields []string) bool {
  1284  	prefix = prefix + "."
  1285  	for _, field := range fields {
  1286  		fieldName := prefix + field
  1287  		if v.IsSet(fieldName) {
  1288  			return true
  1289  		}
  1290  	}
  1291  	return false
  1292  }
  1293  
  1294  func setBidderDefaults(v *viper.Viper, bidder string) {
  1295  	adapterCfgPrefix := "adapters." + bidder
  1296  	v.BindEnv(adapterCfgPrefix + ".disabled")
  1297  	v.BindEnv(adapterCfgPrefix + ".endpoint")
  1298  	v.BindEnv(adapterCfgPrefix + ".extra_info")
  1299  	v.BindEnv(adapterCfgPrefix + ".modifyingVastXmlAllowed")
  1300  	v.BindEnv(adapterCfgPrefix + ".debug.allow")
  1301  	v.BindEnv(adapterCfgPrefix + ".gvlVendorID")
  1302  	v.BindEnv(adapterCfgPrefix + ".usersync_url")
  1303  	v.BindEnv(adapterCfgPrefix + ".experiment.adsCert.enabled")
  1304  	v.BindEnv(adapterCfgPrefix + ".platform_id")
  1305  	v.BindEnv(adapterCfgPrefix + ".app_secret")
  1306  	v.BindEnv(adapterCfgPrefix + ".xapi.username")
  1307  	v.BindEnv(adapterCfgPrefix + ".xapi.password")
  1308  	v.BindEnv(adapterCfgPrefix + ".xapi.tracker")
  1309  	v.BindEnv(adapterCfgPrefix + ".endpointCompression")
  1310  	v.BindEnv(adapterCfgPrefix + ".openrtb.version")
  1311  	v.BindEnv(adapterCfgPrefix + ".openrtb.gpp-supported")
  1312  
  1313  	v.BindEnv(adapterCfgPrefix + ".usersync.key")
  1314  	v.BindEnv(adapterCfgPrefix + ".usersync.default")
  1315  	v.BindEnv(adapterCfgPrefix + ".usersync.iframe.url")
  1316  	v.BindEnv(adapterCfgPrefix + ".usersync.iframe.redirect_url")
  1317  	v.BindEnv(adapterCfgPrefix + ".usersync.iframe.external_url")
  1318  	v.BindEnv(adapterCfgPrefix + ".usersync.iframe.user_macro")
  1319  	v.BindEnv(adapterCfgPrefix + ".usersync.redirect.url")
  1320  	v.BindEnv(adapterCfgPrefix + ".usersync.redirect.redirect_url")
  1321  	v.BindEnv(adapterCfgPrefix + ".usersync.redirect.external_url")
  1322  	v.BindEnv(adapterCfgPrefix + ".usersync.redirect.user_macro")
  1323  	v.BindEnv(adapterCfgPrefix + ".usersync.external_url")
  1324  	v.BindEnv(adapterCfgPrefix + ".usersync.support_cors")
  1325  }
  1326  
  1327  func isValidCookieSize(maxCookieSize int) error {
  1328  	// If a non-zero-less-than-500-byte "host_cookie.max_cookie_size_bytes" value was specified in the
  1329  	// environment configuration of prebid-server, default to 500 bytes
  1330  	if maxCookieSize != 0 && maxCookieSize < MIN_COOKIE_SIZE_BYTES {
  1331  		return fmt.Errorf("Configured cookie size is less than allowed minimum size of %d \n", MIN_COOKIE_SIZE_BYTES)
  1332  	}
  1333  	return nil
  1334  }
  1335  
  1336  // Tmax Adjustments enables PBS to estimate the tmax value for bidders, indicating the allotted time for them to respond to a request.
  1337  // It's important to note that the calculated tmax is just an estimate and will not be entirely precise.
  1338  // PBS will calculate the bidder tmax as follows:
  1339  // bidderTmax = request.tmax - reqProcessingTime - BidderNetworkLatencyBuffer - PBSResponsePreparationDuration
  1340  // Note that reqProcessingTime is time taken by PBS to process a given request before it is sent to bid adapters and is computed at run time.
  1341  type TmaxAdjustments struct {
  1342  	// Enabled indicates whether bidder tmax should be calculated and passed on to bid adapters
  1343  	Enabled bool `mapstructure:"enabled"`
  1344  	// BidderNetworkLatencyBuffer accounts for network delays between PBS and bidder servers.
  1345  	// A value of 0 indicates no network latency buffer should be accounted for when calculating the bidder tmax.
  1346  	BidderNetworkLatencyBuffer uint `mapstructure:"bidder_network_latency_buffer_ms"`
  1347  	// PBSResponsePreparationDuration accounts for amount of time required for PBS to process all bidder responses and generate final response for a request.
  1348  	// A value of 0 indicates PBS response preparation time shouldn't be accounted for when calculating bidder tmax.
  1349  	PBSResponsePreparationDuration uint `mapstructure:"pbs_response_preparation_duration_ms"`
  1350  	// BidderResponseDurationMin is the minimum amount of time expected to get a response from a bidder request.
  1351  	// PBS won't send a request to the bidder if the bidder tmax calculated is less than the BidderResponseDurationMin value
  1352  	BidderResponseDurationMin uint `mapstructure:"bidder_response_duration_min_ms"`
  1353  }