From 609636e7790fc321c305a0e181f470cab593c2b8 Mon Sep 17 00:00:00 2001 From: Nick Jacob Date: Wed, 5 Mar 2025 16:31:29 -0500 Subject: [PATCH 1/3] Work in progress: implementation of alternate bidder codes --- .../server/auction/BidResponseCreator.java | 140 +++++++++++++----- .../server/auction/ExchangeService.java | 4 + .../Ortb2ImplicitParametersResolver.java | 7 + .../prebid/server/bidder/amx/AmxBidder.java | 4 +- .../prebid/server/bidder/model/BidderBid.java | 13 +- .../ExtRequestAlternateBidderCodes.java | 21 +++ .../ExtRequestAlternateBidderCodesBidder.java | 15 ++ .../openrtb/ext/request/ExtRequestPrebid.java | 5 + .../settings/model/AccountAuctionConfig.java | 4 + src/main/resources/application.yaml | 1 + 10 files changed, 170 insertions(+), 44 deletions(-) create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestAlternateBidderCodes.java create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestAlternateBidderCodesBidder.java diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index 4242281a5dd..b7f48750c2a 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -29,6 +29,7 @@ import org.prebid.server.auction.model.BidInfo; import org.prebid.server.auction.model.BidRejectionTracker; import org.prebid.server.auction.model.BidRequestCacheInfo; +import org.prebid.server.auction.model.BidderRequest; import org.prebid.server.auction.model.BidderResponse; import org.prebid.server.auction.model.BidderResponseInfo; import org.prebid.server.auction.model.CachedDebugLog; @@ -74,6 +75,8 @@ import org.prebid.server.proto.openrtb.ext.request.ExtOptions; import org.prebid.server.proto.openrtb.ext.request.ExtPriceGranularity; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestAlternateBidderCodes; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestAlternateBidderCodesBidder; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidChannel; import org.prebid.server.proto.openrtb.ext.request.ExtRequestTargeting; @@ -106,6 +109,7 @@ import org.prebid.server.settings.model.AccountTargetingConfig; import org.prebid.server.settings.model.VideoStoredDataResult; import org.prebid.server.spring.config.model.CacheDefaultTtlProperties; +import org.prebid.server.util.ObjectUtil; import org.prebid.server.util.StreamUtil; import org.prebid.server.vast.VastModifier; @@ -265,6 +269,18 @@ private Future create(VideoStoredDataResult videoStoredDataResult, eventsContext)); } + private String seatForBid(Set allowedAlternateBidderCodes, String bidder, String wantedSeat) { + if (allowedAlternateBidderCodes == null || wantedSeat == null) { + return bidder; + } + + if (allowedAlternateBidderCodes.contains(wantedSeat) || allowedAlternateBidderCodes.contains("*")) { + return wantedSeat; + } + + return bidder; + } + private Future> updateBids(List bidderResponses, VideoStoredDataResult videoStoredDataResult, AuctionContext auctionContext, @@ -274,6 +290,7 @@ private Future> updateBids(List bidderRespo for (final BidderResponse bidderResponse : bidderResponses) { final String bidder = bidderResponse.getBidder(); + final Set allowedAlternateBidderCodes = alternateBidderCodesForBidder(bidder, auctionContext.getBidRequest()): final List modifiedBidderBids = new ArrayList<>(); final BidderSeatBid seatBid = bidderResponse.getSeatBid(); @@ -283,10 +300,14 @@ private Future> updateBids(List bidderRespo final Bid updatedBid = updateBid( receivedBid, bidType, bidder, videoStoredDataResult, auctionContext, eventsContext); - modifiedBidderBids.add(bidderBid.toBuilder().bid(updatedBid).build()); + + modifiedBidderBids.add(bidderBid.toBuilder().bid(updatedBid) + .seat(seatForBid(allowedAlternateBidderCodes, bidder, bidderBid.getSeat())) + .build()); } final BidderSeatBid modifiedSeatBid = seatBid.with(modifiedBidderBids); + result.add(bidderResponse.with(modifiedSeatBid)); } @@ -406,6 +427,31 @@ private ExtBidPrebid updateBidExtPrebid(Bid bid, .build(); } + private Set alternateBidderCodesForBidder(String bidder, BidRequest bidRequest) { + final ExtRequestAlternateBidderCodes alternateBidderCodes = ObjectUtil.getIfNotNull(bidRequest.getExt().getPrebid(), ExtRequestPrebid::getAlternatebiddercodes); + + if (alternateBidderCodes == null) { + return null; + } + + if (!alternateBidderCodes.getEnabled()) { + return null; + } + + final Map alternateBidderCodesBidderMap = alternateBidderCodes.getBidders(); + if (alternateBidderCodesBidderMap == null) { + return null; + } + + final ExtRequestAlternateBidderCodesBidder alternateBidderCodesBidder = alternateBidderCodesBidderMap.get(bidder); + if (alternateBidderCodesBidder == null || !alternateBidderCodesBidder.getEnabled()) { + return null; + } + + final List allowedAlternates = alternateBidderCodesBidder.getAllowedBidderCodes(); + return allowedAlternates != null ? new HashSet<>(allowedAlternates) : null; + } + /** * Checks whether bidder responses are empty or contain no bids. */ @@ -425,15 +471,13 @@ private List toBidderResponseInfos(CategoryMappingResult cat final List bidderResponses = categoryMappingResult.getBidderResponses(); for (final BidderResponse bidderResponse : bidderResponses) { - final String bidder = bidderResponse.getBidder(); - final List bidInfos = new ArrayList<>(); final BidderSeatBid seatBid = bidderResponse.getSeatBid(); for (final BidderBid bidderBid : seatBid.getBids()) { final Bid bid = bidderBid.getBid(); final BidType type = bidderBid.getType(); - final BidInfo bidInfo = toBidInfo(bid, type, imps, bidder, categoryMappingResult, cacheInfo, account); + final BidInfo bidInfo = toBidInfo(bid, type, imps, bidderBid.getSeat(), categoryMappingResult, cacheInfo, account); bidInfos.add(bidInfo); } @@ -445,6 +489,7 @@ private List toBidderResponseInfos(CategoryMappingResult cat seatBid.getFledgeAuctionConfigs(), seatBid.getIgi()); + final String bidder = bidderResponse.getBidder(); result.add(BidderResponseInfo.of(bidder, bidderSeatBidInfo, bidderResponse.getResponseTime())); } @@ -1339,7 +1384,7 @@ private BidResponse toBidResponse(List bidderResponseInfos, .map(BidderResponseInfo::getSeatBid) .map(BidderSeatBidInfo::getBidsInfos) .filter(CollectionUtils::isNotEmpty) - .map(bidInfos -> toSeatBid( + .flatMap(bidInfos -> toSeatBids( bidInfos, targeting, bidRequest, @@ -1417,45 +1462,58 @@ private boolean checkEchoVideoAttrs(Imp imp) { } /** - * Creates an OpenRTB {@link SeatBid} for a bidder. It will contain all the bids supplied by a bidder and a "bidder" - * extension field populated. + * Creates a OpenRTB {@link SeatBid}s for a bidder. It will contain all the bids supplied by a bidder and a "bidder" + * extension field populated. Will return a list of a single SeatBid unless the bids have overriden the "bidder". */ - private SeatBid toSeatBid(List bidInfos, - ExtRequestTargeting targeting, - BidRequest bidRequest, - BidRequestCacheInfo requestCacheInfo, - Map bidToCacheInfo, - Account account, - Map> bidErrors, - Map> bidWarnings) { - - final String bidder = bidInfos.stream() - .map(BidInfo::getBidder) - .findFirst() - // Should never occur - .orElseThrow(() -> new IllegalArgumentException("Bidder was not defined for bidInfo")); + private Stream toSeatBids(List bidInfos, + ExtRequestTargeting targeting, + BidRequest bidRequest, + BidRequestCacheInfo requestCacheInfo, + Map bidToCacheInfo, + Account account, + Map> bidErrors, + Map> bidWarnings) { + + final Map> bidsByBidder = new HashMap<>(1); + + for (BidInfo bidInfo : bidInfos) { + bidInfo = injectAdmWithCacheInfo( + bidInfo, + requestCacheInfo, + bidToCacheInfo, + bidErrors); + + if (bidInfo == null) { + continue; + } - final List bids = bidInfos.stream() - .map(bidInfo -> injectAdmWithCacheInfo( - bidInfo, - requestCacheInfo, - bidToCacheInfo, - bidErrors)) - .filter(Objects::nonNull) - .map(bidInfo -> toBid( - bidInfo, - targeting, - bidRequest, - account, - bidWarnings)) - .filter(Objects::nonNull) - .toList(); + final String bidder = bidInfo.getBidder(); + if (bidder == null) { + logger.warn("BidInfo missing bidder, skipping bid", bidInfo); + continue; + } - return SeatBid.builder() - .seat(bidder) - .bid(bids) - .group(0) // prebid cannot support roadblocking - .build(); + final Bid bid = toBid( + bidInfo, + targeting, + bidRequest, + account, + bidWarnings); + + if (bid == null) { + continue; + } + + bidsByBidder.putIfAbsent(bidder, new ArrayList<>(1)).add(bid); + } + + return bidsByBidder.entrySet().stream() + .map((kvp) -> + SeatBid.builder() + .seat(kvp.getKey()) + .bid(kvp.getValue()) + .group(0) // prebid cannot support roadblocking + .build()); } private BidInfo injectAdmWithCacheInfo(BidInfo bidInfo, diff --git a/src/main/java/org/prebid/server/auction/ExchangeService.java b/src/main/java/org/prebid/server/auction/ExchangeService.java index 56cd8192501..2a896af5b5d 100644 --- a/src/main/java/org/prebid/server/auction/ExchangeService.java +++ b/src/main/java/org/prebid/server/auction/ExchangeService.java @@ -78,6 +78,8 @@ import org.prebid.server.proto.openrtb.ext.request.ExtBidderConfigOrtb; import org.prebid.server.proto.openrtb.ext.request.ExtDooh; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestAlternateBidderCodes; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestAlternateBidderCodesBidder; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidBidderConfig; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidCache; @@ -91,6 +93,7 @@ import org.prebid.server.settings.model.Account; import org.prebid.server.util.HttpUtil; import org.prebid.server.util.ListUtil; +import org.prebid.server.util.ObjectUtil; import org.prebid.server.util.PbsUtil; import org.prebid.server.util.StreamUtil; @@ -1201,6 +1204,7 @@ private Future requestBids(BidderRequest bidderRequest, final CaseInsensitiveMultiMap requestHeaders = auctionContext.getHttpRequest().getHeaders(); final String bidderName = bidderRequest.getBidder(); + final String resolvedBidderName = aliases.resolveBidder(bidderName); final Bidder bidder = bidderCatalog.bidderByName(resolvedBidderName); final long bidderTmaxDeductionMs = bidderCatalog.bidderInfoByName(resolvedBidderName).getTmaxDeductionMs(); diff --git a/src/main/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolver.java b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolver.java index 5bcabe413db..d5ed7a1065d 100644 --- a/src/main/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolver.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolver.java @@ -49,6 +49,7 @@ import org.prebid.server.proto.openrtb.ext.request.ExtMediaTypePriceGranularity; import org.prebid.server.proto.openrtb.ext.request.ExtPriceGranularity; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestAlternateBidderCodes; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidCache; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidChannel; @@ -726,6 +727,8 @@ private ExtRequest populateRequestExt(ExtRequest ext, Account account) { final ExtRequestPrebid prebid = ObjectUtil.getIfNotNull(ext, ExtRequest::getPrebid); + final ExtRequestAlternateBidderCodes accountAlternateBidderCodes = ObjectUtil.getIfNotNull( + ObjectUtil.getIfNotNull(account, Account::getAuction), AccountAuctionConfig::getAlternateBidderCodes); final ExtRequestTargeting updatedTargeting = targetingOrNull(prebid, imps, account); final ExtRequestPrebidCache updatedCache = cacheOrNull(prebid); @@ -742,6 +745,10 @@ private ExtRequest populateRequestExt(ExtRequest ext, ObjectUtil.getIfNotNull(prebid, ExtRequestPrebid::getCache))) .channel(ObjectUtils.defaultIfNull(updatedChannel, ObjectUtil.getIfNotNull(prebid, ExtRequestPrebid::getChannel))) + .alternatebiddercodes(ObjectUtils.defaultIfNull( + ObjectUtil.getIfNotNull(prebid, ExtRequestPrebid::getAlternatebiddercodes), + accountAlternateBidderCodes + )) .server(serverInfo.with(endpoint)) .build()); diff --git a/src/main/java/org/prebid/server/bidder/amx/AmxBidder.java b/src/main/java/org/prebid/server/bidder/amx/AmxBidder.java index bed5622ec06..b8247664b74 100644 --- a/src/main/java/org/prebid/server/bidder/amx/AmxBidder.java +++ b/src/main/java/org/prebid/server/bidder/amx/AmxBidder.java @@ -173,8 +173,8 @@ private BidderBid createBidderBid(Bid bid, String cur, List errors) errors.add(BidderError.badInput(e.getMessage())); return null; } - // TODO: After adding support to change seat data, add bid.ext bidderCode processing - return BidderBid.of(resolveBid(bid, amxBidExt.getDemandSource()), getBidType(amxBidExt), cur); + + return BidderBid.of(resolveBid(bid, amxBidExt.getDemandSource()), getBidType(amxBidExt), cur, amxBidExt.getBidderCode()); } private AmxBidExt parseBidderExt(ObjectNode ext) { diff --git a/src/main/java/org/prebid/server/bidder/model/BidderBid.java b/src/main/java/org/prebid/server/bidder/model/BidderBid.java index ef4b18eaa2d..ee9ecd48776 100644 --- a/src/main/java/org/prebid/server/bidder/model/BidderBid.java +++ b/src/main/java/org/prebid/server/bidder/model/BidderBid.java @@ -45,11 +45,22 @@ public class BidderBid { */ PriceFloorInfo priceFloorInfo; - public static BidderBid of(Bid bid, BidType bidType, String bidCurrency) { + /** + * The seat, which will override the default seat (e.g. the bidder name) + * if alternate-bidder-codes (ext.prebid.alternatebiddercodes) are allowed + */ + String seat; + + public static BidderBid of(Bid bid, BidType bidType, String bidCurrency, String seat) { return BidderBid.builder() .bid(bid) .type(bidType) .bidCurrency(bidCurrency) + .seat(seat) .build(); } + + public static BidderBid of(Bid bid, BidType bidType, String bidCurrency) { + return of(bid, bidType, bidCurrency, null); + } } diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestAlternateBidderCodes.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestAlternateBidderCodes.java new file mode 100644 index 00000000000..5f5e46571ff --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestAlternateBidderCodes.java @@ -0,0 +1,21 @@ +package org.prebid.server.proto.openrtb.ext.request; + +import lombok.Builder; +import lombok.Value; + +import java.util.Map; + + +/** + * Defines the contract for bidrequest.ext.prebid.alternatebiddercodes + */ +@Builder(toBuilder = true) +@Value +public class ExtRequestAlternateBidderCodes { + /** + * Is this feature enabled + */ + Boolean enabled; + + Map bidders; +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestAlternateBidderCodesBidder.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestAlternateBidderCodesBidder.java new file mode 100644 index 00000000000..4d32ab69527 --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestAlternateBidderCodesBidder.java @@ -0,0 +1,15 @@ +package org.prebid.server.proto.openrtb.ext.request; + +import lombok.Builder; +import lombok.Value; + +import java.util.List; + +@Builder(toBuilder = true) +@Value +public class ExtRequestAlternateBidderCodesBidder { + + Boolean enabled; + + List allowedBidderCodes; +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java index 33b326b2638..9460cb18951 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java @@ -41,6 +41,11 @@ public class ExtRequestPrebid { */ Map aliases; + /** + * Defines the contract for bidrequest.ext.prebid.alternatebiddercodes + */ + ExtRequestAlternateBidderCodes alternatebiddercodes; + /** * Defines the contract for bidrequest.ext.prebid.aliasgvlids */ diff --git a/src/main/java/org/prebid/server/settings/model/AccountAuctionConfig.java b/src/main/java/org/prebid/server/settings/model/AccountAuctionConfig.java index ac7da04dd31..73ba0a3f126 100644 --- a/src/main/java/org/prebid/server/settings/model/AccountAuctionConfig.java +++ b/src/main/java/org/prebid/server/settings/model/AccountAuctionConfig.java @@ -6,6 +6,7 @@ import lombok.Builder; import lombok.Value; import org.prebid.server.auction.model.PaaFormat; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestAlternateBidderCodes; import org.prebid.server.spring.config.bidder.model.MediaType; import java.util.Map; @@ -32,6 +33,9 @@ public class AccountAuctionConfig { @JsonAlias("debug-allow") Boolean debugAllow; + @JsonAlias("alternate-bidder-codes") + ExtRequestAlternateBidderCodes alternateBidderCodes; + @JsonAlias("bid-validations") AccountBidValidationConfig bidValidations; diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 64ce4e516a4..602fa78f83b 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -102,6 +102,7 @@ adapter-defaults: allow: true auction: ad-server-currency: USD + alternate-bidder-codes: blocklisted-accounts: blocklisted-apps: biddertmax: From 65e89f249bb3a6764936ec2aa4d539d816248c24 Mon Sep 17 00:00:00 2001 From: Nick Jacob Date: Wed, 5 Mar 2025 16:43:44 -0500 Subject: [PATCH 2/3] working implementation, needs tests --- .../auction/AllowedAlternateBidderCodes.java | 64 +++++++++++++++++++ .../server/auction/BidResponseCreator.java | 52 ++------------- .../server/auction/ExchangeService.java | 3 - .../prebid/server/bidder/amx/AmxBidder.java | 4 +- .../ExtRequestAlternateBidderCodes.java | 1 + .../server/bidder/amx/AmxBidderTest.java | 6 ++ 6 files changed, 81 insertions(+), 49 deletions(-) create mode 100644 src/main/java/org/prebid/server/auction/AllowedAlternateBidderCodes.java diff --git a/src/main/java/org/prebid/server/auction/AllowedAlternateBidderCodes.java b/src/main/java/org/prebid/server/auction/AllowedAlternateBidderCodes.java new file mode 100644 index 00000000000..14abc3761a1 --- /dev/null +++ b/src/main/java/org/prebid/server/auction/AllowedAlternateBidderCodes.java @@ -0,0 +1,64 @@ +package org.prebid.server.auction; + +import com.iab.openrtb.request.BidRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestAlternateBidderCodes; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestAlternateBidderCodesBidder; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; +import org.prebid.server.util.ObjectUtil; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Helper class for applying the allow-alternate-bidder-codes configuration + */ +public class AllowedAlternateBidderCodes { + + private static final String WILDCARD = "*"; + + private AllowedAlternateBidderCodes() { } + + public static Set allowedCodesForBidder(String bidder, BidRequest bidRequest) { + final ExtRequestAlternateBidderCodes alternateBidderCodes = ObjectUtil.getIfNotNull( + bidRequest.getExt().getPrebid(), ExtRequestPrebid::getAlternatebiddercodes); + + if (alternateBidderCodes == null) { + return null; + } + + if (!alternateBidderCodes.getEnabled()) { + return null; + } + + final Map alternateBidderCodesBidderMap = + alternateBidderCodes.getBidders(); + + if (alternateBidderCodesBidderMap == null) { + return null; + } + + final ExtRequestAlternateBidderCodesBidder alternateBidderCodesBidder = + alternateBidderCodesBidderMap.get(bidder); + + if (alternateBidderCodesBidder == null || !alternateBidderCodesBidder.getEnabled()) { + return null; + } + + final List allowedAlternates = alternateBidderCodesBidder.getAllowedBidderCodes(); + return allowedAlternates != null ? new HashSet<>(allowedAlternates) : null; + } + + public static String applySeatForBid(Set allowedAlternateBidderCodes, String bidder, String wantedSeat) { + if (allowedAlternateBidderCodes == null || wantedSeat == null) { + return bidder; + } + + if (allowedAlternateBidderCodes.contains(wantedSeat) || allowedAlternateBidderCodes.contains(WILDCARD)) { + return wantedSeat; + } + + return bidder; + } +} diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index b7f48750c2a..053e81d9493 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -29,7 +29,6 @@ import org.prebid.server.auction.model.BidInfo; import org.prebid.server.auction.model.BidRejectionTracker; import org.prebid.server.auction.model.BidRequestCacheInfo; -import org.prebid.server.auction.model.BidderRequest; import org.prebid.server.auction.model.BidderResponse; import org.prebid.server.auction.model.BidderResponseInfo; import org.prebid.server.auction.model.CachedDebugLog; @@ -75,8 +74,6 @@ import org.prebid.server.proto.openrtb.ext.request.ExtOptions; import org.prebid.server.proto.openrtb.ext.request.ExtPriceGranularity; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestAlternateBidderCodes; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestAlternateBidderCodesBidder; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidChannel; import org.prebid.server.proto.openrtb.ext.request.ExtRequestTargeting; @@ -109,7 +106,6 @@ import org.prebid.server.settings.model.AccountTargetingConfig; import org.prebid.server.settings.model.VideoStoredDataResult; import org.prebid.server.spring.config.model.CacheDefaultTtlProperties; -import org.prebid.server.util.ObjectUtil; import org.prebid.server.util.StreamUtil; import org.prebid.server.vast.VastModifier; @@ -269,18 +265,6 @@ private Future create(VideoStoredDataResult videoStoredDataResult, eventsContext)); } - private String seatForBid(Set allowedAlternateBidderCodes, String bidder, String wantedSeat) { - if (allowedAlternateBidderCodes == null || wantedSeat == null) { - return bidder; - } - - if (allowedAlternateBidderCodes.contains(wantedSeat) || allowedAlternateBidderCodes.contains("*")) { - return wantedSeat; - } - - return bidder; - } - private Future> updateBids(List bidderResponses, VideoStoredDataResult videoStoredDataResult, AuctionContext auctionContext, @@ -290,7 +274,8 @@ private Future> updateBids(List bidderRespo for (final BidderResponse bidderResponse : bidderResponses) { final String bidder = bidderResponse.getBidder(); - final Set allowedAlternateBidderCodes = alternateBidderCodesForBidder(bidder, auctionContext.getBidRequest()): + final Set allowedAlternateBidderCodes = AllowedAlternateBidderCodes.allowedCodesForBidder( + bidder, auctionContext.getBidRequest()); final List modifiedBidderBids = new ArrayList<>(); final BidderSeatBid seatBid = bidderResponse.getSeatBid(); @@ -302,7 +287,8 @@ private Future> updateBids(List bidderRespo receivedBid, bidType, bidder, videoStoredDataResult, auctionContext, eventsContext); modifiedBidderBids.add(bidderBid.toBuilder().bid(updatedBid) - .seat(seatForBid(allowedAlternateBidderCodes, bidder, bidderBid.getSeat())) + .seat(AllowedAlternateBidderCodes.applySeatForBid( + allowedAlternateBidderCodes, bidder, bidderBid.getSeat())) .build()); } @@ -427,31 +413,6 @@ private ExtBidPrebid updateBidExtPrebid(Bid bid, .build(); } - private Set alternateBidderCodesForBidder(String bidder, BidRequest bidRequest) { - final ExtRequestAlternateBidderCodes alternateBidderCodes = ObjectUtil.getIfNotNull(bidRequest.getExt().getPrebid(), ExtRequestPrebid::getAlternatebiddercodes); - - if (alternateBidderCodes == null) { - return null; - } - - if (!alternateBidderCodes.getEnabled()) { - return null; - } - - final Map alternateBidderCodesBidderMap = alternateBidderCodes.getBidders(); - if (alternateBidderCodesBidderMap == null) { - return null; - } - - final ExtRequestAlternateBidderCodesBidder alternateBidderCodesBidder = alternateBidderCodesBidderMap.get(bidder); - if (alternateBidderCodesBidder == null || !alternateBidderCodesBidder.getEnabled()) { - return null; - } - - final List allowedAlternates = alternateBidderCodesBidder.getAllowedBidderCodes(); - return allowedAlternates != null ? new HashSet<>(allowedAlternates) : null; - } - /** * Checks whether bidder responses are empty or contain no bids. */ @@ -477,7 +438,8 @@ private List toBidderResponseInfos(CategoryMappingResult cat for (final BidderBid bidderBid : seatBid.getBids()) { final Bid bid = bidderBid.getBid(); final BidType type = bidderBid.getType(); - final BidInfo bidInfo = toBidInfo(bid, type, imps, bidderBid.getSeat(), categoryMappingResult, cacheInfo, account); + final BidInfo bidInfo = toBidInfo( + bid, type, imps, bidderBid.getSeat(), categoryMappingResult, cacheInfo, account); bidInfos.add(bidInfo); } @@ -1508,7 +1470,7 @@ private Stream toSeatBids(List bidInfos, } return bidsByBidder.entrySet().stream() - .map((kvp) -> + .map(kvp -> SeatBid.builder() .seat(kvp.getKey()) .bid(kvp.getValue()) diff --git a/src/main/java/org/prebid/server/auction/ExchangeService.java b/src/main/java/org/prebid/server/auction/ExchangeService.java index 2a896af5b5d..d9adc3c8283 100644 --- a/src/main/java/org/prebid/server/auction/ExchangeService.java +++ b/src/main/java/org/prebid/server/auction/ExchangeService.java @@ -78,8 +78,6 @@ import org.prebid.server.proto.openrtb.ext.request.ExtBidderConfigOrtb; import org.prebid.server.proto.openrtb.ext.request.ExtDooh; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestAlternateBidderCodes; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestAlternateBidderCodesBidder; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidBidderConfig; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidCache; @@ -93,7 +91,6 @@ import org.prebid.server.settings.model.Account; import org.prebid.server.util.HttpUtil; import org.prebid.server.util.ListUtil; -import org.prebid.server.util.ObjectUtil; import org.prebid.server.util.PbsUtil; import org.prebid.server.util.StreamUtil; diff --git a/src/main/java/org/prebid/server/bidder/amx/AmxBidder.java b/src/main/java/org/prebid/server/bidder/amx/AmxBidder.java index b8247664b74..4c25cbc0086 100644 --- a/src/main/java/org/prebid/server/bidder/amx/AmxBidder.java +++ b/src/main/java/org/prebid/server/bidder/amx/AmxBidder.java @@ -174,7 +174,9 @@ private BidderBid createBidderBid(Bid bid, String cur, List errors) return null; } - return BidderBid.of(resolveBid(bid, amxBidExt.getDemandSource()), getBidType(amxBidExt), cur, amxBidExt.getBidderCode()); + return BidderBid.of( + resolveBid(bid, amxBidExt.getDemandSource()), + getBidType(amxBidExt), cur, amxBidExt.getBidderCode()); } private AmxBidExt parseBidderExt(ObjectNode ext) { diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestAlternateBidderCodes.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestAlternateBidderCodes.java index 5f5e46571ff..00ba6aa1f52 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestAlternateBidderCodes.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestAlternateBidderCodes.java @@ -12,6 +12,7 @@ @Builder(toBuilder = true) @Value public class ExtRequestAlternateBidderCodes { + /** * Is this feature enabled */ diff --git a/src/test/java/org/prebid/server/bidder/amx/AmxBidderTest.java b/src/test/java/org/prebid/server/bidder/amx/AmxBidderTest.java index bf5d788808f..776b04ccc83 100644 --- a/src/test/java/org/prebid/server/bidder/amx/AmxBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/amx/AmxBidderTest.java @@ -316,6 +316,8 @@ public void makeBidsShouldSetDemandSourceFromBidExtDsField() throws JsonProcessi // given final ObjectNode givenBidExt = mapper.createObjectNode(); givenBidExt.set("ds", new TextNode("someDs")); + givenBidExt.set("bc", new TextNode("someBc")); + final BidderCall httpCall = givenHttpCall( BidRequest.builder() .imp(singletonList(Imp.builder().video(Video.builder().build()).id("123").build())) @@ -328,6 +330,10 @@ public void makeBidsShouldSetDemandSourceFromBidExtDsField() throws JsonProcessi // then assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .extracting(BidderBid::getSeat) + .containsExactly("someBc"); + assertThat(result.getValue()) .extracting(BidderBid::getBid) .extracting(Bid::getExt) From b95f0677c85fef2c4408fb42873fd9bef8554a5b Mon Sep 17 00:00:00 2001 From: Nick Jacob Date: Wed, 5 Mar 2025 16:47:43 -0500 Subject: [PATCH 3/3] almost working --- .../java/org/prebid/server/auction/BidResponseCreator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index 053e81d9493..475d0ecb767 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -1466,7 +1466,8 @@ private Stream toSeatBids(List bidInfos, continue; } - bidsByBidder.putIfAbsent(bidder, new ArrayList<>(1)).add(bid); + bidsByBidder.putIfAbsent(bidder, new ArrayList<>(1)); + bidsByBidder.get(bidder).add(bid); } return bidsByBidder.entrySet().stream()