Skip to content

Commit

Permalink
Initial infrastructure to support bidder openRTB support flags (#2540)
Browse files Browse the repository at this point in the history
  • Loading branch information
hhhjort committed Feb 7, 2023
1 parent 15119b3 commit a58b8f5
Show file tree
Hide file tree
Showing 9 changed files with 290 additions and 123 deletions.
11 changes: 10 additions & 1 deletion config/bidderinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ type BidderInfo struct {
PlatformID string `yaml:"platform_id" mapstructure:"platform_id"`
AppSecret string `yaml:"app_secret" mapstructure:"app_secret"`
// EndpointCompression determines, if set, the type of compression the bid request will undergo before being sent to the corresponding bid server
EndpointCompression string `yaml:"endpointCompression" mapstructure:"endpointCompression"`
EndpointCompression string `yaml:"endpointCompression" mapstructure:"endpointCompression"`
OpenRTB *OpenRTBInfo `yaml:"openrtb" mapstructure:"openrtb"`
}

// BidderInfoExperiment specifies non-production ready feature config for a bidder
Expand Down Expand Up @@ -87,6 +88,14 @@ type AdapterXAPI struct {
Tracker string `yaml:"tracker" mapstructure:"tracker"`
}

// OpenRTBInfo specifies the versions/aspects of openRTB that a bidder supports
// Version is not yet actively supported
// GPPSupported is not yet actively supported
type OpenRTBInfo struct {
Version string `yaml:"version" mapstructure:"version"`
GPPSupported bool `yaml:"gpp-supported" mapstructure:"gpp-supported"`
}

// Syncer specifies the user sync settings for a bidder. This struct is shared by the account config,
// so it needs to have both yaml and mapstructure mappings.
type Syncer struct {
Expand Down
16 changes: 12 additions & 4 deletions config/bidderinfo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,24 @@ package config

import (
"errors"
"gopkg.in/yaml.v3"
"strings"
"testing"

"gopkg.in/yaml.v3"

"github.com/prebid/prebid-server/openrtb_ext"
"github.com/stretchr/testify/assert"
)

const testInfoFilesPathValid = "./test/bidder-info-valid"
const testSimpleYAML = `
maintainer:
email: "some-email@domain.com"
email: some-email@domain.com
gvlVendorID: 42
`
const fullBidderYAMLConfig = `
maintainer:
email: "some-email@domain.com"
email: some-email@domain.com
capabilities:
app:
mediaTypes:
Expand All @@ -37,7 +38,10 @@ gvlVendorID: 42
experiment:
adsCert:
enabled: true
endpointCompression: "GZIP"
endpointCompression: GZIP
openrtb:
version: 2.6
gpp-supported: true
`

func TestLoadBidderInfoFromDisk(t *testing.T) {
Expand Down Expand Up @@ -990,6 +994,10 @@ func TestReadFullYamlBidderConfig(t *testing.T) {
},
Experiment: BidderInfoExperiment{AdsCert: BidderAdsCert{Enabled: true}},
EndpointCompression: "GZIP",
OpenRTB: &OpenRTBInfo{
Version: "2.6",
GPPSupported: true,
},
},
}
assert.Equalf(t, expectedBidderInfo, actualBidderInfo, "Bidder info objects aren't matching")
Expand Down
30 changes: 16 additions & 14 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -1406,20 +1406,22 @@ func bindDatabaseEnvVars(v *viper.Viper) {

func setBidderDefaults(v *viper.Viper, bidder string) {
adapterCfgPrefix := "adapters." + bidder
v.BindEnv(adapterCfgPrefix+".disabled", "")
v.BindEnv(adapterCfgPrefix+".endpoint", "")
v.BindEnv(adapterCfgPrefix+".extra_info", "")
v.BindEnv(adapterCfgPrefix+".modifyingVastXmlAllowed", "")
v.BindEnv(adapterCfgPrefix+".debug.allow", "")
v.BindEnv(adapterCfgPrefix+".gvlVendorID", "")
v.BindEnv(adapterCfgPrefix+".usersync_url", "")
v.BindEnv(adapterCfgPrefix+".experiment.adsCert.enabled", "")
v.BindEnv(adapterCfgPrefix+".platform_id", "")
v.BindEnv(adapterCfgPrefix+".app_secret", "")
v.BindEnv(adapterCfgPrefix+".xapi.username", "")
v.BindEnv(adapterCfgPrefix+".xapi.password", "")
v.BindEnv(adapterCfgPrefix+".xapi.tracker", "")
v.BindEnv(adapterCfgPrefix+".endpointCompression", "")
v.BindEnv(adapterCfgPrefix + ".disabled")
v.BindEnv(adapterCfgPrefix + ".endpoint")
v.BindEnv(adapterCfgPrefix + ".extra_info")
v.BindEnv(adapterCfgPrefix + ".modifyingVastXmlAllowed")
v.BindEnv(adapterCfgPrefix + ".debug.allow")
v.BindEnv(adapterCfgPrefix + ".gvlVendorID")
v.BindEnv(adapterCfgPrefix + ".usersync_url")
v.BindEnv(adapterCfgPrefix + ".experiment.adsCert.enabled")
v.BindEnv(adapterCfgPrefix + ".platform_id")
v.BindEnv(adapterCfgPrefix + ".app_secret")
v.BindEnv(adapterCfgPrefix + ".xapi.username")
v.BindEnv(adapterCfgPrefix + ".xapi.password")
v.BindEnv(adapterCfgPrefix + ".xapi.tracker")
v.BindEnv(adapterCfgPrefix + ".endpointCompression")
v.BindEnv(adapterCfgPrefix + ".openrtb.version")
v.BindEnv(adapterCfgPrefix + ".openrtb.gpp-supported")

v.BindEnv(adapterCfgPrefix + ".usersync.key")
v.BindEnv(adapterCfgPrefix + ".usersync.default")
Expand Down
8 changes: 8 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,11 @@ func TestBidderInfoFromEnv(t *testing.T) {
} else {
defer os.Unsetenv("PBS_ADAPTERS_BIDDER1_USERSYNC_REDIRECT_URL")
}
if oldval, ok := os.LookupEnv("PBS_ADAPTERS_BIDDER1_OPENRTB_VERSION"); ok {
defer os.Setenv("PBS_ADAPTERS_BIDDER1_OPENRTB_VERSION", oldval)
} else {
defer os.Unsetenv("PBS_ADAPTERS_BIDDER1_OPENRTB_VERSION")
}

// set new
os.Setenv("PBS_ADAPTERS_BIDDER1_DISABLED", "true")
Expand All @@ -870,6 +875,7 @@ func TestBidderInfoFromEnv(t *testing.T) {
os.Setenv("PBS_ADAPTERS_BIDDER1_EXPERIMENT_ADSCERT_ENABLED", "true")
os.Setenv("PBS_ADAPTERS_BIDDER1_XAPI_USERNAME", "username_override")
os.Setenv("PBS_ADAPTERS_BIDDER1_USERSYNC_REDIRECT_URL", "http://some.url/sync?redirect={{.RedirectURL}}")
os.Setenv("PBS_ADAPTERS_BIDDER1_OPENRTB_VERSION", "2.6")

cfg, _ := newDefaultConfig(t)

Expand All @@ -882,6 +888,8 @@ func TestBidderInfoFromEnv(t *testing.T) {

assert.Equal(t, true, cfg.BidderInfos["bidder1"].Experiment.AdsCert.Enabled)
assert.Equal(t, "username_override", cfg.BidderInfos["bidder1"].XAPI.Username)

assert.Equal(t, "2.6", cfg.BidderInfos["bidder1"].OpenRTB.Version)
}

func TestMigrateConfigPurposeOneTreatment(t *testing.T) {
Expand Down
45 changes: 29 additions & 16 deletions exchange/exchange.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ type exchange struct {
adsCertSigner adscert.Signer
server config.Server
bidValidationEnforcement config.Validations
requestSplitter requestSplitter
}

// Container to pass out response ext data from the GetAllBids goroutines back into the main thread
Expand Down Expand Up @@ -131,29 +132,41 @@ func NewExchange(adapters map[openrtb_ext.BidderName]AdaptedBidder, cache prebid
gdprDefaultValue = gdpr.SignalNo
}

return &exchange{
adapterMap: adapters,
bidderInfo: infos,
privacyConfig := config.Privacy{
CCPA: cfg.CCPA,
GDPR: cfg.GDPR,
LMT: cfg.LMT,
}
requestSplitter := requestSplitter{
bidderToSyncerKey: bidderToSyncerKey,
cache: cache,
cacheTime: time.Duration(cfg.CacheURL.ExpectedTimeMillis) * time.Millisecond,
categoriesFetcher: categoriesFetcher,
currencyConverter: currencyConverter,
externalURL: cfg.ExternalURL,
me: metricsEngine,
privacyConfig: privacyConfig,
gdprPermsBuilder: gdprPermsBuilder,
tcf2ConfigBuilder: tcf2CfgBuilder,
me: metricsEngine,
gdprDefaultValue: gdprDefaultValue,
privacyConfig: config.Privacy{
CCPA: cfg.CCPA,
GDPR: cfg.GDPR,
LMT: cfg.LMT,
},
hostSChainNode: cfg.HostSChainNode,
bidderInfo: infos,
}

return &exchange{
adapterMap: adapters,
bidderInfo: infos,
bidderToSyncerKey: bidderToSyncerKey,
cache: cache,
cacheTime: time.Duration(cfg.CacheURL.ExpectedTimeMillis) * time.Millisecond,
categoriesFetcher: categoriesFetcher,
currencyConverter: currencyConverter,
externalURL: cfg.ExternalURL,
gdprPermsBuilder: gdprPermsBuilder,
tcf2ConfigBuilder: tcf2CfgBuilder,
me: metricsEngine,
gdprDefaultValue: gdprDefaultValue,
privacyConfig: privacyConfig,
bidIDGenerator: &bidIDGenerator{cfg.GenerateBidID},
hostSChainNode: cfg.HostSChainNode,
adsCertSigner: adsCertSigner,
server: config.Server{ExternalUrl: cfg.ExternalURL, GvlID: cfg.GDPR.HostVendorID, DataCenter: cfg.DataCenter},
bidValidationEnforcement: cfg.Validations,
requestSplitter: requestSplitter,
}
}

Expand Down Expand Up @@ -269,7 +282,7 @@ func (e *exchange) HoldAuction(ctx context.Context, r AuctionRequest, debugLog *
gdprDefaultValue := e.parseGDPRDefaultValue(r.BidRequestWrapper.BidRequest)

// Slice of BidRequests, each a copy of the original cleaned to only contain bidder data for the named bidder
bidderRequests, privacyLabels, errs := cleanOpenRTBRequests(ctx, r, requestExt, e.bidderToSyncerKey, e.me, gdprDefaultValue, e.privacyConfig, e.gdprPermsBuilder, e.tcf2ConfigBuilder, e.hostSChainNode)
bidderRequests, privacyLabels, errs := e.requestSplitter.cleanOpenRTBRequests(ctx, r, requestExt, gdprDefaultValue)

e.me.RecordRequestPrivacy(privacyLabels)

Expand Down
55 changes: 53 additions & 2 deletions exchange/exchange_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,11 @@ func TestDebugBehaviour(t *testing.T) {
}.Builder
e.currencyConverter = currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
e.categoriesFetcher = categoriesFetcher

e.requestSplitter = requestSplitter{
me: &metricsConf.NilMetricsEngine{},
gdprPermsBuilder: e.gdprPermsBuilder,
tcf2ConfigBuilder: e.tcf2ConfigBuilder,
}
ctx := context.Background()

// Run tests
Expand Down Expand Up @@ -505,6 +509,11 @@ func TestTwoBiddersDebugDisabledAndEnabled(t *testing.T) {
}.Builder
e.currencyConverter = currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
e.categoriesFetcher = categoriesFetcher
e.requestSplitter = requestSplitter{
me: e.me,
gdprPermsBuilder: e.gdprPermsBuilder,
tcf2ConfigBuilder: e.tcf2ConfigBuilder,
}

debugLog := DebugLog{Enabled: true}

Expand Down Expand Up @@ -668,6 +677,11 @@ func TestOverrideWithCustomCurrency(t *testing.T) {
e.currencyConverter = mockCurrencyConverter
e.categoriesFetcher = categoriesFetcher
e.bidIDGenerator = &mockBidIDGenerator{false, false}
e.requestSplitter = requestSplitter{
me: e.me,
gdprPermsBuilder: e.gdprPermsBuilder,
tcf2ConfigBuilder: e.tcf2ConfigBuilder,
}

// Define mock incoming bid requeset
mockBidRequest := &openrtb2.BidRequest{
Expand Down Expand Up @@ -774,6 +788,11 @@ func TestAdapterCurrency(t *testing.T) {
openrtb_ext.BidderName("foo"): AdaptBidder(mockBidder, nil, &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, openrtb_ext.BidderName("foo"), nil, ""),
},
}
e.requestSplitter = requestSplitter{
me: e.me,
gdprPermsBuilder: e.gdprPermsBuilder,
tcf2ConfigBuilder: e.tcf2ConfigBuilder,
}

// Define Bid Request
request := &openrtb2.BidRequest{
Expand Down Expand Up @@ -1154,6 +1173,11 @@ func TestReturnCreativeEndToEnd(t *testing.T) {
e.currencyConverter = currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
e.categoriesFetcher = categoriesFetcher
e.bidIDGenerator = &mockBidIDGenerator{false, false}
e.requestSplitter = requestSplitter{
me: e.me,
gdprPermsBuilder: e.gdprPermsBuilder,
tcf2ConfigBuilder: e.tcf2ConfigBuilder,
}

// Define mock incoming bid requeset
mockBidRequest := &openrtb2.BidRequest{
Expand Down Expand Up @@ -2422,9 +2446,20 @@ func newExchangeForTests(t *testing.T, filename string, expectations map[string]
hostSChainNode = nil
}

metricsEngine := metricsConf.NewMetricsEngine(&config.Configuration{}, openrtb_ext.CoreBidderNames(), nil, nil)
requestSplitter := requestSplitter{
bidderToSyncerKey: bidderToSyncerKey,
me: metricsEngine,
privacyConfig: privacyConfig,
gdprPermsBuilder: gdprPermsBuilder,
tcf2ConfigBuilder: tcf2ConfigBuilder,
hostSChainNode: hostSChainNode,
bidderInfo: bidderInfos,
}

return &exchange{
adapterMap: bidderAdapters,
me: metricsConf.NewMetricsEngine(&config.Configuration{}, openrtb_ext.CoreBidderNames(), nil, nil),
me: metricsEngine,
cache: &wellBehavedCache{},
cacheTime: 0,
currencyConverter: currency.NewRateConverter(&http.Client{}, "", time.Duration(0)),
Expand All @@ -2440,6 +2475,7 @@ func newExchangeForTests(t *testing.T, filename string, expectations map[string]
hostSChainNode: hostSChainNode,
server: config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "Datacenter"},
bidValidationEnforcement: hostBidValidation,
requestSplitter: requestSplitter,
}
}

Expand Down Expand Up @@ -4120,6 +4156,11 @@ func TestAuctionDebugEnabled(t *testing.T) {
e.tcf2ConfigBuilder = fakeTCF2ConfigBuilder{
cfg: gdpr.NewTCF2Config(config.TCF2{}, config.AccountGDPR{}),
}.Builder
e.requestSplitter = requestSplitter{
me: e.me,
gdprPermsBuilder: e.gdprPermsBuilder,
tcf2ConfigBuilder: e.tcf2ConfigBuilder,
}

ctx := context.Background()

Expand Down Expand Up @@ -4632,6 +4673,11 @@ func TestOverrideConfigAlternateBidderCodesWithRequestValues(t *testing.T) {
e.currencyConverter = currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
e.categoriesFetcher = categoriesFetcher
e.bidIDGenerator = &mockBidIDGenerator{false, false}
e.requestSplitter = requestSplitter{
me: e.me,
gdprPermsBuilder: e.gdprPermsBuilder,
tcf2ConfigBuilder: e.tcf2ConfigBuilder,
}

// Define mock incoming bid requeset
mockBidRequest := &openrtb2.BidRequest{
Expand Down Expand Up @@ -5035,6 +5081,11 @@ func TestModulesCanBeExecutedForMultipleBiddersSimultaneously(t *testing.T) {
cfg: gdpr.NewTCF2Config(config.TCF2{}, config.AccountGDPR{}),
}.Builder
e.currencyConverter = currency.NewRateConverter(&http.Client{}, "", time.Duration(0))
e.requestSplitter = requestSplitter{
me: e.me,
gdprPermsBuilder: e.gdprPermsBuilder,
tcf2ConfigBuilder: e.tcf2ConfigBuilder,
}

bidRequest := &openrtb2.BidRequest{
ID: "some-request-id",
Expand Down
5 changes: 5 additions & 0 deletions exchange/targeting_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ func runTargetingAuction(t *testing.T, mockBids map[openrtb_ext.BidderName][]*op
categoriesFetcher: categoriesFetcher,
bidIDGenerator: &mockBidIDGenerator{false, false},
}
ex.requestSplitter = requestSplitter{
me: ex.me,
gdprPermsBuilder: ex.gdprPermsBuilder,
tcf2ConfigBuilder: ex.tcf2ConfigBuilder,
}

imps := buildImps(t, mockBids)

Expand Down
Loading

0 comments on commit a58b8f5

Please sign in to comment.