diff --git a/analytics/pubmatic/logger.go b/analytics/pubmatic/logger.go
index c90a146753c..77dc727ebed 100644
--- a/analytics/pubmatic/logger.go
+++ b/analytics/pubmatic/logger.go
@@ -360,8 +360,8 @@ func getPartnerRecordsByImp(ao analytics.AuctionObject, rCtx *models.RequestCtx)
price := bid.Price
if ao.Response.Cur != models.USD {
- if bidCtx.EG != 0 { // valid-bids + dropped-bids+ default-bids
- price = bidCtx.EG
+ if bidCtx.EN != 0 { // valid-bids + dropped-bids+ default-bids
+ price = bidCtx.EN
} else if bidExt.OriginalBidCPMUSD != 0 { // valid non-bids
price = bidExt.OriginalBidCPMUSD
}
@@ -403,11 +403,11 @@ func getPartnerRecordsByImp(ao analytics.AuctionObject, rCtx *models.RequestCtx)
}
if pr.NetECPM == 0 {
- pr.NetECPM = models.GetNetEcpm(price, revShare)
+ pr.NetECPM = models.ToFixed(price, models.BID_PRECISION)
}
if pr.GrossECPM == 0 {
- pr.GrossECPM = models.GetGrossEcpm(price)
+ pr.GrossECPM = models.GetGrossEcpmFromNetEcpm(price, revShare)
}
if pr.PartnerSize == "" {
diff --git a/analytics/pubmatic/logger_test.go b/analytics/pubmatic/logger_test.go
index c9e00314950..61457307e6a 100644
--- a/analytics/pubmatic/logger_test.go
+++ b/analytics/pubmatic/logger_test.go
@@ -3024,8 +3024,8 @@ func TestGetPartnerRecordsByImpForRevShareAndBidCPM(t *testing.T) {
partners: map[string][]PartnerRecord{
"imp1": {
{
- NetECPM: 90,
- GrossECPM: 100,
+ NetECPM: 100,
+ GrossECPM: 111.11,
OriginalCPM: 100,
OriginalCur: "USD",
PartnerID: "pubmatic",
@@ -3198,8 +3198,8 @@ func TestGetPartnerRecordsByImpForRevShareAndBidCPM(t *testing.T) {
partners: map[string][]PartnerRecord{
"imp1": {
{
- NetECPM: 90,
- GrossECPM: 100,
+ NetECPM: 100,
+ GrossECPM: 111.11,
OriginalCPM: 200,
OriginalCur: "INR",
PartnerID: "pubmatic",
@@ -3568,11 +3568,11 @@ func TestGetLogAuctionObjectAsURL(t *testing.T) {
rCtx: &models.RequestCtx{
PubID: 5890,
DeviceCtx: models.DeviceCtx{
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{
- ATTS: ptrutil.ToPtr(openrtb_ext.IOSAppTrackingStatusRestricted),
- },
- },
+ Ext: func() *models.ExtDevice {
+ extDevice := models.ExtDevice{}
+ extDevice.UnmarshalJSON([]byte(`{"atts":1}`))
+ return &extDevice
+ }(),
},
},
logInfo: true,
diff --git a/analytics/pubmatic/record.go b/analytics/pubmatic/record.go
index 91f162434ac..6e2782602f5 100644
--- a/analytics/pubmatic/record.go
+++ b/analytics/pubmatic/record.go
@@ -51,9 +51,9 @@ type record struct {
// Device struct for storing device information
type Device struct {
- Platform models.DevicePlatform `json:"plt,omitempty"`
- IFAType *models.DeviceIFAType `json:"ifty,omitempty"` //OTT-416, adding device.ext.ifa_type
- ATTS *openrtb_ext.IOSAppTrackingStatus `json:"atts,omitempty"` //device.ext.atts
+ Platform models.DevicePlatform `json:"plt,omitempty"`
+ IFAType *models.DeviceIFAType `json:"ifty,omitempty"` //OTT-416, adding device.ext.ifa_type
+ ATTS *float64 `json:"atts,omitempty"` //device.ext.atts
}
/*
@@ -199,7 +199,7 @@ func (wlog *WloggerRecord) logDeviceObject(dvc *models.DeviceCtx) {
wlog.Device.Platform = dvc.Platform
wlog.Device.IFAType = dvc.IFATypeID
if dvc.Ext != nil {
- wlog.record.Device.ATTS = dvc.Ext.ATTS
+ wlog.record.Device.ATTS, _ = dvc.Ext.GetAtts()
}
}
diff --git a/analytics/pubmatic/record_test.go b/analytics/pubmatic/record_test.go
index a8b8142f959..f1bfb2eb141 100644
--- a/analytics/pubmatic/record_test.go
+++ b/analytics/pubmatic/record_test.go
@@ -415,9 +415,7 @@ func TestLogDeviceObject(t *testing.T) {
dvc: &models.DeviceCtx{
Platform: models.DevicePlatformDesktop,
IFATypeID: ptrutil.ToPtr(models.DeviceIFATypeID[models.DeviceIFATypeDPID]),
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{},
- },
+ Ext: &models.ExtDevice{},
},
},
want: Device{
@@ -431,17 +429,17 @@ func TestLogDeviceObject(t *testing.T) {
dvc: &models.DeviceCtx{
Platform: models.DevicePlatformDesktop,
IFATypeID: ptrutil.ToPtr(models.DeviceIFATypeID[models.DeviceIFATypeDPID]),
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{
- ATTS: ptrutil.ToPtr(openrtb_ext.IOSAppTrackingStatusNotDetermined),
- },
- },
+ Ext: func() *models.ExtDevice {
+ extDevice := models.ExtDevice{}
+ extDevice.UnmarshalJSON([]byte(`{"atts":0}`))
+ return &extDevice
+ }(),
},
},
want: Device{
Platform: models.DevicePlatformDesktop,
IFAType: ptrutil.ToPtr(models.DeviceIFATypeID[models.DeviceIFATypeDPID]),
- ATTS: ptrutil.ToPtr(openrtb_ext.IOSAppTrackingStatusNotDetermined),
+ ATTS: ptrutil.ToPtr(float64(openrtb_ext.IOSAppTrackingStatusNotDetermined)),
},
},
}
diff --git a/go.mod b/go.mod
index 71d1d3b6b84..bbc148ac39c 100644
--- a/go.mod
+++ b/go.mod
@@ -2,7 +2,7 @@ module github.com/PubMatic-OpenWrap/prebid-server
go 1.20
-replace git.pubmatic.com/vastunwrap => git.pubmatic.com/PubMatic/vastunwrap v0.0.0-20231102070946-3c5a3bc1dff5
+replace git.pubmatic.com/vastunwrap => git.pubmatic.com/PubMatic/vastunwrap v0.0.0-20240215114830-026b72bf5a2f
require (
github.com/DATA-DOG/go-sqlmock v1.5.0
@@ -79,7 +79,6 @@ require (
github.com/subosito/gotenv v1.3.0 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
- github.com/yudai/pp v2.0.1+incompatible // indirect
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect
golang.org/x/sys v0.14.0 // indirect
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
diff --git a/go.sum b/go.sum
index 2530cd440cf..6a0671527af 100644
--- a/go.sum
+++ b/go.sum
@@ -49,8 +49,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
-git.pubmatic.com/PubMatic/vastunwrap v0.0.0-20231102070946-3c5a3bc1dff5 h1:nK2YP3aS8+5dwc5cMJ8IxI0Sh7yfd858LKmcvwfkOUo=
-git.pubmatic.com/PubMatic/vastunwrap v0.0.0-20231102070946-3c5a3bc1dff5/go.mod h1:dgTumQ6/KYeLbpWq3HVOaqkZos6Q0QGwZmQmEIhQ3To=
+git.pubmatic.com/PubMatic/vastunwrap v0.0.0-20240215114830-026b72bf5a2f h1:nCrSziQxM2ITd9w71lhqAhIyZthZvvBn78aYvdQmt8s=
+git.pubmatic.com/PubMatic/vastunwrap v0.0.0-20240215114830-026b72bf5a2f/go.mod h1:dgTumQ6/KYeLbpWq3HVOaqkZos6Q0QGwZmQmEIhQ3To=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
@@ -503,7 +503,6 @@ github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FB
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI=
-github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/modules/pubmatic/openwrap/auctionresponsehook.go b/modules/pubmatic/openwrap/auctionresponsehook.go
index 9a8859c6edc..ef25402c093 100644
--- a/modules/pubmatic/openwrap/auctionresponsehook.go
+++ b/modules/pubmatic/openwrap/auctionresponsehook.go
@@ -117,12 +117,12 @@ func (m OpenWrap) handleAuctionResponseHook(
// set response netecpm and logger/tracker en
revShare := models.GetRevenueShare(rctx.PartnerConfigMap[partnerID])
- bidExt.NetECPM = models.GetNetEcpm(bid.Price, revShare)
- eg = bid.Price
+ bidExt.NetECPM = models.ToFixed(bid.Price, models.BID_PRECISION)
+ eg = models.GetGrossEcpmFromNetEcpm(bid.Price, revShare)
en = bidExt.NetECPM
if payload.BidResponse.Cur != "USD" {
- eg = bidExt.OriginalBidCPMUSD
- en = models.GetNetEcpm(bidExt.OriginalBidCPMUSD, revShare)
+ eg = models.GetGrossEcpmFromNetEcpm(bidExt.OriginalBidCPMUSD, revShare)
+ en = bidExt.OriginalBidCPMUSD
bidExt.OriginalBidCPMUSD = 0
}
diff --git a/modules/pubmatic/openwrap/auctionresponsehook_test.go b/modules/pubmatic/openwrap/auctionresponsehook_test.go
index a6d0ef18f9f..6b0c0e63ddf 100644
--- a/modules/pubmatic/openwrap/auctionresponsehook_test.go
+++ b/modules/pubmatic/openwrap/auctionresponsehook_test.go
@@ -7,6 +7,7 @@ import (
"time"
"github.com/golang/mock/gomock"
+ "github.com/prebid/openrtb/v19/adcom1"
"github.com/prebid/openrtb/v19/openrtb2"
"github.com/prebid/openrtb/v19/openrtb3"
"github.com/prebid/prebid-server/hooks/hookstage"
@@ -1563,3 +1564,342 @@ func TestAuctionResponseHookForEndpointWebS2S(t *testing.T) {
})
}
}
+
+func TestOpenWrap_handleAuctionResponseHook(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ mockCache := mock_cache.NewMockCache(ctrl)
+ tbf.SetAndResetTBFConfig(mockCache, nil)
+ defer ctrl.Finish()
+
+ type want struct {
+ result hookstage.HookResult[hookstage.AuctionResponsePayload]
+ bidResponse json.RawMessage
+ err error
+ }
+ type args struct {
+ ctx context.Context
+ moduleCtx hookstage.ModuleInvocationContext
+ payload hookstage.AuctionResponsePayload
+ }
+ tests := []struct {
+ name string
+ args args
+ want want
+ doMutate bool
+ setup func() *mock_metrics.MockMetricsEngine
+ }{
+ {
+ name: "empty moduleContext",
+ args: args{
+ ctx: nil,
+ moduleCtx: hookstage.ModuleInvocationContext{},
+ payload: hookstage.AuctionResponsePayload{},
+ },
+ doMutate: false,
+ want: want{
+ result: hookstage.HookResult[hookstage.AuctionResponsePayload]{
+ DebugMessages: []string{"error: module-ctx not found in handleAuctionResponseHook()"},
+ },
+ err: nil,
+ },
+ },
+ {
+ name: "empty requestContext",
+ args: args{
+ ctx: nil,
+ moduleCtx: hookstage.ModuleInvocationContext{
+ ModuleContext: hookstage.ModuleContext{
+ "rctx": nil,
+ },
+ },
+ payload: hookstage.AuctionResponsePayload{},
+ },
+ doMutate: false,
+ want: want{
+ result: hookstage.HookResult[hookstage.AuctionResponsePayload]{
+ DebugMessages: []string{"error: request-ctx not found in handleAuctionResponseHook()"},
+ },
+ err: nil,
+ },
+ },
+ {
+ name: "requestContext is not of type RequestCtx",
+ args: args{
+ ctx: nil,
+ moduleCtx: hookstage.ModuleInvocationContext{
+ ModuleContext: hookstage.ModuleContext{
+ "rctx": "request-ctx", // request-ctx is not of type RequestCtx
+ },
+ },
+ payload: hookstage.AuctionResponsePayload{},
+ },
+ doMutate: false,
+ want: want{
+ result: hookstage.HookResult[hookstage.AuctionResponsePayload]{
+ DebugMessages: []string{"error: request-ctx not found in handleAuctionResponseHook()"},
+ },
+ err: nil,
+ },
+ },
+ {
+ name: "requestContext has sshb=1(request should not execute module hook)",
+ args: args{
+ ctx: nil,
+ moduleCtx: hookstage.ModuleInvocationContext{
+ ModuleContext: hookstage.ModuleContext{
+ "rctx": models.RequestCtx{
+ Sshb: "1",
+ },
+ },
+ },
+ payload: hookstage.AuctionResponsePayload{},
+ },
+ doMutate: false,
+ want: want{
+ result: hookstage.HookResult[hookstage.AuctionResponsePayload]{},
+ err: nil,
+ },
+ },
+ {
+ name: "empty bidResponse",
+ args: args{
+ ctx: nil,
+ moduleCtx: hookstage.ModuleInvocationContext{
+ ModuleContext: hookstage.ModuleContext{
+ "rctx": models.RequestCtx{
+ Sshb: "0",
+ PubID: 5890,
+ PubIDStr: "5890",
+ },
+ },
+ },
+ payload: hookstage.AuctionResponsePayload{
+ BidResponse: &openrtb2.BidResponse{
+ SeatBid: []openrtb2.SeatBid{},
+ },
+ },
+ },
+ doMutate: true,
+ setup: func() *mock_metrics.MockMetricsEngine {
+ mockEngine := mock_metrics.NewMockMetricsEngine(ctrl)
+ mockEngine.EXPECT().RecordNobidErrPrebidServerResponse("5890")
+ mockEngine.EXPECT().RecordPublisherResponseTimeStats("5890", gomock.Any())
+ return mockEngine
+ },
+ want: want{
+ result: hookstage.HookResult[hookstage.AuctionResponsePayload]{},
+ err: nil,
+ bidResponse: json.RawMessage(`{"id":"","ext":{"matchedimpression":{}}}`),
+ },
+ },
+ {
+ name: "valid bidResponse with banner bids",
+ args: args{
+ ctx: nil,
+ moduleCtx: hookstage.ModuleInvocationContext{
+ ModuleContext: hookstage.ModuleContext{
+ "rctx": models.RequestCtx{
+ PubID: 5890,
+ PubIDStr: "5890",
+ Platform: "web",
+ ImpBidCtx: map[string]models.ImpCtx{
+ "Div1": {
+ Bidders: map[string]models.PartnerData{
+ "pubmatic": {
+ PartnerID: 123,
+ PrebidBidderCode: "pubmatic",
+ },
+ },
+ Video: &openrtb2.Video{},
+ Type: "video",
+ Banner: true,
+ },
+ },
+ BidderResponseTimeMillis: map[string]int{},
+ SeatNonBids: map[string][]openrtb_ext.NonBid{},
+ LogInfoFlag: 1,
+ ReturnAllBidStatus: true,
+ Debug: true,
+ ClientConfigFlag: 1,
+ PartnerConfigMap: map[int]map[string]string{
+ 123: {
+ models.PARTNER_ID: "123",
+ models.PREBID_PARTNER_NAME: "pubmatic",
+ models.BidderCode: "pubmatic",
+ models.SERVER_SIDE_FLAG: "1",
+ models.KEY_GEN_PATTERN: "_AU_@_W_x_H_",
+ models.TIMEOUT: "200",
+ },
+ -1: {
+ models.DisplayVersionID: "1",
+ "refreshInterval": "30",
+ "rev_share": "0.5",
+ },
+ },
+ },
+ },
+ },
+ payload: hookstage.AuctionResponsePayload{
+ BidResponse: &openrtb2.BidResponse{
+ ID: "12345",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "Div1",
+ Price: 5,
+ AdM: "
",
+ Ext: json.RawMessage(`{"bidtype":0,"deal_channel":1,"dspid":6,"origbidcpm":8,"origbidcur":"USD","prebid":{"bidid":"bb57a9e3-fdc2-4772-8071-112dd7f50a6a","meta":{"adaptercode":"pubmatic","advertiserId":4098,"agencyId":4098,"demandSource":"6","mediaType":"banner","networkId":6},"targeting":{"hb_bidder_pubmatic":"pubmatic","hb_deal_pubmatic":"PUBDEAL1","hb_pb_pubmatic":"8.00","hb_size_pubmatic":"728x90"},"type":"banner","video":{"duration":0,"primary_category":"","vasttagid":""}}}`),
+ },
+ },
+ Seat: "pubmatic",
+ },
+ },
+ Ext: json.RawMessage(`{"responsetimemillis":{"pubmatic":8}}`),
+ },
+ },
+ },
+ setup: func() *mock_metrics.MockMetricsEngine {
+ mockEngine := mock_metrics.NewMockMetricsEngine(ctrl)
+ mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("web", "5890", "pubmatic")
+ mockEngine.EXPECT().RecordPartnerResponseTimeStats("5890", "pubmatic", 8)
+ mockEngine.EXPECT().RecordPublisherResponseTimeStats("5890", gomock.Any())
+ mockEngine.EXPECT().RecordPublisherPartnerNoCookieStats("5890", gomock.Any()).AnyTimes()
+ return mockEngine
+ },
+ doMutate: true,
+ want: want{
+ result: hookstage.HookResult[hookstage.AuctionResponsePayload]{
+ DebugMessages: []string{`[{"PubID":5890,"ProfileID":0,"DisplayID":0,"VersionID":0,"DisplayVersionID":0,"SSAuction":0,"SummaryDisable":0,"LogInfoFlag":1,"SSAI":"","PartnerConfigMap":{"-1":{"displayVersionId":"1","refreshInterval":"30","rev_share":"0.5"},"123":{"bidderCode":"pubmatic","kgp":"_AU_@_W_x_H_","partnerId":"123","prebidPartnerName":"pubmatic","serverSideEnabled":"1","timeout":"200"}},"SupportDeals":false,"Platform":"web","LoggerImpressionID":"","ClientConfigFlag":1,"IP":"","TMax":0,"IsTestRequest":0,"ABTestConfig":0,"ABTestConfigApplied":0,"IsCTVRequest":false,"TrackerEndpoint":"","VideoErrorTrackerEndpoint":"","UA":"","Cookies":"","UidCookie":null,"KADUSERCookie":null,"ParsedUidCookie":null,"OriginCookie":"","Debug":true,"Trace":false,"PageURL":"","StartTime":0,"DevicePlatform":0,"Trackers":{"bid-id-1":{"Tracker":{"PubID":5890,"PageURL":"","Timestamp":0,"IID":"","ProfileID":"0","VersionID":"0","SlotID":"","Adunit":"","PartnerInfo":{"PartnerID":"pubmatic","BidderCode":"pubmatic","KGPV":"","GrossECPM":0,"NetECPM":0,"BidID":"bb57a9e3-fdc2-4772-8071-112dd7f50a6a","OrigBidID":"bid-id-1","AdSize":"0x0","AdDuration":0,"Adformat":"banner","ServerSide":1,"Advertiser":"","FloorValue":0,"FloorRuleValue":0,"DealID":"-1"},"RewardedInventory":0,"SURL":"","Platform":0,"SSAI":"","AdPodSlot":0,"TestGroup":0,"Origin":"","FloorSkippedFlag":null,"FloorModelVersion":"","FloorSource":null,"FloorType":0,"CustomDimensions":"","LoggerData":{"KGPSV":"","FloorProvider":"","FloorFetchStatus":null}},"TrackerURL":"https:?adv=\u0026af=banner\u0026aps=0\u0026au=\u0026bc=pubmatic\u0026bidid=bb57a9e3-fdc2-4772-8071-112dd7f50a6a\u0026di=-1\u0026eg=0\u0026en=0\u0026ft=0\u0026iid=\u0026kgpv=\u0026orig=\u0026origbidid=bid-id-1\u0026pdvid=0\u0026pid=0\u0026plt=0\u0026pn=pubmatic\u0026psz=0x0\u0026pubid=5890\u0026purl=\u0026sl=1\u0026slot=\u0026ss=1\u0026tgid=0\u0026tst=0","ErrorURL":"","Price":5,"PriceModel":"CPM","PriceCurrency":""}},"PrebidBidderCode":null,"ImpBidCtx":{"Div1":{"ImpID":"","TagID":"","Div":"","SlotName":"","AdUnitName":"","Secure":0,"BidFloor":0,"BidFloorCur":"","IsRewardInventory":null,"Banner":true,"Video":{"mimes":null},"Native":null,"IncomingSlots":null,"Type":"video","Bidders":{"pubmatic":{"PartnerID":123,"PrebidBidderCode":"pubmatic","MatchedSlot":"","KGP":"","KGPV":"","IsRegex":false,"Params":null,"VASTTagFlag":false,"VASTTagFlags":null}},"NonMapped":null,"NewExt":null,"BidCtx":{"bid-id-1":{"prebid":{"meta":{"adaptercode":"pubmatic","advertiserId":4098,"agencyId":4098,"demandSource":"6","mediaType":"banner","networkId":6},"type":"banner","bidid":"bb57a9e3-fdc2-4772-8071-112dd7f50a6a"},"refreshInterval":30,"crtype":"banner","dspid":6,"netecpm":5,"origbidcpm":8,"origbidcur":"USD","EG":0,"EN":0}},"BannerAdUnitCtx":{"MatchedSlot":"","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":null,"AppliedSlotAdUnitConfig":null,"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"VideoAdUnitCtx":{"MatchedSlot":"","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":null,"AppliedSlotAdUnitConfig":null,"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"BidderError":"","IsAdPodRequest":false}},"Aliases":null,"NewReqExt":null,"ResponseExt":{"responsetimemillis":{"pubmatic":8}},"MarketPlaceBidders":null,"AdapterThrottleMap":null,"AdUnitConfig":null,"Source":"","Origin":"","SendAllBids":false,"WinningBids":{"Div1":{"ID":"bid-id-1","NetEcpm":5,"BidDealTierSatisfied":false,"Nbr":null}},"DroppedBids":null,"DefaultBids":{},"SeatNonBids":{},"BidderResponseTimeMillis":{"pubmatic":8},"Endpoint":"","PubIDStr":"5890","ProfileIDStr":"","MetricsEngine":{},"ReturnAllBidStatus":true,"Sshb":"","DCName":"","CachePutMiss":0,"MatchedImpression":{"pubmatic":0},"CustomDimensions":null}]`},
+ },
+ err: nil,
+ bidResponse: json.RawMessage(`{"id":"12345","seatbid":[{"bid":[{"id":"bid-id-1","impid":"Div1","price":5,"adm":"\u003cimg src=\"http://ads.pubmatic.com/AdTag/728x90.png\"\u003e\u003c/img\u003e\u003cdiv style=\"position:absolute;left:0px;top:0px;visibility:hidden;\"\u003e\u003cimg src=\"https://t.pubmatic.com/wt?adv=\u0026af=banner\u0026aps=0\u0026au=%2F43743431%2FDMDemo\u0026bc=appnexus\u0026bidid=4033c510-6d67-4af6-b53f-682ff1a580c3\u0026di=-1\u0026eg=14\u0026en=14\u0026frv=1.57\u0026ft=0\u0026fv=1.57\u0026iid=429d469d-8cfb-495a-9f0c-5f48aa0ede40\u0026kgpv=\u0026orig=ebay.com\u0026origbidid=718825584\u0026pdvid=1\u0026pid=22503\u0026plt=1\u0026pn=appnexus\u0026psz=728x90\u0026pubid=5890\u0026purl=http%3A%2F%2Febay.com%2Finte%2Fautomation%2Fs2s_activation%2Fbanner-with-gdpr-pubmatic-denied-defaultbidder.html%3Fprofileid%3D22503%26pwtv%3D1%26pwtvc%3D1%26appnexus_banner_fixedbid%3D14%26fixedbid%3D1%26debug%3D1\u0026sl=1\u0026slot=%2F43743431%2FDMDemo\u0026ss=1\u0026tgid=0\u0026tst=1704357774\"\u003e\u003c/div\u003e\u003cdiv style=\"position:absolute;left:0px;top:0px;visibility:hidden;\"\u003e\u003cimg src=\"https:?adv=\u0026af=banner\u0026aps=0\u0026au=\u0026bc=pubmatic\u0026bidid=bb57a9e3-fdc2-4772-8071-112dd7f50a6a\u0026di=-1\u0026eg=0\u0026en=0\u0026ft=0\u0026iid=\u0026kgpv=\u0026orig=\u0026origbidid=bid-id-1\u0026pdvid=0\u0026pid=0\u0026plt=0\u0026pn=pubmatic\u0026psz=0x0\u0026pubid=5890\u0026purl=\u0026sl=1\u0026slot=\u0026ss=1\u0026tgid=0\u0026tst=0\"\u003e\u003c/div\u003e","ext":{"prebid":{"meta":{"adaptercode":"pubmatic","advertiserId":4098,"agencyId":4098,"demandSource":"6","mediaType":"banner","networkId":6},"type":"banner","bidid":"bb57a9e3-fdc2-4772-8071-112dd7f50a6a"},"refreshInterval":30,"crtype":"banner","dspid":6,"netecpm":5,"origbidcpm":8,"origbidcur":"USD"}}],"seat":"pubmatic"}],"ext":{"responsetimemillis":{"pubmatic":8},"matchedimpression":{"pubmatic":0},"loginfo":{"tracker":"?adv=\u0026af=\u0026aps=0\u0026au=%24%7BADUNIT%7D\u0026bc=%24%7BBIDDER_CODE%7D\u0026bidid=%24%7BBID_ID%7D\u0026di=\u0026eg=%24%7BG_ECPM%7D\u0026en=%24%7BN_ECPM%7D\u0026ft=0\u0026iid=\u0026kgpv=%24%7BKGPV%7D\u0026orig=\u0026origbidid=%24%7BORIGBID_ID%7D\u0026pdvid=0\u0026pid=0\u0026plt=0\u0026pn=%24%7BPARTNER_NAME%7D\u0026psz=\u0026pubid=5890\u0026purl=\u0026rwrd=%24%7BREWARDED%7D\u0026sl=1\u0026slot=%24%7BSLOT_ID%7D\u0026ss=0\u0026tgid=0\u0026tst=0"}}}`),
+ },
+ },
+ {
+ name: "valid bidResponse with video bids",
+ args: args{
+ ctx: nil,
+ moduleCtx: hookstage.ModuleInvocationContext{
+ ModuleContext: hookstage.ModuleContext{
+ "rctx": models.RequestCtx{
+ PubID: 5890,
+ PubIDStr: "5890",
+ Platform: "web",
+ ImpBidCtx: map[string]models.ImpCtx{
+ "Div1": {
+ Bidders: map[string]models.PartnerData{
+ "pubmatic": {
+ PartnerID: 123,
+ PrebidBidderCode: "pubmatic",
+ },
+ },
+ Video: &openrtb2.Video{
+ MaxDuration: 20,
+ MinDuration: 10,
+ SkipAfter: 2,
+ Skip: ptrutil.ToPtr[int8](1),
+ SkipMin: 1,
+ BAttr: []adcom1.CreativeAttribute{adcom1.CreativeAttribute(1)},
+ PlaybackMethod: []adcom1.PlaybackMethod{adcom1.PlaybackPageLoadSoundOn},
+ },
+ Type: "video",
+ Banner: false,
+ },
+ },
+ BidderResponseTimeMillis: map[string]int{},
+ SeatNonBids: map[string][]openrtb_ext.NonBid{},
+ LogInfoFlag: 1,
+ ReturnAllBidStatus: true,
+ Debug: true,
+ PartnerConfigMap: map[int]map[string]string{
+ 123: {
+ models.PARTNER_ID: "123",
+ models.PREBID_PARTNER_NAME: "pubmatic",
+ models.BidderCode: "pubmatic",
+ models.SERVER_SIDE_FLAG: "1",
+ models.KEY_GEN_PATTERN: "_AU_@_W_x_H_",
+ models.TIMEOUT: "200",
+ },
+ -1: {
+ models.DisplayVersionID: "1",
+ "refreshInterval": "30",
+ "rev_share": "0.5",
+ },
+ },
+ },
+ },
+ },
+ payload: hookstage.AuctionResponsePayload{
+ BidResponse: &openrtb2.BidResponse{
+ ID: "12345",
+ SeatBid: []openrtb2.SeatBid{
+ {
+ Bid: []openrtb2.Bid{
+ {
+ ID: "bid-id-1",
+ ImpID: "Div1",
+ Price: 5,
+ AdM: "",
+ Ext: json.RawMessage(`{"bidtype":0,"deal_channel":1,"dspid":6,"origbidcpm":8,"origbidcur":"USD","prebid":{"bidid":"bb57a9e3-fdc2-4772-8071-112dd7f50a6a","meta":{"adaptercode":"pubmatic","advertiserId":4098,"agencyId":4098,"demandSource":"6","mediaType":"banner","networkId":6},"targeting":{"hb_bidder_pubmatic":"pubmatic","hb_deal_pubmatic":"PUBDEAL1","hb_pb_pubmatic":"8.00","hb_size_pubmatic":"728x90"},"type":"video","video":{"duration":0,"primary_category":"","vasttagid":""}}}`),
+ },
+ },
+ Seat: "pubmatic",
+ },
+ },
+ Ext: json.RawMessage(`{"responsetimemillis":{"pubmatic":8}}`),
+ },
+ },
+ },
+ setup: func() *mock_metrics.MockMetricsEngine {
+ mockEngine := mock_metrics.NewMockMetricsEngine(ctrl)
+ mockEngine.EXPECT().RecordPlatformPublisherPartnerResponseStats("web", "5890", "pubmatic")
+ mockEngine.EXPECT().RecordPartnerResponseTimeStats("5890", "pubmatic", 8)
+ mockEngine.EXPECT().RecordPublisherResponseTimeStats("5890", gomock.Any())
+ mockEngine.EXPECT().RecordPublisherPartnerNoCookieStats("5890", gomock.Any()).AnyTimes()
+ return mockEngine
+ },
+ doMutate: true,
+ want: want{
+ result: hookstage.HookResult[hookstage.AuctionResponsePayload]{},
+ err: nil,
+ bidResponse: json.RawMessage(`{"id":"12345","seatbid":[{"bid":[{"id":"bid-id-1","impid":"Div1","price":5,"adm":"\u003cVAST version=\"3.0\"\u003e\u003cAd\u003e\u003cWrapper\u003e\u003cImpression\u003e\u003c![CDATA[https:?adv=\u0026af=video\u0026aps=0\u0026au=\u0026bc=pubmatic\u0026bidid=bb57a9e3-fdc2-4772-8071-112dd7f50a6a\u0026di=-1\u0026eg=0\u0026en=0\u0026ft=0\u0026iid=\u0026kgpv=\u0026orig=\u0026origbidid=bid-id-1\u0026pdvid=0\u0026pid=0\u0026plt=0\u0026pn=pubmatic\u0026psz=0x0\u0026pubid=5890\u0026purl=\u0026sl=1\u0026slot=\u0026ss=1\u0026tgid=0\u0026tst=0]]\u003e\u003c/Impression\u003e\u003c/Wrapper\u003e\u003c/Ad\u003e\u003c/VAST\u003e","ext":{"prebid":{"meta":{"adaptercode":"pubmatic","advertiserId":4098,"agencyId":4098,"demandSource":"6","mediaType":"banner","networkId":6},"type":"video","bidid":"bb57a9e3-fdc2-4772-8071-112dd7f50a6a"},"refreshInterval":30,"crtype":"video","video":{"minduration":10,"maxduration":20,"skip":1,"skipmin":1,"skipafter":2,"battr":[1],"playbackmethod":[1]},"dspid":6,"netecpm":5,"origbidcpm":8,"origbidcur":"USD"}}],"seat":"pubmatic"}],"ext":{"responsetimemillis":{"pubmatic":8},"matchedimpression":{"pubmatic":0},"loginfo":{"tracker":"?adv=\u0026af=\u0026aps=0\u0026au=%24%7BADUNIT%7D\u0026bc=%24%7BBIDDER_CODE%7D\u0026bidid=%24%7BBID_ID%7D\u0026di=\u0026eg=%24%7BG_ECPM%7D\u0026en=%24%7BN_ECPM%7D\u0026ft=0\u0026iid=\u0026kgpv=%24%7BKGPV%7D\u0026orig=\u0026origbidid=%24%7BORIGBID_ID%7D\u0026pdvid=0\u0026pid=0\u0026plt=0\u0026pn=%24%7BPARTNER_NAME%7D\u0026psz=\u0026pubid=5890\u0026purl=\u0026rwrd=%24%7BREWARDED%7D\u0026sl=1\u0026slot=%24%7BSLOT_ID%7D\u0026ss=0\u0026tgid=0\u0026tst=0"}}}`),
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ var mockEngine *mock_metrics.MockMetricsEngine
+ if tt.setup != nil {
+ mockEngine = tt.setup()
+ }
+ m := OpenWrap{
+ cache: mockCache,
+ metricEngine: mockEngine,
+ }
+ moduleCtx, ok := tt.args.moduleCtx.ModuleContext["rctx"]
+ if ok {
+ rCtx, ok := moduleCtx.(models.RequestCtx)
+ if ok {
+ rCtx.MetricsEngine = mockEngine
+ tt.args.moduleCtx.ModuleContext["rctx"] = rCtx
+ }
+ }
+ hookResult, err := m.handleAuctionResponseHook(tt.args.ctx, tt.args.moduleCtx, tt.args.payload)
+ assert.Equal(t, tt.want.err, err, tt.name)
+ if tt.doMutate {
+ mutations := hookResult.ChangeSet.Mutations()
+ assert.NotEmpty(t, mutations, tt.name)
+ for _, mut := range mutations {
+ result, err := mut.Apply(tt.args.payload)
+ gotBidResponse, _ := json.Marshal(result.BidResponse)
+ assert.Nil(t, err, tt.name)
+ assert.Equal(t, tt.want.bidResponse, json.RawMessage(gotBidResponse), tt.name)
+ }
+ return
+ }
+ assert.Equal(t, tt.want.result.DebugMessages, hookResult.DebugMessages, tt.name)
+ })
+ }
+}
diff --git a/modules/pubmatic/openwrap/beforevalidationhook.go b/modules/pubmatic/openwrap/beforevalidationhook.go
index 660bc789fb6..6e5faa38033 100644
--- a/modules/pubmatic/openwrap/beforevalidationhook.go
+++ b/modules/pubmatic/openwrap/beforevalidationhook.go
@@ -48,14 +48,6 @@ func (m OpenWrap) handleBeforeValidationHook(
}
}()
- // return prebid validation error
- if len(payload.BidRequest.Imp) == 0 || (payload.BidRequest.Site == nil && payload.BidRequest.App == nil) {
- result.Reject = false
- m.metricEngine.RecordBadRequests(rCtx.Endpoint, getPubmaticErrorCode(nbr.InvalidRequestExt))
- m.metricEngine.RecordNobidErrPrebidServerRequests(rCtx.PubIDStr, nbr.InvalidRequestExt)
- return result, nil
- }
-
//Do not execute the module for requests processed in SSHB(8001)
if rCtx.Sshb == "1" {
result.Reject = false
@@ -68,6 +60,14 @@ func (m OpenWrap) handleBeforeValidationHook(
return result, nil
}
+ // return prebid validation error
+ if len(payload.BidRequest.Imp) == 0 || (payload.BidRequest.Site == nil && payload.BidRequest.App == nil) {
+ result.Reject = false
+ m.metricEngine.RecordBadRequests(rCtx.Endpoint, getPubmaticErrorCode(nbr.InvalidRequestExt))
+ m.metricEngine.RecordNobidErrPrebidServerRequests(rCtx.PubIDStr, nbr.InvalidRequestExt)
+ return result, nil
+ }
+
pubID, err := getPubID(*payload.BidRequest)
if err != nil {
result.NbrCode = nbr.InvalidPublisherID
@@ -114,6 +114,7 @@ func (m OpenWrap) handleBeforeValidationHook(
err = errors.New("failed to get profile data: received empty data")
}
result.Errors = append(result.Errors, err.Error())
+ rCtx.ImpBidCtx = getDefaultImpBidCtx(*payload.BidRequest) // for wrapper logger sz
m.metricEngine.RecordPublisherInvalidProfileRequests(rCtx.Endpoint, rCtx.PubIDStr, rCtx.ProfileIDStr)
m.metricEngine.RecordPublisherInvalidProfileImpressions(rCtx.PubIDStr, rCtx.ProfileIDStr, len(payload.BidRequest.Imp))
return result, err
@@ -128,6 +129,7 @@ func (m OpenWrap) handleBeforeValidationHook(
result.NbrCode = nbr.InvalidPlatform
err = errors.New("failed to get platform data")
result.Errors = append(result.Errors, err.Error())
+ rCtx.ImpBidCtx = getDefaultImpBidCtx(*payload.BidRequest) // for wrapper logger sz
m.metricEngine.RecordPublisherInvalidProfileRequests(rCtx.Endpoint, rCtx.PubIDStr, rCtx.ProfileIDStr)
m.metricEngine.RecordPublisherInvalidProfileImpressions(rCtx.PubIDStr, rCtx.ProfileIDStr, len(payload.BidRequest.Imp))
return result, err
@@ -135,7 +137,6 @@ func (m OpenWrap) handleBeforeValidationHook(
rCtx.Platform = platform
rCtx.DeviceCtx.Platform = getDevicePlatform(rCtx, payload.BidRequest)
rCtx.SendAllBids = isSendAllBids(rCtx)
- rCtx.TMax = m.setTimeout(rCtx, payload.BidRequest)
m.metricEngine.RecordPublisherRequests(rCtx.Endpoint, rCtx.PubIDStr, rCtx.Platform)
@@ -145,6 +146,9 @@ func (m OpenWrap) handleBeforeValidationHook(
result.Warnings = append(result.Warnings, "update the rCtx.PartnerConfigMap with ABTest data")
}
+ //TMax should be updated after ABTest processing
+ rCtx.TMax = m.setTimeout(rCtx, payload.BidRequest)
+
var allPartnersThrottledFlag bool
rCtx.AdapterThrottleMap, allPartnersThrottledFlag = GetAdapterThrottleMap(rCtx.PartnerConfigMap)
if allPartnersThrottledFlag {
@@ -177,6 +181,7 @@ func (m OpenWrap) handleBeforeValidationHook(
isAdPodRequest := false
disabledSlots := 0
serviceSideBidderPresent := false
+ requestExt.Prebid.BidAdjustmentFactors = map[string]float64{}
aliasgvlids := make(map[string]uint16)
for i := 0; i < len(payload.BidRequest.Imp); i++ {
@@ -192,6 +197,7 @@ func (m OpenWrap) handleBeforeValidationHook(
result.NbrCode = nbr.InternalError
err = errors.New("failed to parse imp.ext: " + imp.ID)
result.Errors = append(result.Errors, err.Error())
+ rCtx.ImpBidCtx = map[string]models.ImpCtx{} // do not create "s" object in owlogger
return result, err
}
}
@@ -202,6 +208,7 @@ func (m OpenWrap) handleBeforeValidationHook(
result.NbrCode = nbr.InvalidImpressionTagID
err = errors.New("tagid missing for imp: " + imp.ID)
result.Errors = append(result.Errors, err.Error())
+ rCtx.ImpBidCtx = map[string]models.ImpCtx{} // do not create "s" object in owlogger
return result, err
}
@@ -358,6 +365,8 @@ func (m OpenWrap) handleBeforeValidationHook(
updateAliasGVLIds(aliasgvlids, bidderCode, partnerConfig)
}
+ revShare := models.GetRevenueShare(rCtx.PartnerConfigMap[partnerID])
+ requestExt.Prebid.BidAdjustmentFactors[bidderCode] = models.GetBidAdjustmentValue(revShare)
serviceSideBidderPresent = true
} // for(rctx.PartnerConfigMap
@@ -841,7 +850,7 @@ func getPageURL(bidRequest *openrtb2.BidRequest) string {
func getVASTEventMacros(rctx models.RequestCtx) map[string]string {
macros := map[string]string{
string(models.MacroProfileID): fmt.Sprintf("%d", rctx.ProfileID),
- string(models.MacroProfileVersionID): fmt.Sprintf("%d", rctx.DisplayID),
+ string(models.MacroProfileVersionID): fmt.Sprintf("%d", rctx.DisplayVersionID),
string(models.MacroUnixTimeStamp): fmt.Sprintf("%d", rctx.StartTime),
string(models.MacroPlatform): fmt.Sprintf("%d", rctx.DeviceCtx.Platform),
string(models.MacroWrapperImpressionID): rctx.LoggerImpressionID,
diff --git a/modules/pubmatic/openwrap/beforevalidationhook_test.go b/modules/pubmatic/openwrap/beforevalidationhook_test.go
index 071654738f0..9a947eccbd4 100644
--- a/modules/pubmatic/openwrap/beforevalidationhook_test.go
+++ b/modules/pubmatic/openwrap/beforevalidationhook_test.go
@@ -165,7 +165,7 @@ func TestGetVASTEventMacros(t *testing.T) {
args: args{
rctx: models.RequestCtx{
ProfileID: 1234,
- DisplayID: 1234,
+ DisplayVersionID: 1234,
StartTime: 1234,
LoggerImpressionID: "1234",
SSAI: "",
@@ -187,7 +187,7 @@ func TestGetVASTEventMacros(t *testing.T) {
args: args{
rctx: models.RequestCtx{
ProfileID: 1234,
- DisplayID: 1234,
+ DisplayVersionID: 1234,
StartTime: 1234,
LoggerImpressionID: "1234",
SSAI: "1234",
@@ -2481,7 +2481,6 @@ func TestOpenWrap_handleBeforeValidationHook(t *testing.T) {
"adunit@700x900": "1232433543534543",
},
})
-
//prometheus metrics
mockEngine.EXPECT().RecordPublisherProfileRequests("5890", "1234")
mockEngine.EXPECT().RecordPublisherRequests(rctx.Endpoint, "5890", rctx.Platform)
@@ -2494,12 +2493,12 @@ func TestOpenWrap_handleBeforeValidationHook(t *testing.T) {
NbrCode: 0,
Message: "",
ChangeSet: hookstage.ChangeSet[hookstage.BeforeValidationRequestPayload]{},
- DebugMessages: []string{`new imp: {"123":{"ImpID":"123","TagID":"adunit","Div":"","SlotName":"adunit","AdUnitName":"adunit","Secure":0,"BidFloor":0,"BidFloorCur":"","IsRewardInventory":null,"Banner":true,"Video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"Native":{"request":""},"IncomingSlots":["640x480v","700x900","728x90","300x250"],"Type":"video","Bidders":{"appnexus":{"PartnerID":2,"PrebidBidderCode":"appnexus","MatchedSlot":"adunit@700x900","KGP":"_AU_@_W_x_H_","KGPV":"","IsRegex":false,"Params":{"placementId":0,"site":"12313","adtag":"45343"},"VASTTagFlag":false,"VASTTagFlags":null}},"NonMapped":{},"NewExt":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"site":"12313","adtag":"45343"}}}},"BidCtx":{},"BannerAdUnitCtx":{"MatchedSlot":"adunit@700x900","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":{"banner":{"enabled":false}},"AppliedSlotAdUnitConfig":{"banner":{"enabled":false}},"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"VideoAdUnitCtx":{"MatchedSlot":"adunit@640x480","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":{"video":{"enabled":false}},"AppliedSlotAdUnitConfig":{"video":{"enabled":false}},"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"BidderError":"","IsAdPodRequest":false}}`, `new request.ext: {"prebid":{"bidderparams":{"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true},"macros":{"[PLATFORM]":"3","[PROFILE_ID]":"1234","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}`},
+ DebugMessages: []string{`new imp: {"123":{"ImpID":"123","TagID":"adunit","Div":"","SlotName":"adunit","AdUnitName":"adunit","Secure":0,"BidFloor":0,"BidFloorCur":"","IsRewardInventory":null,"Banner":true,"Video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"Native":{"request":""},"IncomingSlots":["640x480v","700x900","728x90","300x250"],"Type":"video","Bidders":{"appnexus":{"PartnerID":2,"PrebidBidderCode":"appnexus","MatchedSlot":"adunit@700x900","KGP":"_AU_@_W_x_H_","KGPV":"","IsRegex":false,"Params":{"placementId":0,"site":"12313","adtag":"45343"},"VASTTagFlag":false,"VASTTagFlags":null}},"NonMapped":{},"NewExt":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"site":"12313","adtag":"45343"}}}},"BidCtx":{},"BannerAdUnitCtx":{"MatchedSlot":"adunit@700x900","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":{"banner":{"enabled":false}},"AppliedSlotAdUnitConfig":{"banner":{"enabled":false}},"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"VideoAdUnitCtx":{"MatchedSlot":"adunit@640x480","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":{"video":{"enabled":false}},"AppliedSlotAdUnitConfig":{"video":{"enabled":false}},"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"BidderError":"","IsAdPodRequest":false}}`, `new request.ext: {"prebid":{"bidadjustmentfactors":{"appnexus":1},"bidderparams":{"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true},"macros":{"[PLATFORM]":"3","[PROFILE_ID]":"1234","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}`},
AnalyticsTags: hookanalytics.Analytics{Activities: nil},
},
wantErr: false,
doMutate: true,
- wantBidRequest: json.RawMessage(`{"id":"123-456-789","imp":[{"id":"123","native":{"request":""},"tagid":"adunit","ext":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"site":"12313","adtag":"45343"}}}}}],"site":{"domain":"test.com","page":"www.test.com","publisher":{"id":"5890"}},"device":{"ua":"Mozilla/5.0(X11;Linuxx86_64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/52.0.2743.82Safari/537.36","ip":"127.0.0.1"},"user":{"id":"119208432","buyeruid":"1rwe432","yob":1980,"gender":"F","customdata":"7D75D25F-FAC9-443D-B2D1-B17FEE11E027","geo":{"country":"US","region":"CA","metro":"90001","city":"Alamo"}},"wseat":["Wseat_0","Wseat_1"],"bseat":["Bseat_0","Bseat_1"],"cur":["cur_0","cur_1"],"wlang":["Wlang_0","Wlang_1"],"bcat":["bcat_0","bcat_1"],"badv":["badv_0","badv_1"],"bapp":["bapp_0","bapp_1"],"source":{"tid":"123-456-789","ext":{"omidpn":"MyIntegrationPartner","omidpv":"7.1"}},"ext":{"prebid":{"bidderparams":{"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true},"macros":{"[PLATFORM]":"3","[PROFILE_ID]":"1234","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}}`),
+ wantBidRequest: json.RawMessage(`{"id":"123-456-789","imp":[{"id":"123","native":{"request":""},"tagid":"adunit","ext":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"site":"12313","adtag":"45343"}}}}}],"site":{"domain":"test.com","page":"www.test.com","publisher":{"id":"5890"}},"device":{"ua":"Mozilla/5.0(X11;Linuxx86_64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/52.0.2743.82Safari/537.36","ip":"127.0.0.1"},"user":{"id":"119208432","buyeruid":"1rwe432","yob":1980,"gender":"F","customdata":"7D75D25F-FAC9-443D-B2D1-B17FEE11E027","geo":{"country":"US","region":"CA","metro":"90001","city":"Alamo"}},"wseat":["Wseat_0","Wseat_1"],"bseat":["Bseat_0","Bseat_1"],"cur":["cur_0","cur_1"],"wlang":["Wlang_0","Wlang_1"],"bcat":["bcat_0","bcat_1"],"badv":["badv_0","badv_1"],"bapp":["bapp_0","bapp_1"],"source":{"tid":"123-456-789","ext":{"omidpn":"MyIntegrationPartner","omidpv":"7.1"}},"ext":{"prebid":{"bidadjustmentfactors":{"appnexus":1},"bidderparams":{"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true},"macros":{"[PLATFORM]":"3","[PROFILE_ID]":"1234","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}}`),
},
{
name: "no_serviceSideBidderPresent",
@@ -2678,10 +2677,10 @@ func TestOpenWrap_handleBeforeValidationHook(t *testing.T) {
Reject: false,
NbrCode: 0,
ChangeSet: hookstage.ChangeSet[hookstage.BeforeValidationRequestPayload]{},
- DebugMessages: []string{`new imp: {"123":{"ImpID":"123","TagID":"adunit","Div":"","SlotName":"adunit","AdUnitName":"adunit","Secure":0,"BidFloor":4.3,"BidFloorCur":"USD","IsRewardInventory":null,"Banner":true,"Video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"Native":null,"IncomingSlots":["300x250","640x480v","700x900","728x90"],"Type":"video","Bidders":{"appnexus":{"PartnerID":2,"PrebidBidderCode":"appnexus","MatchedSlot":"adunit@700x900","KGP":"_AU_@_W_x_H_","KGPV":"","IsRegex":false,"Params":{"placementId":0,"site":"12313","adtag":"45343"},"VASTTagFlag":false,"VASTTagFlags":null},"dm-alias":{"PartnerID":3,"PrebidBidderCode":"districtm","MatchedSlot":"adunit@700x900","KGP":"_AU_@_W_x_H_","KGPV":"","IsRegex":false,"Params":{"placementId":0,"site":"12313","adtag":"45343"},"VASTTagFlag":false,"VASTTagFlags":null},"pub2-alias":{"PartnerID":1,"PrebidBidderCode":"pubmatic2","MatchedSlot":"adunit@700x900","KGP":"_AU_@_W_x_H_","KGPV":"","IsRegex":false,"Params":{"publisherId":"5890","adSlot":"adunit@700x900","wrapper":{"version":1,"profile":1234}},"VASTTagFlag":false,"VASTTagFlags":null}},"NonMapped":{},"NewExt":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"site":"12313","adtag":"45343"},"dm-alias":{"placementId":0,"site":"12313","adtag":"45343"},"pub2-alias":{"publisherId":"5890","adSlot":"adunit@700x900","wrapper":{"version":1,"profile":1234}}}}},"BidCtx":{},"BannerAdUnitCtx":{"MatchedSlot":"","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":null,"AppliedSlotAdUnitConfig":null,"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"VideoAdUnitCtx":{"MatchedSlot":"","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":null,"AppliedSlotAdUnitConfig":null,"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"BidderError":"","IsAdPodRequest":false}}`, `new request.ext: {"prebid":{"aliases":{"dm-alias":"appnexus","pub2-alias":"pubmatic"},"aliasgvlids":{"dm-alias":99,"pub2-alias":130},"bidderparams":{"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true},"macros":{"[PLATFORM]":"3","[PROFILE_ID]":"1234","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}`},
+ DebugMessages: []string{`new imp: {"123":{"ImpID":"123","TagID":"adunit","Div":"","SlotName":"adunit","AdUnitName":"adunit","Secure":0,"BidFloor":4.3,"BidFloorCur":"USD","IsRewardInventory":null,"Banner":true,"Video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"Native":null,"IncomingSlots":["640x480v","700x900","728x90","300x250"],"Type":"video","Bidders":{"appnexus":{"PartnerID":2,"PrebidBidderCode":"appnexus","MatchedSlot":"adunit@700x900","KGP":"_AU_@_W_x_H_","KGPV":"","IsRegex":false,"Params":{"placementId":0,"adtag":"45343","site":"12313"},"VASTTagFlag":false,"VASTTagFlags":null},"dm-alias":{"PartnerID":3,"PrebidBidderCode":"districtm","MatchedSlot":"adunit@700x900","KGP":"_AU_@_W_x_H_","KGPV":"","IsRegex":false,"Params":{"placementId":0,"site":"12313","adtag":"45343"},"VASTTagFlag":false,"VASTTagFlags":null},"pub2-alias":{"PartnerID":1,"PrebidBidderCode":"pubmatic2","MatchedSlot":"adunit@700x900","KGP":"_AU_@_W_x_H_","KGPV":"","IsRegex":false,"Params":{"publisherId":"5890","adSlot":"adunit@700x900","wrapper":{"version":1,"profile":1234}},"VASTTagFlag":false,"VASTTagFlags":null}},"NonMapped":{},"NewExt":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"adtag":"45343","site":"12313"},"dm-alias":{"placementId":0,"site":"12313","adtag":"45343"},"pub2-alias":{"publisherId":"5890","adSlot":"adunit@700x900","wrapper":{"version":1,"profile":1234}}}}},"BidCtx":{},"BannerAdUnitCtx":{"MatchedSlot":"","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":null,"AppliedSlotAdUnitConfig":null,"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"VideoAdUnitCtx":{"MatchedSlot":"","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":null,"AppliedSlotAdUnitConfig":null,"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"BidderError":"","IsAdPodRequest":false}}`, `new request.ext: {"prebid":{"aliases":{"dm-alias":"appnexus","pub2-alias":"pubmatic"},"aliasgvlids":{"dm-alias":99,"pub2-alias":130},"bidadjustmentfactors":{"appnexus":1,"dm-alias":1,"pub2-alias":1},"bidderparams":{"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true},"macros":{"[PLATFORM]":"3","[PROFILE_ID]":"1234","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}`},
AnalyticsTags: hookanalytics.Analytics{},
},
- wantBidRequest: json.RawMessage(`{"id":"123-456-789","imp":[{"id":"123","banner":{"format":[{"w":728,"h":90},{"w":300,"h":250}],"w":700,"h":900},"video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"tagid":"adunit","bidfloor":4.3,"bidfloorcur":"USD","ext":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"site":"12313","adtag":"45343"},"dm-alias":{"placementId":0,"adtag":"45343","site":"12313"},"pub2-alias":{"publisherId":"5890","adSlot":"adunit@700x900","wrapper":{"version":1,"profile":1234}}}}}}],"site":{"domain":"test.com","page":"www.test.com","publisher":{"id":"5890"}},"device":{"ua":"Mozilla/5.0(X11;Linuxx86_64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/52.0.2743.82Safari/537.36","ip":"127.0.0.1"},"user":{"id":"119208432","buyeruid":"1rwe432","yob":1980,"gender":"F","customdata":"7D75D25F-FAC9-443D-B2D1-B17FEE11E027","geo":{"country":"US","region":"CA","metro":"90001","city":"Alamo"}},"wseat":["Wseat_0","Wseat_1"],"bseat":["Bseat_0","Bseat_1"],"cur":["cur_0","cur_1"],"wlang":["Wlang_0","Wlang_1"],"bcat":["bcat_0","bcat_1"],"badv":["badv_0","badv_1"],"bapp":["bapp_0","bapp_1"],"source":{"tid":"123-456-789","ext":{"omidpn":"MyIntegrationPartner","omidpv":"7.1"}},"ext":{"prebid":{"aliases":{"dm-alias":"appnexus","pub2-alias":"pubmatic"},"aliasgvlids":{"dm-alias":99,"pub2-alias":130},"bidderparams":{"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true},"macros":{"[PLATFORM]":"3","[PROFILE_ID]":"1234","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}}`),
+ wantBidRequest: json.RawMessage(`{"id":"123-456-789","imp":[{"id":"123","banner":{"format":[{"w":728,"h":90},{"w":300,"h":250}],"w":700,"h":900},"video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"tagid":"adunit","bidfloor":4.3,"bidfloorcur":"USD","ext":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"adtag":"45343","site":"12313"},"dm-alias":{"placementId":0,"site":"12313","adtag":"45343"},"pub2-alias":{"publisherId":"5890","adSlot":"adunit@700x900","wrapper":{"version":1,"profile":1234}}}}}}],"site":{"domain":"test.com","page":"www.test.com","publisher":{"id":"5890"}},"device":{"ua":"Mozilla/5.0(X11;Linuxx86_64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/52.0.2743.82Safari/537.36","ip":"127.0.0.1"},"user":{"id":"119208432","buyeruid":"1rwe432","yob":1980,"gender":"F","customdata":"7D75D25F-FAC9-443D-B2D1-B17FEE11E027","geo":{"country":"US","region":"CA","metro":"90001","city":"Alamo"}},"wseat":["Wseat_0","Wseat_1"],"bseat":["Bseat_0","Bseat_1"],"cur":["cur_0","cur_1"],"wlang":["Wlang_0","Wlang_1"],"bcat":["bcat_0","bcat_1"],"badv":["badv_0","badv_1"],"bapp":["bapp_0","bapp_1"],"source":{"tid":"123-456-789","ext":{"omidpn":"MyIntegrationPartner","omidpv":"7.1"}},"ext":{"prebid":{"aliases":{"dm-alias":"appnexus","pub2-alias":"pubmatic"},"aliasgvlids":{"dm-alias":99,"pub2-alias":130},"bidadjustmentfactors":{"appnexus":1,"dm-alias":1,"pub2-alias":1},"bidderparams":{"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true},"macros":{"[PLATFORM]":"3","[PROFILE_ID]":"1234","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}}`),
wantErr: false,
doMutate: true,
},
@@ -2768,10 +2767,10 @@ func TestOpenWrap_handleBeforeValidationHook(t *testing.T) {
Reject: false,
NbrCode: 0,
ChangeSet: hookstage.ChangeSet[hookstage.BeforeValidationRequestPayload]{},
- DebugMessages: []string{`new imp: {"123":{"ImpID":"123","TagID":"adunit","Div":"","SlotName":"adunit","AdUnitName":"adunit","Secure":0,"BidFloor":4.3,"BidFloorCur":"USD","IsRewardInventory":null,"Banner":true,"Video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"Native":null,"IncomingSlots":["700x900","728x90","300x250","640x480v"],"Type":"video","Bidders":{"appnexus":{"PartnerID":2,"PrebidBidderCode":"appnexus","MatchedSlot":"adunit@700x900","KGP":"_AU_@_W_x_H_","KGPV":"","IsRegex":false,"Params":{"placementId":0,"site":"12313","adtag":"45343"},"VASTTagFlag":false,"VASTTagFlags":null}},"NonMapped":{},"NewExt":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"site":"12313","adtag":"45343"}}}},"BidCtx":{},"BannerAdUnitCtx":{"MatchedSlot":"","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":null,"AppliedSlotAdUnitConfig":null,"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"VideoAdUnitCtx":{"MatchedSlot":"","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":null,"AppliedSlotAdUnitConfig":null,"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"BidderError":"","IsAdPodRequest":false}}`, `new request.ext: {"prebid":{"bidderparams":{"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true},"macros":{"[PLATFORM]":"3","[PROFILE_ID]":"1234","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}`},
+ DebugMessages: []string{`new imp: {"123":{"ImpID":"123","TagID":"adunit","Div":"","SlotName":"adunit","AdUnitName":"adunit","Secure":0,"BidFloor":4.3,"BidFloorCur":"USD","IsRewardInventory":null,"Banner":true,"Video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"Native":null,"IncomingSlots":["300x250","640x480v","700x900","728x90"],"Type":"video","Bidders":{"appnexus":{"PartnerID":2,"PrebidBidderCode":"appnexus","MatchedSlot":"adunit@700x900","KGP":"_AU_@_W_x_H_","KGPV":"","IsRegex":false,"Params":{"placementId":0,"site":"12313","adtag":"45343"},"VASTTagFlag":false,"VASTTagFlags":null}},"NonMapped":{},"NewExt":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"site":"12313","adtag":"45343"}}}},"BidCtx":{},"BannerAdUnitCtx":{"MatchedSlot":"","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":null,"AppliedSlotAdUnitConfig":null,"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"VideoAdUnitCtx":{"MatchedSlot":"","IsRegex":false,"MatchedRegex":"","SelectedSlotAdUnitConfig":null,"AppliedSlotAdUnitConfig":null,"UsingDefaultConfig":false,"AllowedConnectionTypes":null},"BidderError":"","IsAdPodRequest":false}}`, `new request.ext: {"prebid":{"bidadjustmentfactors":{"appnexus":1},"bidderparams":{"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true},"macros":{"[PLATFORM]":"3","[PROFILE_ID]":"1234","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}`},
AnalyticsTags: hookanalytics.Analytics{},
},
- wantBidRequest: json.RawMessage(`{"id":"123-456-789","imp":[{"id":"123","banner":{"format":[{"w":728,"h":90},{"w":300,"h":250}],"w":700,"h":900},"video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"tagid":"adunit","bidfloor":4.3,"bidfloorcur":"USD","ext":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"adtag":"45343","site":"12313"}}}}}],"site":{"domain":"test.com","page":"www.test.com","publisher":{"id":"5890"}},"device":{"ua":"Mozilla/5.0(X11;Linuxx86_64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/52.0.2743.82Safari/537.36","ip":"127.0.0.1"},"user":{"id":"119208432","buyeruid":"1rwe432","yob":1980,"gender":"F","customdata":"7D75D25F-FAC9-443D-B2D1-B17FEE11E027","geo":{"country":"US","region":"CA","metro":"90001","city":"Alamo"}},"wseat":["Wseat_0","Wseat_1"],"bseat":["Bseat_0","Bseat_1"],"cur":["cur_0","cur_1"],"wlang":["Wlang_0","Wlang_1"],"bcat":["bcat_0","bcat_1"],"badv":["badv_0","badv_1"],"bapp":["bapp_0","bapp_1"],"source":{"tid":"123-456-789","ext":{"omidpn":"MyIntegrationPartner","omidpv":"7.1"}},"ext":{"prebid":{"bidderparams":{"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true},"macros":{"[PLATFORM]":"3","[PROFILE_ID]":"1234","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}}`),
+ wantBidRequest: json.RawMessage(`{"id":"123-456-789","imp":[{"id":"123","banner":{"format":[{"w":728,"h":90},{"w":300,"h":250}],"w":700,"h":900},"video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"tagid":"adunit","bidfloor":4.3,"bidfloorcur":"USD","ext":{"data":{"pbadslot":"adunit"},"prebid":{"bidder":{"appnexus":{"placementId":0,"site":"12313","adtag":"45343"}}}}}],"site":{"domain":"test.com","page":"www.test.com","publisher":{"id":"5890"}},"device":{"ua":"Mozilla/5.0(X11;Linuxx86_64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/52.0.2743.82Safari/537.36","ip":"127.0.0.1"},"user":{"id":"119208432","buyeruid":"1rwe432","yob":1980,"gender":"F","customdata":"7D75D25F-FAC9-443D-B2D1-B17FEE11E027","geo":{"country":"US","region":"CA","metro":"90001","city":"Alamo"}},"wseat":["Wseat_0","Wseat_1"],"bseat":["Bseat_0","Bseat_1"],"cur":["cur_0","cur_1"],"wlang":["Wlang_0","Wlang_1"],"bcat":["bcat_0","bcat_1"],"badv":["badv_0","badv_1"],"bapp":["bapp_0","bapp_1"],"source":{"tid":"123-456-789","ext":{"omidpn":"MyIntegrationPartner","omidpv":"7.1"}},"ext":{"prebid":{"bidadjustmentfactors":{"appnexus":1},"bidderparams":{"pubmatic":{"wiid":""}},"debug":true,"floors":{"enforcement":{"enforcepbs":true},"enabled":true},"targeting":{"pricegranularity":{"precision":2,"ranges":[{"min":0,"max":5,"increment":0.05},{"min":5,"max":10,"increment":0.1},{"min":10,"max":20,"increment":0.5}]},"mediatypepricegranularity":{},"includewinners":true,"includebidderkeys":true},"macros":{"[PLATFORM]":"3","[PROFILE_ID]":"1234","[PROFILE_VERSION]":"1","[UNIX_TIMESTAMP]":"0","[WRAPPER_IMPRESSION_ID]":""}}}}`),
wantErr: false,
doMutate: true,
},
@@ -2978,6 +2977,299 @@ func TestUserAgent_handleBeforeValidationHook(t *testing.T) {
}
}
+func TestImpBidCtx_handleBeforeValidationHook(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+ mockCache := mock_cache.NewMockCache(ctrl)
+ mockEngine := mock_metrics.NewMockMetricsEngine(ctrl)
+ type fields struct {
+ cfg config.Config
+ cache cache.Cache
+ metricEngine metrics.MetricsEngine
+ }
+ type args struct {
+ ctx context.Context
+ moduleCtx hookstage.ModuleInvocationContext
+ payload hookstage.BeforeValidationRequestPayload
+ bidrequest json.RawMessage
+ }
+ type want struct {
+ rctx *models.RequestCtx
+ error bool
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ want want
+ setup func()
+ }{
+ {
+ name: "default_impctx_if_getProfileData_fails",
+ args: args{
+ ctx: context.Background(),
+ moduleCtx: hookstage.ModuleInvocationContext{
+ ModuleContext: hookstage.ModuleContext{
+ "rctx": rctx,
+ },
+ },
+ bidrequest: json.RawMessage(`{"id":"123-456-789","imp":[{"id":"123","video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"tagid":"adunit","ext":{"wrapper":{"div":"div"},"bidder":{"pubmatic":{"keywords":[{"key":"pmzoneid","value":["val1","val2"]}]}},"prebid":{}}}],"site":{"domain":"test.com","page":"www.test.com","publisher":{"id":"5890"}},"device":{"ua":"Mozilla/5.0(X11;Linuxx86_64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/52.0.2743.82Safari/537.36","ip":"123.145.167.10"},"user":{"id":"119208432","buyeruid":"1rwe432","yob":1980,"gender":"F","geo":{"country":"US","region":"CA","metro":"90001","city":"Alamo"}},"wseat":["Wseat_0","Wseat_1"],"bseat":["Bseat_0","Bseat_1"],"cur":["cur_0","cur_1"],"wlang":["Wlang_0","Wlang_1"],"bcat":["bcat_0","bcat_1"],"badv":["badv_0","badv_1"],"bapp":["bapp_0","bapp_1"],"source":{"ext":{"omidpn":"MyIntegrationPartner","omidpv":"7.1"}},"ext":{"prebid":{},"wrapper":{"test":123,"profileid":123,"versionid":1,"wiid":"test_display_wiid"}}}`),
+ },
+ fields: fields{
+ cache: mockCache,
+ metricEngine: mockEngine,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ 2: {
+ models.PARTNER_ID: "2",
+ models.PREBID_PARTNER_NAME: "appnexus",
+ models.BidderCode: "appnexus",
+ models.SERVER_SIDE_FLAG: "1",
+ models.KEY_GEN_PATTERN: "_AU_@_W_x_H_",
+ models.TIMEOUT: "200",
+ },
+ -1: {
+ models.PLATFORM_KEY: models.PLATFORM_APP,
+ models.DisplayVersionID: "1",
+ },
+ }, errors.New("test"))
+ mockEngine.EXPECT().RecordPublisherProfileRequests("5890", "1234")
+ mockEngine.EXPECT().RecordBadRequests(rctx.Endpoint, getPubmaticErrorCode(nbr.InvalidProfileConfiguration))
+ mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", nbr.InvalidProfileConfiguration)
+ mockEngine.EXPECT().RecordPublisherInvalidProfileRequests(rctx.Endpoint, "5890", rctx.ProfileIDStr)
+ mockEngine.EXPECT().RecordPublisherInvalidProfileImpressions("5890", rctx.ProfileIDStr, gomock.Any())
+ },
+ want: want{
+ rctx: &models.RequestCtx{
+ ImpBidCtx: map[string]models.ImpCtx{
+ "123": {
+ IncomingSlots: []string{
+ "640x480v",
+ },
+ SlotName: "adunit",
+ AdUnitName: "adunit",
+ },
+ },
+ },
+ error: true,
+ },
+ },
+ {
+ name: "default_impctx_if_platform_is_missing",
+ args: args{
+ ctx: context.Background(),
+ moduleCtx: hookstage.ModuleInvocationContext{
+ ModuleContext: hookstage.ModuleContext{
+ "rctx": rctx,
+ },
+ },
+ bidrequest: json.RawMessage(`{"id":"123-456-789","imp":[{"id":"123","video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"tagid":"adunit","ext":{"wrapper":{"div":"div"},"bidder":{"pubmatic":{"keywords":[{"key":"pmzoneid","value":["val1","val2"]}]}},"prebid":{}}}],"site":{"domain":"test.com","page":"www.test.com","publisher":{"id":"5890"}},"device":{"ua":"Mozilla/5.0(X11;Linuxx86_64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/52.0.2743.82Safari/537.36","ip":"123.145.167.10"},"user":{"id":"119208432","buyeruid":"1rwe432","yob":1980,"gender":"F","geo":{"country":"US","region":"CA","metro":"90001","city":"Alamo"}},"wseat":["Wseat_0","Wseat_1"],"bseat":["Bseat_0","Bseat_1"],"cur":["cur_0","cur_1"],"wlang":["Wlang_0","Wlang_1"],"bcat":["bcat_0","bcat_1"],"badv":["badv_0","badv_1"],"bapp":["bapp_0","bapp_1"],"source":{"ext":{"omidpn":"MyIntegrationPartner","omidpv":"7.1"}},"ext":{"prebid":{},"wrapper":{"test":123,"profileid":123,"versionid":1,"wiid":"test_display_wiid"}}}`),
+ },
+ fields: fields{
+ cache: mockCache,
+ metricEngine: mockEngine,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ 2: {
+ models.PARTNER_ID: "2",
+ models.PREBID_PARTNER_NAME: "appnexus",
+ models.BidderCode: "appnexus",
+ models.SERVER_SIDE_FLAG: "1",
+ models.KEY_GEN_PATTERN: "_AU_@_W_x_H_",
+ models.TIMEOUT: "200",
+ },
+ -1: {
+ models.DisplayVersionID: "1",
+ },
+ }, nil)
+ //prometheus metrics
+ mockEngine.EXPECT().RecordPublisherProfileRequests("5890", "1234")
+ mockEngine.EXPECT().RecordBadRequests(rctx.Endpoint, getPubmaticErrorCode(nbr.InvalidPlatform))
+ mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", nbr.InvalidPlatform)
+ mockEngine.EXPECT().RecordPublisherInvalidProfileRequests(rctx.Endpoint, "5890", rctx.ProfileIDStr)
+ mockEngine.EXPECT().RecordPublisherInvalidProfileImpressions("5890", rctx.ProfileIDStr, gomock.Any())
+ },
+ want: want{
+ rctx: &models.RequestCtx{
+ ImpBidCtx: map[string]models.ImpCtx{
+ "123": {
+ IncomingSlots: []string{
+ "640x480v",
+ },
+ SlotName: "adunit",
+ AdUnitName: "adunit",
+ },
+ },
+ },
+ error: true,
+ },
+ },
+ {
+ name: "default_impctx_if_all_partners_throttled",
+ args: args{
+ ctx: context.Background(),
+ moduleCtx: hookstage.ModuleInvocationContext{
+ ModuleContext: hookstage.ModuleContext{
+ "rctx": rctx,
+ },
+ },
+ bidrequest: json.RawMessage(`{"id":"123-456-789","imp":[{"id":"123","video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"tagid":"adunit","ext":{"wrapper":{"div":"div"},"bidder":{"pubmatic":{"keywords":[{"key":"pmzoneid","value":["val1","val2"]}]}},"prebid":{}}}],"site":{"domain":"test.com","page":"www.test.com","publisher":{"id":"5890"}},"device":{"ua":"Mozilla/5.0(X11;Linuxx86_64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/52.0.2743.82Safari/537.36","ip":"123.145.167.10"},"user":{"id":"119208432","buyeruid":"1rwe432","yob":1980,"gender":"F","geo":{"country":"US","region":"CA","metro":"90001","city":"Alamo"}},"wseat":["Wseat_0","Wseat_1"],"bseat":["Bseat_0","Bseat_1"],"cur":["cur_0","cur_1"],"wlang":["Wlang_0","Wlang_1"],"bcat":["bcat_0","bcat_1"],"badv":["badv_0","badv_1"],"bapp":["bapp_0","bapp_1"],"source":{"ext":{"omidpn":"MyIntegrationPartner","omidpv":"7.1"}},"ext":{"prebid":{},"wrapper":{"test":123,"profileid":123,"versionid":1,"wiid":"test_display_wiid"}}}`),
+ },
+ fields: fields{
+ cache: mockCache,
+ metricEngine: mockEngine,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ 2: {
+ models.PARTNER_ID: "2",
+ models.PREBID_PARTNER_NAME: "appnexus",
+ models.BidderCode: "appnexus",
+ models.SERVER_SIDE_FLAG: "1",
+ models.KEY_GEN_PATTERN: "_AU_@_W_x_H_",
+ models.TIMEOUT: "200",
+ models.THROTTLE: "0",
+ },
+ -1: {
+ models.DisplayVersionID: "1",
+ models.PLATFORM_KEY: models.PLATFORM_APP,
+ },
+ }, nil)
+ //prometheus metrics
+ mockEngine.EXPECT().RecordPublisherProfileRequests("5890", "1234")
+ mockEngine.EXPECT().RecordBadRequests(rctx.Endpoint, getPubmaticErrorCode(nbr.AllPartnerThrottled))
+ mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", nbr.AllPartnerThrottled)
+ mockEngine.EXPECT().RecordPublisherRequests(rctx.Endpoint, "5890", rctx.Platform)
+ },
+ want: want{
+ error: false,
+ rctx: &models.RequestCtx{
+ ImpBidCtx: map[string]models.ImpCtx{
+ "123": {
+ IncomingSlots: []string{
+ "640x480v",
+ },
+ SlotName: "adunit",
+ AdUnitName: "adunit",
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "empty_impctx_if_TagID_not_present_in_imp",
+ args: args{
+ ctx: context.Background(),
+ moduleCtx: hookstage.ModuleInvocationContext{
+ ModuleContext: hookstage.ModuleContext{
+ "rctx": rctx,
+ },
+ },
+ bidrequest: json.RawMessage(`{"id":"123-456-789","imp":[{"id":"123","video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"ext":{"wrapper":{"div":"div"},"bidder":{"pubmatic":{"keywords":[{"key":"pmzoneid","value":["val1","val2"]}]}},"prebid":{}}},{"id":"456","video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"ext":{"wrapper":{"div":"div"},"bidder":{"pubmatic":{"keywords":[{"key":"pmzoneid","value":["val1","val2"]}]}},"prebid":{}}}],"site":{"domain":"test.com","page":"www.test.com","publisher":{"id":"5890"}},"device":{"ua":"Mozilla/5.0(X11;Linuxx86_64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/52.0.2743.82Safari/537.36","ip":"123.145.167.10"},"user":{"id":"119208432"},"source":{"ext":{"omidpn":"MyIntegrationPartner","omidpv":"7.1"}},"ext":{"prebid":{},"wrapper":{"test":123,"profileid":123,"versionid":1,"wiid":"test_display_wiid"}}}`),
+ },
+ fields: fields{
+ cache: mockCache,
+ metricEngine: mockEngine,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ 2: {
+ models.PARTNER_ID: "2",
+ models.PREBID_PARTNER_NAME: "appnexus",
+ models.BidderCode: "appnexus",
+ models.SERVER_SIDE_FLAG: "1",
+ models.KEY_GEN_PATTERN: "_AU_@_W_x_H_",
+ models.TIMEOUT: "200",
+ },
+ -1: {
+ models.DisplayVersionID: "1",
+ models.PLATFORM_KEY: models.PLATFORM_APP,
+ },
+ }, nil)
+ mockCache.EXPECT().GetAdunitConfigFromCache(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&adunitconfig.AdUnitConfig{})
+ //prometheus metrics
+ mockEngine.EXPECT().RecordPublisherProfileRequests("5890", "1234")
+ mockEngine.EXPECT().RecordBadRequests(rctx.Endpoint, getPubmaticErrorCode(nbr.InvalidImpressionTagID))
+ mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", nbr.InvalidImpressionTagID)
+ mockEngine.EXPECT().RecordPublisherRequests(rctx.Endpoint, "5890", rctx.Platform)
+ },
+ want: want{
+ rctx: &models.RequestCtx{
+ ImpBidCtx: map[string]models.ImpCtx{},
+ },
+ error: true,
+ },
+ },
+ {
+ name: "empty_impctx_if_imp_ext_parse_fails",
+ args: args{
+ ctx: context.Background(),
+ moduleCtx: hookstage.ModuleInvocationContext{
+ ModuleContext: hookstage.ModuleContext{
+ "rctx": rctx,
+ },
+ },
+ bidrequest: json.RawMessage(`{"id":"123-456-789","imp":[{"id":"123","video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"ext":{"wrapper":"invalid","bidder":{"pubmatic":{"keywords":[{"key":"pmzoneid","value":["val1","val2"]}]}},"prebid":{}}},{"id":"456","video":{"mimes":["video/mp4","video/mpeg"],"w":640,"h":480},"ext":{"wrapper":{"div":"div"},"bidder":{"pubmatic":{"keywords":[{"key":"pmzoneid","value":["val1","val2"]}]}},"prebid":{}}}],"site":{"domain":"test.com","page":"www.test.com","publisher":{"id":"5890"}},"device":{"ua":"Mozilla/5.0(X11;Linuxx86_64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/52.0.2743.82Safari/537.36","ip":"123.145.167.10"},"user":{"id":"119208432"},"source":{"ext":{"omidpn":"MyIntegrationPartner","omidpv":"7.1"}},"ext":{"prebid":{},"wrapper":{"test":123,"profileid":123,"versionid":1,"wiid":"test_display_wiid"}}}`),
+ },
+ fields: fields{
+ cache: mockCache,
+ metricEngine: mockEngine,
+ },
+ setup: func() {
+ mockCache.EXPECT().GetPartnerConfigMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(map[int]map[string]string{
+ 2: {
+ models.PARTNER_ID: "2",
+ models.PREBID_PARTNER_NAME: "appnexus",
+ models.BidderCode: "appnexus",
+ models.SERVER_SIDE_FLAG: "1",
+ models.KEY_GEN_PATTERN: "_AU_@_W_x_H_",
+ models.TIMEOUT: "200",
+ },
+ -1: {
+ models.DisplayVersionID: "1",
+ models.PLATFORM_KEY: models.PLATFORM_APP,
+ },
+ }, nil)
+ mockCache.EXPECT().GetAdunitConfigFromCache(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&adunitconfig.AdUnitConfig{})
+ //prometheus metrics
+ mockEngine.EXPECT().RecordPublisherProfileRequests("5890", "1234")
+ mockEngine.EXPECT().RecordBadRequests(rctx.Endpoint, getPubmaticErrorCode(nbr.InternalError))
+ mockEngine.EXPECT().RecordNobidErrPrebidServerRequests("5890", nbr.InternalError)
+ mockEngine.EXPECT().RecordPublisherRequests(rctx.Endpoint, "5890", rctx.Platform)
+ },
+ want: want{
+ rctx: &models.RequestCtx{
+ ImpBidCtx: map[string]models.ImpCtx{},
+ },
+ error: true,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if tt.setup != nil {
+ tt.setup()
+ }
+ adapters.InitBidders("./static/bidder-params/")
+ m := OpenWrap{
+ cfg: tt.fields.cfg,
+ cache: tt.fields.cache,
+ metricEngine: tt.fields.metricEngine,
+ }
+ tt.args.payload.BidRequest = &openrtb2.BidRequest{}
+ json.Unmarshal(tt.args.bidrequest, tt.args.payload.BidRequest)
+
+ _, err := m.handleBeforeValidationHook(tt.args.ctx, tt.args.moduleCtx, tt.args.payload)
+ assert.Equal(t, tt.want.error, err != nil, "mismatched error")
+ iRctx := tt.args.moduleCtx.ModuleContext["rctx"]
+ gotRctx := iRctx.(models.RequestCtx)
+ assert.Equal(t, tt.want.rctx.ImpBidCtx, gotRctx.ImpBidCtx, "mismatched rctx.ImpBidCtx")
+ })
+ }
+}
+
func TestGetSlotName(t *testing.T) {
type args struct {
tagId string
diff --git a/modules/pubmatic/openwrap/device.go b/modules/pubmatic/openwrap/device.go
index 6b608c23451..1e5ae197851 100644
--- a/modules/pubmatic/openwrap/device.go
+++ b/modules/pubmatic/openwrap/device.go
@@ -1,7 +1,6 @@
package openwrap
import (
- "encoding/json"
"strings"
"github.com/prebid/openrtb/v19/openrtb2"
@@ -21,7 +20,7 @@ func populateDeviceContext(dvc *models.DeviceCtx, device *openrtb2.Device) {
//unmarshal device ext
var deviceExt models.ExtDevice
- if err := json.Unmarshal(device.Ext, &deviceExt); err != nil {
+ if err := deviceExt.UnmarshalJSON(device.Ext); err != nil {
return
}
dvc.Ext = &deviceExt
@@ -36,29 +35,45 @@ func updateDeviceIFADetails(dvc *models.DeviceCtx) {
}
deviceExt := dvc.Ext
- deviceExt.IFAType = strings.TrimSpace(deviceExt.IFAType)
- deviceExt.SessionID = strings.TrimSpace(deviceExt.SessionID)
-
- //refactor below condition
- if deviceExt.IFAType != "" {
- if dvc.DeviceIFA != "" {
- if _, ok := models.DeviceIFATypeID[strings.ToLower(deviceExt.IFAType)]; !ok {
- deviceExt.IFAType = ""
- }
- } else if deviceExt.SessionID != "" {
- dvc.DeviceIFA = deviceExt.SessionID
- deviceExt.IFAType = models.DeviceIFATypeSESSIONID
- } else {
- deviceExt.IFAType = ""
+ extIFATypeStr, _ := deviceExt.GetIFAType()
+ extSessionIDStr, _ := deviceExt.GetSessionID()
+
+ if extIFATypeStr == "" {
+ if extSessionIDStr == "" {
+ deviceExt.DeleteIFAType()
+ deviceExt.DeleteSessionID()
+ return
+ }
+ dvc.DeviceIFA = extSessionIDStr
+ extIFATypeStr = models.DeviceIFATypeSESSIONID
+ }
+ if dvc.DeviceIFA != "" {
+ if _, ok := models.DeviceIFATypeID[strings.ToLower(extIFATypeStr)]; !ok {
+ extIFATypeStr = ""
}
- } else if deviceExt.SessionID != "" {
- dvc.DeviceIFA = deviceExt.SessionID
- deviceExt.IFAType = models.DeviceIFATypeSESSIONID
+ } else if extSessionIDStr != "" {
+ dvc.DeviceIFA = extSessionIDStr
+ extIFATypeStr = models.DeviceIFATypeSESSIONID
+
+ } else {
+ extIFATypeStr = ""
}
- if ifaTypeID, ok := models.DeviceIFATypeID[strings.ToLower(deviceExt.IFAType)]; ok {
+ if ifaTypeID, ok := models.DeviceIFATypeID[strings.ToLower(extIFATypeStr)]; ok {
dvc.IFATypeID = &ifaTypeID
}
+
+ if extIFATypeStr == "" {
+ deviceExt.DeleteIFAType()
+ } else {
+ deviceExt.SetIFAType(extIFATypeStr)
+ }
+
+ if extSessionIDStr == "" {
+ deviceExt.DeleteSessionID()
+ } else {
+ deviceExt.SetSessionID(extSessionIDStr)
+ }
}
func amendDeviceObject(device *openrtb2.Device, dvc *models.DeviceCtx) {
@@ -73,6 +88,6 @@ func amendDeviceObject(device *openrtb2.Device, dvc *models.DeviceCtx) {
//update device extension
if dvc.Ext != nil {
- device.Ext, _ = json.Marshal(dvc.Ext)
+ device.Ext, _ = dvc.Ext.MarshalJSON()
}
}
diff --git a/modules/pubmatic/openwrap/device_test.go b/modules/pubmatic/openwrap/device_test.go
index 633f8d9333e..9cbfd4877ff 100644
--- a/modules/pubmatic/openwrap/device_test.go
+++ b/modules/pubmatic/openwrap/device_test.go
@@ -7,7 +7,6 @@ import (
"github.com/prebid/openrtb/v19/openrtb2"
"github.com/prebid/prebid-server/modules/pubmatic/openwrap/models"
- "github.com/prebid/prebid-server/openrtb_ext"
"github.com/prebid/prebid-server/util/ptrutil"
"github.com/stretchr/testify/assert"
)
@@ -68,7 +67,11 @@ func TestPopulateDeviceExt(t *testing.T) {
want: want{
deviceCtx: models.DeviceCtx{
DeviceIFA: `test_ifa`,
- Ext: &models.ExtDevice{},
+ Ext: func() *models.ExtDevice {
+ deviceExt := &models.ExtDevice{}
+ deviceExt.UnmarshalJSON([]byte(`{"anykey": "anyval"}`))
+ return deviceExt
+ }(),
},
},
},
@@ -82,6 +85,7 @@ func TestPopulateDeviceExt(t *testing.T) {
want: want{
deviceCtx: models.DeviceCtx{
DeviceIFA: `test_ifa`,
+ Ext: models.NewExtDevice(),
},
},
},
@@ -97,7 +101,7 @@ func TestPopulateDeviceExt(t *testing.T) {
/* removed_invalid_ifatype */
deviceCtx: models.DeviceCtx{
DeviceIFA: `test_ifa`,
- Ext: &models.ExtDevice{},
+ Ext: models.NewExtDevice(),
},
},
},
@@ -113,11 +117,11 @@ func TestPopulateDeviceExt(t *testing.T) {
deviceCtx: models.DeviceCtx{
DeviceIFA: `test_ifa`,
IFATypeID: ptrutil.ToPtr(models.DeviceIFATypeID[models.DeviceIFATypeDPID]),
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{
- IFAType: `DpId`,
- },
- },
+ Ext: func() *models.ExtDevice {
+ deviceExt := &models.ExtDevice{}
+ deviceExt.SetIFAType("DpId")
+ return deviceExt
+ }(),
},
},
},
@@ -133,11 +137,11 @@ func TestPopulateDeviceExt(t *testing.T) {
deviceCtx: models.DeviceCtx{
DeviceIFA: `test_ifa`,
IFATypeID: ptrutil.ToPtr(models.DeviceIFATypeID[models.DeviceIFATypeSESSIONID]),
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{
- IFAType: `sessionid`,
- },
- },
+ Ext: func() *models.ExtDevice {
+ deviceExt := &models.ExtDevice{}
+ deviceExt.SetIFAType("sessionid")
+ return deviceExt
+ }(),
},
},
},
@@ -150,7 +154,7 @@ func TestPopulateDeviceExt(t *testing.T) {
},
want: want{
deviceCtx: models.DeviceCtx{
- Ext: &models.ExtDevice{},
+ Ext: models.NewExtDevice(),
},
},
},
@@ -165,6 +169,11 @@ func TestPopulateDeviceExt(t *testing.T) {
want: want{
deviceCtx: models.DeviceCtx{
DeviceIFA: `test_ifa`,
+ Ext: func() *models.ExtDevice {
+ deviceExt := &models.ExtDevice{}
+ deviceExt.UnmarshalJSON([]byte(`{"atts":"invalid_value"}`))
+ return deviceExt
+ }(),
},
},
},
@@ -177,11 +186,11 @@ func TestPopulateDeviceExt(t *testing.T) {
},
want: want{
deviceCtx: models.DeviceCtx{
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{
- ATTS: ptrutil.ToPtr(openrtb_ext.IOSAppTrackingStatusRestricted),
- },
- },
+ Ext: func() *models.ExtDevice {
+ deviceExt := &models.ExtDevice{}
+ deviceExt.UnmarshalJSON([]byte(`{"atts":1}`))
+ return deviceExt
+ }(),
},
},
},
@@ -197,12 +206,12 @@ func TestPopulateDeviceExt(t *testing.T) {
deviceCtx: models.DeviceCtx{
DeviceIFA: `test_ifa`,
IFATypeID: ptrutil.ToPtr(models.DeviceIFATypeID[models.DeviceIFATypeSESSIONID]),
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{
- IFAType: `sessionid`,
- ATTS: ptrutil.ToPtr(openrtb_ext.IOSAppTrackingStatusRestricted),
- },
- },
+ Ext: func() *models.ExtDevice {
+ deviceExt := &models.ExtDevice{}
+ deviceExt.UnmarshalJSON([]byte(`{"atts":1}`))
+ deviceExt.SetIFAType("sessionid")
+ return deviceExt
+ }(),
},
},
},
@@ -259,15 +268,15 @@ func TestUpdateDeviceIFADetails(t *testing.T) {
name: `ifa_type_present_ifa_missing`,
args: args{
dvc: &models.DeviceCtx{
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{
- IFAType: models.DeviceIFATypeDPID,
- },
- },
+ Ext: func() *models.ExtDevice {
+ ext := &models.ExtDevice{}
+ ext.SetIFAType(models.DeviceIFATypeDPID)
+ return ext
+ }(),
},
},
want: &models.DeviceCtx{
- Ext: &models.ExtDevice{},
+ Ext: models.NewExtDevice(),
},
},
{
@@ -275,18 +284,16 @@ func TestUpdateDeviceIFADetails(t *testing.T) {
args: args{
dvc: &models.DeviceCtx{
DeviceIFA: `sample_ifa_value`,
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{
- IFAType: `wrong_ifa_type`,
- },
- },
+ Ext: func() *models.ExtDevice {
+ ext := &models.ExtDevice{}
+ ext.SetIFAType("wrong_ifa_type")
+ return ext
+ }(),
},
},
want: &models.DeviceCtx{
DeviceIFA: `sample_ifa_value`,
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{},
- },
+ Ext: models.NewExtDevice(),
},
},
{
@@ -294,21 +301,21 @@ func TestUpdateDeviceIFADetails(t *testing.T) {
args: args{
dvc: &models.DeviceCtx{
DeviceIFA: `sample_ifa_value`,
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{
- IFAType: models.DeviceIFATypeDPID,
- },
- },
+ Ext: func() *models.ExtDevice {
+ ext := &models.ExtDevice{}
+ ext.SetIFAType(models.DeviceIFATypeDPID)
+ return ext
+ }(),
},
},
want: &models.DeviceCtx{
DeviceIFA: `sample_ifa_value`,
IFATypeID: ptrutil.ToPtr(models.DeviceIFATypeID[models.DeviceIFATypeDPID]),
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{
- IFAType: models.DeviceIFATypeDPID,
- },
- },
+ Ext: func() *models.ExtDevice {
+ ext := &models.ExtDevice{}
+ ext.SetIFAType(models.DeviceIFATypeDPID)
+ return ext
+ }(),
},
},
{
@@ -316,61 +323,59 @@ func TestUpdateDeviceIFADetails(t *testing.T) {
args: args{
dvc: &models.DeviceCtx{
DeviceIFA: `sample_ifa_value`,
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{
- IFAType: strings.ToUpper(models.DeviceIFATypeDPID),
- },
- },
+ Ext: func() *models.ExtDevice {
+ ext := &models.ExtDevice{}
+ ext.SetIFAType(strings.ToUpper(models.DeviceIFATypeDPID))
+ return ext
+ }(),
},
},
want: &models.DeviceCtx{
DeviceIFA: `sample_ifa_value`,
IFATypeID: ptrutil.ToPtr(models.DeviceIFATypeID[models.DeviceIFATypeDPID]),
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{
- IFAType: strings.ToUpper(models.DeviceIFATypeDPID),
- },
- },
+ Ext: func() *models.ExtDevice {
+ ext := &models.ExtDevice{}
+ ext.SetIFAType(strings.ToUpper(models.DeviceIFATypeDPID))
+ return ext
+ }(),
},
},
{
name: `ifa_type_present_session_id_present`,
args: args{
dvc: &models.DeviceCtx{
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{
- IFAType: models.DeviceIFATypeDPID,
- },
- SessionID: `sample_session_id`,
- },
+ Ext: func() *models.ExtDevice {
+ ext := &models.ExtDevice{}
+ ext.SetIFAType(strings.ToUpper(models.DeviceIFATypeDPID))
+ ext.SetSessionID(`sample_session_id`)
+ return ext
+ }(),
},
},
want: &models.DeviceCtx{
DeviceIFA: `sample_session_id`,
IFATypeID: ptrutil.ToPtr(models.DeviceIFATypeID[models.DeviceIFATypeSESSIONID]),
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{
- IFAType: models.DeviceIFATypeSESSIONID,
- },
- SessionID: `sample_session_id`,
- },
+ Ext: func() *models.ExtDevice {
+ ext := &models.ExtDevice{}
+ ext.SetIFAType(models.DeviceIFATypeSESSIONID)
+ ext.SetSessionID(`sample_session_id`)
+ return ext
+ }(),
},
},
{
name: `ifa_type_present_session_id_missing`,
args: args{
dvc: &models.DeviceCtx{
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{
- IFAType: models.DeviceIFATypeDPID,
- },
- },
+ Ext: func() *models.ExtDevice {
+ deviceExt := &models.ExtDevice{}
+ deviceExt.SetIFAType(models.DeviceIFATypeDPID)
+ return deviceExt
+ }(),
},
},
want: &models.DeviceCtx{
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{},
- },
+ Ext: models.NewExtDevice(),
},
},
{
@@ -378,21 +383,22 @@ func TestUpdateDeviceIFADetails(t *testing.T) {
args: args{
dvc: &models.DeviceCtx{
DeviceIFA: `existing_ifa_id`,
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{},
- SessionID: `sample_session_id`,
- },
+ Ext: func() *models.ExtDevice {
+ deviceExt := &models.ExtDevice{}
+ deviceExt.SetSessionID(`sample_session_id`)
+ return deviceExt
+ }(),
},
},
want: &models.DeviceCtx{
DeviceIFA: `sample_session_id`,
IFATypeID: ptrutil.ToPtr(models.DeviceIFATypeID[models.DeviceIFATypeSESSIONID]),
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{
- IFAType: models.DeviceIFATypeSESSIONID,
- },
- SessionID: `sample_session_id`,
- },
+ Ext: func() *models.ExtDevice {
+ deviceExt := &models.ExtDevice{}
+ deviceExt.SetSessionID(`sample_session_id`)
+ deviceExt.SetIFAType(models.DeviceIFATypeSESSIONID)
+ return deviceExt
+ }(),
},
},
// TODO: Add test cases.
@@ -460,9 +466,11 @@ func TestAmendDeviceObject(t *testing.T) {
},
dvc: &models.DeviceCtx{
DeviceIFA: `new_ifa`,
- Ext: &models.ExtDevice{
- SessionID: `sample_session`,
- },
+ Ext: func() *models.ExtDevice {
+ deviceExt := &models.ExtDevice{}
+ deviceExt.SetSessionID("sample_session")
+ return deviceExt
+ }(),
},
},
want: &openrtb2.Device{
@@ -481,9 +489,11 @@ func TestAmendDeviceObject(t *testing.T) {
},
dvc: &models.DeviceCtx{
DeviceIFA: `new_ifa`,
- Ext: &models.ExtDevice{
- SessionID: `sample_session`,
- },
+ Ext: func() *models.ExtDevice {
+ deviceExt := &models.ExtDevice{}
+ deviceExt.SetSessionID("sample_session")
+ return deviceExt
+ }(),
},
},
want: &openrtb2.Device{
@@ -497,6 +507,7 @@ func TestAmendDeviceObject(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
amendDeviceObject(tt.args.device, tt.args.dvc)
+ assert.Equal(t, tt.args.device, tt.want, "mismatched device object")
})
}
}
diff --git a/modules/pubmatic/openwrap/endpoints/legacy/openrtb/v25/video.go b/modules/pubmatic/openwrap/endpoints/legacy/openrtb/v25/video.go
index 17dd0d81b2f..c0015b20743 100644
--- a/modules/pubmatic/openwrap/endpoints/legacy/openrtb/v25/video.go
+++ b/modules/pubmatic/openwrap/endpoints/legacy/openrtb/v25/video.go
@@ -217,13 +217,11 @@ func ConvertVideoToAuctionRequest(payload hookstage.EntrypointPayload, result *h
var deviceExt models.ExtDevice
if session_id := GetValueFromRequest(values, redirectQueryParams, models.DeviceExtSessionID); session_id != nil {
- deviceExt.SessionID = GetString(session_id)
+ deviceExt.SetSessionID(GetString(session_id))
}
if ifaType := GetValueFromRequest(values, redirectQueryParams, models.DeviceExtIfaType); ifaType != nil {
- deviceExt.ExtDevice = openrtb_ext.ExtDevice{
- IFAType: GetString(ifaType),
- }
+ deviceExt.SetIFAType(GetString(ifaType))
}
bidRequest.Device.Ext, _ = json.Marshal(deviceExt)
} else {
diff --git a/modules/pubmatic/openwrap/entrypointhook.go b/modules/pubmatic/openwrap/entrypointhook.go
index 3c8b789c3df..51d493f0b0f 100644
--- a/modules/pubmatic/openwrap/entrypointhook.go
+++ b/modules/pubmatic/openwrap/entrypointhook.go
@@ -53,51 +53,16 @@ func (m OpenWrap) handleEntrypointHook(
if queryParams.Get("sshb") == "1" {
return result, nil
}
-
- switch payload.Request.URL.Path {
- // Direct call to 8000 port
- case hookexecution.EndpointAuction:
- switch source {
- case "pbjs":
- endpoint = models.EndpointWebS2S
- requestExtWrapper, err = models.GetRequestExtWrapper(payload.Body)
- case "owsdk":
- requestExtWrapper, err = models.GetRequestExtWrapper(payload.Body, "ext", "wrapper")
- endpoint = models.EndpointV25
- default:
- rCtx.Endpoint = models.EndpointHybrid
- return result, nil
- }
- // call to 8001 port and here via reverse proxy
- case OpenWrapAuction: // legacy hybrid api should not execute module
- // m.metricEngine.RecordPBSAuctionRequestsStats() //TODO: uncomment after hybrid call through module
+ endpoint = GetEndpoint(payload.Request.URL.Path, source)
+ if endpoint == models.EndpointHybrid {
rCtx.Endpoint = models.EndpointHybrid
return result, nil
- case OpenWrapV25:
- requestExtWrapper, err = models.GetRequestExtWrapper(payload.Body, "ext", "wrapper")
- endpoint = models.EndpointV25
- case OpenWrapV25Video:
- requestExtWrapper, err = v25.ConvertVideoToAuctionRequest(payload, &result)
- endpoint = models.EndpointVideo
- case OpenWrapAmp:
- requestExtWrapper, pubid, err = models.GetQueryParamRequestExtWrapper(payload.Request)
- endpoint = models.EndpointAMP
- case OpenWrapOpenRTBVideo:
- requestExtWrapper, err = models.GetRequestExtWrapper(payload.Body, "ext", "wrapper")
- endpoint = models.EndpointVideo
- case OpenWrapVAST:
- requestExtWrapper, err = models.GetRequestExtWrapper(payload.Body, "ext", "wrapper")
- endpoint = models.EndpointVAST
- case OpenWrapJSON:
- requestExtWrapper, err = models.GetRequestExtWrapper(payload.Body, "ext", "wrapper")
- endpoint = models.EndpointJson
- default:
- // we should return from here
}
// init default for all modules
result.Reject = true
+ requestExtWrapper, err = GetRequestWrapper(payload, result, endpoint)
if err != nil {
result.NbrCode = nbr.InvalidRequestWrapperExtension
result.Errors = append(result.Errors, err.Error())
@@ -169,3 +134,53 @@ func (m OpenWrap) handleEntrypointHook(
result.Reject = false
return result, nil
}
+
+func GetRequestWrapper(payload hookstage.EntrypointPayload, result hookstage.HookResult[hookstage.EntrypointPayload], endpoint string) (models.RequestExtWrapper, error) {
+ var requestExtWrapper models.RequestExtWrapper
+ var err error
+ switch endpoint {
+ case models.EndpintInappVideo:
+ requestExtWrapper, err = v25.ConvertVideoToAuctionRequest(payload, &result)
+ case models.EndpointAMP:
+ requestExtWrapper, err = models.GetQueryParamRequestExtWrapper(payload.Request)
+ case models.EndpointV25:
+ fallthrough
+ case models.EndpointVideo, models.EndpointVAST, models.EndpointJson:
+ requestExtWrapper, err = models.GetRequestExtWrapper(payload.Body, "ext", "wrapper")
+ case models.EndpointWebS2S:
+ fallthrough
+ default:
+ requestExtWrapper, err = models.GetRequestExtWrapper(payload.Body)
+ }
+
+ return requestExtWrapper, err
+}
+
+func GetEndpoint(path, source string) string {
+ switch path {
+ case hookexecution.EndpointAuction:
+ switch source {
+ case "pbjs":
+ return models.EndpointWebS2S
+ case "owsdk":
+ return models.EndpointV25
+ default:
+ return models.EndpointHybrid
+ }
+ case OpenWrapAuction:
+ return models.EndpointHybrid
+ case OpenWrapV25:
+ return models.EndpointV25
+ case OpenWrapV25Video:
+ return models.EndpintInappVideo
+ case OpenWrapAmp:
+ return models.EndpointAMP
+ case OpenWrapOpenRTBVideo:
+ return models.EndpointVideo
+ case OpenWrapVAST:
+ return models.EndpointVAST
+ case OpenWrapJSON:
+ return models.EndpointJson
+ }
+ return ""
+}
diff --git a/modules/pubmatic/openwrap/entrypointhook_test.go b/modules/pubmatic/openwrap/entrypointhook_test.go
index bfb48f3826b..aee2e5af9bd 100644
--- a/modules/pubmatic/openwrap/entrypointhook_test.go
+++ b/modules/pubmatic/openwrap/entrypointhook_test.go
@@ -6,6 +6,7 @@ import (
"testing"
"github.com/golang/mock/gomock"
+ "github.com/prebid/prebid-server/hooks/hookexecution"
"github.com/prebid/prebid-server/hooks/hookstage"
"github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache"
"github.com/prebid/prebid-server/modules/pubmatic/openwrap/config"
@@ -529,3 +530,148 @@ func TestOpenWrap_handleEntrypointHook(t *testing.T) {
})
}
}
+
+func TestGetRequestWrapper(t *testing.T) {
+ type args struct {
+ payload hookstage.EntrypointPayload
+ result hookstage.HookResult[hookstage.EntrypointPayload]
+ endpoint string
+ }
+ tests := []struct {
+ name string
+ args args
+ want models.RequestExtWrapper
+ wantErr bool
+ }{
+ {
+ name: "EndpointWebS2S",
+ args: args{
+ payload: hookstage.EntrypointPayload{
+ Body: []byte(`{"ext":{"wrapper":{"profileid":5890,"versionid":1},"prebid":{"bidderparams":{"pubmatic":{"wrapper":{"profileid":100,"versionid":2}}}}}}`),
+ },
+ result: hookstage.HookResult[hookstage.EntrypointPayload]{},
+ endpoint: models.EndpointWebS2S,
+ },
+ want: models.RequestExtWrapper{
+ SSAuctionFlag: -1,
+ ProfileId: 100,
+ VersionId: 2,
+ },
+ wantErr: false,
+ },
+ {
+ name: "EndpointV25",
+ args: args{
+ payload: hookstage.EntrypointPayload{
+ Body: []byte(`{"ext":{"wrapper":{"profileid":5890,"versionid":1},"prebid":{"bidderparams":{"pubmatic":{"wrapper":{"profileid":100,"versionid":2}}}}}}`),
+ },
+ result: hookstage.HookResult[hookstage.EntrypointPayload]{},
+ endpoint: models.EndpointV25,
+ },
+ want: models.RequestExtWrapper{
+ SSAuctionFlag: -1,
+ ProfileId: 5890,
+ VersionId: 1,
+ },
+ },
+ //TODO: Add test cases for other endpoints after migration(AMP, Video, VAST, JSON, InappVideo)
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := GetRequestWrapper(tt.args.payload, tt.args.result, tt.args.endpoint)
+ assert.Equal(t, err != nil, tt.wantErr)
+ assert.Equal(t, tt.want, got)
+ })
+ }
+}
+
+func TestGetEndpoint(t *testing.T) {
+ type args struct {
+ path string
+ source string
+ }
+ tests := []struct {
+ name string
+ args args
+ want string
+ }{
+ {
+ name: "EndpointAuction Activation",
+ args: args{
+ path: hookexecution.EndpointAuction,
+ source: "pbjs",
+ },
+ want: models.EndpointWebS2S,
+ },
+ {
+ name: "EndpointAuction inapp",
+ args: args{
+ path: hookexecution.EndpointAuction,
+ source: "owsdk",
+ },
+ want: models.EndpointV25,
+ },
+ {
+ name: "EndpointAuction default",
+ args: args{
+ path: hookexecution.EndpointAuction,
+ },
+ want: models.EndpointHybrid,
+ },
+ {
+ name: "OpenWrapAuction",
+ args: args{
+ path: OpenWrapAuction,
+ },
+ want: models.EndpointHybrid,
+ },
+ {
+ name: "OpenWrapV25",
+ args: args{
+ path: OpenWrapV25,
+ },
+ want: models.EndpointV25,
+ },
+ {
+ name: "OpenWrapV25Video",
+ args: args{
+ path: OpenWrapV25Video,
+ },
+ want: models.EndpintInappVideo,
+ },
+ {
+ name: "OpenWrapAmp",
+ args: args{
+ path: OpenWrapAmp,
+ },
+ want: models.EndpointAMP,
+ },
+ {
+ name: "OpenWrapOpenRTBVideo",
+ args: args{
+ path: OpenWrapOpenRTBVideo,
+ },
+ want: models.EndpointVideo,
+ },
+ {
+ name: "OpenWrapVAST",
+ args: args{
+ path: OpenWrapVAST,
+ },
+ want: models.EndpointVAST,
+ },
+ {
+ name: "OpenWrapJSON",
+ args: args{
+ path: OpenWrapJSON,
+ },
+ want: models.EndpointJson,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := GetEndpoint(tt.args.path, tt.args.source)
+ assert.Equal(t, tt.want, got)
+ })
+ }
+}
diff --git a/modules/pubmatic/openwrap/logger_test.go b/modules/pubmatic/openwrap/logger_test.go
new file mode 100644
index 00000000000..cad1a487354
--- /dev/null
+++ b/modules/pubmatic/openwrap/logger_test.go
@@ -0,0 +1,145 @@
+package openwrap
+
+import (
+ "testing"
+
+ "github.com/prebid/openrtb/v19/openrtb2"
+ "github.com/prebid/prebid-server/util/ptrutil"
+ "github.com/stretchr/testify/assert"
+)
+
+func Test_getIncomingSlots(t *testing.T) {
+ type args struct {
+ imp openrtb2.Imp
+ }
+ tests := []struct {
+ name string
+ args args
+ want []string
+ }{
+ {
+ name: "only_native_slot",
+ args: args{
+ imp: openrtb2.Imp{
+ ID: "1",
+ Native: &openrtb2.Native{
+ Request: `{"ver":"1.2"}`,
+ },
+ },
+ },
+ want: []string{"1x1"},
+ },
+ {
+ name: "native_with_other_slots_then_do_not_consider_native",
+ args: args{
+ imp: openrtb2.Imp{
+ ID: "1",
+ Native: &openrtb2.Native{
+ Request: `{"ver":"1.2"}`,
+ },
+ Banner: &openrtb2.Banner{
+ W: ptrutil.ToPtr[int64](300),
+ H: ptrutil.ToPtr[int64](250),
+ },
+ },
+ },
+ want: []string{"300x250"},
+ },
+ {
+ name: "only_banner_slot",
+ args: args{
+ imp: openrtb2.Imp{
+ ID: "1",
+ Banner: &openrtb2.Banner{
+ W: ptrutil.ToPtr[int64](300),
+ H: ptrutil.ToPtr[int64](250),
+ },
+ },
+ },
+ want: []string{"300x250"},
+ },
+ {
+ name: "banner_with_format",
+ args: args{
+ imp: openrtb2.Imp{
+ ID: "1",
+ Banner: &openrtb2.Banner{
+ W: ptrutil.ToPtr[int64](300),
+ H: ptrutil.ToPtr[int64](250),
+ Format: []openrtb2.Format{
+ {
+ W: 400,
+ H: 300,
+ },
+ },
+ },
+ },
+ },
+ want: []string{"300x250", "400x300"},
+ },
+ {
+ name: "only_video_slot",
+ args: args{
+ imp: openrtb2.Imp{
+ ID: "1",
+ Video: &openrtb2.Video{
+ W: 300,
+ H: 250,
+ },
+ },
+ },
+ want: []string{"300x250v"},
+ },
+ {
+ name: "all_slots",
+ args: args{
+ imp: openrtb2.Imp{
+ ID: "1",
+ Native: &openrtb2.Native{
+ Request: `{"ver":"1.2"}`,
+ },
+ Banner: &openrtb2.Banner{
+ W: ptrutil.ToPtr[int64](300),
+ H: ptrutil.ToPtr[int64](250),
+ Format: []openrtb2.Format{
+ {
+ W: 400,
+ H: 300,
+ },
+ },
+ },
+ Video: &openrtb2.Video{
+ W: 300,
+ H: 250,
+ },
+ },
+ },
+ want: []string{"300x250", "400x300", "300x250v"},
+ },
+ {
+ name: "duplicate_slot",
+ args: args{
+ imp: openrtb2.Imp{
+ ID: "1",
+ Banner: &openrtb2.Banner{
+ W: ptrutil.ToPtr[int64](300),
+ H: ptrutil.ToPtr[int64](250),
+ Format: []openrtb2.Format{
+ {
+ W: 300,
+ H: 250,
+ },
+ },
+ },
+ },
+ },
+ want: []string{"300x250"},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ slots := getIncomingSlots(tt.args.imp)
+ assert.ElementsMatch(t, tt.want, slots, "mismatched slots")
+ })
+ }
+}
diff --git a/modules/pubmatic/openwrap/models/adunitconfig/adunitconfig.go b/modules/pubmatic/openwrap/models/adunitconfig/adunitconfig.go
index 7e8ccc78917..bbe3bdb4807 100644
--- a/modules/pubmatic/openwrap/models/adunitconfig/adunitconfig.go
+++ b/modules/pubmatic/openwrap/models/adunitconfig/adunitconfig.go
@@ -72,13 +72,14 @@ type AdConfig struct {
BidFloorCur *string `json:"bidfloorcur,omitempty"`
Floors *openrtb_ext.PriceFloorRules `json:"floors,omitempty"`
- Exp *int `json:"exp,omitempty"`
- Banner *Banner `json:"banner,omitempty"`
- Native *Native `json:"native,omitempty"`
- Video *Video `json:"video,omitempty"`
- App *openrtb2.App `json:"app,omitempty"`
- Device *openrtb2.Device `json:"device,omitempty"`
- Transparency *Transparency `json:"transparency,omitempty"`
- Regex *bool `json:"regex,omitempty"`
- UniversalPixel []UniversalPixel `json:"universalpixel,omitempty"`
+ Exp *int `json:"exp,omitempty"`
+ Banner *Banner `json:"banner,omitempty"`
+ Native *Native `json:"native,omitempty"`
+ Video *Video `json:"video,omitempty"`
+ App *openrtb2.App `json:"app,omitempty"`
+ Device *openrtb2.Device `json:"device,omitempty"`
+ Transparency *Transparency `json:"transparency,omitempty"`
+ Regex *bool `json:"regex,omitempty"`
+ UniversalPixel []UniversalPixel `json:"universalpixel,omitempty"`
+ EnableGAMUrlLookup bool `json:"enablegamurllookup,omitempty"`
}
diff --git a/modules/pubmatic/openwrap/models/amp.go b/modules/pubmatic/openwrap/models/amp.go
index 1cd1a513b93..38e886ea19d 100644
--- a/modules/pubmatic/openwrap/models/amp.go
+++ b/modules/pubmatic/openwrap/models/amp.go
@@ -5,15 +5,15 @@ import (
"strconv"
)
-func GetQueryParamRequestExtWrapper(request *http.Request) (RequestExtWrapper, int, error) {
+func GetQueryParamRequestExtWrapper(request *http.Request) (RequestExtWrapper, error) {
extWrapper := RequestExtWrapper{
SSAuctionFlag: -1,
}
values := request.URL.Query()
- pubid, _ := strconv.Atoi(values.Get(PUBID_KEY))
+ extWrapper.PubId, _ = strconv.Atoi(values.Get(PUBID_KEY))
extWrapper.ProfileId, _ = strconv.Atoi(values.Get(PROFILEID_KEY))
extWrapper.VersionId, _ = strconv.Atoi(values.Get(VERSION_KEY))
- return extWrapper, pubid, nil
+ return extWrapper, nil
}
diff --git a/modules/pubmatic/openwrap/models/constants.go b/modules/pubmatic/openwrap/models/constants.go
index 935bf4f92d1..78be2effa15 100755
--- a/modules/pubmatic/openwrap/models/constants.go
+++ b/modules/pubmatic/openwrap/models/constants.go
@@ -31,6 +31,7 @@ const (
GDPR_ENABLED = "gdpr"
PLATFORM_KEY = "platform"
SendAllBidsKey = "sendAllBids"
+ VastUnwrapperEnableKey = "enableVastUnwrapper"
SSTimeoutKey = "ssTimeout"
PWC = "awc"
MAX_SLOT_COUNT = 5000
@@ -422,20 +423,21 @@ const (
)
const (
- EndpointV25 = "v25"
- EndpointAMP = "amp"
- EndpointVideo = "video"
- EndpointJson = "json"
- EndpointORTB = "ortb"
- EndpointVAST = "vast"
- EndpointWebS2S = "webs2s"
- EndPointCTV = "ctv"
- EndpointHybrid = "hybrid"
- Openwrap = "openwrap"
- ImpTypeBanner = "banner"
- ImpTypeVideo = "video"
- ContentTypeSite = "site"
- ContentTypeApp = "app"
+ EndpointV25 = "v25"
+ EndpointAMP = "amp"
+ EndpintInappVideo = "inappvideo"
+ EndpointVideo = "video"
+ EndpointJson = "json"
+ EndpointORTB = "ortb"
+ EndpointVAST = "vast"
+ EndpointWebS2S = "webs2s"
+ EndPointCTV = "ctv"
+ EndpointHybrid = "hybrid"
+ Openwrap = "openwrap"
+ ImpTypeBanner = "banner"
+ ImpTypeVideo = "video"
+ ContentTypeSite = "site"
+ ContentTypeApp = "app"
)
const (
diff --git a/modules/pubmatic/openwrap/models/device.go b/modules/pubmatic/openwrap/models/device.go
index 109c1a467f7..a6955241e5d 100644
--- a/modules/pubmatic/openwrap/models/device.go
+++ b/modules/pubmatic/openwrap/models/device.go
@@ -1,6 +1,9 @@
package models
-import "github.com/prebid/prebid-server/openrtb_ext"
+import (
+ "encoding/json"
+ "strings"
+)
const (
//Device.DeviceType values as per OpenRTB-API-Specification-Version-2-5
@@ -56,8 +59,96 @@ const (
DeviceIFATypeSESSIONID = "sessionid"
)
+// device.ext related keys
+const (
+ ExtDeviceIFAType = "ifa_type"
+ ExtDeviceSessionID = "session_id"
+ ExtDeviceAtts = "atts"
+)
+
+// ExtDevice will store device.ext parameters
type ExtDevice struct {
- openrtb_ext.ExtDevice
- SessionID string `json:"session_id,omitempty"`
- IDFV string `json:"idfv,omitempty"`
+ data map[string]any
+}
+
+func NewExtDevice() *ExtDevice {
+ return &ExtDevice{
+ data: make(map[string]any),
+ }
+}
+
+func (e *ExtDevice) UnmarshalJSON(data []byte) error {
+ var intermediate map[string]interface{}
+ if err := json.Unmarshal(data, &intermediate); err != nil {
+ return err
+ }
+ e.data = intermediate
+ return nil
+}
+
+func (e *ExtDevice) MarshalJSON() ([]byte, error) {
+ return json.Marshal(e.data)
+}
+
+func (e *ExtDevice) getStringValue(key string) (value string, found bool) {
+ if e.data == nil {
+ return value, found
+ }
+ val, found := e.data[key]
+ if !found {
+ return "", found
+ }
+ value, found = val.(string)
+ return strings.TrimSpace(value), found
+}
+
+func (e *ExtDevice) GetIFAType() (value string, found bool) {
+ return e.getStringValue(ExtDeviceIFAType)
+}
+
+func (e *ExtDevice) GetSessionID() (value string, found bool) {
+ return e.getStringValue(ExtDeviceSessionID)
+}
+
+func (e *ExtDevice) getFloatValue(key string) (value float64, found bool) {
+ if e.data == nil {
+ return value, found
+ }
+ val, found := e.data[key]
+ if !found {
+ return 0, found
+ }
+ value, found = val.(float64)
+ return value, found
+}
+
+func (e *ExtDevice) GetAtts() (value *float64, found bool) {
+ val, ok := e.getFloatValue(ExtDeviceAtts)
+ if !ok {
+ return nil, ok
+ }
+ return &val, ok
+}
+
+func (e *ExtDevice) setStringValue(key, value string) {
+ if e.data == nil {
+ e.data = make(map[string]any)
+ }
+ e.data[key] = value
+}
+
+func (e *ExtDevice) SetIFAType(ifaType string) {
+ e.setStringValue(ExtDeviceIFAType, ifaType)
+}
+
+func (e *ExtDevice) SetSessionID(sessionID string) {
+ e.setStringValue(ExtDeviceSessionID, sessionID)
+}
+
+func (e *ExtDevice) DeleteIFAType() {
+ delete(e.data, ExtDeviceIFAType)
+}
+
+func (e *ExtDevice) DeleteSessionID() {
+ delete(e.data, ExtDeviceSessionID)
}
diff --git a/modules/pubmatic/openwrap/models/request.go b/modules/pubmatic/openwrap/models/request.go
index c2ed52b042a..ef2c4059c2c 100644
--- a/modules/pubmatic/openwrap/models/request.go
+++ b/modules/pubmatic/openwrap/models/request.go
@@ -106,6 +106,7 @@ type RequestExtWrapper struct {
ABTestConfig int `json:"abtest,omitempty"`
LoggerImpressionID string `json:"wiid,omitempty"`
SSAI string `json:"ssai,omitempty"`
+ PubId int `json:"-"`
}
type BidderWrapper struct {
diff --git a/modules/pubmatic/openwrap/models/tracker.go b/modules/pubmatic/openwrap/models/tracker.go
index cbf73f63120..0b007471663 100644
--- a/modules/pubmatic/openwrap/models/tracker.go
+++ b/modules/pubmatic/openwrap/models/tracker.go
@@ -1,7 +1,5 @@
package models
-import "github.com/prebid/prebid-server/openrtb_ext"
-
// OWTracker vast video parameters to be injected
type OWTracker struct {
Tracker Tracker
@@ -39,7 +37,7 @@ type Tracker struct {
FloorSource *int
FloorType int
CustomDimensions string
- ATTS *openrtb_ext.IOSAppTrackingStatus
+ ATTS *float64
LoggerData LoggerData // need this in logger to avoid duplicate computation
ImpID string `json:"-"`
diff --git a/modules/pubmatic/openwrap/models/utils.go b/modules/pubmatic/openwrap/models/utils.go
index 5e1864eb98a..8281827b8f6 100644
--- a/modules/pubmatic/openwrap/models/utils.go
+++ b/modules/pubmatic/openwrap/models/utils.go
@@ -139,19 +139,14 @@ func GetRevenueShare(partnerConfig map[string]string) float64 {
func GetNetEcpm(price float64, revShare float64) float64 {
if revShare == 0 {
- return toFixed(price, BID_PRECISION)
+ return ToFixed(price, BID_PRECISION)
}
price = price * (1 - revShare/100)
- return toFixed(price, BID_PRECISION)
+ return ToFixed(price, BID_PRECISION)
}
func GetGrossEcpm(price float64) float64 {
- return toFixed(price, BID_PRECISION)
-}
-
-func toFixed(num float64, precision int) float64 {
- output := math.Pow(10, float64(precision))
- return float64(round(num*output)) / output
+ return ToFixed(price, BID_PRECISION)
}
func round(num float64) int {
@@ -413,3 +408,21 @@ func GetFloorsDetails(responseExt openrtb_ext.ExtBidResponse) (floorDetails Floo
}
return floorDetails
}
+
+func GetGrossEcpmFromNetEcpm(netEcpm float64, revShare float64) float64 {
+
+ if revShare == 100 {
+ return 0
+ }
+ originalBidPrice := netEcpm / (1 - revShare/100)
+ return ToFixed(originalBidPrice, BID_PRECISION)
+}
+
+func GetBidAdjustmentValue(revShare float64) float64 {
+ return (1 - revShare/100)
+}
+
+func ToFixed(num float64, precision int) float64 {
+ output := math.Pow(10, float64(precision))
+ return float64(round(num*output)) / output
+}
diff --git a/modules/pubmatic/openwrap/models/utils_test.go b/modules/pubmatic/openwrap/models/utils_test.go
index fe3870580f4..77ba2bb2f3b 100644
--- a/modules/pubmatic/openwrap/models/utils_test.go
+++ b/modules/pubmatic/openwrap/models/utils_test.go
@@ -1331,3 +1331,107 @@ func TestGetKGPSV(t *testing.T) {
})
}
}
+
+func TestGetGrossEcpmFromNetEcpm(t *testing.T) {
+ type args struct {
+ netEcpm float64
+ revShare float64
+ }
+ tests := []struct {
+ name string
+ args args
+ want float64
+ }{
+ {
+ name: "When netcpm is 100 and revShare is 0",
+ args: args{
+ netEcpm: 100,
+ revShare: 0,
+ },
+ want: 100,
+ },
+ {
+ name: "When netcpm is 0 and revShare is 100",
+ args: args{
+ netEcpm: 0,
+ revShare: 100,
+ },
+ want: 0,
+ },
+ {
+ name: "When netcpm is 100 and revShare is 50",
+ args: args{
+ netEcpm: 100,
+ revShare: 50,
+ },
+ want: 200,
+ },
+ {
+ name: "When netcpm is 80 and revShare is 20",
+ args: args{
+ netEcpm: 80,
+ revShare: 20,
+ },
+ want: 100,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := GetGrossEcpmFromNetEcpm(tt.args.netEcpm, tt.args.revShare); got != tt.want {
+ t.Errorf("GetGrossEcpmFromNetEcpm() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestToFixed(t *testing.T) {
+ type args struct {
+ num float64
+ precision int
+ }
+ tests := []struct {
+ name string
+ args args
+ want float64
+ }{
+ {
+ name: "Rounding of 0.1",
+ args: args{
+ num: 0.1,
+ precision: 2,
+ },
+ want: 0.10,
+ },
+ {
+ name: "Rounding of 0.1101",
+ args: args{
+ num: 0.1101,
+ precision: 2,
+ },
+ want: 0.11,
+ },
+ {
+ name: "Rounding of 0.10000000149011612",
+ args: args{
+ num: 0.10000000149011612,
+ precision: 2,
+ },
+ want: 0.10,
+ },
+ {
+ name: "Rounding of 0.10000000149011612",
+ args: args{
+ num: 0.10000000149011612,
+ precision: 3,
+ },
+ want: 0.100,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := ToFixed(tt.args.num, tt.args.precision); got != tt.want {
+ t.Errorf("toFixed() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
diff --git a/modules/pubmatic/openwrap/openwrap.go b/modules/pubmatic/openwrap/openwrap.go
index e29ea26f007..0193bb75ff0 100644
--- a/modules/pubmatic/openwrap/openwrap.go
+++ b/modules/pubmatic/openwrap/openwrap.go
@@ -8,6 +8,8 @@ import (
"strings"
"time"
+ "sync"
+
"github.com/golang/glog"
gocache "github.com/patrickmn/go-cache"
"github.com/prebid/prebid-server/currency"
@@ -35,7 +37,10 @@ type OpenWrap struct {
currencyConversion currency.Conversions
}
+var ow *OpenWrap
+
func initOpenWrap(rawCfg json.RawMessage, moduleDeps moduledeps.ModuleDeps) (OpenWrap, error) {
+ var once sync.Once
cfg := config.Config{}
err := json.Unmarshal(rawCfg, &cfg)
@@ -75,12 +80,15 @@ func initOpenWrap(rawCfg json.RawMessage, moduleDeps moduledeps.ModuleDeps) (Ope
// Init TBF (tracking-beacon-first) feature related services
tbf.Init(cfg.Cache.CacheDefaultExpiry, owCache)
- return OpenWrap{
- cfg: cfg,
- cache: owCache,
- metricEngine: &metricEngine,
- currencyConversion: moduleDeps.CurrencyConversion,
- }, nil
+ once.Do(func() {
+ ow = &OpenWrap{
+ cfg: cfg,
+ cache: owCache,
+ metricEngine: &metricEngine,
+ currencyConversion: moduleDeps.CurrencyConversion,
+ }
+ })
+ return *ow, nil
}
func open(driverName string, cfg config.Database) (*sql.DB, error) {
diff --git a/modules/pubmatic/openwrap/openwrap_sshb.go b/modules/pubmatic/openwrap/openwrap_sshb.go
index 057cc9d2bbb..6fbe8482c1c 100644
--- a/modules/pubmatic/openwrap/openwrap_sshb.go
+++ b/modules/pubmatic/openwrap/openwrap_sshb.go
@@ -1,9 +1,16 @@
package openwrap
import (
+ "github.com/prebid/openrtb/v19/openrtb2"
cache "github.com/prebid/prebid-server/modules/pubmatic/openwrap/cache"
"github.com/prebid/prebid-server/modules/pubmatic/openwrap/config"
metrics "github.com/prebid/prebid-server/modules/pubmatic/openwrap/metrics"
+ "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models"
+ vastmodels "github.com/prebid/prebid-server/modules/pubmatic/vastunwrap/models"
+)
+
+const (
+ VastUnwrapperEnableValue = "1"
)
// GetConfig Temporary function to expose config to SSHB
@@ -36,3 +43,19 @@ func (ow *OpenWrap) SetCache(c cache.Cache) {
func (ow *OpenWrap) SetMetricEngine(m metrics.MetricsEngine) {
ow.metricEngine = m
}
+
+// GetVastUnwrapEnabled function return vastunwrap flag from the database
+func GetVastUnwrapEnabled(rctx vastmodels.RequestCtx) bool {
+ rCtx := models.RequestCtx{
+ Endpoint: rctx.Endpoint,
+ PubID: rctx.PubID,
+ ProfileID: rctx.ProfileID,
+ DisplayID: rctx.DisplayID,
+ }
+ partnerConfigMap, err := ow.getProfileData(rCtx, openrtb2.BidRequest{})
+ if err != nil || len(partnerConfigMap) == 0 {
+ return false
+ }
+ rCtx.PartnerConfigMap = partnerConfigMap
+ return models.GetVersionLevelPropertyFromPartnerConfig(rCtx.PartnerConfigMap, models.VastUnwrapperEnableKey) == VastUnwrapperEnableValue
+}
diff --git a/modules/pubmatic/openwrap/tracker/create.go b/modules/pubmatic/openwrap/tracker/create.go
index a2a84f4aaaf..7d79ecb52f9 100644
--- a/modules/pubmatic/openwrap/tracker/create.go
+++ b/modules/pubmatic/openwrap/tracker/create.go
@@ -87,7 +87,7 @@ func createTrackers(rctx models.RequestCtx, trackers map[string]models.OWTracker
)
if rctx.DeviceCtx.Ext != nil {
- tracker.ATTS = rctx.DeviceCtx.Ext.ATTS
+ tracker.ATTS, _ = rctx.DeviceCtx.Ext.GetAtts()
}
if impCtx, ok := rctx.ImpBidCtx[bid.ImpID]; ok {
diff --git a/modules/pubmatic/openwrap/tracker/create_test.go b/modules/pubmatic/openwrap/tracker/create_test.go
index f5f38ec92d6..d47edc3f349 100644
--- a/modules/pubmatic/openwrap/tracker/create_test.go
+++ b/modules/pubmatic/openwrap/tracker/create_test.go
@@ -110,11 +110,11 @@ func Test_createTrackers(t *testing.T) {
rctx: func() models.RequestCtx {
testRctx := rctx
testRctx.StartTime = startTime
- testRctx.DeviceCtx.Ext = &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{
- ATTS: ptrutil.ToPtr(openrtb_ext.IOSAppTrackingStatusRestricted),
- },
- }
+ testRctx.DeviceCtx.Ext = func() *models.ExtDevice {
+ extDevice := models.ExtDevice{}
+ extDevice.UnmarshalJSON([]byte(`{"atts":1}`))
+ return &extDevice
+ }()
return testRctx
}(),
bidResponse: &openrtb2.BidResponse{
@@ -176,7 +176,7 @@ func Test_createTrackers(t *testing.T) {
KGPSV: "adunit-1@250x300",
},
CustomDimensions: "author=henry",
- ATTS: ptrutil.ToPtr(openrtb_ext.IOSAppTrackingStatusRestricted),
+ ATTS: ptrutil.ToPtr(float64(openrtb_ext.IOSAppTrackingStatusRestricted)),
},
TrackerURL: "https:?adv=domain.com&af=banner&aps=0&atts=1&au=adunit-1&bc=pubmatic&bidid=bidID-1&cds=author%3Dhenry&di=deal-id-1&dur=20&eg=8.7&en=8.7&frv=4.4&ft=0&fv=6.4&iid=loggerIID&kgpv=adunit-1%40250x300&orig=publisher.com&origbidid=bidID-1&pdvid=1&pid=1234&plt=5&pn=prebidBidderCode&psz=250x300&pubid=5890&purl=abc.com&sl=1&slot=impID-1_adunit-1&ss=1&ssai=mediatailor&tgid=1&tst=" + strconv.FormatInt(startTime, 10),
Price: 8.7,
diff --git a/modules/pubmatic/openwrap/tracker/tracker.go b/modules/pubmatic/openwrap/tracker/tracker.go
index 19ae629a190..1ea29ffe0c1 100644
--- a/modules/pubmatic/openwrap/tracker/tracker.go
+++ b/modules/pubmatic/openwrap/tracker/tracker.go
@@ -13,7 +13,7 @@ func GetTrackerInfo(rCtx models.RequestCtx, responseExt openrtb_ext.ExtBidRespon
tracker := models.Tracker{
PubID: rCtx.PubID,
ProfileID: fmt.Sprintf("%d", rCtx.ProfileID),
- VersionID: fmt.Sprintf("%d", rCtx.DisplayID),
+ VersionID: fmt.Sprintf("%d", rCtx.DisplayVersionID),
PageURL: rCtx.PageURL,
Timestamp: rCtx.StartTime,
IID: rCtx.LoggerImpressionID,
@@ -27,7 +27,7 @@ func GetTrackerInfo(rCtx models.RequestCtx, responseExt openrtb_ext.ExtBidRespon
}
if rCtx.DeviceCtx.Ext != nil {
- tracker.ATTS = rCtx.DeviceCtx.Ext.ATTS
+ tracker.ATTS, _ = rCtx.DeviceCtx.Ext.GetAtts()
}
constructedURLString := constructTrackerURL(rCtx, tracker)
diff --git a/modules/pubmatic/openwrap/tracker/tracker_test.go b/modules/pubmatic/openwrap/tracker/tracker_test.go
index e6289411af1..e6e78fe0a32 100644
--- a/modules/pubmatic/openwrap/tracker/tracker_test.go
+++ b/modules/pubmatic/openwrap/tracker/tracker_test.go
@@ -1,6 +1,7 @@
package tracker
import (
+ "encoding/json"
"strconv"
"testing"
"time"
@@ -8,6 +9,7 @@ import (
"github.com/prebid/prebid-server/modules/pubmatic/openwrap/models"
"github.com/prebid/prebid-server/openrtb_ext"
"github.com/prebid/prebid-server/util/ptrutil"
+ "github.com/stretchr/testify/assert"
)
func TestGetTrackerInfo(t *testing.T) {
@@ -28,6 +30,7 @@ func TestGetTrackerInfo(t *testing.T) {
TrackerEndpoint: "localhost:8080/wt",
PubID: 123,
ProfileID: 1,
+ DisplayVersionID: 2,
VersionID: 1,
PageURL: "www.test.com",
LoggerImpressionID: "iid123",
@@ -36,16 +39,16 @@ func TestGetTrackerInfo(t *testing.T) {
ABTestConfigApplied: 1,
DeviceCtx: models.DeviceCtx{
Platform: models.DevicePlatformMobileAppAndroid,
- Ext: &models.ExtDevice{
- ExtDevice: openrtb_ext.ExtDevice{
- ATTS: ptrutil.ToPtr(openrtb_ext.IOSAppTrackingStatusRestricted),
- },
- },
+ Ext: func() *models.ExtDevice {
+ extDevice := models.ExtDevice{}
+ json.Unmarshal([]byte(`{"atts":1}`), &extDevice)
+ return &extDevice
+ }(),
},
},
responseExt: openrtb_ext.ExtBidResponse{},
},
- want: "localhost:8080/wt?adv=&af=&aps=0&atts=1&au=%24%7BADUNIT%7D&bc=%24%7BBIDDER_CODE%7D&bidid=%24%7BBID_ID%7D&di=&eg=%24%7BG_ECPM%7D&en=%24%7BN_ECPM%7D&ft=0&iid=iid123&kgpv=%24%7BKGPV%7D&orig=www.publisher.com&origbidid=%24%7BORIGBID_ID%7D&pdvid=0&pid=1&plt=5&pn=%24%7BPARTNER_NAME%7D&psz=&pubid=123&purl=www.test.com&rwrd=%24%7BREWARDED%7D&sl=1&slot=%24%7BSLOT_ID%7D&ss=0&tgid=1&tst=" + strconv.FormatInt(startTime, 10),
+ want: "localhost:8080/wt?adv=&af=&aps=0&atts=1&au=%24%7BADUNIT%7D&bc=%24%7BBIDDER_CODE%7D&bidid=%24%7BBID_ID%7D&di=&eg=%24%7BG_ECPM%7D&en=%24%7BN_ECPM%7D&ft=0&iid=iid123&kgpv=%24%7BKGPV%7D&orig=www.publisher.com&origbidid=%24%7BORIGBID_ID%7D&pdvid=2&pid=1&plt=5&pn=%24%7BPARTNER_NAME%7D&psz=&pubid=123&purl=www.test.com&rwrd=%24%7BREWARDED%7D&sl=1&slot=%24%7BSLOT_ID%7D&ss=0&tgid=1&tst=" + strconv.FormatInt(startTime, 10),
},
{
name: "all_tracker_info_with_floors",
@@ -55,6 +58,7 @@ func TestGetTrackerInfo(t *testing.T) {
PubID: 123,
ProfileID: 1,
VersionID: 1,
+ DisplayVersionID: 2,
PageURL: "www.test.com",
LoggerImpressionID: "iid123",
StartTime: startTime,
@@ -83,14 +87,13 @@ func TestGetTrackerInfo(t *testing.T) {
},
},
},
- want: "localhost:8080/wt?adv=&af=&aps=0&au=%24%7BADUNIT%7D&bc=%24%7BBIDDER_CODE%7D&bidid=%24%7BBID_ID%7D&di=&eg=%24%7BG_ECPM%7D&en=%24%7BN_ECPM%7D&fmv=version+1&fskp=1&fsrc=2&ft=1&iid=iid123&kgpv=%24%7BKGPV%7D&orig=www.publisher.com&origbidid=%24%7BORIGBID_ID%7D&pdvid=0&pid=1&plt=5&pn=%24%7BPARTNER_NAME%7D&psz=&pubid=123&purl=www.test.com&rwrd=%24%7BREWARDED%7D&sl=1&slot=%24%7BSLOT_ID%7D&ss=0&tgid=1&tst=" + strconv.FormatInt(startTime, 10),
+ want: "localhost:8080/wt?adv=&af=&aps=0&au=%24%7BADUNIT%7D&bc=%24%7BBIDDER_CODE%7D&bidid=%24%7BBID_ID%7D&di=&eg=%24%7BG_ECPM%7D&en=%24%7BN_ECPM%7D&fmv=version+1&fskp=1&fsrc=2&ft=1&iid=iid123&kgpv=%24%7BKGPV%7D&orig=www.publisher.com&origbidid=%24%7BORIGBID_ID%7D&pdvid=2&pid=1&plt=5&pn=%24%7BPARTNER_NAME%7D&psz=&pubid=123&purl=www.test.com&rwrd=%24%7BREWARDED%7D&sl=1&slot=%24%7BSLOT_ID%7D&ss=0&tgid=1&tst=" + strconv.FormatInt(startTime, 10),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- if got := GetTrackerInfo(tt.args.rCtx, tt.args.responseExt); got != tt.want {
- t.Errorf("GetTrackerInfo() = %v, want %v", got, tt.want)
- }
+ got := GetTrackerInfo(tt.args.rCtx, tt.args.responseExt)
+ assert.Equal(t, tt.want, got)
})
}
}
diff --git a/modules/pubmatic/openwrap/util.go b/modules/pubmatic/openwrap/util.go
index 7c992ec89d5..26900e92ca8 100644
--- a/modules/pubmatic/openwrap/util.go
+++ b/modules/pubmatic/openwrap/util.go
@@ -27,7 +27,9 @@ var (
ctvRegex *regexp.Regexp
)
-const test = "_test"
+const (
+ test = "_test"
+)
func init() {
widthRegEx = regexp.MustCompile(models.MACRO_WIDTH)
diff --git a/modules/pubmatic/vastunwrap/constant.go b/modules/pubmatic/vastunwrap/constant.go
index d850198dc72..23bd1b38391 100644
--- a/modules/pubmatic/vastunwrap/constant.go
+++ b/modules/pubmatic/vastunwrap/constant.go
@@ -14,4 +14,8 @@ const (
ContentType = "Content-Type"
UnwrapTimeout = "unwrap-timeout"
MediaTypeVideo = "video"
+ ProfileId = "profileID"
+ VersionId = "versionID"
+ DisplayId = "DisplayID"
+ Endpoint = "Endpoint"
)
diff --git a/modules/pubmatic/vastunwrap/entryhook.go b/modules/pubmatic/vastunwrap/entryhook.go
index 6b9bcbaf462..8cb30effeab 100644
--- a/modules/pubmatic/vastunwrap/entryhook.go
+++ b/modules/pubmatic/vastunwrap/entryhook.go
@@ -2,11 +2,14 @@ package vastunwrap
import (
"context"
+ "fmt"
"math/rand"
"runtime/debug"
"github.com/golang/glog"
"github.com/prebid/prebid-server/hooks/hookstage"
+ "github.com/prebid/prebid-server/modules/pubmatic/openwrap"
+ ow_models "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models"
"github.com/prebid/prebid-server/modules/pubmatic/vastunwrap/models"
)
@@ -14,30 +17,52 @@ var getRandomNumber = func() int {
return rand.Intn(100)
}
+// supportedEndpoints holds the list of endpoints which supports VAST-unwrap feature
+var supportedEndpoints = map[string]struct{}{
+ ow_models.EndpointVAST: {},
+ ow_models.EndpointVideo: {},
+ ow_models.EndpointJson: {},
+ ow_models.EndpointV25: {},
+}
+
func getVastUnwrapperEnable(ctx context.Context, field string) bool {
vastEnableUnwrapper, _ := ctx.Value(field).(string)
return vastEnableUnwrapper == "1"
}
-
func handleEntrypointHook(
_ context.Context,
_ hookstage.ModuleInvocationContext,
- payload hookstage.EntrypointPayload, config VastUnwrapModule,
+ payload hookstage.EntrypointPayload,
) (hookstage.HookResult[hookstage.EntrypointPayload], error) {
defer func() {
if r := recover(); r != nil {
glog.Errorf("body:[%s] Error:[%v] stacktrace:[%s]", string(payload.Body), r, string(debug.Stack()))
}
}()
- result := hookstage.HookResult[hookstage.EntrypointPayload]{}
- vastRequestContext := models.RequestCtx{
- VastUnwrapEnabled: getVastUnwrapperEnable(payload.Request.Context(), VastUnwrapEnabled),
+ result := hookstage.HookResult[hookstage.EntrypointPayload]{
+ ModuleContext: make(hookstage.ModuleContext),
}
-
- if !vastRequestContext.VastUnwrapEnabled {
- vastRequestContext.VastUnwrapStatsEnabled = getRandomNumber() < config.StatTrafficPercentage
+ vastRequestContext := models.RequestCtx{}
+ queryParams := payload.Request.URL.Query()
+ source := queryParams.Get("source")
+ if queryParams.Get("sshb") == "1" {
+ vastRequestContext = models.RequestCtx{
+ VastUnwrapEnabled: getVastUnwrapperEnable(payload.Request.Context(), VastUnwrapEnabled),
+ Redirect: true,
+ }
+ } else {
+ endpoint := openwrap.GetEndpoint(payload.Request.URL.Path, source)
+ if _, ok := supportedEndpoints[endpoint]; !ok {
+ result.DebugMessages = append(result.DebugMessages, fmt.Sprintf("%s endpoint does not support vast-unwrap feature", endpoint))
+ return result, nil
+ }
+ requestExtWrapper, _ := openwrap.GetRequestWrapper(payload, result, endpoint)
+ vastRequestContext = models.RequestCtx{
+ ProfileID: requestExtWrapper.ProfileId,
+ DisplayID: requestExtWrapper.VersionId,
+ Endpoint: endpoint,
+ }
}
- result.ModuleContext = make(hookstage.ModuleContext)
result.ModuleContext[RequestContext] = vastRequestContext
return result, nil
}
diff --git a/modules/pubmatic/vastunwrap/entryhook_test.go b/modules/pubmatic/vastunwrap/entryhook_test.go
index 0ef9d120397..f3e6a71b359 100644
--- a/modules/pubmatic/vastunwrap/entryhook_test.go
+++ b/modules/pubmatic/vastunwrap/entryhook_test.go
@@ -3,65 +3,161 @@ package vastunwrap
import (
"context"
"net/http"
- "reflect"
"testing"
"github.com/prebid/prebid-server/hooks/hookstage"
+ ow_models "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models"
"github.com/prebid/prebid-server/modules/pubmatic/vastunwrap/models"
+ "github.com/stretchr/testify/assert"
)
func TestHandleEntrypointHook(t *testing.T) {
type args struct {
payload hookstage.EntrypointPayload
- config VastUnwrapModule
}
tests := []struct {
- name string
- args args
- randomNum int
- want hookstage.HookResult[hookstage.EntrypointPayload]
+ name string
+ args args
+ want hookstage.HookResult[hookstage.EntrypointPayload]
}{
{
- name: "Disable Vast Unwrapper",
+ name: "Disable Vast Unwrapper for CTV video/openrtb request",
args: args{
payload: hookstage.EntrypointPayload{
Request: func() *http.Request {
ctx := context.WithValue(context.Background(), VastUnwrapEnabled, "0")
- r, _ := http.NewRequestWithContext(ctx, "", "", nil)
+ ctx = context.WithValue(ctx, ProfileId, 0)
+ ctx = context.WithValue(ctx, VersionId, 0)
+ ctx = context.WithValue(ctx, DisplayId, 0)
+ ctx = context.WithValue(ctx, Endpoint, "")
+ r, _ := http.NewRequestWithContext(ctx, "POST", "http://localhost/video/openrtb?sshb=1", nil)
return r
}(),
},
- config: VastUnwrapModule{
- TrafficPercentage: 2,
- Enabled: false,
+ },
+ want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false, Redirect: true}}},
+ },
+ {
+ name: "Enable Vast Unwrapper for CTV video/openrtb request",
+ args: args{
+ payload: hookstage.EntrypointPayload{
+ Request: func() *http.Request {
+ ctx := context.WithValue(context.Background(), VastUnwrapEnabled, "1")
+ ctx = context.WithValue(ctx, ProfileId, 0)
+ ctx = context.WithValue(ctx, VersionId, 0)
+ ctx = context.WithValue(ctx, DisplayId, 0)
+ ctx = context.WithValue(ctx, Endpoint, "")
+ r, _ := http.NewRequestWithContext(ctx, "POST", "http://localhost/video/openrtb?sshb=1", nil)
+ return r
+ }(),
+ },
+ },
+ want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true, Redirect: true}}},
+ },
+ {
+ name: "Vast Unwrapper for IN-APP openrtb2/auction request",
+ args: args{
+ payload: hookstage.EntrypointPayload{
+ Request: func() *http.Request {
+ r, _ := http.NewRequest("POST", "http://localhost/openrtb2/auction?source=owsdk", nil)
+ return r
+ }(),
+ Body: []byte(`{"ext":{"wrapper":{"profileid":5890,"versionid":1}}}`),
},
},
- want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false}}},
+ want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false, Redirect: false, ProfileID: 5890, DisplayID: 1, Endpoint: ow_models.EndpointV25}}},
},
{
- name: "Enable Vast Unwrapper",
+ name: "Vast Unwrapper for IN-APP /openrtb/2.5 request coming from SSHB",
args: args{
payload: hookstage.EntrypointPayload{
Request: func() *http.Request {
ctx := context.WithValue(context.Background(), VastUnwrapEnabled, "1")
- r, _ := http.NewRequestWithContext(ctx, "", "", nil)
+ r, _ := http.NewRequestWithContext(ctx, "POST", "http://localhost/openrtb2/auction?sshb=1", nil)
return r
}(),
+ Body: []byte(`{"ext":{"wrapper":{"profileid":5890,"versionid":1}}}`),
},
- config: VastUnwrapModule{
- TrafficPercentage: 2,
+ },
+ want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true, Redirect: true, ProfileID: 0, DisplayID: 0, Endpoint: ""}}},
+ },
+ {
+ name: "Vast Unwrapper for IN-APP /openrtb/2.5 request directly coming to prebid",
+ args: args{
+ payload: hookstage.EntrypointPayload{
+ Request: func() *http.Request {
+ ctx := context.WithValue(context.Background(), VastUnwrapEnabled, "1")
+ r, _ := http.NewRequestWithContext(ctx, "POST", "http://localhost/openrtb/2.5", nil)
+ return r
+ }(),
+ Body: []byte(`{"ext":{"wrapper":{"profileid":5890,"versionid":1}}}`),
+ },
+ },
+ want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false, Redirect: false, ProfileID: 5890, DisplayID: 1, Endpoint: ow_models.EndpointV25}}},
+ },
+ {
+ name: "Vast Unwrapper for WebS2S activation request",
+ args: args{
+ payload: hookstage.EntrypointPayload{
+ Request: func() *http.Request {
+ ctx := context.WithValue(context.Background(), VastUnwrapEnabled, "1")
+ r, _ := http.NewRequestWithContext(ctx, "POST", "http://localhost/openrtb2/auction?source=pbjs", nil)
+ return r
+ }(),
+ Body: []byte(`{"ext":{"wrapper":{"profileid":5890,"versionid":1}}}`),
+ },
+ },
+ want: hookstage.HookResult[hookstage.EntrypointPayload]{
+ ModuleContext: hookstage.ModuleContext{},
+ DebugMessages: []string{"webs2s endpoint does not support vast-unwrap feature"},
+ },
+ },
+ {
+ name: "Vast Unwrapper for Hybrid request",
+ args: args{
+ payload: hookstage.EntrypointPayload{
+ Request: func() *http.Request {
+ ctx := context.WithValue(context.Background(), VastUnwrapEnabled, "1")
+ r, _ := http.NewRequestWithContext(ctx, "POST", "http://localhost:8001/pbs/openrtb2/auction", nil)
+ return r
+ }(),
+ Body: []byte(`{"ext":{"wrapper":{"profileid":5890,"versionid":1}}}`),
+ },
+ },
+ want: hookstage.HookResult[hookstage.EntrypointPayload]{
+ ModuleContext: hookstage.ModuleContext{},
+ DebugMessages: []string{"hybrid endpoint does not support vast-unwrap feature"},
+ },
+ },
+ {
+ name: "Vast Unwrapper for AMP request coming from SSHB",
+ args: args{
+ payload: hookstage.EntrypointPayload{
+ Request: func() *http.Request {
+ r, _ := http.NewRequest("GET", "http://localhost:8001/amp?sshb=1&v=1&w=300&h=250", nil)
+ return r
+ }(),
+ },
+ },
+ want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false, Redirect: true, Endpoint: ""}}},
+ },
+ {
+ name: "Vast Unwrapper for IN-APP OTT request coming from SSHB",
+ args: args{
+ payload: hookstage.EntrypointPayload{
+ Request: func() *http.Request {
+ r, _ := http.NewRequest("GET", "http://localhost:8001/openrtb/2.5/video?sshb=1&owLoggerDebug=1&pubId=5890&profId=2543", nil)
+ return r
+ }(),
},
},
- randomNum: 1,
- want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true}}},
+ want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false, Redirect: true, Endpoint: ""}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- got, _ := handleEntrypointHook(nil, hookstage.ModuleInvocationContext{}, tt.args.payload, tt.args.config)
- if !reflect.DeepEqual(got, tt.want) {
- t.Errorf("handleEntrypointHook() = %v, want %v", got, tt.want)
- }
+ got, _ := handleEntrypointHook(nil, hookstage.ModuleInvocationContext{}, tt.args.payload)
+ assert.Equal(t, tt.want, got, "mismatched handleEntrypointHook output")
})
}
}
diff --git a/modules/pubmatic/vastunwrap/hook_raw_bidder_response.go b/modules/pubmatic/vastunwrap/hook_raw_bidder_response.go
index 0d09dba143b..42149ca02e3 100644
--- a/modules/pubmatic/vastunwrap/hook_raw_bidder_response.go
+++ b/modules/pubmatic/vastunwrap/hook_raw_bidder_response.go
@@ -1,6 +1,8 @@
package vastunwrap
import (
+ "fmt"
+ "strconv"
"sync"
"github.com/prebid/prebid-server/adapters"
@@ -19,8 +21,21 @@ func (m VastUnwrapModule) handleRawBidderResponseHook(
result.DebugMessages = append(result.DebugMessages, "error: request-ctx not found in handleRawBidderResponseHook()")
return result, nil
}
+ vastUnwrapEnabled := vastRequestContext.VastUnwrapEnabled
+ if !vastRequestContext.Redirect {
+ pubId, _ := strconv.Atoi(miCtx.AccountID)
+ vastRequestContext.PubID = pubId
+ vastUnwrapEnabled = getRandomNumber() < m.TrafficPercentage && m.getVastUnwrapEnable(vastRequestContext)
+ result.DebugMessages = append(result.DebugMessages,
+ fmt.Sprintf("found request without sshb=1 in handleRawBidderResponseHook() for pubid:[%d]", vastRequestContext.PubID))
+ }
+
+ vastRequestContext.VastUnwrapEnabled = vastUnwrapEnabled
+ vastRequestContext.VastUnwrapStatsEnabled = getRandomNumber() < m.StatTrafficPercentage
+
if !vastRequestContext.VastUnwrapEnabled && !vastRequestContext.VastUnwrapStatsEnabled {
- result.DebugMessages = append(result.DebugMessages, "error: vast unwrap flag is not enabled in handleRawBidderResponseHook()")
+ result.DebugMessages = append(result.DebugMessages,
+ fmt.Sprintf("error: vast unwrap flag is not enabled in handleRawBidderResponseHook() for pubid:[%d]", vastRequestContext.PubID))
return result, nil
}
diff --git a/modules/pubmatic/vastunwrap/hook_raw_bidder_response_test.go b/modules/pubmatic/vastunwrap/hook_raw_bidder_response_test.go
index 74edcadc0e2..5ac49374be4 100644
--- a/modules/pubmatic/vastunwrap/hook_raw_bidder_response_test.go
+++ b/modules/pubmatic/vastunwrap/hook_raw_bidder_response_test.go
@@ -23,21 +23,25 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
mockMetricsEngine := mock_stats.NewMockMetricsEngine(ctrl)
VastUnWrapModule := VastUnwrapModule{Cfg: config.VastUnWrapCfg{MaxWrapperSupport: 5, StatConfig: unWrapCfg.StatConfig{Endpoint: "http://10.172.141.13:8080", RefershIntervalInSec: 1}, APPConfig: config.AppConfig{UnwrapDefaultTimeout: 1500}}, MetricsEngine: mockMetricsEngine}
type args struct {
- module VastUnwrapModule
- payload hookstage.RawBidderResponsePayload
- moduleInvocationCtx hookstage.ModuleInvocationContext
- unwrapTimeout int
- url string
- wantAdM bool
+ module VastUnwrapModule
+ payload hookstage.RawBidderResponsePayload
+ moduleInvocationCtx hookstage.ModuleInvocationContext
+ unwrapTimeout int
+ url string
+ wantAdM bool
+ randomNumber int
+ trafficPercentage int
+ statTrafficPercentage int
}
tests := []struct {
- name string
- args args
- wantResult hookstage.HookResult[hookstage.RawBidderResponsePayload]
- expectedBids []*adapters.TypedBid
- setup func()
- wantErr bool
- unwrapRequest func(w http.ResponseWriter, req *http.Request)
+ name string
+ args args
+ wantResult hookstage.HookResult[hookstage.RawBidderResponsePayload]
+ expectedBids []*adapters.TypedBid
+ setup func()
+ wantErr bool
+ unwrapRequest func(w http.ResponseWriter, req *http.Request)
+ getVastUnwrapEnable func(rctx models.RequestCtx) bool
}{
{
name: "Empty Request Context",
@@ -65,7 +69,7 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
BidType: "video",
}}},
- moduleInvocationCtx: hookstage.ModuleInvocationContext{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false}}},
+ moduleInvocationCtx: hookstage.ModuleInvocationContext{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false, Redirect: true}}},
},
wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
wantErr: false,
@@ -90,7 +94,9 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
}},
Bidder: "pubmatic",
},
- moduleInvocationCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false, VastUnwrapStatsEnabled: true}}},
+ moduleInvocationCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false, VastUnwrapStatsEnabled: true, Redirect: true}}},
+ statTrafficPercentage: 100,
+ randomNumber: 10,
},
wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
setup: func() {
@@ -128,7 +134,7 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
Bidder: "pubmatic",
},
- moduleInvocationCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true}}},
+ moduleInvocationCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true, Redirect: true}}},
url: UnwrapURL,
},
wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
@@ -164,7 +170,7 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
Bidder: "pubmatic",
},
- moduleInvocationCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true}}},
+ moduleInvocationCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true, Redirect: true}}},
url: UnwrapURL,
},
wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
@@ -214,9 +220,11 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
}},
Bidder: "pubmatic",
},
- moduleInvocationCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true}}},
+ moduleInvocationCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true, Redirect: true}}},
url: UnwrapURL,
wantAdM: true,
+ randomNumber: 10,
+ trafficPercentage: 100,
},
wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
setup: func() {
@@ -265,7 +273,7 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
}},
Bidder: "pubmatic",
},
- moduleInvocationCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true}}},
+ moduleInvocationCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true, Redirect: true}}},
url: UnwrapURL,
},
wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
@@ -308,17 +316,66 @@ func TestHandleRawBidderResponseHook(t *testing.T) {
},
wantErr: false,
},
+
+ {
+ name: "Set Vast Unwrapper to true in request context with type video and source owsdk",
+ args: args{
+ module: VastUnWrapModule,
+ payload: hookstage.RawBidderResponsePayload{
+ Bids: []*adapters.TypedBid{
+ {
+ Bid: &openrtb2.Bid{
+ ID: "Bid-123",
+ ImpID: fmt.Sprintf("div-adunit-%d", 123),
+ Price: 2.1,
+ AdM: vastXMLAdM,
+ CrID: "Cr-234",
+ W: 100,
+ H: 50,
+ },
+ BidType: "video",
+ },
+ },
+ Bidder: "pubmatic",
+ },
+ moduleInvocationCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{Redirect: false, ProfileID: 5890, DisplayID: 1, Endpoint: "/openrtb/video"}}},
+ url: UnwrapURL,
+ },
+ wantResult: hookstage.HookResult[hookstage.RawBidderResponsePayload]{Reject: false},
+ setup: func() {
+ mockMetricsEngine.EXPECT().RecordRequestStatus("5890", "pubmatic", "0").AnyTimes()
+ mockMetricsEngine.EXPECT().RecordWrapperCount("5890", "pubmatic", "1").AnyTimes()
+ mockMetricsEngine.EXPECT().RecordRequestTime("5890", "pubmatic", gomock.Any()).AnyTimes()
+ mockMetricsEngine.EXPECT().RecordUnwrapRespTime("5890", "1", gomock.Any()).AnyTimes()
+ },
+ unwrapRequest: func(w http.ResponseWriter, req *http.Request) {
+ w.Header().Add("unwrap-status", "0")
+ w.Header().Add("unwrap-count", "1")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(inlineXMLAdM))
+ },
+ getVastUnwrapEnable: func(rctx models.RequestCtx) bool {
+ return true
+ },
+ wantErr: false,
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.setup != nil {
tt.setup()
}
+ getRandomNumber = func() int {
+ return tt.args.randomNumber
+ }
m := VastUnwrapModule{
- Cfg: tt.args.module.Cfg,
- Enabled: true,
- MetricsEngine: mockMetricsEngine,
- unwrapRequest: tt.unwrapRequest,
+ Cfg: tt.args.module.Cfg,
+ Enabled: true,
+ MetricsEngine: mockMetricsEngine,
+ unwrapRequest: tt.unwrapRequest,
+ getVastUnwrapEnable: tt.getVastUnwrapEnable,
+ TrafficPercentage: tt.args.trafficPercentage,
+ StatTrafficPercentage: tt.args.statTrafficPercentage,
}
_, err := m.handleRawBidderResponseHook(tt.args.moduleInvocationCtx, tt.args.payload, "test")
if !assert.NoError(t, err, tt.wantErr) {
diff --git a/modules/pubmatic/vastunwrap/models/request.go b/modules/pubmatic/vastunwrap/models/request.go
index 60dc655a600..fcc9ed4fac9 100644
--- a/modules/pubmatic/vastunwrap/models/request.go
+++ b/modules/pubmatic/vastunwrap/models/request.go
@@ -1,7 +1,10 @@
package models
type RequestCtx struct {
- UA string
- VastUnwrapEnabled bool
- VastUnwrapStatsEnabled bool
+ UA string
+ VastUnwrapEnabled bool
+ PubID, ProfileID, DisplayID int
+ Endpoint string
+ VastUnwrapStatsEnabled bool
+ Redirect bool
}
diff --git a/modules/pubmatic/vastunwrap/module.go b/modules/pubmatic/vastunwrap/module.go
index e98d5cf58b4..9e98fe348b6 100644
--- a/modules/pubmatic/vastunwrap/module.go
+++ b/modules/pubmatic/vastunwrap/module.go
@@ -13,6 +13,8 @@ import (
"github.com/golang/glog"
"github.com/prebid/prebid-server/hooks/hookstage"
"github.com/prebid/prebid-server/modules/moduledeps"
+ openwrap "github.com/prebid/prebid-server/modules/pubmatic/openwrap"
+ "github.com/prebid/prebid-server/modules/pubmatic/vastunwrap/models"
metrics "github.com/prebid/prebid-server/modules/pubmatic/vastunwrap/stats"
)
@@ -23,6 +25,7 @@ type VastUnwrapModule struct {
Enabled bool `mapstructure:"enabled" json:"enabled"`
MetricsEngine metrics.MetricsEngine
unwrapRequest func(w http.ResponseWriter, r *http.Request)
+ getVastUnwrapEnable func(rctx models.RequestCtx) bool
}
func Builder(rawCfg json.RawMessage, deps moduledeps.ModuleDeps) (interface{}, error) {
@@ -49,6 +52,7 @@ func initVastUnwrap(rawCfg json.RawMessage, deps moduledeps.ModuleDeps) (VastUnw
Enabled: vastUnwrapModuleCfg.Enabled,
MetricsEngine: metricEngine,
unwrapRequest: vastunwrap.UnwrapRequest,
+ getVastUnwrapEnable: openwrap.GetVastUnwrapEnabled,
}, nil
}
@@ -71,7 +75,7 @@ func (m VastUnwrapModule) HandleEntrypointHook(
payload hookstage.EntrypointPayload,
) (hookstage.HookResult[hookstage.EntrypointPayload], error) {
if m.Enabled {
- return handleEntrypointHook(ctx, miCtx, payload, m)
+ return handleEntrypointHook(ctx, miCtx, payload)
}
return hookstage.HookResult[hookstage.EntrypointPayload]{}, nil
}
diff --git a/modules/pubmatic/vastunwrap/module_test.go b/modules/pubmatic/vastunwrap/module_test.go
index 8269a386b5e..cb4d7804313 100644
--- a/modules/pubmatic/vastunwrap/module_test.go
+++ b/modules/pubmatic/vastunwrap/module_test.go
@@ -53,15 +53,15 @@ func TestVastUnwrapModuleHandleEntrypointHook(t *testing.T) {
},
TrafficPercentage: 2}},
args: args{
- miCtx: hookstage.ModuleInvocationContext{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true}}},
+ miCtx: hookstage.ModuleInvocationContext{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true, Redirect: true}}},
payload: hookstage.EntrypointPayload{
Request: func() *http.Request {
ctx := context.WithValue(context.Background(), VastUnwrapEnabled, "1")
- r, _ := http.NewRequestWithContext(ctx, "", "", nil)
+ r, _ := http.NewRequestWithContext(ctx, "POST", "http://localhost/video/openrtb?sshb=1", nil)
return r
}(),
}},
- want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true}}},
+ want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true, Redirect: true}}},
},
{
name: "Vast unwrap is disabled in the config",
@@ -78,7 +78,7 @@ func TestVastUnwrapModuleHandleEntrypointHook(t *testing.T) {
payload: hookstage.EntrypointPayload{
Request: func() *http.Request {
ctx := context.WithValue(context.Background(), VastUnwrapEnabled, "1")
- r, _ := http.NewRequestWithContext(ctx, "", "", nil)
+ r, _ := http.NewRequestWithContext(ctx, "POST", "http://localhost/video/openrtb?sshb=1", nil)
return r
}(),
}},
@@ -111,10 +111,11 @@ func TestVastUnwrapModuleHandleRawBidderResponseHook(t *testing.T) {
cfg VastUnwrapModule
}
type args struct {
- in0 context.Context
- miCtx hookstage.ModuleInvocationContext
- payload hookstage.RawBidderResponsePayload
- wantAdM bool
+ in0 context.Context
+ miCtx hookstage.ModuleInvocationContext
+ payload hookstage.RawBidderResponsePayload
+ wantAdM bool
+ randomNumber int
}
tests := []struct {
name string
@@ -134,9 +135,9 @@ func TestVastUnwrapModuleHandleRawBidderResponseHook(t *testing.T) {
StatConfig: unWrapCfg.StatConfig{Endpoint: "http://10.172.141.13:8080", RefershIntervalInSec: 1},
ServerConfig: unWrapCfg.ServerConfig{ServerName: "", DCName: "OW_DC"},
},
- TrafficPercentage: 2}},
+ TrafficPercentage: 100}},
args: args{
- miCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true}}},
+ miCtx: hookstage.ModuleInvocationContext{AccountID: "5890", ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true, Redirect: true}}},
payload: hookstage.RawBidderResponsePayload{
Bids: []*adapters.TypedBid{
{
@@ -153,7 +154,8 @@ func TestVastUnwrapModuleHandleRawBidderResponseHook(t *testing.T) {
}},
Bidder: "pubmatic",
},
- wantAdM: true,
+ wantAdM: true,
+ randomNumber: 10,
},
setup: func() {
mockMetricsEngine.EXPECT().RecordRequestStatus("5890", "pubmatic", "0")
@@ -205,11 +207,15 @@ func TestVastUnwrapModuleHandleRawBidderResponseHook(t *testing.T) {
if tt.setup != nil {
tt.setup()
}
+ getRandomNumber = func() int {
+ return tt.args.randomNumber
+ }
m := VastUnwrapModule{
- Cfg: tt.fields.cfg.Cfg,
- Enabled: tt.fields.cfg.Enabled,
- MetricsEngine: mockMetricsEngine,
- unwrapRequest: tt.unwrapRequest,
+ Cfg: tt.fields.cfg.Cfg,
+ Enabled: tt.fields.cfg.Enabled,
+ MetricsEngine: mockMetricsEngine,
+ unwrapRequest: tt.unwrapRequest,
+ TrafficPercentage: tt.fields.cfg.TrafficPercentage,
}
_, err := m.HandleRawBidderResponseHook(tt.args.in0, tt.args.miCtx, tt.args.payload)
if !assert.NoError(t, err, tt.wantErr) {