From 59b03c8f0538d286cb17ac8b854e20cd1226a7a5 Mon Sep 17 00:00:00 2001 From: AlexBVolcy <74930484+AlexBVolcy@users.noreply.github.com> Date: Tue, 14 Dec 2021 09:32:51 -0800 Subject: [PATCH 01/10] Integration Type Handling --- analytics/event.go | 15 ++++----- config/accounts.go | 15 ++++----- config/config.go | 3 ++ endpoints/events/event.go | 13 +++++--- endpoints/events/event_test.go | 22 +++++++++++--- endpoints/events/vtrack.go | 25 +++++++-------- endpoints/events/vtrack_test.go | 4 +-- endpoints/openrtb2/auction.go | 22 ++++++++++++++ endpoints/openrtb2/auction_test.go | 49 ++++++++++++++++++++++++++++++ exchange/events.go | 9 +++--- openrtb_ext/request.go | 1 + 11 files changed, 137 insertions(+), 41 deletions(-) diff --git a/analytics/event.go b/analytics/event.go index 5350223d8d1..1683191d322 100644 --- a/analytics/event.go +++ b/analytics/event.go @@ -28,11 +28,12 @@ const ( ) type EventRequest struct { - Type EventType `json:"type,omitempty"` - Format ResponseFormat `json:"format,omitempty"` - Analytics Analytics `json:"analytics,omitempty"` - BidID string `json:"bidid,omitempty"` - AccountID string `json:"account_id,omitempty"` - Bidder string `json:"bidder,omitempty"` - Timestamp int64 `json:"timestamp,omitempty"` + Type EventType `json:"type,omitempty"` + Format ResponseFormat `json:"format,omitempty"` + Analytics Analytics `json:"analytics,omitempty"` + BidID string `json:"bidid,omitempty"` + AccountID string `json:"account_id,omitempty"` + Bidder string `json:"bidder,omitempty"` + Timestamp int64 `json:"timestamp,omitempty"` + IntegrationType string `json:"integration_type,omitempty"` } diff --git a/config/accounts.go b/config/accounts.go index f7b380fca48..5a6e82dce04 100644 --- a/config/accounts.go +++ b/config/accounts.go @@ -13,13 +13,14 @@ const ( // Account represents a publisher account configuration type Account struct { - ID string `mapstructure:"id" json:"id"` - Disabled bool `mapstructure:"disabled" json:"disabled"` - CacheTTL DefaultTTLs `mapstructure:"cache_ttl" json:"cache_ttl"` - EventsEnabled bool `mapstructure:"events_enabled" json:"events_enabled"` - CCPA AccountCCPA `mapstructure:"ccpa" json:"ccpa"` - GDPR AccountGDPR `mapstructure:"gdpr" json:"gdpr"` - DebugAllow bool `mapstructure:"debug_allow" json:"debug_allow"` + ID string `mapstructure:"id" json:"id"` + Disabled bool `mapstructure:"disabled" json:"disabled"` + CacheTTL DefaultTTLs `mapstructure:"cache_ttl" json:"cache_ttl"` + EventsEnabled bool `mapstructure:"events_enabled" json:"events_enabled"` + CCPA AccountCCPA `mapstructure:"ccpa" json:"ccpa"` + GDPR AccountGDPR `mapstructure:"gdpr" json:"gdpr"` + DebugAllow bool `mapstructure:"debug_allow" json:"debug_allow"` + DefaultIntegration string `mapstructure:"default_integration"` } // AccountCCPA represents account-specific CCPA configuration diff --git a/config/config.go b/config/config.go index 41809aea97f..b5208792ce3 100644 --- a/config/config.go +++ b/config/config.go @@ -88,6 +88,8 @@ type Configuration struct { GenerateBidID bool `mapstructure:"generate_bid_id"` // 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. GenerateRequestID bool `mapstructure:"generate_request_id"` + // Integration Type value lives in config so that it can be updated from the request, and then passed for the event URL + IntegrationType string } const MIN_COOKIE_SIZE_BYTES = 500 @@ -970,6 +972,7 @@ func SetupViper(v *viper.Viper, filename string) { v.SetDefault("auto_gen_source_tid", true) v.SetDefault("generate_bid_id", false) v.SetDefault("generate_request_id", false) + v.SetDefault("account_defaults.default_integration", "") // Default Integration For Accounts Can Be Set Here v.SetDefault("request_timeout_headers.request_time_in_queue", "") v.SetDefault("request_timeout_headers.request_timeout_in_queue", "") diff --git a/endpoints/events/event.go b/endpoints/events/event.go index 5974ba9f7d8..64cb3f353a0 100644 --- a/endpoints/events/event.go +++ b/endpoints/events/event.go @@ -26,10 +26,11 @@ const ( AccountIdParameter = "a" // Optional - BidderParameter = "bidder" - TimestampParameter = "ts" - FormatParameter = "f" - AnalyticsParameter = "x" + BidderParameter = "bidder" + TimestampParameter = "ts" + FormatParameter = "f" + AnalyticsParameter = "x" + IntegrationTypeParameter = "int" ) type eventEndpoint struct { @@ -225,6 +226,10 @@ func optionalParameters(request *analytics.EventRequest) string { r.Add(AnalyticsParameter, string(analytics.Disabled)) } + if request.IntegrationType != "" { + r.Add(IntegrationTypeParameter, request.IntegrationType) + } + opt := r.Encode() if opt != "" { diff --git a/endpoints/events/event_test.go b/endpoints/events/event_test.go index ba8071843f4..813a5f3200f 100644 --- a/endpoints/events/event_test.go +++ b/endpoints/events/event_test.go @@ -4,16 +4,17 @@ import ( "context" "encoding/base64" "encoding/json" - "github.com/prebid/prebid-server/analytics" - "github.com/prebid/prebid-server/config" - "github.com/prebid/prebid-server/stored_requests" - "github.com/stretchr/testify/assert" "io/ioutil" "net/http" "net/http/httptest" "strings" "testing" "time" + + "github.com/prebid/prebid-server/analytics" + "github.com/prebid/prebid-server/config" + "github.com/prebid/prebid-server/stored_requests" + "github.com/stretchr/testify/assert" ) // Mock Analytics Module @@ -652,6 +653,19 @@ func TestEventRequestToUrl(t *testing.T) { }, want: "http://localhost:8000/event?t=win&b=bidid&a=accountId&bidder=bidder&f=i&ts=1234567&x=0", }, + "three": { + er: &analytics.EventRequest{ + Type: analytics.Win, + BidID: "bidid", + AccountID: "accountId", + Bidder: "bidder", + Timestamp: 1234567, + Format: analytics.Image, + Analytics: analytics.Disabled, + IntegrationType: "integrationType", + }, + want: "http://localhost:8000/event?t=win&b=bidid&a=accountId&bidder=bidder&f=i&int=integrationType&ts=1234567&x=0", + }, } for name, test := range tests { diff --git a/endpoints/events/vtrack.go b/endpoints/events/vtrack.go index da845162de2..7a685725f41 100644 --- a/endpoints/events/vtrack.go +++ b/endpoints/events/vtrack.go @@ -128,15 +128,16 @@ func (v *vtrackEndpoint) Handle(w http.ResponseWriter, r *http.Request, _ httpro } // GetVastUrlTracking creates a vast url tracking -func GetVastUrlTracking(externalUrl string, bidid string, bidder string, accountId string, timestamp int64) string { +func GetVastUrlTracking(externalUrl string, bidid string, bidder string, accountId string, timestamp int64, integrationType string) string { eventReq := &analytics.EventRequest{ - Type: analytics.Imp, - BidID: bidid, - AccountID: accountId, - Bidder: bidder, - Timestamp: timestamp, - Format: analytics.Blank, + Type: analytics.Imp, + BidID: bidid, + AccountID: accountId, + Bidder: bidder, + Timestamp: timestamp, + Format: analytics.Blank, + IntegrationType: integrationType, } return EventRequestToUrl(externalUrl, eventReq) @@ -229,7 +230,7 @@ func (v *vtrackEndpoint) cachePutObjects(ctx context.Context, req *BidCacheReque } if _, ok := biddersAllowingVastUpdate[c.Bidder]; ok && nc.Data != nil { - nc.Data = ModifyVastXmlJSON(v.Cfg.ExternalURL, nc.Data, c.BidID, c.Bidder, accountId, c.Timestamp) + nc.Data = ModifyVastXmlJSON(v.Cfg.ExternalURL, nc.Data, c.BidID, c.Bidder, accountId, c.Timestamp, v.Cfg.IntegrationType) } cacheables = append(cacheables, *nc) @@ -269,7 +270,7 @@ func getAccountId(httpRequest *http.Request) string { } // ModifyVastXmlString rewrites and returns the string vastXML and a flag indicating if it was modified -func ModifyVastXmlString(externalUrl, vast, bidid, bidder, accountID string, timestamp int64) (string, bool) { +func ModifyVastXmlString(externalUrl, vast, bidid, bidder, accountID string, timestamp int64, integrationType string) (string, bool) { ci := strings.Index(vast, ImpressionCloseTag) // no impression tag - pass it as it is @@ -277,7 +278,7 @@ func ModifyVastXmlString(externalUrl, vast, bidid, bidder, accountID string, tim return vast, false } - vastUrlTracking := GetVastUrlTracking(externalUrl, bidid, bidder, accountID, timestamp) + vastUrlTracking := GetVastUrlTracking(externalUrl, bidid, bidder, accountID, timestamp, integrationType) impressionUrl := "" oi := strings.Index(vast, ImpressionOpenTag) @@ -289,13 +290,13 @@ func ModifyVastXmlString(externalUrl, vast, bidid, bidder, accountID string, tim } // ModifyVastXmlJSON modifies BidCacheRequest element Vast XML data -func ModifyVastXmlJSON(externalUrl string, data json.RawMessage, bidid, bidder, accountId string, timestamp int64) json.RawMessage { +func ModifyVastXmlJSON(externalUrl string, data json.RawMessage, bidid, bidder, accountId string, timestamp int64, integrationType string) json.RawMessage { var vast string if err := json.Unmarshal(data, &vast); err != nil { // failed to decode json, fall back to string vast = string(data) } - vast, ok := ModifyVastXmlString(externalUrl, vast, bidid, bidder, accountId, timestamp) + vast, ok := ModifyVastXmlString(externalUrl, vast, bidid, bidder, accountId, timestamp, integrationType) if !ok { return data } diff --git a/endpoints/events/vtrack_test.go b/endpoints/events/vtrack_test.go index 1766f2e2e0d..54c041bde43 100644 --- a/endpoints/events/vtrack_test.go +++ b/endpoints/events/vtrack_test.go @@ -633,8 +633,8 @@ func TestShouldRespondWithInternalErrorPbsCacheIsNotConfigured(t *testing.T) { } func TestVastUrlShouldReturnExpectedUrl(t *testing.T) { - url := GetVastUrlTracking("http://external-url", "bidId", "bidder", "accountId", 1000) - assert.Equal(t, "http://external-url/event?t=imp&b=bidId&a=accountId&bidder=bidder&f=b&ts=1000", url, "Invalid vast url") + url := GetVastUrlTracking("http://external-url", "bidId", "bidder", "accountId", 1000, "integrationType") + assert.Equal(t, "http://external-url/event?t=imp&b=bidId&a=accountId&bidder=bidder&f=b&int=integrationType&ts=1000", url, "Invalid vast url") } func getValidVTrackRequestBody(withImpression bool, withContent bool) (string, error) { diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go index 8e9725f37f2..cb6bd49af29 100644 --- a/endpoints/openrtb2/auction.go +++ b/endpoints/openrtb2/auction.go @@ -309,6 +309,13 @@ func (deps *endpointDeps) parseRequest(httpRequest *http.Request) (req *openrtb_ lmt.ModifyForIOS(req.BidRequest) + // Integration Type Handling + err = deps.setIntegrationType(req) + if err != nil { + errs = []error{err} + return + } + errL := deps.validateRequest(req, false) if len(errL) > 0 { errs = append(errs, errL...) @@ -1795,3 +1802,18 @@ func checkIfAppRequest(request []byte) (bool, error) { } return false, nil } + +func (deps *endpointDeps) setIntegrationType(req *openrtb_ext.RequestWrapper) error { + reqExt, err := req.GetRequestExt() + if err != nil { + return err + } + reqPrebid := reqExt.GetPrebid() + if reqPrebid == nil { + reqPrebid = &openrtb_ext.ExtRequestPrebid{Integration: deps.cfg.AccountDefaults.DefaultIntegration} + reqExt.SetPrebid(reqPrebid) + req.RebuildRequest() + } + deps.cfg.IntegrationType = reqPrebid.Integration + return nil +} diff --git a/endpoints/openrtb2/auction_test.go b/endpoints/openrtb2/auction_test.go index af68d693243..cc8d026471d 100644 --- a/endpoints/openrtb2/auction_test.go +++ b/endpoints/openrtb2/auction_test.go @@ -1386,6 +1386,55 @@ func TestValidateOrFillChannel(t *testing.T) { } } +func TestSetIntegrationType(t *testing.T) { + deps := &endpointDeps{ + fakeUUIDGenerator{}, + &nobidExchange{}, + newParamsValidator(t), + &mockStoredReqFetcher{}, + empty_fetcher.EmptyFetcher{}, + empty_fetcher.EmptyFetcher{}, + &config.Configuration{MaxRequestSize: maxSize, AccountDefaults: config.Account{DefaultIntegration: "TestDefaultIntegrationType"}}, + &metricsConfig.NilMetricsEngine{}, + analyticsConf.NewPBSAnalytics(&config.Analytics{}), + map[string]string{}, + false, + []byte{}, + openrtb_ext.BuildBidderMap(), + nil, + nil, + hardcodedResponseIPValidator{response: true}, + } + + testCases := []struct { + description string + givenRequestWrapper *openrtb_ext.RequestWrapper + expectedError error + expectedIntegrationType string + }{ + { + description: "Request has integration type defined, expect that same integration type", + givenRequestWrapper: &openrtb_ext.RequestWrapper{ + BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"integration": "TestIntegrationType"}}`)}, + }, + expectedIntegrationType: "TestIntegrationType", + }, + { + description: "Request doesn't have request.ext.prebid path, expect default integration value", + givenRequestWrapper: &openrtb_ext.RequestWrapper{ + BidRequest: &openrtb2.BidRequest{Ext: []byte(``)}, + }, + expectedIntegrationType: "TestDefaultIntegrationType", + }, + } + + for _, test := range testCases { + err := deps.setIntegrationType(test.givenRequestWrapper) + assert.Empty(t, err, test.description) + assert.Equalf(t, test.expectedIntegrationType, deps.cfg.IntegrationType, "Integration type information isn't correct: %s\n", test.description) + } +} + func TestStoredRequestGenerateUuid(t *testing.T) { uuid := "foo" diff --git a/exchange/events.go b/exchange/events.go index bedafddf5a0..4c31f8ddbdb 100644 --- a/exchange/events.go +++ b/exchange/events.go @@ -4,11 +4,10 @@ import ( "encoding/json" "time" - "github.com/evanphx/json-patch" + jsonpatch "github.com/evanphx/json-patch" "github.com/prebid/prebid-server/analytics" "github.com/prebid/prebid-server/config" "github.com/prebid/prebid-server/endpoints/events" - "github.com/prebid/prebid-server/metrics" "github.com/prebid/prebid-server/openrtb_ext" ) @@ -18,7 +17,7 @@ type eventTracking struct { enabledForAccount bool enabledForRequest bool auctionTimestampMs int64 - integration metrics.DemandSource // web app amp + integrationType string bidderInfos config.BidderInfos externalURL string } @@ -30,7 +29,7 @@ func getEventTracking(requestExtPrebid *openrtb_ext.ExtRequestPrebid, ts time.Ti enabledForAccount: account.EventsEnabled, enabledForRequest: requestExtPrebid != nil && requestExtPrebid.Events != nil, auctionTimestampMs: ts.UnixNano() / 1e+6, - integration: "", // TODO: add integration support, see #1428 + integrationType: requestExtPrebid.Integration, bidderInfos: bidderInfos, externalURL: externalURL, } @@ -66,7 +65,7 @@ func (ev *eventTracking) modifyBidVAST(pbsBid *pbsOrtbBid, bidderName openrtb_ex if len(pbsBid.generatedBidID) > 0 { bidID = pbsBid.generatedBidID } - if newVastXML, ok := events.ModifyVastXmlString(ev.externalURL, vastXML, bidID, bidderName.String(), ev.accountID, ev.auctionTimestampMs); ok { + if newVastXML, ok := events.ModifyVastXmlString(ev.externalURL, vastXML, bidID, bidderName.String(), ev.accountID, ev.auctionTimestampMs, ev.integrationType); ok { bid.AdM = newVastXML } } diff --git a/openrtb_ext/request.go b/openrtb_ext/request.go index a65e8d3c7b1..60af1b6adc6 100644 --- a/openrtb_ext/request.go +++ b/openrtb_ext/request.go @@ -32,6 +32,7 @@ type ExtRequestPrebid struct { Channel *ExtRequestPrebidChannel `json:"channel,omitempty"` Data *ExtRequestPrebidData `json:"data,omitempty"` Debug bool `json:"debug,omitempty"` + Integration string `json:"integration,omitempty"` Events json.RawMessage `json:"events,omitempty"` SChains []*ExtRequestPrebidSChain `json:"schains,omitempty"` StoredRequest *ExtStoredRequest `json:"storedrequest,omitempty"` From 71f7ff527d23d8d10be3f4d53cf3688d1b22ea95 Mon Sep 17 00:00:00 2001 From: AlexBVolcy <74930484+AlexBVolcy@users.noreply.github.com> Date: Mon, 10 Jan 2022 15:50:30 -0800 Subject: [PATCH 02/10] Addressing comments, fixed tests --- analytics/event.go | 16 ++++++++-------- config/accounts.go | 2 +- config/config.go | 2 +- endpoints/events/event.go | 4 ++-- endpoints/events/event_test.go | 18 +++++++++--------- endpoints/events/vtrack.go | 16 ++++++++-------- endpoints/openrtb2/auction.go | 4 +++- endpoints/openrtb2/auction_test.go | 8 ++++++++ .../invalid-whole/cache-nothing.json | 2 +- 9 files changed, 41 insertions(+), 31 deletions(-) diff --git a/analytics/event.go b/analytics/event.go index 1683191d322..56b757693e6 100644 --- a/analytics/event.go +++ b/analytics/event.go @@ -28,12 +28,12 @@ const ( ) type EventRequest struct { - Type EventType `json:"type,omitempty"` - Format ResponseFormat `json:"format,omitempty"` - Analytics Analytics `json:"analytics,omitempty"` - BidID string `json:"bidid,omitempty"` - AccountID string `json:"account_id,omitempty"` - Bidder string `json:"bidder,omitempty"` - Timestamp int64 `json:"timestamp,omitempty"` - IntegrationType string `json:"integration_type,omitempty"` + Type EventType `json:"type,omitempty"` + Format ResponseFormat `json:"format,omitempty"` + Analytics Analytics `json:"analytics,omitempty"` + BidID string `json:"bidid,omitempty"` + AccountID string `json:"account_id,omitempty"` + Bidder string `json:"bidder,omitempty"` + Timestamp int64 `json:"timestamp,omitempty"` + Integration string `json:"integration,omitempty"` } diff --git a/config/accounts.go b/config/accounts.go index 5a6e82dce04..dd4d273ebcf 100644 --- a/config/accounts.go +++ b/config/accounts.go @@ -20,7 +20,7 @@ type Account struct { CCPA AccountCCPA `mapstructure:"ccpa" json:"ccpa"` GDPR AccountGDPR `mapstructure:"gdpr" json:"gdpr"` DebugAllow bool `mapstructure:"debug_allow" json:"debug_allow"` - DefaultIntegration string `mapstructure:"default_integration"` + DefaultIntegration string `mapstructure:"default_integration" json:"default_integration"` } // AccountCCPA represents account-specific CCPA configuration diff --git a/config/config.go b/config/config.go index 2ab6cc9ddeb..15276598441 100644 --- a/config/config.go +++ b/config/config.go @@ -1003,7 +1003,7 @@ func SetupViper(v *viper.Viper, filename string) { v.SetDefault("auto_gen_source_tid", true) v.SetDefault("generate_bid_id", false) v.SetDefault("generate_request_id", false) - v.SetDefault("account_defaults.default_integration", "") // Default Integration For Accounts Can Be Set Here + v.SetDefault("account_defaults.default_integration", "") v.SetDefault("request_timeout_headers.request_time_in_queue", "") v.SetDefault("request_timeout_headers.request_timeout_in_queue", "") diff --git a/endpoints/events/event.go b/endpoints/events/event.go index 64cb3f353a0..d187d5fafd1 100644 --- a/endpoints/events/event.go +++ b/endpoints/events/event.go @@ -226,8 +226,8 @@ func optionalParameters(request *analytics.EventRequest) string { r.Add(AnalyticsParameter, string(analytics.Disabled)) } - if request.IntegrationType != "" { - r.Add(IntegrationTypeParameter, request.IntegrationType) + if request.Integration != "" { + r.Add(IntegrationTypeParameter, request.Integration) } opt := r.Encode() diff --git a/endpoints/events/event_test.go b/endpoints/events/event_test.go index 813a5f3200f..f8431ad5913 100644 --- a/endpoints/events/event_test.go +++ b/endpoints/events/event_test.go @@ -655,16 +655,16 @@ func TestEventRequestToUrl(t *testing.T) { }, "three": { er: &analytics.EventRequest{ - Type: analytics.Win, - BidID: "bidid", - AccountID: "accountId", - Bidder: "bidder", - Timestamp: 1234567, - Format: analytics.Image, - Analytics: analytics.Disabled, - IntegrationType: "integrationType", + Type: analytics.Win, + BidID: "bidid", + AccountID: "accountId", + Bidder: "bidder", + Timestamp: 1234567, + Format: analytics.Image, + Analytics: analytics.Disabled, + Integration: "integration", }, - want: "http://localhost:8000/event?t=win&b=bidid&a=accountId&bidder=bidder&f=i&int=integrationType&ts=1234567&x=0", + want: "http://localhost:8000/event?t=win&b=bidid&a=accountId&bidder=bidder&f=i&int=integration&ts=1234567&x=0", }, } diff --git a/endpoints/events/vtrack.go b/endpoints/events/vtrack.go index 7a685725f41..ec9907025b1 100644 --- a/endpoints/events/vtrack.go +++ b/endpoints/events/vtrack.go @@ -128,16 +128,16 @@ func (v *vtrackEndpoint) Handle(w http.ResponseWriter, r *http.Request, _ httpro } // GetVastUrlTracking creates a vast url tracking -func GetVastUrlTracking(externalUrl string, bidid string, bidder string, accountId string, timestamp int64, integrationType string) string { +func GetVastUrlTracking(externalUrl string, bidid string, bidder string, accountId string, timestamp int64, integration string) string { eventReq := &analytics.EventRequest{ - Type: analytics.Imp, - BidID: bidid, - AccountID: accountId, - Bidder: bidder, - Timestamp: timestamp, - Format: analytics.Blank, - IntegrationType: integrationType, + Type: analytics.Imp, + BidID: bidid, + AccountID: accountId, + Bidder: bidder, + Timestamp: timestamp, + Format: analytics.Blank, + Integration: integration, } return EventRequestToUrl(externalUrl, eventReq) diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go index 96c69eb6afc..cda7ef3059a 100644 --- a/endpoints/openrtb2/auction.go +++ b/endpoints/openrtb2/auction.go @@ -1838,7 +1838,9 @@ func (deps *endpointDeps) setIntegrationType(req *openrtb_ext.RequestWrapper) er if reqPrebid == nil { reqPrebid = &openrtb_ext.ExtRequestPrebid{Integration: deps.cfg.AccountDefaults.DefaultIntegration} reqExt.SetPrebid(reqPrebid) - req.RebuildRequest() + } else if reqPrebid.Integration == "" { + reqPrebid.Integration = deps.cfg.AccountDefaults.DefaultIntegration + reqExt.SetPrebid(reqPrebid) } deps.cfg.IntegrationType = reqPrebid.Integration return nil diff --git a/endpoints/openrtb2/auction_test.go b/endpoints/openrtb2/auction_test.go index eef3bc0e874..e08a6fd5030 100644 --- a/endpoints/openrtb2/auction_test.go +++ b/endpoints/openrtb2/auction_test.go @@ -1709,6 +1709,7 @@ func TestSetIntegrationType(t *testing.T) { nil, nil, hardcodedResponseIPValidator{response: true}, + empty_fetcher.EmptyFetcher{}, } testCases := []struct { @@ -1731,6 +1732,13 @@ func TestSetIntegrationType(t *testing.T) { }, expectedIntegrationType: "TestDefaultIntegrationType", }, + { + description: "Test 3", + givenRequestWrapper: &openrtb_ext.RequestWrapper{ + BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"integration": ""}}`)}, + }, + expectedIntegrationType: "TestDefaultIntegrationType", + }, } for _, test := range testCases { diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/cache-nothing.json b/endpoints/openrtb2/sample-requests/invalid-whole/cache-nothing.json index 76dc1c2bb5c..5e2ac8f737d 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/cache-nothing.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/cache-nothing.json @@ -27,5 +27,5 @@ } }, "expectedReturnCode": 400, - "expectedErrorMessage": "Invalid request: request.ext is invalid: request.ext.prebid.cache requires one of the \"bids\" or \"vastxml\" properties\n" + "expectedErrorMessage": "Invalid request: request.ext.prebid.cache requires one of the \"bids\" or \"vastxml\" properties\n" } From 1e6272862af0d26cdc55b087360ebca79a8b1611 Mon Sep 17 00:00:00 2001 From: AlexBVolcy <74930484+AlexBVolcy@users.noreply.github.com> Date: Thu, 20 Jan 2022 09:42:34 -0800 Subject: [PATCH 03/10] Updated vtrack URL integration, altered tests, refactoring --- config/config.go | 3 -- endpoints/events/vtrack.go | 24 +++++++++----- endpoints/openrtb2/auction.go | 31 ++++++++++++------- endpoints/openrtb2/auction_test.go | 18 +++++++---- .../invalid-whole/cache-nothing.json | 4 +-- 5 files changed, 50 insertions(+), 30 deletions(-) diff --git a/config/config.go b/config/config.go index 15276598441..1b415fdf798 100644 --- a/config/config.go +++ b/config/config.go @@ -89,8 +89,6 @@ type Configuration struct { GenerateBidID bool `mapstructure:"generate_bid_id"` // 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. GenerateRequestID bool `mapstructure:"generate_request_id"` - // Integration Type value lives in config so that it can be updated from the request, and then passed for the event URL - IntegrationType string } const MIN_COOKIE_SIZE_BYTES = 500 @@ -1003,7 +1001,6 @@ func SetupViper(v *viper.Viper, filename string) { v.SetDefault("auto_gen_source_tid", true) v.SetDefault("generate_bid_id", false) v.SetDefault("generate_request_id", false) - v.SetDefault("account_defaults.default_integration", "") v.SetDefault("request_timeout_headers.request_time_in_queue", "") v.SetDefault("request_timeout_headers.request_timeout_in_queue", "") diff --git a/endpoints/events/vtrack.go b/endpoints/events/vtrack.go index ec9907025b1..0c20fe9fca1 100644 --- a/endpoints/events/vtrack.go +++ b/endpoints/events/vtrack.go @@ -21,9 +21,10 @@ import ( ) const ( - AccountParameter = "a" - ImpressionCloseTag = "" - ImpressionOpenTag = "" + AccountParameter = "a" + IntegrationParameter = "int" + ImpressionCloseTag = "" + ImpressionOpenTag = "" ) type vtrackEndpoint struct { @@ -69,6 +70,9 @@ func (v *vtrackEndpoint) Handle(w http.ResponseWriter, r *http.Request, _ httpro return } + // get integration value from request parameter + integrationType := getIntegrationType(r) + // parse puts request from request body req, err := ParseVTrackRequest(r, v.Cfg.MaxRequestSize+1) @@ -96,7 +100,7 @@ func (v *vtrackEndpoint) Handle(w http.ResponseWriter, r *http.Request, _ httpro // insert impression tracking if account allows events and bidder allows VAST modification if v.Cache != nil { - cachingResponse, errs := v.handleVTrackRequest(ctx, req, account) + cachingResponse, errs := v.handleVTrackRequest(ctx, req, account, integrationType) if len(errs) > 0 { w.WriteHeader(http.StatusInternalServerError) @@ -191,10 +195,10 @@ func ParseVTrackRequest(httpRequest *http.Request, maxRequestSize int64) (req *B } // handleVTrackRequest handles a VTrack request -func (v *vtrackEndpoint) handleVTrackRequest(ctx context.Context, req *BidCacheRequest, account *config.Account) (*BidCacheResponse, []error) { +func (v *vtrackEndpoint) handleVTrackRequest(ctx context.Context, req *BidCacheRequest, account *config.Account, integration string) (*BidCacheResponse, []error) { biddersAllowingVastUpdate := getBiddersAllowingVastUpdate(req, &v.BidderInfos, v.Cfg.VTrack.AllowUnknownBidder) // cache data - r, errs := v.cachePutObjects(ctx, req, biddersAllowingVastUpdate, account.ID) + r, errs := v.cachePutObjects(ctx, req, biddersAllowingVastUpdate, account.ID, integration) // handle pbs caching errors if len(errs) != 0 { @@ -217,7 +221,7 @@ func (v *vtrackEndpoint) handleVTrackRequest(ctx context.Context, req *BidCacheR } // cachePutObjects caches BidCacheRequest data -func (v *vtrackEndpoint) cachePutObjects(ctx context.Context, req *BidCacheRequest, biddersAllowingVastUpdate map[string]struct{}, accountId string) ([]string, []error) { +func (v *vtrackEndpoint) cachePutObjects(ctx context.Context, req *BidCacheRequest, biddersAllowingVastUpdate map[string]struct{}, accountId string, integration string) ([]string, []error) { var cacheables []prebid_cache_client.Cacheable for _, c := range req.Puts { @@ -230,7 +234,7 @@ func (v *vtrackEndpoint) cachePutObjects(ctx context.Context, req *BidCacheReque } if _, ok := biddersAllowingVastUpdate[c.Bidder]; ok && nc.Data != nil { - nc.Data = ModifyVastXmlJSON(v.Cfg.ExternalURL, nc.Data, c.BidID, c.Bidder, accountId, c.Timestamp, v.Cfg.IntegrationType) + nc.Data = ModifyVastXmlJSON(v.Cfg.ExternalURL, nc.Data, c.BidID, c.Bidder, accountId, c.Timestamp, integration) } cacheables = append(cacheables, *nc) @@ -269,6 +273,10 @@ func getAccountId(httpRequest *http.Request) string { return httpRequest.URL.Query().Get(AccountParameter) } +func getIntegrationType(httpRequest *http.Request) string { + return httpRequest.URL.Query().Get(IntegrationParameter) +} + // ModifyVastXmlString rewrites and returns the string vastXML and a flag indicating if it was modified func ModifyVastXmlString(externalUrl, vast, bidid, bidder, accountID string, timestamp int64, integrationType string) (string, bool) { ci := strings.Index(vast, ImpressionCloseTag) diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go index cda7ef3059a..efc02b7f8f5 100644 --- a/endpoints/openrtb2/auction.go +++ b/endpoints/openrtb2/auction.go @@ -193,6 +193,14 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http return } + // Set Integration Information + err := deps.setIntegrationType(req, account) + if err != nil { + errL = append(errL, err) + writeError(errL, w, &labels) + return + } + // rebuild/resync the request in the request wrapper. if err := req.RebuildRequest(); err != nil { errL = append(errL, err) @@ -312,13 +320,6 @@ func (deps *endpointDeps) parseRequest(httpRequest *http.Request) (req *openrtb_ lmt.ModifyForIOS(req.BidRequest) - // Integration Type Handling - err = deps.setIntegrationType(req) - if err != nil { - errs = []error{err} - return - } - errL := deps.validateRequest(req, false) if len(errL) > 0 { errs = append(errs, errL...) @@ -1829,19 +1830,27 @@ func checkIfAppRequest(request []byte) (bool, error) { return false, nil } -func (deps *endpointDeps) setIntegrationType(req *openrtb_ext.RequestWrapper) error { +func (deps *endpointDeps) setIntegrationType(req *openrtb_ext.RequestWrapper, account *config.Account) error { reqExt, err := req.GetRequestExt() if err != nil { return err } reqPrebid := reqExt.GetPrebid() if reqPrebid == nil { - reqPrebid = &openrtb_ext.ExtRequestPrebid{Integration: deps.cfg.AccountDefaults.DefaultIntegration} + reqPrebid = &openrtb_ext.ExtRequestPrebid{Integration: account.DefaultIntegration} reqExt.SetPrebid(reqPrebid) } else if reqPrebid.Integration == "" { - reqPrebid.Integration = deps.cfg.AccountDefaults.DefaultIntegration + reqPrebid.Integration = account.DefaultIntegration reqExt.SetPrebid(reqPrebid) } - deps.cfg.IntegrationType = reqPrebid.Integration return nil } + +func getIntegrationFromRequest(req *openrtb_ext.RequestWrapper) (string, error) { + reqExt, err := req.GetRequestExt() + if err != nil { + return "", err + } + reqPrebid := reqExt.GetPrebid() + return reqPrebid.Integration, nil +} diff --git a/endpoints/openrtb2/auction_test.go b/endpoints/openrtb2/auction_test.go index e08a6fd5030..173a8d4cd7d 100644 --- a/endpoints/openrtb2/auction_test.go +++ b/endpoints/openrtb2/auction_test.go @@ -1699,7 +1699,7 @@ func TestSetIntegrationType(t *testing.T) { &mockStoredReqFetcher{}, empty_fetcher.EmptyFetcher{}, empty_fetcher.EmptyFetcher{}, - &config.Configuration{MaxRequestSize: maxSize, AccountDefaults: config.Account{DefaultIntegration: "TestDefaultIntegrationType"}}, + &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, analyticsConf.NewPBSAnalytics(&config.Analytics{}), map[string]string{}, @@ -1715,6 +1715,7 @@ func TestSetIntegrationType(t *testing.T) { testCases := []struct { description string givenRequestWrapper *openrtb_ext.RequestWrapper + givenAccount *config.Account expectedError error expectedIntegrationType string }{ @@ -1723,6 +1724,7 @@ func TestSetIntegrationType(t *testing.T) { givenRequestWrapper: &openrtb_ext.RequestWrapper{ BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"integration": "TestIntegrationType"}}`)}, }, + givenAccount: &config.Account{DefaultIntegration: "TestDefaultIntegration"}, expectedIntegrationType: "TestIntegrationType", }, { @@ -1730,21 +1732,25 @@ func TestSetIntegrationType(t *testing.T) { givenRequestWrapper: &openrtb_ext.RequestWrapper{ BidRequest: &openrtb2.BidRequest{Ext: []byte(``)}, }, - expectedIntegrationType: "TestDefaultIntegrationType", + givenAccount: &config.Account{DefaultIntegration: "TestDefaultIntegration"}, + expectedIntegrationType: "TestDefaultIntegration", }, { - description: "Test 3", + description: "Request has blank integration in request, expect default integration value ", givenRequestWrapper: &openrtb_ext.RequestWrapper{ BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"integration": ""}}`)}, }, - expectedIntegrationType: "TestDefaultIntegrationType", + givenAccount: &config.Account{DefaultIntegration: "TestDefaultIntegration"}, + expectedIntegrationType: "TestDefaultIntegration", }, } for _, test := range testCases { - err := deps.setIntegrationType(test.givenRequestWrapper) + err := deps.setIntegrationType(test.givenRequestWrapper, test.givenAccount) assert.Empty(t, err, test.description) - assert.Equalf(t, test.expectedIntegrationType, deps.cfg.IntegrationType, "Integration type information isn't correct: %s\n", test.description) + integrationTypeFromReq, err2 := getIntegrationFromRequest(test.givenRequestWrapper) + assert.Empty(t, err2, test.description) + assert.Equalf(t, test.expectedIntegrationType, integrationTypeFromReq, "Integration type information isn't correct: %s\n", test.description) } } diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/cache-nothing.json b/endpoints/openrtb2/sample-requests/invalid-whole/cache-nothing.json index 5e2ac8f737d..9bbc96609bf 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/cache-nothing.json +++ b/endpoints/openrtb2/sample-requests/invalid-whole/cache-nothing.json @@ -27,5 +27,5 @@ } }, "expectedReturnCode": 400, - "expectedErrorMessage": "Invalid request: request.ext.prebid.cache requires one of the \"bids\" or \"vastxml\" properties\n" -} + "expectedErrorMessage": "Invalid request: request.ext is invalid: request.ext.prebid.cache requires one of the \"bids\" or \"vastxml\" properties\n" +} \ No newline at end of file From 5bbabae49eb3bfec26e7b4494581c51ecd341504 Mon Sep 17 00:00:00 2001 From: AlexBVolcy <74930484+AlexBVolcy@users.noreply.github.com> Date: Tue, 25 Jan 2022 14:25:30 -0800 Subject: [PATCH 04/10] Added integration type validation, minor refactoring --- endpoints/openrtb2/auction.go | 34 +++++++++++++++++++++------- endpoints/openrtb2/auction_test.go | 36 ++++++++++++++++++++++++++---- 2 files changed, 58 insertions(+), 12 deletions(-) diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go index efc02b7f8f5..4e235a07a25 100644 --- a/endpoints/openrtb2/auction.go +++ b/endpoints/openrtb2/auction.go @@ -12,6 +12,7 @@ import ( "regexp" "strconv" "time" + "unicode" "github.com/prebid/prebid-server/firstpartydata" @@ -47,6 +48,7 @@ import ( const storedRequestTimeoutMillis = 50 const ampChannel = "amp" const appChannel = "app" +const integrationParamMaxLength = 64 var ( dntKey string = http.CanonicalHeaderKey("DNT") @@ -1836,21 +1838,37 @@ func (deps *endpointDeps) setIntegrationType(req *openrtb_ext.RequestWrapper, ac return err } reqPrebid := reqExt.GetPrebid() - if reqPrebid == nil { + if reqPrebid == nil && account != nil { + err := validateIntegrationType(account.DefaultIntegration) + if err != nil { + return err + } reqPrebid = &openrtb_ext.ExtRequestPrebid{Integration: account.DefaultIntegration} reqExt.SetPrebid(reqPrebid) - } else if reqPrebid.Integration == "" { + } else if reqPrebid.Integration == "" && account.DefaultIntegration != "" { + err := validateIntegrationType(account.DefaultIntegration) + if err != nil { + return err + } reqPrebid.Integration = account.DefaultIntegration reqExt.SetPrebid(reqPrebid) + } else { + err := validateIntegrationType(reqPrebid.Integration) + if err != nil { + return err + } } return nil } -func getIntegrationFromRequest(req *openrtb_ext.RequestWrapper) (string, error) { - reqExt, err := req.GetRequestExt() - if err != nil { - return "", err +func validateIntegrationType(integrationType string) error { + if len(integrationType) > integrationParamMaxLength { + return errors.New("integration type length is too long") } - reqPrebid := reqExt.GetPrebid() - return reqPrebid.Integration, nil + for _, char := range integrationType { + if !(unicode.IsDigit(char) || unicode.IsLetter(char)) && char != '-' && char != '_' { + return errors.New("integration type can only contain numbers, letters and these characters '-', '_'") + } + } + return nil } diff --git a/endpoints/openrtb2/auction_test.go b/endpoints/openrtb2/auction_test.go index 173a8d4cd7d..8f8c0cf98b1 100644 --- a/endpoints/openrtb2/auction_test.go +++ b/endpoints/openrtb2/auction_test.go @@ -1743,14 +1743,33 @@ func TestSetIntegrationType(t *testing.T) { givenAccount: &config.Account{DefaultIntegration: "TestDefaultIntegration"}, expectedIntegrationType: "TestDefaultIntegration", }, + { + description: "Given integration type is too long, expect error to be thrown", + givenRequestWrapper: &openrtb_ext.RequestWrapper{ + BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"integration": "IntegrationTypeLongerThanMaxIntegrationTypeLongerThanMaxIntegration"}}`)}, + }, + expectedError: errors.New("integration type length is too long"), + }, + { + description: "Default integration type contains invalid characters, expect error to be thrown", + givenRequestWrapper: &openrtb_ext.RequestWrapper{ + BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"integration": ""}}`)}, + }, + givenAccount: &config.Account{DefaultIntegration: "$$TestDefaultIntegration$$"}, + expectedError: errors.New("integration type can only contain numbers, letters and these characters '-', '_'"), + }, } for _, test := range testCases { err := deps.setIntegrationType(test.givenRequestWrapper, test.givenAccount) - assert.Empty(t, err, test.description) - integrationTypeFromReq, err2 := getIntegrationFromRequest(test.givenRequestWrapper) - assert.Empty(t, err2, test.description) - assert.Equalf(t, test.expectedIntegrationType, integrationTypeFromReq, "Integration type information isn't correct: %s\n", test.description) + if test.expectedError != nil { + assert.Equalf(t, test.expectedError, err, "Error doesn't match expected") + } else { + assert.Empty(t, err, test.description) + integrationTypeFromReq, err2 := getIntegrationFromRequest(test.givenRequestWrapper) + assert.Empty(t, err2, test.description) + assert.Equalf(t, test.expectedIntegrationType, integrationTypeFromReq, "Integration type information isn't correct: %s\n", test.description) + } } } @@ -4531,3 +4550,12 @@ func getObject(t *testing.T, filename, key string) json.RawMessage { } return obj } + +func getIntegrationFromRequest(req *openrtb_ext.RequestWrapper) (string, error) { + reqExt, err := req.GetRequestExt() + if err != nil { + return "", err + } + reqPrebid := reqExt.GetPrebid() + return reqPrebid.Integration, nil +} From 75c980edc2844e40b9d7089c74076bd8525eb430 Mon Sep 17 00:00:00 2001 From: AlexBVolcy <74930484+AlexBVolcy@users.noreply.github.com> Date: Wed, 26 Jan 2022 14:38:33 -0800 Subject: [PATCH 05/10] Updated JSON exchange tests, updated event URL to apply integration type --- exchange/events.go | 11 ++++++----- .../events-bid-account-off-request-on.json | 9 +++++---- .../events-bid-account-on-request-off.json | 12 +++++++----- .../events-vast-account-off-request-on.json | 5 +++-- .../events-vast-account-on-request-off.json | 7 ++++--- 5 files changed, 25 insertions(+), 19 deletions(-) diff --git a/exchange/events.go b/exchange/events.go index 4c31f8ddbdb..263eff10963 100644 --- a/exchange/events.go +++ b/exchange/events.go @@ -112,10 +112,11 @@ func (ev *eventTracking) makeEventURL(evType analytics.EventType, pbsBid *pbsOrt } return events.EventRequestToUrl(ev.externalURL, &analytics.EventRequest{ - Type: evType, - BidID: bidId, - Bidder: string(bidderName), - AccountID: ev.accountID, - Timestamp: ev.auctionTimestampMs, + Type: evType, + BidID: bidId, + Bidder: string(bidderName), + AccountID: ev.accountID, + Timestamp: ev.auctionTimestampMs, + Integration: ev.integrationType, }) } diff --git a/exchange/exchangetest/events-bid-account-off-request-on.json b/exchange/exchangetest/events-bid-account-off-request-on.json index b88ec67c2bc..1dd2648e0d1 100644 --- a/exchange/exchangetest/events-bid-account-off-request-on.json +++ b/exchange/exchangetest/events-bid-account-off-request-on.json @@ -20,6 +20,7 @@ ], "ext": { "prebid": { + "integration" : "testIntegrationType", "events": {} } } @@ -75,8 +76,8 @@ "prebid": { "type": "banner", "events": { - "imp": "http://localhost/event?t=imp&b=winning-bid&a=testaccount&bidder=appnexus&ts=1234567890", - "win": "http://localhost/event?t=win&b=winning-bid&a=testaccount&bidder=appnexus&ts=1234567890" + "imp": "http://localhost/event?t=imp&b=winning-bid&a=testaccount&bidder=appnexus&int=testIntegrationType&ts=1234567890", + "win": "http://localhost/event?t=win&b=winning-bid&a=testaccount&bidder=appnexus&int=testIntegrationType&ts=1234567890" } } } @@ -92,8 +93,8 @@ "prebid": { "type": "banner", "events": { - "imp": "http://localhost/event?t=imp&b=losing-bid&a=testaccount&bidder=appnexus&ts=1234567890", - "win": "http://localhost/event?t=win&b=losing-bid&a=testaccount&bidder=appnexus&ts=1234567890" + "imp": "http://localhost/event?t=imp&b=losing-bid&a=testaccount&bidder=appnexus&int=testIntegrationType&ts=1234567890", + "win": "http://localhost/event?t=win&b=losing-bid&a=testaccount&bidder=appnexus&int=testIntegrationType&ts=1234567890" } } } diff --git a/exchange/exchangetest/events-bid-account-on-request-off.json b/exchange/exchangetest/events-bid-account-on-request-off.json index e440b0309bb..31e519b2796 100644 --- a/exchange/exchangetest/events-bid-account-on-request-off.json +++ b/exchange/exchangetest/events-bid-account-on-request-off.json @@ -19,7 +19,9 @@ } ], "ext": { - "prebid": {} + "prebid": { + "integration" : "testIntegrationType" + } } } }, @@ -73,8 +75,8 @@ "prebid": { "type": "banner", "events": { - "imp": "http://localhost/event?t=imp&b=winning-bid&a=testaccount&bidder=appnexus&ts=1234567890", - "win": "http://localhost/event?t=win&b=winning-bid&a=testaccount&bidder=appnexus&ts=1234567890" + "imp": "http://localhost/event?t=imp&b=winning-bid&a=testaccount&bidder=appnexus&int=testIntegrationType&ts=1234567890", + "win": "http://localhost/event?t=win&b=winning-bid&a=testaccount&bidder=appnexus&int=testIntegrationType&ts=1234567890" } } } @@ -90,8 +92,8 @@ "prebid": { "type": "banner", "events": { - "imp": "http://localhost/event?t=imp&b=losing-bid&a=testaccount&bidder=appnexus&ts=1234567890", - "win": "http://localhost/event?t=win&b=losing-bid&a=testaccount&bidder=appnexus&ts=1234567890" + "imp": "http://localhost/event?t=imp&b=losing-bid&a=testaccount&bidder=appnexus&int=testIntegrationType&ts=1234567890", + "win": "http://localhost/event?t=win&b=losing-bid&a=testaccount&bidder=appnexus&int=testIntegrationType&ts=1234567890" } } } diff --git a/exchange/exchangetest/events-vast-account-off-request-on.json b/exchange/exchangetest/events-vast-account-off-request-on.json index 13afb8409af..262b859a500 100644 --- a/exchange/exchangetest/events-vast-account-off-request-on.json +++ b/exchange/exchangetest/events-vast-account-off-request-on.json @@ -31,6 +31,7 @@ "includewinners": true, "includebidderkeys": false }, + "integration" : "testIntegrationType", "events": {} } } @@ -121,7 +122,7 @@ "bid": [ { "id": "winning-bid", - "adm": "prebid.org wrapper", + "adm": "prebid.org wrapper", "nurl": "http://domain.com/winning-bid", "impid": "my-imp-id", "price": 0.71, @@ -145,7 +146,7 @@ }, { "id": "losing-bid", - "adm": "prebid.org wrapper", + "adm": "prebid.org wrapper", "nurl": "http://domain.com/losing-bid", "impid": "my-imp-id", "price": 0.21, diff --git a/exchange/exchangetest/events-vast-account-on-request-off.json b/exchange/exchangetest/events-vast-account-on-request-off.json index 21f47356d5b..c5941e25a77 100644 --- a/exchange/exchangetest/events-vast-account-on-request-off.json +++ b/exchange/exchangetest/events-vast-account-on-request-off.json @@ -26,7 +26,8 @@ "targeting": { "includewinners": true, "includebidderkeys": false - } + }, + "integration" : "testIntegrationType" } } } @@ -115,7 +116,7 @@ "bid": [ { "id": "winning-bid", - "adm": "prebid.org wrapper", + "adm": "prebid.org wrapper", "nurl": "http://domain.com/winning-bid", "impid": "my-imp-id", "price": 0.71, @@ -138,7 +139,7 @@ }, { "id": "losing-bid", - "adm": "prebid.org wrapper", + "adm": "prebid.org wrapper", "nurl": "http://domain.com/losing-bid", "impid": "my-imp-id", "price": 0.21, From c12acb373a92b5cba9841e3586a661318547b298 Mon Sep 17 00:00:00 2001 From: AlexBVolcy <74930484+AlexBVolcy@users.noreply.github.com> Date: Mon, 7 Feb 2022 09:51:54 -0800 Subject: [PATCH 06/10] Added integration validation to event/vtrack URLs --- endpoints/events/event.go | 29 +++++++++++++++++++++++++++++ endpoints/events/event_test.go | 17 +++++++++-------- endpoints/events/vtrack.go | 15 ++++++++++++--- endpoints/openrtb2/auction.go | 27 --------------------------- endpoints/openrtb2/auction_test.go | 29 +++++------------------------ 5 files changed, 55 insertions(+), 62 deletions(-) diff --git a/endpoints/events/event.go b/endpoints/events/event.go index d187d5fafd1..6cc535729f5 100644 --- a/endpoints/events/event.go +++ b/endpoints/events/event.go @@ -8,6 +8,7 @@ import ( "net/url" "strconv" "time" + "unicode" "github.com/julienschmidt/httprouter" accountService "github.com/prebid/prebid-server/account" @@ -33,6 +34,8 @@ const ( IntegrationTypeParameter = "int" ) +const integrationParamMaxLength = 64 + type eventEndpoint struct { Accounts stored_requests.AccountFetcher Analytics analytics.PBSAnalyticsModule @@ -163,6 +166,10 @@ func ParseEventRequest(r *http.Request) (*analytics.EventRequest, []error) { errs = append(errs, err) } + if err := readIntegrationType(event, r); err != nil { + errs = append(errs, err) + } + // Bidder event.Bidder = r.URL.Query().Get(BidderParameter) @@ -328,3 +335,25 @@ func checkRequiredParameter(httpRequest *http.Request, parameter string) (string return t, nil } + +func readIntegrationType(er *analytics.EventRequest, httpRequest *http.Request) error { + integrationType := httpRequest.URL.Query().Get(IntegrationParameter) + err := validateIntegrationType(integrationType) + if err != nil { + return err + } + er.Integration = integrationType + return nil +} + +func validateIntegrationType(integrationType string) error { + if len(integrationType) > integrationParamMaxLength { + return errors.New("integration type length is too long") + } + for _, char := range integrationType { + if !(unicode.IsDigit(char) || unicode.IsLetter(char)) && char != '-' && char != '_' { + return errors.New("integration type can only contain numbers, letters and these characters '-', '_'") + } + } + return nil +} diff --git a/endpoints/events/event_test.go b/endpoints/events/event_test.go index f8431ad5913..47e51ff3186 100644 --- a/endpoints/events/event_test.go +++ b/endpoints/events/event_test.go @@ -588,15 +588,16 @@ func TestShouldParseEventCorrectly(t *testing.T) { expected *analytics.EventRequest }{ "one": { - req: httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder", strings.NewReader("")), + req: httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder&int=intType", strings.NewReader("")), expected: &analytics.EventRequest{ - Type: analytics.Win, - BidID: "bidId", - Timestamp: 1000, - Bidder: "bidder", - AccountID: "", - Format: analytics.Blank, - Analytics: analytics.Enabled, + Type: analytics.Win, + BidID: "bidId", + Timestamp: 1000, + Bidder: "bidder", + AccountID: "", + Format: analytics.Blank, + Analytics: analytics.Enabled, + Integration: "intType", }, }, "two": { diff --git a/endpoints/events/vtrack.go b/endpoints/events/vtrack.go index 0c20fe9fca1..4bead1453e8 100644 --- a/endpoints/events/vtrack.go +++ b/endpoints/events/vtrack.go @@ -71,7 +71,11 @@ func (v *vtrackEndpoint) Handle(w http.ResponseWriter, r *http.Request, _ httpro } // get integration value from request parameter - integrationType := getIntegrationType(r) + integrationType, err := getIntegrationType(r) + if err != nil { + w.Write([]byte(fmt.Sprintf("Invalid integration type: %s\n", err.Error()))) + return + } // parse puts request from request body req, err := ParseVTrackRequest(r, v.Cfg.MaxRequestSize+1) @@ -273,8 +277,13 @@ func getAccountId(httpRequest *http.Request) string { return httpRequest.URL.Query().Get(AccountParameter) } -func getIntegrationType(httpRequest *http.Request) string { - return httpRequest.URL.Query().Get(IntegrationParameter) +func getIntegrationType(httpRequest *http.Request) (string, error) { + integrationType := httpRequest.URL.Query().Get(IntegrationParameter) + err := validateIntegrationType(integrationType) + if err != nil { + return "", err + } + return integrationType, nil } // ModifyVastXmlString rewrites and returns the string vastXML and a flag indicating if it was modified diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go index 4e235a07a25..d5f074512b0 100644 --- a/endpoints/openrtb2/auction.go +++ b/endpoints/openrtb2/auction.go @@ -12,7 +12,6 @@ import ( "regexp" "strconv" "time" - "unicode" "github.com/prebid/prebid-server/firstpartydata" @@ -48,7 +47,6 @@ import ( const storedRequestTimeoutMillis = 50 const ampChannel = "amp" const appChannel = "app" -const integrationParamMaxLength = 64 var ( dntKey string = http.CanonicalHeaderKey("DNT") @@ -1839,36 +1837,11 @@ func (deps *endpointDeps) setIntegrationType(req *openrtb_ext.RequestWrapper, ac } reqPrebid := reqExt.GetPrebid() if reqPrebid == nil && account != nil { - err := validateIntegrationType(account.DefaultIntegration) - if err != nil { - return err - } reqPrebid = &openrtb_ext.ExtRequestPrebid{Integration: account.DefaultIntegration} reqExt.SetPrebid(reqPrebid) } else if reqPrebid.Integration == "" && account.DefaultIntegration != "" { - err := validateIntegrationType(account.DefaultIntegration) - if err != nil { - return err - } reqPrebid.Integration = account.DefaultIntegration reqExt.SetPrebid(reqPrebid) - } else { - err := validateIntegrationType(reqPrebid.Integration) - if err != nil { - return err - } - } - return nil -} - -func validateIntegrationType(integrationType string) error { - if len(integrationType) > integrationParamMaxLength { - return errors.New("integration type length is too long") - } - for _, char := range integrationType { - if !(unicode.IsDigit(char) || unicode.IsLetter(char)) && char != '-' && char != '_' { - return errors.New("integration type can only contain numbers, letters and these characters '-', '_'") - } } return nil } diff --git a/endpoints/openrtb2/auction_test.go b/endpoints/openrtb2/auction_test.go index 8f8c0cf98b1..bef065c382a 100644 --- a/endpoints/openrtb2/auction_test.go +++ b/endpoints/openrtb2/auction_test.go @@ -1716,7 +1716,6 @@ func TestSetIntegrationType(t *testing.T) { description string givenRequestWrapper *openrtb_ext.RequestWrapper givenAccount *config.Account - expectedError error expectedIntegrationType string }{ { @@ -1743,33 +1742,15 @@ func TestSetIntegrationType(t *testing.T) { givenAccount: &config.Account{DefaultIntegration: "TestDefaultIntegration"}, expectedIntegrationType: "TestDefaultIntegration", }, - { - description: "Given integration type is too long, expect error to be thrown", - givenRequestWrapper: &openrtb_ext.RequestWrapper{ - BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"integration": "IntegrationTypeLongerThanMaxIntegrationTypeLongerThanMaxIntegration"}}`)}, - }, - expectedError: errors.New("integration type length is too long"), - }, - { - description: "Default integration type contains invalid characters, expect error to be thrown", - givenRequestWrapper: &openrtb_ext.RequestWrapper{ - BidRequest: &openrtb2.BidRequest{Ext: []byte(`{"prebid":{"integration": ""}}`)}, - }, - givenAccount: &config.Account{DefaultIntegration: "$$TestDefaultIntegration$$"}, - expectedError: errors.New("integration type can only contain numbers, letters and these characters '-', '_'"), - }, } for _, test := range testCases { err := deps.setIntegrationType(test.givenRequestWrapper, test.givenAccount) - if test.expectedError != nil { - assert.Equalf(t, test.expectedError, err, "Error doesn't match expected") - } else { - assert.Empty(t, err, test.description) - integrationTypeFromReq, err2 := getIntegrationFromRequest(test.givenRequestWrapper) - assert.Empty(t, err2, test.description) - assert.Equalf(t, test.expectedIntegrationType, integrationTypeFromReq, "Integration type information isn't correct: %s\n", test.description) - } + assert.Empty(t, err, test.description) + integrationTypeFromReq, err2 := getIntegrationFromRequest(test.givenRequestWrapper) + assert.Empty(t, err2, test.description) + assert.Equalf(t, test.expectedIntegrationType, integrationTypeFromReq, "Integration type information isn't correct: %s\n", test.description) + } } From f12d6f4558bec7bdeb5c89f30796024fbf47402a Mon Sep 17 00:00:00 2001 From: AlexBVolcy <74930484+AlexBVolcy@users.noreply.github.com> Date: Mon, 7 Feb 2022 16:35:27 -0800 Subject: [PATCH 07/10] Added more tests for integration validation --- endpoints/events/event_test.go | 68 ++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/endpoints/events/event_test.go b/endpoints/events/event_test.go index 47e51ff3186..ddcae3c7aaf 100644 --- a/endpoints/events/event_test.go +++ b/endpoints/events/event_test.go @@ -4,6 +4,7 @@ import ( "context" "encoding/base64" "encoding/json" + "errors" "io/ioutil" "net/http" "net/http/httptest" @@ -677,3 +678,70 @@ func TestEventRequestToUrl(t *testing.T) { }) } } + +func TestReadIntegrationType(t *testing.T) { + testCases := []struct { + description string + givenHttpRequest *http.Request + givenEventRequest *analytics.EventRequest + expectedIntegrationType string + expectedError error + }{ + { + description: "Integration type in http request is valid, expect same integration time and no errors", + givenHttpRequest: httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder&int=TestIntegrationType", strings.NewReader("")), + givenEventRequest: &analytics.EventRequest{ + Type: analytics.Imp, + BidID: "bidid", + AccountID: "accountId", + Bidder: "bidder", + Timestamp: 1234567, + Format: analytics.Blank, + Analytics: analytics.Enabled, + Integration: "", + }, + expectedIntegrationType: "TestIntegrationType", + expectedError: nil, + }, + { + description: "Integration type in http request is too long, expect too long error", + givenHttpRequest: httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder&int=TestIntegrationTypeTooLongTestIntegrationTypeTooLongTestIntegrationType", strings.NewReader("")), + givenEventRequest: &analytics.EventRequest{ + Type: analytics.Imp, + BidID: "bidid", + AccountID: "accountId", + Bidder: "bidder", + Timestamp: 1234567, + Format: analytics.Blank, + Analytics: analytics.Enabled, + Integration: "", + }, + expectedError: errors.New("integration type length is too long"), + }, + { + description: "Integration type in http request contains invalid character, expect invalid character error", + givenHttpRequest: httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder&int=Te$tIntegrationType", strings.NewReader("")), + givenEventRequest: &analytics.EventRequest{ + Type: analytics.Imp, + BidID: "bidid", + AccountID: "accountId", + Bidder: "bidder", + Timestamp: 1234567, + Format: analytics.Blank, + Analytics: analytics.Enabled, + Integration: "", + }, + expectedError: errors.New("integration type can only contain numbers, letters and these characters '-', '_'"), + }, + } + + for _, test := range testCases { + err := readIntegrationType(test.givenEventRequest, test.givenHttpRequest) + if err != nil { + assert.Equal(t, test.expectedError, err, test.description) + } else { + assert.Empty(t, err, test.description) + assert.Equalf(t, test.expectedIntegrationType, test.givenEventRequest.Integration, test.description) + } + } +} From afa43b1042f38068b6415def3ab5980c96151df3 Mon Sep 17 00:00:00 2001 From: AlexBVolcy <74930484+AlexBVolcy@users.noreply.github.com> Date: Tue, 8 Feb 2022 12:32:09 -0800 Subject: [PATCH 08/10] Address minor feedback --- endpoints/events/event.go | 2 +- endpoints/events/event_test.go | 44 ++++++--------------------------- endpoints/events/vtrack_test.go | 38 ++++++++++++++++++++++++++++ endpoints/openrtb2/auction.go | 6 ++++- 4 files changed, 51 insertions(+), 39 deletions(-) diff --git a/endpoints/events/event.go b/endpoints/events/event.go index 6cc535729f5..fd47683ae49 100644 --- a/endpoints/events/event.go +++ b/endpoints/events/event.go @@ -351,7 +351,7 @@ func validateIntegrationType(integrationType string) error { return errors.New("integration type length is too long") } for _, char := range integrationType { - if !(unicode.IsDigit(char) || unicode.IsLetter(char)) && char != '-' && char != '_' { + if !unicode.IsDigit(char) && !unicode.IsLetter(char) && char != '-' && char != '_' { return errors.New("integration type can only contain numbers, letters and these characters '-', '_'") } } diff --git a/endpoints/events/event_test.go b/endpoints/events/event_test.go index ddcae3c7aaf..e75c33a5f31 100644 --- a/endpoints/events/event_test.go +++ b/endpoints/events/event_test.go @@ -683,65 +683,35 @@ func TestReadIntegrationType(t *testing.T) { testCases := []struct { description string givenHttpRequest *http.Request - givenEventRequest *analytics.EventRequest expectedIntegrationType string expectedError error }{ { - description: "Integration type in http request is valid, expect same integration time and no errors", - givenHttpRequest: httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder&int=TestIntegrationType", strings.NewReader("")), - givenEventRequest: &analytics.EventRequest{ - Type: analytics.Imp, - BidID: "bidid", - AccountID: "accountId", - Bidder: "bidder", - Timestamp: 1234567, - Format: analytics.Blank, - Analytics: analytics.Enabled, - Integration: "", - }, + description: "Integration type in http request is valid, expect same integration time and no errors", + givenHttpRequest: httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder&int=TestIntegrationType", strings.NewReader("")), expectedIntegrationType: "TestIntegrationType", expectedError: nil, }, { description: "Integration type in http request is too long, expect too long error", givenHttpRequest: httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder&int=TestIntegrationTypeTooLongTestIntegrationTypeTooLongTestIntegrationType", strings.NewReader("")), - givenEventRequest: &analytics.EventRequest{ - Type: analytics.Imp, - BidID: "bidid", - AccountID: "accountId", - Bidder: "bidder", - Timestamp: 1234567, - Format: analytics.Blank, - Analytics: analytics.Enabled, - Integration: "", - }, - expectedError: errors.New("integration type length is too long"), + expectedError: errors.New("integration type length is too long"), }, { description: "Integration type in http request contains invalid character, expect invalid character error", givenHttpRequest: httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder&int=Te$tIntegrationType", strings.NewReader("")), - givenEventRequest: &analytics.EventRequest{ - Type: analytics.Imp, - BidID: "bidid", - AccountID: "accountId", - Bidder: "bidder", - Timestamp: 1234567, - Format: analytics.Blank, - Analytics: analytics.Enabled, - Integration: "", - }, - expectedError: errors.New("integration type can only contain numbers, letters and these characters '-', '_'"), + expectedError: errors.New("integration type can only contain numbers, letters and these characters '-', '_'"), }, } for _, test := range testCases { - err := readIntegrationType(test.givenEventRequest, test.givenHttpRequest) + testEventRequest := &analytics.EventRequest{} + err := readIntegrationType(testEventRequest, test.givenHttpRequest) if err != nil { assert.Equal(t, test.expectedError, err, test.description) } else { assert.Empty(t, err, test.description) - assert.Equalf(t, test.expectedIntegrationType, test.givenEventRequest.Integration, test.description) + assert.Equalf(t, test.expectedIntegrationType, testEventRequest.Integration, test.description) } } } diff --git a/endpoints/events/vtrack_test.go b/endpoints/events/vtrack_test.go index 54c041bde43..1d792b6b12d 100644 --- a/endpoints/events/vtrack_test.go +++ b/endpoints/events/vtrack_test.go @@ -4,8 +4,10 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "io/ioutil" + "net/http" "net/http/httptest" "strings" "testing" @@ -690,3 +692,39 @@ func getVTrackRequestData(wi bool, wic bool) (db []byte, e error) { return data.Bytes(), e } + +func TestGetIntegrationType(t *testing.T) { + testCases := []struct { + description string + givenHttpRequest *http.Request + expectedIntegrationType string + expectedError error + }{ + { + description: "Integration type in http request is valid, expect same integration time and no errors", + givenHttpRequest: httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder&int=TestIntegrationType", strings.NewReader("")), + expectedIntegrationType: "TestIntegrationType", + expectedError: nil, + }, + { + description: "Integration type in http request is too long, expect too long error", + givenHttpRequest: httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder&int=TestIntegrationTypeTooLongTestIntegrationTypeTooLongTestIntegrationType", strings.NewReader("")), + expectedError: errors.New("integration type length is too long"), + }, + { + description: "Integration type in http request contains invalid character, expect invalid character error", + givenHttpRequest: httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder&int=Te$tIntegrationType", strings.NewReader("")), + expectedError: errors.New("integration type can only contain numbers, letters and these characters '-', '_'"), + }, + } + + for _, test := range testCases { + integrationType, err := getIntegrationType(test.givenHttpRequest) + if err != nil { + assert.Equal(t, test.expectedError, err, test.description) + } else { + assert.Empty(t, err, test.description) + assert.Equalf(t, test.expectedIntegrationType, integrationType, test.description) + } + } +} diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go index 0d98fbd2ef9..c953d12d08a 100644 --- a/endpoints/openrtb2/auction.go +++ b/endpoints/openrtb2/auction.go @@ -1887,7 +1887,11 @@ func (deps *endpointDeps) setIntegrationType(req *openrtb_ext.RequestWrapper, ac return err } reqPrebid := reqExt.GetPrebid() - if reqPrebid == nil && account != nil { + + if account == nil { + return nil + } + if reqPrebid == nil { reqPrebid = &openrtb_ext.ExtRequestPrebid{Integration: account.DefaultIntegration} reqExt.SetPrebid(reqPrebid) } else if reqPrebid.Integration == "" && account.DefaultIntegration != "" { From a609124495d9c3a099bcb4ff07523add2e11d288 Mon Sep 17 00:00:00 2001 From: AlexBVolcy <74930484+AlexBVolcy@users.noreply.github.com> Date: Tue, 8 Feb 2022 13:49:39 -0800 Subject: [PATCH 09/10] Added test coverage for readIntegrationType error --- endpoints/events/event_test.go | 35 ++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/endpoints/events/event_test.go b/endpoints/events/event_test.go index e75c33a5f31..6de3936da3f 100644 --- a/endpoints/events/event_test.go +++ b/endpoints/events/event_test.go @@ -394,6 +394,41 @@ func TestShouldNotPassEventToAnalyticsReporterWhenAccountNotFound(t *testing.T) assert.Equal(t, "Account 'testacc' doesn't support events", string(d)) } +func TestShouldReturnBadRequestWhenIntegrationValueIsInvalid(t *testing.T) { + // mock AccountsFetcher + mockAccountsFetcher := &mockAccountsFetcher{} + + // mock PBS Analytics Module + mockAnalyticsModule := &eventsMockAnalyticsModule{ + Fail: false, + } + + // mock config + cfg := &config.Configuration{ + AccountDefaults: config.Account{}, + } + + // prepare + reqData := "" + + req := httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder&int=Te$tIntegrationType", strings.NewReader(reqData)) + recorder := httptest.NewRecorder() + + e := NewEventEndpoint(cfg, mockAccountsFetcher, mockAnalyticsModule) + + // execute + e(recorder, req, nil) + + d, err := ioutil.ReadAll(recorder.Result().Body) + if err != nil { + t.Fatal(err) + } + + // validate + assert.Equal(t, 400, recorder.Result().StatusCode, "Expected 400 on request with invalid integration type parameter") + assert.Equal(t, "invalid request: integration type can only contain numbers, letters and these characters '-', '_'\n", string(d)) +} + func TestShouldNotPassEventToAnalyticsReporterWhenAccountEventNotEnabled(t *testing.T) { // mock AccountsFetcher From e7f1c644fd0afecbaf3fe3380769833b75b25e6b Mon Sep 17 00:00:00 2001 From: AlexBVolcy <74930484+AlexBVolcy@users.noreply.github.com> Date: Wed, 9 Feb 2022 16:33:27 -0800 Subject: [PATCH 10/10] Minor feedback updates --- endpoints/events/event_test.go | 2 +- endpoints/events/vtrack.go | 1 + endpoints/events/vtrack_test.go | 2 +- endpoints/openrtb2/auction.go | 4 ++-- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/endpoints/events/event_test.go b/endpoints/events/event_test.go index 6de3936da3f..09ad6d5747a 100644 --- a/endpoints/events/event_test.go +++ b/endpoints/events/event_test.go @@ -742,7 +742,7 @@ func TestReadIntegrationType(t *testing.T) { for _, test := range testCases { testEventRequest := &analytics.EventRequest{} err := readIntegrationType(testEventRequest, test.givenHttpRequest) - if err != nil { + if test.expectedError != nil { assert.Equal(t, test.expectedError, err, test.description) } else { assert.Empty(t, err, test.description) diff --git a/endpoints/events/vtrack.go b/endpoints/events/vtrack.go index 4bead1453e8..5e6a90249d1 100644 --- a/endpoints/events/vtrack.go +++ b/endpoints/events/vtrack.go @@ -73,6 +73,7 @@ func (v *vtrackEndpoint) Handle(w http.ResponseWriter, r *http.Request, _ httpro // get integration value from request parameter integrationType, err := getIntegrationType(r) if err != nil { + w.WriteHeader(http.StatusBadRequest) w.Write([]byte(fmt.Sprintf("Invalid integration type: %s\n", err.Error()))) return } diff --git a/endpoints/events/vtrack_test.go b/endpoints/events/vtrack_test.go index 1d792b6b12d..d8905d7b443 100644 --- a/endpoints/events/vtrack_test.go +++ b/endpoints/events/vtrack_test.go @@ -720,7 +720,7 @@ func TestGetIntegrationType(t *testing.T) { for _, test := range testCases { integrationType, err := getIntegrationType(test.givenHttpRequest) - if err != nil { + if test.expectedError != nil { assert.Equal(t, test.expectedError, err, test.description) } else { assert.Empty(t, err, test.description) diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go index c953d12d08a..33db0a94434 100644 --- a/endpoints/openrtb2/auction.go +++ b/endpoints/openrtb2/auction.go @@ -1888,13 +1888,13 @@ func (deps *endpointDeps) setIntegrationType(req *openrtb_ext.RequestWrapper, ac } reqPrebid := reqExt.GetPrebid() - if account == nil { + if account == nil || account.DefaultIntegration == "" { return nil } if reqPrebid == nil { reqPrebid = &openrtb_ext.ExtRequestPrebid{Integration: account.DefaultIntegration} reqExt.SetPrebid(reqPrebid) - } else if reqPrebid.Integration == "" && account.DefaultIntegration != "" { + } else if reqPrebid.Integration == "" { reqPrebid.Integration = account.DefaultIntegration reqExt.SetPrebid(reqPrebid) }