From 1810e87e310e635b80863beeb5f697f1e586155f Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Mon, 16 Dec 2024 13:49:00 +0200 Subject: [PATCH 01/19] Added new PAA iab model. --- .../bidder/model/CompositeBidderResponse.java | 4 ++++ .../openrtb/ext/response/ExtBidResponse.java | 5 +++++ .../proto/openrtb/ext/response/ExtIgi.java | 20 +++++++++++++++++ .../proto/openrtb/ext/response/ExtIgiIgb.java | 22 +++++++++++++++++++ .../proto/openrtb/ext/response/ExtIgiIgs.java | 16 ++++++++++++++ .../openrtb/ext/response/ExtIgiIgsExt.java | 11 ++++++++++ 6 files changed, 78 insertions(+) create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgi.java create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgb.java create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgs.java create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgsExt.java diff --git a/src/main/java/org/prebid/server/bidder/model/CompositeBidderResponse.java b/src/main/java/org/prebid/server/bidder/model/CompositeBidderResponse.java index 7e5a31f16b0..8e80ea8b604 100644 --- a/src/main/java/org/prebid/server/bidder/model/CompositeBidderResponse.java +++ b/src/main/java/org/prebid/server/bidder/model/CompositeBidderResponse.java @@ -3,6 +3,7 @@ import lombok.Builder; import lombok.Value; import org.prebid.server.bidder.Bidder; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; import java.util.Collections; @@ -26,6 +27,9 @@ public class CompositeBidderResponse { */ List fledgeAuctionConfigs; + + List igi; + public static CompositeBidderResponse empty() { return builder().build(); } diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtBidResponse.java b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtBidResponse.java index 115ce7b3ff9..6f4b3904fd7 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtBidResponse.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtBidResponse.java @@ -48,6 +48,11 @@ public class ExtBidResponse { */ Map usersync; + /** + * Defines the contract for bidresponse.ext.igi + */ + List igi; + /** * Defines the contract for bidresponse.ext.prebid */ diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgi.java b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgi.java new file mode 100644 index 00000000000..fc63c1288bc --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgi.java @@ -0,0 +1,20 @@ +package org.prebid.server.proto.openrtb.ext.response; + +import lombok.Builder; +import lombok.Value; + +import java.util.List; + +/** + * Defines the contract for bidresponse.ext.igi + */ +@Value +@Builder +public class ExtIgi { + + String impid; + + List igb; + + List igs; +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgb.java b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgb.java new file mode 100644 index 00000000000..aca3758c7aa --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgb.java @@ -0,0 +1,22 @@ +package org.prebid.server.proto.openrtb.ext.response; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.Builder; +import lombok.Value; + +@Value +@Builder +public class ExtIgiIgb { + + String origin; + + Double maxbid; + + @Builder.Default + String cur = "USD"; + + JsonNode pbs; + + ObjectNode ps; +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgs.java b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgs.java new file mode 100644 index 00000000000..3330f1fa37c --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgs.java @@ -0,0 +1,16 @@ +package org.prebid.server.proto.openrtb.ext.response; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.Builder; +import lombok.Value; + +@Value +@Builder +public class ExtIgiIgs { + + String impid; + + ObjectNode config; + + ExtIgiIgsExt ext; +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgsExt.java b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgsExt.java new file mode 100644 index 00000000000..979b7fe6e13 --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgsExt.java @@ -0,0 +1,11 @@ +package org.prebid.server.proto.openrtb.ext.response; + +import lombok.Value; + +@Value(staticConstructor = "of") +public class ExtIgiIgsExt { + + String bidder; + + String adapter; +} From abd310491ef079f27c69b6b114b750fedc580d0c Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Fri, 20 Dec 2024 14:44:23 +0200 Subject: [PATCH 02/19] PAA WIP. --- .../server/auction/BidResponseCreator.java | 27 +++++++++++++++++- .../bidder/consumable/ConsumableBidder.java | 9 ++++-- .../server/bidder/criteo/CriteoBidder.java | 28 +++++++------------ .../bidder/criteo/CriteoExtBidResponse.java | 3 +- .../criteo/CriteoIgiExtBidResponse.java | 13 --------- .../criteo/CriteoIgsIgiExtBidResponse.java | 10 ------- .../org/prebid/server/bidder/ix/IxBidder.java | 23 +++++++-------- .../bidder/medianet/MedianetBidder.java | 18 ++++++------ .../server/bidder/model/BidderSeatBid.java | 5 ++++ .../bidder/model/BidderSeatBidInfo.java | 12 +++++++- .../bidder/model/CompositeBidderResponse.java | 9 ------ .../server/bidder/openx/OpenxBidder.java | 21 +++++++++----- .../bidder/pubmatic/PubmaticBidder.java | 22 +++++++++------ .../proto/openrtb/ext/response/ExtIgi.java | 2 +- .../proto/openrtb/ext/response/ExtIgiIgs.java | 6 ++-- 15 files changed, 114 insertions(+), 94 deletions(-) delete mode 100644 src/main/java/org/prebid/server/bidder/criteo/CriteoIgiExtBidResponse.java delete mode 100644 src/main/java/org/prebid/server/bidder/criteo/CriteoIgsIgiExtBidResponse.java diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index 31ed4ee1403..a41c0d9d38b 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -82,6 +82,9 @@ import org.prebid.server.proto.openrtb.ext.response.ExtBidderError; import org.prebid.server.proto.openrtb.ext.response.ExtDebugTrace; import org.prebid.server.proto.openrtb.ext.response.ExtHttpCall; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; +import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgs; +import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgsExt; import org.prebid.server.proto.openrtb.ext.response.ExtResponseCache; import org.prebid.server.proto.openrtb.ext.response.ExtResponseDebug; import org.prebid.server.proto.openrtb.ext.response.ExtTraceActivityInfrastructure; @@ -414,7 +417,8 @@ private List toBidderResponseInfos(CategoryMappingResult cat seatBid.getHttpCalls(), seatBid.getErrors(), seatBid.getWarnings(), - seatBid.getFledgeAuctionConfigs()); + seatBid.getFledgeAuctionConfigs(), + seatBid.getIgi()); result.add(BidderResponseInfo.of(bidder, bidderSeatBidInfo, bidderResponse.getResponseTime())); } @@ -762,6 +766,7 @@ private ExtBidResponse toExtBidResponse(List bidderResponseI final Map responseTimeMillis = toResponseTimes(bidderResponseInfos, cacheResult); + final List extIgi = toExtBidResponseIgi(bidderResponseInfos); final ExtBidResponseFledge extBidResponseFledge = toExtBidResponseFledge(bidderResponseInfos, auctionContext); final ExtBidResponsePrebid prebid = toExtBidResponsePrebid( auctionTimestamp, auctionContext.getBidRequest(), extBidResponseFledge); @@ -772,6 +777,7 @@ private ExtBidResponse toExtBidResponse(List bidderResponseI .warnings(warnings) .responsetimemillis(responseTimeMillis) .tmaxrequest(auctionContext.getBidRequest().getTmax()) + .igi(extIgi) .prebid(prebid) .build(); } @@ -827,6 +833,25 @@ private static FledgeAuctionConfig fledgeConfigWithBidder(FledgeAuctionConfig fl .build(); } + private static List toExtBidResponseIgi(List bidderResponseInfos) { + return bidderResponseInfos.stream() + .flatMap(responseInfo -> responseInfo.getSeatBid().getIgi().stream() + .map(igi -> extIgiWithBidder(igi, responseInfo.getBidder()))) + .toList(); + } + + private static ExtIgi extIgiWithBidder(ExtIgi extIgi, String bidderName) { + final List extIgiIgs = CollectionUtils.emptyIfNull(extIgi.getIgs()).stream() + .map(igs -> Optional.ofNullable(igs) + .map(ExtIgiIgs::toBuilder) + .orElseGet(ExtIgiIgs::builder) + .ext(ExtIgiIgsExt.of(bidderName, bidderName)) + .build()) + .toList(); + + return extIgi.toBuilder().igs(extIgiIgs).build(); + } + private static ExtResponseDebug toExtResponseDebug(List bidderResponseInfos, AuctionContext auctionContext, CacheServiceResult cacheResult, diff --git a/src/main/java/org/prebid/server/bidder/consumable/ConsumableBidder.java b/src/main/java/org/prebid/server/bidder/consumable/ConsumableBidder.java index 344680b9aa4..5b70032a98d 100644 --- a/src/main/java/org/prebid/server/bidder/consumable/ConsumableBidder.java +++ b/src/main/java/org/prebid/server/bidder/consumable/ConsumableBidder.java @@ -121,9 +121,12 @@ public Result> makeBids(BidderCall httpCall, BidRequ public CompositeBidderResponse makeBidderResponse(BidderCall httpCall, BidRequest bidRequest) { try { final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class); - final List bidderErrors = new ArrayList<>(); - return CompositeBidderResponse.builder().bids(extractConsumableBids(bidRequest, bidResponse, bidderErrors)) - .errors(bidderErrors).build(); + final List errors = new ArrayList<>(); + + return CompositeBidderResponse.builder() + .bids(extractConsumableBids(bidRequest, bidResponse, errors)) + .errors(errors) + .build(); } catch (DecodeException e) { return CompositeBidderResponse.withError(BidderError.badServerResponse(e.getMessage())); } diff --git a/src/main/java/org/prebid/server/bidder/criteo/CriteoBidder.java b/src/main/java/org/prebid/server/bidder/criteo/CriteoBidder.java index 064bac48c48..9bf68e89e24 100644 --- a/src/main/java/org/prebid/server/bidder/criteo/CriteoBidder.java +++ b/src/main/java/org/prebid/server/bidder/criteo/CriteoBidder.java @@ -19,7 +19,7 @@ import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidMeta; -import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; @@ -31,7 +31,6 @@ public class CriteoBidder implements Bidder { - private static final String BIDDER_NAME = "criteo"; private final String endpointUrl; private final JacksonMapper mapper; @@ -55,9 +54,12 @@ public Result> makeBids(BidderCall httpCall, BidRequ public CompositeBidderResponse makeBidderResponse(BidderCall httpCall, BidRequest bidRequest) { try { final CriteoBidResponse bidResponse = mapper.decodeValue( - httpCall.getResponse().getBody(), - CriteoBidResponse.class); - return CompositeBidderResponse.withBids(extractBids(bidResponse), extractFledge(bidResponse)); + httpCall.getResponse().getBody(), CriteoBidResponse.class); + + return CompositeBidderResponse.builder() + .bids(extractBids(bidResponse)) + .igi(extractIgi(bidResponse)) + .build(); } catch (DecodeException | PreBidException e) { return CompositeBidderResponse.withError(BidderError.badServerResponse(e.getMessage())); } @@ -105,21 +107,11 @@ private ObjectNode makeExt(String networkName) { .build()); } - private static List extractFledge(CriteoBidResponse bidResponse) { - final List fledgeConfigs = Optional.ofNullable(bidResponse) + private static List extractIgi(CriteoBidResponse bidResponse) { + return Optional.ofNullable(bidResponse) .map(CriteoBidResponse::getExt) .map(CriteoExtBidResponse::getIgi) .filter(CollectionUtils::isNotEmpty) - .orElse(Collections.emptyList()) - .stream() - .filter(igi -> CollectionUtils.isNotEmpty(igi.getIgs()) && igi.getIgs().getFirst() != null) - .map(igi -> FledgeAuctionConfig.builder() - .impId(igi.getImpId()) - .bidder(BIDDER_NAME) - .config(igi.getIgs().getFirst().getConfig()) - .build()) - .toList(); - - return CollectionUtils.isEmpty(fledgeConfigs) ? null : fledgeConfigs; + .orElse(Collections.emptyList()); } } diff --git a/src/main/java/org/prebid/server/bidder/criteo/CriteoExtBidResponse.java b/src/main/java/org/prebid/server/bidder/criteo/CriteoExtBidResponse.java index 8f332b2f3bd..dda26a73ef7 100644 --- a/src/main/java/org/prebid/server/bidder/criteo/CriteoExtBidResponse.java +++ b/src/main/java/org/prebid/server/bidder/criteo/CriteoExtBidResponse.java @@ -1,11 +1,12 @@ package org.prebid.server.bidder.criteo; import lombok.Value; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; import java.util.List; @Value(staticConstructor = "of") public class CriteoExtBidResponse { - List igi; + List igi; } diff --git a/src/main/java/org/prebid/server/bidder/criteo/CriteoIgiExtBidResponse.java b/src/main/java/org/prebid/server/bidder/criteo/CriteoIgiExtBidResponse.java deleted file mode 100644 index 6bdac80ad2f..00000000000 --- a/src/main/java/org/prebid/server/bidder/criteo/CriteoIgiExtBidResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.prebid.server.bidder.criteo; - -import lombok.Value; - -import java.util.List; - -@Value(staticConstructor = "of") -public class CriteoIgiExtBidResponse { - - String impId; - - List igs; -} diff --git a/src/main/java/org/prebid/server/bidder/criteo/CriteoIgsIgiExtBidResponse.java b/src/main/java/org/prebid/server/bidder/criteo/CriteoIgsIgiExtBidResponse.java deleted file mode 100644 index b34d76e0646..00000000000 --- a/src/main/java/org/prebid/server/bidder/criteo/CriteoIgsIgiExtBidResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.prebid.server.bidder.criteo; - -import com.fasterxml.jackson.databind.node.ObjectNode; -import lombok.Value; - -@Value(staticConstructor = "of") -public class CriteoIgsIgiExtBidResponse { - - ObjectNode config; -} diff --git a/src/main/java/org/prebid/server/bidder/ix/IxBidder.java b/src/main/java/org/prebid/server/bidder/ix/IxBidder.java index 5fb26e698fd..de3b080d6a7 100644 --- a/src/main/java/org/prebid/server/bidder/ix/IxBidder.java +++ b/src/main/java/org/prebid/server/bidder/ix/IxBidder.java @@ -42,7 +42,8 @@ import org.prebid.server.proto.openrtb.ext.request.ix.ExtImpIx; import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidVideo; -import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; +import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgs; import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; import org.prebid.server.util.ObjectUtil; @@ -233,11 +234,12 @@ public Result> makeBids(BidderCall httpCall, BidRequ public CompositeBidderResponse makeBidderResponse(BidderCall httpCall, BidRequest bidRequest) { try { final IxBidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), IxBidResponse.class); - final List bidderErrors = new ArrayList<>(); + final List errors = new ArrayList<>(); + return CompositeBidderResponse.builder() - .bids(extractBids(bidRequest, bidResponse, bidderErrors)) - .fledgeAuctionConfigs(extractFledge(bidResponse)) - .errors(bidderErrors) + .bids(extractBids(bidRequest, bidResponse, errors)) + .igi(extractIgi(bidResponse)) + .errors(errors) .build(); } catch (DecodeException e) { return CompositeBidderResponse.withError(BidderError.badServerResponse(e.getMessage())); @@ -406,17 +408,16 @@ private static ExtBidPrebidVideo videoInfo(ExtBidPrebidVideo extBidPrebidVideo) : null; } - private List extractFledge(IxBidResponse bidResponse) { - return Optional.ofNullable(bidResponse) + private List extractIgi(IxBidResponse bidResponse) { + final List igs = Optional.ofNullable(bidResponse) .map(IxBidResponse::getExt) .map(IxExtBidResponse::getProtectedAudienceAuctionConfigs) .orElse(Collections.emptyList()) .stream() .filter(Objects::nonNull) - .map(ixAuctionConfig -> FledgeAuctionConfig.builder() - .impId(ixAuctionConfig.getBidId()) - .config(ixAuctionConfig.getConfig()) - .build()) + .map(config -> ExtIgiIgs.builder().impId(config.getBidId()).config(config.getConfig()).build()) .toList(); + + return Collections.singletonList(ExtIgi.builder().igs(igs).build()); } } diff --git a/src/main/java/org/prebid/server/bidder/medianet/MedianetBidder.java b/src/main/java/org/prebid/server/bidder/medianet/MedianetBidder.java index d184aefc297..8ad676c0eed 100644 --- a/src/main/java/org/prebid/server/bidder/medianet/MedianetBidder.java +++ b/src/main/java/org/prebid/server/bidder/medianet/MedianetBidder.java @@ -19,7 +19,8 @@ import org.prebid.server.json.DecodeException; import org.prebid.server.json.JacksonMapper; import org.prebid.server.proto.openrtb.ext.response.BidType; -import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; +import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgs; import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; @@ -64,12 +65,9 @@ public final CompositeBidderResponse makeBidderResponse(BidderCall h } final List errors = new ArrayList<>(); - final List bids = extractBids(httpCall.getRequest().getPayload(), bidResponse, errors); - final List fledgeAuctionConfigs = extractFledge(bidResponse); - return CompositeBidderResponse.builder() - .bids(bids) - .fledgeAuctionConfigs(fledgeAuctionConfigs) + .bids(extractBids(httpCall.getRequest().getPayload(), bidResponse, errors)) + .igi(extractIgi(bidResponse)) .errors(errors) .build(); } @@ -138,15 +136,17 @@ private static BidType resolveBidTypeFromImpId(String impId, List imps) { return BidType.banner; } - private static List extractFledge(MedianetBidResponse bidResponse) { - return Optional.ofNullable(bidResponse) + private static List extractIgi(MedianetBidResponse bidResponse) { + final List igs = Optional.ofNullable(bidResponse) .map(MedianetBidResponse::getExt) .map(MedianetBidResponseExt::getIgi) .orElse(Collections.emptyList()) .stream() .map(InterestGroupAuctionIntent::getIgs) .flatMap(Collection::stream) - .map(e -> FledgeAuctionConfig.builder().impId(e.getImpId()).config(e.getConfig()).build()) + .map(e -> ExtIgiIgs.builder().impId(e.getImpId()).config(e.getConfig()).build()) .toList(); + + return Collections.singletonList(ExtIgi.builder().igs(igs).build()); } } diff --git a/src/main/java/org/prebid/server/bidder/model/BidderSeatBid.java b/src/main/java/org/prebid/server/bidder/model/BidderSeatBid.java index 6cdc55cccb9..8022b8667f1 100644 --- a/src/main/java/org/prebid/server/bidder/model/BidderSeatBid.java +++ b/src/main/java/org/prebid/server/bidder/model/BidderSeatBid.java @@ -4,6 +4,7 @@ import lombok.Value; import org.prebid.server.bidder.Bidder; import org.prebid.server.proto.openrtb.ext.response.ExtHttpCall; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; import java.util.Collections; @@ -53,9 +54,13 @@ public class BidderSeatBid { @Builder.Default List warnings = Collections.emptyList(); + @Deprecated @Builder.Default List fledgeAuctionConfigs = Collections.emptyList(); + @Builder.Default + List igi = Collections.emptyList(); + public BidderSeatBid with(List bids) { return toBuilder().bids(bids).build(); } diff --git a/src/main/java/org/prebid/server/bidder/model/BidderSeatBidInfo.java b/src/main/java/org/prebid/server/bidder/model/BidderSeatBidInfo.java index 37ff7cccfc2..1cc6f182343 100644 --- a/src/main/java/org/prebid/server/bidder/model/BidderSeatBidInfo.java +++ b/src/main/java/org/prebid/server/bidder/model/BidderSeatBidInfo.java @@ -4,6 +4,7 @@ import lombok.Value; import org.prebid.server.auction.model.BidInfo; import org.prebid.server.proto.openrtb.ext.response.ExtHttpCall; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; import java.util.List; @@ -20,9 +21,18 @@ public class BidderSeatBidInfo { List warnings; + @Deprecated List fledgeAuctionConfigs; + List igi; + public BidderSeatBidInfo with(List bids) { - return BidderSeatBidInfo.of(bids, this.httpCalls, this.errors, this.warnings, this.fledgeAuctionConfigs); + return BidderSeatBidInfo.of( + bids, + this.httpCalls, + this.errors, + this.warnings, + this.fledgeAuctionConfigs, + this.igi); } } diff --git a/src/main/java/org/prebid/server/bidder/model/CompositeBidderResponse.java b/src/main/java/org/prebid/server/bidder/model/CompositeBidderResponse.java index 8e80ea8b604..31db729e326 100644 --- a/src/main/java/org/prebid/server/bidder/model/CompositeBidderResponse.java +++ b/src/main/java/org/prebid/server/bidder/model/CompositeBidderResponse.java @@ -34,15 +34,6 @@ public static CompositeBidderResponse empty() { return builder().build(); } - public static CompositeBidderResponse withBids(List bids, - List fledgeAuctionConfigs) { - - return builder() - .bids(bids) - .fledgeAuctionConfigs(fledgeAuctionConfigs) - .build(); - } - public static CompositeBidderResponse withError(BidderError error) { return builder().errors(Collections.singletonList(error)).build(); } diff --git a/src/main/java/org/prebid/server/bidder/openx/OpenxBidder.java b/src/main/java/org/prebid/server/bidder/openx/OpenxBidder.java index 2ef79d3bfd4..dda14dd2c4e 100644 --- a/src/main/java/org/prebid/server/bidder/openx/OpenxBidder.java +++ b/src/main/java/org/prebid/server/bidder/openx/OpenxBidder.java @@ -30,7 +30,8 @@ import org.prebid.server.proto.openrtb.ext.request.openx.ExtImpOpenx; import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidVideo; -import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; +import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgs; import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; @@ -84,9 +85,13 @@ public Result>> makeHttpRequests(BidRequest bidRequ @Override public CompositeBidderResponse makeBidderResponse(BidderCall httpCall, BidRequest bidRequest) { try { - final OpenxBidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), - OpenxBidResponse.class); - return CompositeBidderResponse.withBids(extractBids(bidRequest, bidResponse), extractFledge(bidResponse)); + final OpenxBidResponse bidResponse = mapper.decodeValue( + httpCall.getResponse().getBody(), OpenxBidResponse.class); + + return CompositeBidderResponse.builder() + .bids(extractBids(bidRequest, bidResponse)) + .igi(extractIgi(bidResponse)) + .build(); } catch (DecodeException e) { return CompositeBidderResponse.withError(BidderError.badServerResponse(e.getMessage())); } @@ -283,14 +288,16 @@ private static BidType getBidType(Bid bid, Map impIdToBidType) return impIdToBidType.getOrDefault(bid.getImpid(), BidType.banner); } - private static List extractFledge(OpenxBidResponse bidResponse) { - return Optional.ofNullable(bidResponse) + private static List extractIgi(OpenxBidResponse bidResponse) { + final List igs = Optional.ofNullable(bidResponse) .map(OpenxBidResponse::getExt) .map(OpenxBidResponseExt::getFledgeAuctionConfigs) .orElse(Collections.emptyMap()) .entrySet() .stream() - .map(e -> FledgeAuctionConfig.builder().impId(e.getKey()).config(e.getValue()).build()) + .map(e -> ExtIgiIgs.builder().impId(e.getKey()).config(e.getValue()).build()) .toList(); + + return Collections.singletonList(ExtIgi.builder().igs(igs).build()); } } diff --git a/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java b/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java index a60a6ab2efa..723ccceea3c 100644 --- a/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java +++ b/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java @@ -39,7 +39,8 @@ import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidVideo; -import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; +import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgs; import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; import org.prebid.server.util.StreamUtil; @@ -458,11 +459,14 @@ public Result> makeBids(BidderCall httpCall, BidRequ @Override public CompositeBidderResponse makeBidderResponse(BidderCall httpCall, BidRequest bidRequest) { try { - final List bidderErrors = new ArrayList<>(); final PubmaticBidResponse bidResponse = mapper.decodeValue( - httpCall.getResponse().getBody(), - PubmaticBidResponse.class); - return CompositeBidderResponse.withBids(extractBids(bidResponse, bidderErrors), extractFledge(bidResponse)); + httpCall.getResponse().getBody(), PubmaticBidResponse.class); + final List errors = new ArrayList<>(); + + return CompositeBidderResponse.builder() + .bids(extractBids(bidResponse, errors)) + .igi(extractIgi(bidResponse)) + .build(); } catch (DecodeException | PreBidException e) { return CompositeBidderResponse.withError(BidderError.badServerResponse(e.getMessage())); } @@ -571,14 +575,16 @@ private static Integer getDealPriority(PubmaticBidExt bidExt) { .orElse(null); } - private static List extractFledge(PubmaticBidResponse bidResponse) { - return Optional.ofNullable(bidResponse) + private static List extractIgi(PubmaticBidResponse bidResponse) { + final List igs = Optional.ofNullable(bidResponse) .map(PubmaticBidResponse::getExt) .map(PubmaticExtBidResponse::getFledgeAuctionConfigs) .orElse(Collections.emptyMap()) .entrySet() .stream() - .map(e -> FledgeAuctionConfig.builder().impId(e.getKey()).config(e.getValue()).build()) + .map(e -> ExtIgiIgs.builder().impId(e.getKey()).config(e.getValue()).build()) .toList(); + + return Collections.singletonList(ExtIgi.builder().igs(igs).build()); } } diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgi.java b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgi.java index fc63c1288bc..6df4b2db44d 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgi.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgi.java @@ -9,7 +9,7 @@ * Defines the contract for bidresponse.ext.igi */ @Value -@Builder +@Builder(toBuilder = true) public class ExtIgi { String impid; diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgs.java b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgs.java index 3330f1fa37c..ac05c677cf7 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgs.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgs.java @@ -1,14 +1,16 @@ package org.prebid.server.proto.openrtb.ext.response; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.Builder; import lombok.Value; @Value -@Builder +@Builder(toBuilder = true) public class ExtIgiIgs { - String impid; + @JsonProperty("impid") + String impId; ObjectNode config; From ebfa6df2f37a946b4c54302773cb56dfd7f6bedc Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Fri, 20 Dec 2024 14:46:48 +0200 Subject: [PATCH 03/19] Refactoring. --- src/main/java/org/prebid/server/bidder/openx/OpenxBidder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/prebid/server/bidder/openx/OpenxBidder.java b/src/main/java/org/prebid/server/bidder/openx/OpenxBidder.java index dda14dd2c4e..2f84fefe8c7 100644 --- a/src/main/java/org/prebid/server/bidder/openx/OpenxBidder.java +++ b/src/main/java/org/prebid/server/bidder/openx/OpenxBidder.java @@ -295,7 +295,7 @@ private static List extractIgi(OpenxBidResponse bidResponse) { .orElse(Collections.emptyMap()) .entrySet() .stream() - .map(e -> ExtIgiIgs.builder().impId(e.getKey()).config(e.getValue()).build()) + .map(ext -> ExtIgiIgs.builder().impId(ext.getKey()).config(ext.getValue()).build()) .toList(); return Collections.singletonList(ExtIgi.builder().igs(igs).build()); From e4a45ef02dd8917aacf773f5d40f32f35741b3a3 Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Thu, 26 Dec 2024 22:28:10 +0200 Subject: [PATCH 04/19] Refactoring. --- .../server/auction/BidResponseCreator.java | 77 ++++++++++++++++--- .../server/auction/model/PaaFormat.java | 12 +++ .../bidder/model/BidderSeatBidInfo.java | 6 +- .../openrtb/ext/request/ExtRequestPrebid.java | 6 ++ .../settings/model/AccountAuctionConfig.java | 4 + 5 files changed, 90 insertions(+), 15 deletions(-) create mode 100644 src/main/java/org/prebid/server/auction/model/PaaFormat.java diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index a41c0d9d38b..355ccfc129b 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -34,6 +34,7 @@ import org.prebid.server.auction.model.CachedDebugLog; import org.prebid.server.auction.model.CategoryMappingResult; import org.prebid.server.auction.model.MultiBidConfig; +import org.prebid.server.auction.model.PaaFormat; import org.prebid.server.auction.model.TargetingInfo; import org.prebid.server.auction.model.debug.DebugContext; import org.prebid.server.auction.requestfactory.Ortb2ImplicitParametersResolver; @@ -766,10 +767,12 @@ private ExtBidResponse toExtBidResponse(List bidderResponseI final Map responseTimeMillis = toResponseTimes(bidderResponseInfos, cacheResult); - final List extIgi = toExtBidResponseIgi(bidderResponseInfos); - final ExtBidResponseFledge extBidResponseFledge = toExtBidResponseFledge(bidderResponseInfos, auctionContext); + final PaaResult paaResult = toPaaOutput(bidderResponseInfos, auctionContext); + final List igi = paaResult.igis(); + final ExtBidResponseFledge fledge = paaResult.fledge(); + final ExtBidResponsePrebid prebid = toExtBidResponsePrebid( - auctionTimestamp, auctionContext.getBidRequest(), extBidResponseFledge); + auctionTimestamp, auctionContext.getBidRequest(), fledge); return ExtBidResponse.builder() .debug(extResponseDebug) @@ -777,11 +780,12 @@ private ExtBidResponse toExtBidResponse(List bidderResponseI .warnings(warnings) .responsetimemillis(responseTimeMillis) .tmaxrequest(auctionContext.getBidRequest().getTmax()) - .igi(extIgi) + .igi(igi) .prebid(prebid) .build(); } + private ExtBidResponsePrebid toExtBidResponsePrebid(long auctionTimestamp, BidRequest bidRequest, ExtBidResponseFledge extBidResponseFledge) { @@ -799,17 +803,52 @@ private ExtBidResponsePrebid toExtBidResponsePrebid(long auctionTimestamp, .build(); } - private ExtBidResponseFledge toExtBidResponseFledge(List bidderResponseInfos, - AuctionContext auctionContext) { + private PaaResult toPaaOutput(List bidderResponseInfos, AuctionContext auctionContext) { + final PaaFormat paaFormat = resolvePaaFormat(auctionContext); + final List extIgi = paaFormat == PaaFormat.IAB ? toExtBidResponseIgi(bidderResponseInfos) : null; final List imps = auctionContext.getBidRequest().getImp(); - final List fledgeConfigs = bidderResponseInfos.stream() - .flatMap(bidderResponseInfo -> fledgeConfigsForBidder(bidderResponseInfo, imps)) + + // TODO: Remove after transition period + final Stream deprecatedFledgeConfigs = bidderResponseInfos.stream() + .flatMap(bidderResponseInfo -> toDeprecatedFledgeConfigs(bidderResponseInfo, imps)); + + final Stream fledgeConfigs = paaFormat == PaaFormat.ORIGINAL + ? bidderResponseInfos.stream().flatMap(BidResponseCreator::toOriginalFledgeFormat) + : Stream.empty(); + + final List combinedFledgeConfigs = Stream.concat(deprecatedFledgeConfigs, fledgeConfigs) .toList(); - return !fledgeConfigs.isEmpty() ? ExtBidResponseFledge.of(fledgeConfigs) : null; + + final ExtBidResponseFledge extBidResponseFledge = combinedFledgeConfigs.isEmpty() + ? null + : ExtBidResponseFledge.of(combinedFledgeConfigs); + + return new PaaResult(extIgi, extBidResponseFledge); + } + + private static Stream toOriginalFledgeFormat(BidderResponseInfo bidderResponseInfo) { + return Optional.ofNullable(bidderResponseInfo.getSeatBid().getIgi()).stream() + .flatMap(Collection::stream) + .filter(Objects::nonNull) + .map(ExtIgi::getIgs) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .map(extIgiIgs -> extIgiIgsToFledgeConfig(extIgiIgs, bidderResponseInfo.getBidder())); } - private Stream fledgeConfigsForBidder(BidderResponseInfo bidderResponseInfo, List imps) { + private static FledgeAuctionConfig extIgiIgsToFledgeConfig(ExtIgiIgs extIgiIgs, String bidder) { + return FledgeAuctionConfig.builder() + .bidder(bidder) + .adapter(bidder) + .impId(extIgiIgs.getImpId()) + .config(extIgiIgs.getConfig()) + .build(); + } + + private Stream toDeprecatedFledgeConfigs(BidderResponseInfo bidderResponseInfo, + List imps) { + return Optional.ofNullable(bidderResponseInfo.getSeatBid().getFledgeAuctionConfigs()) .stream() .flatMap(Collection::stream) @@ -849,7 +888,9 @@ private static ExtIgi extIgiWithBidder(ExtIgi extIgi, String bidderName) { .build()) .toList(); - return extIgi.toBuilder().igs(extIgiIgs).build(); + return extIgiIgs.isEmpty() + ? extIgi + : extIgi.toBuilder().igs(extIgiIgs).build(); } private static ExtResponseDebug toExtResponseDebug(List bidderResponseInfos, @@ -1163,6 +1204,17 @@ private static Map toResponseTimes(Collection Optional.ofNullable(auctionContext.getAccount()) + .map(Account::getAuction) + .map(AccountAuctionConfig::getPaaFormat)) + .orElse(PaaFormat.IAB); // TODO: Decide what default value to use + } + /** * Returns {@link BidResponse} based on list of {@link BidderResponse}s and {@link CacheServiceResult}. */ @@ -1809,4 +1861,7 @@ private T convertValue(JsonNode jsonNode, String key, Class typeClass) { return null; } } + + private record PaaResult(List igis, ExtBidResponseFledge fledge) { + } } diff --git a/src/main/java/org/prebid/server/auction/model/PaaFormat.java b/src/main/java/org/prebid/server/auction/model/PaaFormat.java new file mode 100644 index 00000000000..8367b61c0f2 --- /dev/null +++ b/src/main/java/org/prebid/server/auction/model/PaaFormat.java @@ -0,0 +1,12 @@ +package org.prebid.server.auction.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public enum PaaFormat { + + @JsonProperty("original") + ORIGINAL, + + @JsonProperty("iab") + IAB +} diff --git a/src/main/java/org/prebid/server/bidder/model/BidderSeatBidInfo.java b/src/main/java/org/prebid/server/bidder/model/BidderSeatBidInfo.java index 1cc6f182343..38c9f86433c 100644 --- a/src/main/java/org/prebid/server/bidder/model/BidderSeatBidInfo.java +++ b/src/main/java/org/prebid/server/bidder/model/BidderSeatBidInfo.java @@ -1,6 +1,5 @@ package org.prebid.server.bidder.model; -import lombok.AllArgsConstructor; import lombok.Value; import org.prebid.server.auction.model.BidInfo; import org.prebid.server.proto.openrtb.ext.response.ExtHttpCall; @@ -9,8 +8,7 @@ import java.util.List; -@AllArgsConstructor(staticName = "of") -@Value +@Value(staticConstructor = "of") public class BidderSeatBidInfo { List bidsInfos; @@ -21,7 +19,7 @@ public class BidderSeatBidInfo { List warnings; - @Deprecated + @Deprecated(forRemoval = true) List fledgeAuctionConfigs; List igi; 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 cb325bd088a..33b326b2638 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 @@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.Builder; import lombok.Value; +import org.prebid.server.auction.model.PaaFormat; import org.prebid.server.floors.model.PriceFloorRules; import org.prebid.server.json.deserializer.IntegerFlagDeserializer; @@ -184,4 +185,9 @@ public class ExtRequestPrebid { */ ExtRequestPrebidSdk sdk; + /** + * Defines the contract for bidrequest.ext.prebid.paaformat + */ + @JsonProperty("paaformat") + PaaFormat paaFormat; } 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 9943535aa7e..ac7da04dd31 100644 --- a/src/main/java/org/prebid/server/settings/model/AccountAuctionConfig.java +++ b/src/main/java/org/prebid/server/settings/model/AccountAuctionConfig.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.Builder; import lombok.Value; +import org.prebid.server.auction.model.PaaFormat; import org.prebid.server.spring.config.bidder.model.MediaType; import java.util.Map; @@ -49,4 +50,7 @@ public class AccountAuctionConfig { @JsonProperty("privacysandbox") AccountPrivacySandboxConfig privacySandbox; + + @JsonProperty("paaformat") + PaaFormat paaFormat; } From 824d279af6d77b93fd8f55d1280f7f07ab48d2db Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Thu, 26 Dec 2024 23:38:44 +0200 Subject: [PATCH 05/19] Refactoring. --- .../prebid/server/bidder/HttpBidderRequester.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/prebid/server/bidder/HttpBidderRequester.java b/src/main/java/org/prebid/server/bidder/HttpBidderRequester.java index 787ee1f96d2..8b6a25ea231 100644 --- a/src/main/java/org/prebid/server/bidder/HttpBidderRequester.java +++ b/src/main/java/org/prebid/server/bidder/HttpBidderRequester.java @@ -31,6 +31,7 @@ import org.prebid.server.log.LoggerFactory; import org.prebid.server.model.CaseInsensitiveMultiMap; import org.prebid.server.proto.openrtb.ext.response.ExtHttpCall; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; import org.prebid.server.util.HttpUtil; import org.prebid.server.vertx.httpclient.HttpClient; @@ -248,7 +249,7 @@ private static byte[] gzip(byte[] value) { */ private Future> failResponse(Throwable exception, HttpRequest httpRequest) { conditionalLogger.warn("Error occurred while sending HTTP request to a bidder url: %s with message: %s" - .formatted(httpRequest.getUri(), exception.getMessage()), logSamplingRate); + .formatted(httpRequest.getUri(), exception.getMessage()), logSamplingRate); logger.debug("Error occurred while sending HTTP request to a bidder url: {}", exception, httpRequest.getUri()); @@ -346,6 +347,7 @@ private static class ResultBuilder { private final Map, BidderCall> bidderCallsRecorded = new HashMap<>(); private final List bidsRecorded = new ArrayList<>(); private final List errorsRecorded = new ArrayList<>(); + private final List igiRecorded = new ArrayList<>(); private final List fledgeRecorded = new ArrayList<>(); ResultBuilder(List> httpRequests, @@ -366,6 +368,7 @@ void addHttpCall(BidderCall bidderCall, CompositeBidderResponse bidderRespons handleBids(bidderResponse); handleBidderErrors(bidderResponse); handleBidderCallError(bidderCall); + handleIgis(bidderResponse); handleFledgeAuctionConfigs(bidderResponse); } @@ -429,6 +432,12 @@ private void handleFledgeAuctionConfigs(CompositeBidderResponse bidderResponse) .ifPresent(fledgeRecorded::addAll); } + private void handleIgis(CompositeBidderResponse bidderResponse) { + Optional.ofNullable(bidderResponse) + .map(CompositeBidderResponse::getIgi) + .ifPresent(igiRecorded::addAll); + } + BidderSeatBid toBidderSeatBid(boolean debugEnabled) { final List> httpCalls = new ArrayList<>(bidderCallsRecorded.values()); httpRequests.stream() @@ -446,6 +455,7 @@ BidderSeatBid toBidderSeatBid(boolean debugEnabled) { .bids(bidsRecorded) .httpCalls(extHttpCalls) .errors(errors) + .igi(igiRecorded) .fledgeAuctionConfigs(fledgeRecorded) .build(); } From 4b60b5159bfc9c3224ff278fc26a92287c0d86f4 Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Tue, 7 Jan 2025 15:50:48 +0200 Subject: [PATCH 06/19] Partly fixed unit tests. --- .../server/auction/BidResponseCreator.java | 25 ++++++------ .../bidder/medianet/MedianetBidder.java | 2 +- .../bidder/model/CompositeBidderResponse.java | 1 - .../bidder/pubmatic/PubmaticBidder.java | 2 +- .../proto/openrtb/ext/response/ExtIgi.java | 2 +- .../proto/openrtb/ext/response/ExtIgiIgs.java | 2 +- .../bidder/HttpBidderRequesterTest.java | 22 +++++----- .../bidder/criteo/CriteoBidderTest.java | 40 ++++++++----------- .../server/bidder/openx/OpenxBidderTest.java | 29 +++++++++----- .../bidder/pubmatic/PubmaticBidderTest.java | 15 +++---- 10 files changed, 71 insertions(+), 69 deletions(-) diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index 355ccfc129b..473c09fee39 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -785,7 +785,6 @@ private ExtBidResponse toExtBidResponse(List bidderResponseI .build(); } - private ExtBidResponsePrebid toExtBidResponsePrebid(long auctionTimestamp, BidRequest bidRequest, ExtBidResponseFledge extBidResponseFledge) { @@ -814,7 +813,7 @@ private PaaResult toPaaOutput(List bidderResponseInfos, Auct .flatMap(bidderResponseInfo -> toDeprecatedFledgeConfigs(bidderResponseInfo, imps)); final Stream fledgeConfigs = paaFormat == PaaFormat.ORIGINAL - ? bidderResponseInfos.stream().flatMap(BidResponseCreator::toOriginalFledgeFormat) + ? bidderResponseInfos.stream().flatMap(this::toOriginalFledgeFormat) : Stream.empty(); final List combinedFledgeConfigs = Stream.concat(deprecatedFledgeConfigs, fledgeConfigs) @@ -827,7 +826,7 @@ private PaaResult toPaaOutput(List bidderResponseInfos, Auct return new PaaResult(extIgi, extBidResponseFledge); } - private static Stream toOriginalFledgeFormat(BidderResponseInfo bidderResponseInfo) { + private Stream toOriginalFledgeFormat(BidderResponseInfo bidderResponseInfo) { return Optional.ofNullable(bidderResponseInfo.getSeatBid().getIgi()).stream() .flatMap(Collection::stream) .filter(Objects::nonNull) @@ -837,10 +836,10 @@ private static Stream toOriginalFledgeFormat(BidderResponse .map(extIgiIgs -> extIgiIgsToFledgeConfig(extIgiIgs, bidderResponseInfo.getBidder())); } - private static FledgeAuctionConfig extIgiIgsToFledgeConfig(ExtIgiIgs extIgiIgs, String bidder) { + private FledgeAuctionConfig extIgiIgsToFledgeConfig(ExtIgiIgs extIgiIgs, String bidder) { return FledgeAuctionConfig.builder() .bidder(bidder) - .adapter(bidder) + .adapter(bidderCatalog.resolveBaseBidder(bidder)) .impId(extIgiIgs.getImpId()) .config(extIgiIgs.getConfig()) .build(); @@ -865,26 +864,28 @@ private boolean validateFledgeConfig(FledgeAuctionConfig fledgeAuctionConfig, Li return fledgeEnabled == ExtImpAuctionEnvironment.ON_DEVICE_IG_AUCTION_FLEDGE; } - private static FledgeAuctionConfig fledgeConfigWithBidder(FledgeAuctionConfig fledgeConfig, String bidderName) { + private FledgeAuctionConfig fledgeConfigWithBidder(FledgeAuctionConfig fledgeConfig, String bidder) { return fledgeConfig.toBuilder() - .bidder(bidderName) - .adapter(bidderName) + .bidder(bidder) + .adapter(bidderCatalog.resolveBaseBidder(bidder)) .build(); } - private static List toExtBidResponseIgi(List bidderResponseInfos) { - return bidderResponseInfos.stream() + private List toExtBidResponseIgi(List bidderResponseInfos) { + final List extIgi = bidderResponseInfos.stream() .flatMap(responseInfo -> responseInfo.getSeatBid().getIgi().stream() .map(igi -> extIgiWithBidder(igi, responseInfo.getBidder()))) .toList(); + + return extIgi.isEmpty() ? null : extIgi; } - private static ExtIgi extIgiWithBidder(ExtIgi extIgi, String bidderName) { + private ExtIgi extIgiWithBidder(ExtIgi extIgi, String bidder) { final List extIgiIgs = CollectionUtils.emptyIfNull(extIgi.getIgs()).stream() .map(igs -> Optional.ofNullable(igs) .map(ExtIgiIgs::toBuilder) .orElseGet(ExtIgiIgs::builder) - .ext(ExtIgiIgsExt.of(bidderName, bidderName)) + .ext(ExtIgiIgsExt.of(bidder, bidderCatalog.resolveBaseBidder(bidder))) .build()) .toList(); diff --git a/src/main/java/org/prebid/server/bidder/medianet/MedianetBidder.java b/src/main/java/org/prebid/server/bidder/medianet/MedianetBidder.java index 8ad676c0eed..2829754dddf 100644 --- a/src/main/java/org/prebid/server/bidder/medianet/MedianetBidder.java +++ b/src/main/java/org/prebid/server/bidder/medianet/MedianetBidder.java @@ -144,7 +144,7 @@ private static List extractIgi(MedianetBidResponse bidResponse) { .stream() .map(InterestGroupAuctionIntent::getIgs) .flatMap(Collection::stream) - .map(e -> ExtIgiIgs.builder().impId(e.getImpId()).config(e.getConfig()).build()) + .map(igiIgs -> ExtIgiIgs.builder().impId(igiIgs.getImpId()).config(igiIgs.getConfig()).build()) .toList(); return Collections.singletonList(ExtIgi.builder().igs(igs).build()); diff --git a/src/main/java/org/prebid/server/bidder/model/CompositeBidderResponse.java b/src/main/java/org/prebid/server/bidder/model/CompositeBidderResponse.java index 31db729e326..75a71e0864a 100644 --- a/src/main/java/org/prebid/server/bidder/model/CompositeBidderResponse.java +++ b/src/main/java/org/prebid/server/bidder/model/CompositeBidderResponse.java @@ -27,7 +27,6 @@ public class CompositeBidderResponse { */ List fledgeAuctionConfigs; - List igi; public static CompositeBidderResponse empty() { diff --git a/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java b/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java index 723ccceea3c..1382e99ac39 100644 --- a/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java +++ b/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java @@ -582,7 +582,7 @@ private static List extractIgi(PubmaticBidResponse bidResponse) { .orElse(Collections.emptyMap()) .entrySet() .stream() - .map(e -> ExtIgiIgs.builder().impId(e.getKey()).config(e.getValue()).build()) + .map(config -> ExtIgiIgs.builder().impId(config.getKey()).config(config.getValue()).build()) .toList(); return Collections.singletonList(ExtIgi.builder().igs(igs).build()); diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgi.java b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgi.java index 6df4b2db44d..49e84d9739f 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgi.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgi.java @@ -8,8 +8,8 @@ /** * Defines the contract for bidresponse.ext.igi */ -@Value @Builder(toBuilder = true) +@Value(staticConstructor = "of") public class ExtIgi { String impid; diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgs.java b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgs.java index ac05c677cf7..a243380bb4e 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgs.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgs.java @@ -5,8 +5,8 @@ import lombok.Builder; import lombok.Value; -@Value @Builder(toBuilder = true) +@Value(staticConstructor = "of") public class ExtIgiIgs { @JsonProperty("impid") diff --git a/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java b/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java index 81180793e22..179f2a1ceeb 100644 --- a/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java +++ b/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java @@ -196,7 +196,7 @@ public void shouldPassStoredResponseToBidderMakeBidsMethodAndReturnSeatBids() { emptyList())); final List bids = asList(BidderBid.of(null, null, null), BidderBid.of(null, null, null)); - given(bidder.makeBidderResponse(any(), any())).willReturn(CompositeBidderResponse.withBids(bids, emptyList())); + given(bidder.makeBidderResponse(any(), any())).willReturn(CompositeBidderResponse.builder().bids(bids).build()); final BidderRequest bidderRequest = BidderRequest.builder() .bidder("bidder") @@ -346,7 +346,7 @@ public void shouldReturnBidsCreatedByBidder() { givenSuccessfulBidderMakeHttpRequests(); final List bids = asList(BidderBid.of(null, null, null), BidderBid.of(null, null, null)); - given(bidder.makeBidderResponse(any(), any())).willReturn(CompositeBidderResponse.withBids(bids, emptyList())); + given(bidder.makeBidderResponse(any(), any())).willReturn(CompositeBidderResponse.builder().bids(bids).build()); final BidderRequest bidderRequest = BidderRequest.builder() .bidder("bidder") @@ -379,8 +379,7 @@ public void shouldReturnBidsCreatedByMakeBids() { givenSuccessfulBidderMakeHttpRequests(); final List bids = emptyList(); - given(bidder.makeBidderResponse(any(), any())) - .willReturn(CompositeBidderResponse.withBids(bids, null)); + given(bidder.makeBidderResponse(any(), any())).willReturn(CompositeBidderResponse.builder().bids(bids).build()); final BidderRequest bidderRequest = BidderRequest.builder() .bidder("bidder") @@ -417,8 +416,11 @@ public void shouldReturnFledgeCreatedByBidder() { givenFledgeAuctionConfig("imp-2")); final List bids = emptyList(); - given(bidder.makeBidderResponse(any(), any())) - .willReturn(CompositeBidderResponse.withBids(bids, fledgeAuctionConfigs)); + given(bidder.makeBidderResponse(any(), any())).willReturn( + CompositeBidderResponse.builder() + .bids(bids) + .fledgeAuctionConfigs(fledgeAuctionConfigs) + .build()); final BidderRequest bidderRequest = BidderRequest.builder() .bidder("bidder") @@ -555,8 +557,8 @@ public void processBids(List bids) { final BidderBid bidderBidDeal1 = BidderBid.of(Bid.builder().impid("deal1").dealid("deal1").build(), null, null); final BidderBid bidderBidDeal2 = BidderBid.of(Bid.builder().impid("deal2").dealid("deal2").build(), null, null); given(bidder.makeBidderResponse(any(), any())).willReturn( - CompositeBidderResponse.withBids(singletonList(bidderBidDeal1), emptyList()), - CompositeBidderResponse.withBids(singletonList(bidderBidDeal2), emptyList())); + CompositeBidderResponse.builder().bids(singletonList(bidderBidDeal1)).build(), + CompositeBidderResponse.builder().bids(singletonList(bidderBidDeal2)).build()); // when final BidderSeatBid bidderSeatBid = target.requestBids( @@ -604,7 +606,7 @@ public void shouldFinishWhenAllDealRequestsAreFinishedAndNoDealsProvided() { final BidderBid bidderBid = BidderBid.of(Bid.builder().dealid("deal2").build(), null, null); given(bidder.makeBidderResponse(any(), any())).willReturn( - CompositeBidderResponse.withBids(singletonList(bidderBid), emptyList())); + CompositeBidderResponse.builder().bids(singletonList(bidderBid)).build()); // when final BidderSeatBid bidderSeatBid = @@ -737,7 +739,7 @@ public void shouldReturnRecordBidRejections() throws JsonProcessingException { .bid(Bid.builder().impid("2").build()) .build()); given(bidder.makeBidderResponse(any(), any())) - .willReturn(CompositeBidderResponse.withBids(secondRequestBids, null)); + .willReturn(CompositeBidderResponse.builder().bids(secondRequestBids).build()); final BidderRequest bidderRequest = BidderRequest.builder() .bidder("bidder") diff --git a/src/test/java/org/prebid/server/bidder/criteo/CriteoBidderTest.java b/src/test/java/org/prebid/server/bidder/criteo/CriteoBidderTest.java index 09f2f113fb1..291dd35d415 100644 --- a/src/test/java/org/prebid/server/bidder/criteo/CriteoBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/criteo/CriteoBidderTest.java @@ -20,7 +20,8 @@ import org.prebid.server.bidder.model.HttpResponse; import org.prebid.server.bidder.model.Result; import org.prebid.server.proto.openrtb.ext.response.BidType; -import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; +import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgs; import java.util.List; import java.util.Set; @@ -199,7 +200,7 @@ public void makeBidderResponseShouldReturnBidWithNetworkNameFromExtPrebid() thro // given final BidderCall httpCall = givenHttpCall( givenBidResponse(bid -> bid - .impid("123") + .impid("123") .ext(givenBidExtWithNetwork("anyNetworkName")))); // when @@ -236,18 +237,16 @@ public void makeBidderResponseShouldReturnEmptyNetworkNameWhenBidExtPrebidNotCon @Test public void makeBidderResponseShouldReturnFledgeConfigs() throws JsonProcessingException { // given + final List igs = List.of( + ExtIgiIgs.builder().config(mapper.createObjectNode().put("proterty1", "value1")).build(), + ExtIgiIgs.builder().config(mapper.createObjectNode().put("proterty2", "value2")).build()); + final CriteoBidResponse bidResponseWithFledge = CriteoBidResponse.builder() .ext(CriteoExtBidResponse.of(List.of( - CriteoIgiExtBidResponse.of("imp_id1", List.of( - CriteoIgsIgiExtBidResponse.of( - mapper.createObjectNode().put("proterty1", "value1")), - CriteoIgsIgiExtBidResponse.of( - mapper.createObjectNode().put("proterty2", "value2")))), - CriteoIgiExtBidResponse.of("imp_id2", List.of( - CriteoIgsIgiExtBidResponse.of( - mapper.createObjectNode().put("proterty3", "value3")), - CriteoIgsIgiExtBidResponse.of( - mapper.createObjectNode().put("proterty4", "value4"))))))) + ExtIgi.builder() + .impid("imp_id1") + .igs(igs) + .build()))) .build(); final BidderCall httpCall = givenHttpCall(mapper.writeValueAsString(bidResponseWithFledge)); @@ -255,19 +254,12 @@ public void makeBidderResponseShouldReturnFledgeConfigs() throws JsonProcessingE final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); // then + final List expectedIgs = List.of( + ExtIgiIgs.builder().config(mapper.createObjectNode().put("proterty1", "value1")).build(), + ExtIgiIgs.builder().config(mapper.createObjectNode().put("proterty2", "value2")).build()); + assertThat(result.getErrors()).isEmpty(); - assertThat(result.getFledgeAuctionConfigs()) - .containsExactlyInAnyOrder( - FledgeAuctionConfig.builder() - .bidder("criteo") - .impId("imp_id1") - .config(mapper.createObjectNode().put("proterty1", "value1")) - .build(), - FledgeAuctionConfig.builder() - .bidder("criteo") - .impId("imp_id2") - .config(mapper.createObjectNode().put("proterty3", "value3")) - .build()); + assertThat(result.getIgi()).containsExactly(ExtIgi.builder().impid("imp_id1").igs(expectedIgs).build()); } @Test diff --git a/src/test/java/org/prebid/server/bidder/openx/OpenxBidderTest.java b/src/test/java/org/prebid/server/bidder/openx/OpenxBidderTest.java index 1f218984f91..092d6edbe1a 100644 --- a/src/test/java/org/prebid/server/bidder/openx/OpenxBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/openx/OpenxBidderTest.java @@ -35,7 +35,8 @@ import org.prebid.server.proto.openrtb.ext.request.openx.ExtImpOpenx; import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidVideo; -import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; +import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgs; import java.math.BigDecimal; import java.util.Collections; @@ -504,6 +505,13 @@ public void makeBidsShouldReturnResultWithExpectedFields() throws JsonProcessing final CompositeBidderResponse result = target.makeBidderResponse(httpCall, bidRequest); // then + final ExtIgi igi = ExtIgi.builder() + .igs(singletonList(ExtIgiIgs.builder() + .impId("impId1") + .config(mapper.createObjectNode().put("somevalue", 1)) + .build())) + .build(); + assertThat(result.getErrors()).isEmpty(); assertThat(result.getBids()).hasSize(1) .containsOnly(BidderBid.of( @@ -516,11 +524,7 @@ public void makeBidsShouldReturnResultWithExpectedFields() throws JsonProcessing .adm("
This is an Ad
") .build(), BidType.banner, "UAH")); - assertThat(result.getFledgeAuctionConfigs()) - .containsOnly(FledgeAuctionConfig.builder() - .impId("impId1") - .config(mapper.createObjectNode().put("somevalue", 1)) - .build()); + assertThat(result.getIgi()).containsExactly(igi); } @Test @@ -579,13 +583,16 @@ public void makeBidsShouldReturnFledgeConfigEvenIfNoBids() throws JsonProcessing final CompositeBidderResponse result = target.makeBidderResponse(httpCall, bidRequest); // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getBids()).isEmpty(); - assertThat(result.getFledgeAuctionConfigs()) - .containsOnly(FledgeAuctionConfig.builder() + final ExtIgi igi = ExtIgi.builder() + .igs(singletonList(ExtIgiIgs.builder() .impId("impId1") .config(mapper.createObjectNode().put("somevalue", 1)) - .build()); + .build())) + .build(); + + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getBids()).isEmpty(); + assertThat(result.getIgi()).containsExactly(igi); } @Test diff --git a/src/test/java/org/prebid/server/bidder/pubmatic/PubmaticBidderTest.java b/src/test/java/org/prebid/server/bidder/pubmatic/PubmaticBidderTest.java index 2f0b5ccd49a..a1de06c9d1e 100644 --- a/src/test/java/org/prebid/server/bidder/pubmatic/PubmaticBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/pubmatic/PubmaticBidderTest.java @@ -40,7 +40,8 @@ import org.prebid.server.proto.openrtb.ext.request.pubmatic.ExtImpPubmaticKeyVal; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidVideo; -import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; +import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgs; import org.prebid.server.util.HttpUtil; import java.math.BigDecimal; @@ -1225,11 +1226,11 @@ public void makeBidderResponseShouldReturnBannerBidIfExtBidContainsIllegalBidTyp public void makeBidderResponseShouldReturnFledgeAuctionConfig() throws JsonProcessingException { // given final BidResponse bidResponse = givenBidResponse(bidBuilder -> bidBuilder.impid("imp_id")); - final ObjectNode fledgeAuctionConfig = mapper.createObjectNode(); + final ObjectNode auctionConfig = mapper.createObjectNode(); final PubmaticBidResponse bidResponseWithFledge = PubmaticBidResponse.builder() .cur(bidResponse.getCur()) .seatbid(bidResponse.getSeatbid()) - .ext(PubmaticExtBidResponse.of(Map.of("imp_id", fledgeAuctionConfig))) + .ext(PubmaticExtBidResponse.of(Map.of("imp_id", auctionConfig))) .build(); final BidderCall httpCall = givenHttpCall(mapper.writeValueAsString(bidResponseWithFledge)); @@ -1241,11 +1242,11 @@ public void makeBidderResponseShouldReturnFledgeAuctionConfig() throws JsonProce assertThat(result.getBids()) .containsExactly(BidderBid.of(Bid.builder().impid("imp_id").build(), banner, "USD")); - final FledgeAuctionConfig expectedFledge = FledgeAuctionConfig.builder() - .impId("imp_id") - .config(fledgeAuctionConfig) + final ExtIgi igi = ExtIgi.builder() + .igs(singletonList(ExtIgiIgs.builder().impId("imp_id").config(auctionConfig).build())) .build(); - assertThat(result.getFledgeAuctionConfigs()).containsExactly(expectedFledge); + + assertThat(result.getIgi()).containsExactly(igi); } @Test From 5bf42c60e4703f3fae0a076a545996feb5ee590f Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Tue, 7 Jan 2025 16:21:06 +0200 Subject: [PATCH 07/19] Fixed unit tests. --- .../org/prebid/server/bidder/ix/IxBidder.java | 2 +- .../bidder/medianet/MedianetBidder.java | 2 +- .../server/bidder/openx/OpenxBidder.java | 2 +- .../bidder/pubmatic/PubmaticBidder.java | 2 +- .../auction/BidResponseCreatorTest.java | 6 ++- .../prebid/server/bidder/ix/IxBidderTest.java | 18 ++++---- .../bidder/medianet/MedianetBidderTest.java | 25 ++++++----- .../openrtb2/ix/test-auction-ix-response.json | 42 +------------------ .../it/openrtb2/ix/test-ix-bid-response.json | 40 +----------------- 9 files changed, 34 insertions(+), 105 deletions(-) diff --git a/src/main/java/org/prebid/server/bidder/ix/IxBidder.java b/src/main/java/org/prebid/server/bidder/ix/IxBidder.java index de3b080d6a7..be29b4d1d4a 100644 --- a/src/main/java/org/prebid/server/bidder/ix/IxBidder.java +++ b/src/main/java/org/prebid/server/bidder/ix/IxBidder.java @@ -418,6 +418,6 @@ private List extractIgi(IxBidResponse bidResponse) { .map(config -> ExtIgiIgs.builder().impId(config.getBidId()).config(config.getConfig()).build()) .toList(); - return Collections.singletonList(ExtIgi.builder().igs(igs).build()); + return igs.isEmpty() ? null : Collections.singletonList(ExtIgi.builder().igs(igs).build()); } } diff --git a/src/main/java/org/prebid/server/bidder/medianet/MedianetBidder.java b/src/main/java/org/prebid/server/bidder/medianet/MedianetBidder.java index 2829754dddf..a82d6a72e63 100644 --- a/src/main/java/org/prebid/server/bidder/medianet/MedianetBidder.java +++ b/src/main/java/org/prebid/server/bidder/medianet/MedianetBidder.java @@ -147,6 +147,6 @@ private static List extractIgi(MedianetBidResponse bidResponse) { .map(igiIgs -> ExtIgiIgs.builder().impId(igiIgs.getImpId()).config(igiIgs.getConfig()).build()) .toList(); - return Collections.singletonList(ExtIgi.builder().igs(igs).build()); + return igs.isEmpty() ? null : Collections.singletonList(ExtIgi.builder().igs(igs).build()); } } diff --git a/src/main/java/org/prebid/server/bidder/openx/OpenxBidder.java b/src/main/java/org/prebid/server/bidder/openx/OpenxBidder.java index 2f84fefe8c7..99f35592ea1 100644 --- a/src/main/java/org/prebid/server/bidder/openx/OpenxBidder.java +++ b/src/main/java/org/prebid/server/bidder/openx/OpenxBidder.java @@ -298,6 +298,6 @@ private static List extractIgi(OpenxBidResponse bidResponse) { .map(ext -> ExtIgiIgs.builder().impId(ext.getKey()).config(ext.getValue()).build()) .toList(); - return Collections.singletonList(ExtIgi.builder().igs(igs).build()); + return igs.isEmpty() ? null : Collections.singletonList(ExtIgi.builder().igs(igs).build()); } } diff --git a/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java b/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java index 1382e99ac39..e1e6650e357 100644 --- a/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java +++ b/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java @@ -585,6 +585,6 @@ private static List extractIgi(PubmaticBidResponse bidResponse) { .map(config -> ExtIgiIgs.builder().impId(config.getKey()).config(config.getValue()).build()) .toList(); - return Collections.singletonList(ExtIgi.builder().igs(igs).build()); + return igs.isEmpty() ? null : Collections.singletonList(ExtIgi.builder().igs(igs).build()); } } diff --git a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java index 0e3d0220ba1..f9bade83d18 100644 --- a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java +++ b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java @@ -3468,6 +3468,7 @@ public void shouldCopyImpExtPrebidPassThroughToResponseBidExtPrebidPassThroughWh @Test public void shouldAddExtPrebidFledgeIfAvailable() { // given + given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); final Imp imp = givenImp("i1").toBuilder() .ext(mapper.createObjectNode().put("ae", 1)) .build(); @@ -3497,13 +3498,14 @@ public void shouldAddExtPrebidFledgeIfAvailable() { .usingRecursiveComparison() .isEqualTo(fledgeAuctionConfig.toBuilder() .bidder("bidder1") - .adapter("bidder1") + .adapter("adapter1") .build()); } @Test public void shouldAddExtPrebidFledgeIfAvailableEvenIfBidsEmpty() { // given + given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); final Imp imp = givenImp("i1").toBuilder() .ext(mapper.createObjectNode().put("ae", 1)) .build(); @@ -3532,7 +3534,7 @@ public void shouldAddExtPrebidFledgeIfAvailableEvenIfBidsEmpty() { .usingRecursiveComparison() .isEqualTo(fledgeAuctionConfig.toBuilder() .bidder("bidder1") - .adapter("bidder1") + .adapter("adapter1") .build()); } diff --git a/src/test/java/org/prebid/server/bidder/ix/IxBidderTest.java b/src/test/java/org/prebid/server/bidder/ix/IxBidderTest.java index 35726f5a205..e91a0300df1 100644 --- a/src/test/java/org/prebid/server/bidder/ix/IxBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/ix/IxBidderTest.java @@ -46,7 +46,8 @@ import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidVideo; -import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; +import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgs; import org.prebid.server.version.PrebidVersionProvider; import java.util.List; @@ -771,14 +772,14 @@ public void makeBidderResponseShouldReturnFledgeAuctionConfig() throws JsonProce // given final String impId = "imp_id"; final BidResponse bidResponse = givenBidResponse(bidBuilder -> bidBuilder.impid(impId).mtype(1)); - final ObjectNode fledgeAuctionConfig = mapper.createObjectNode(); + final ObjectNode auctionConfig = mapper.createObjectNode(); final BidRequest bidRequest = BidRequest.builder() .imp(List.of(Imp.builder().id(impId).build())) .build(); final IxBidResponse bidResponseWithFledge = IxBidResponse.builder() .cur(bidResponse.getCur()) .seatbid(bidResponse.getSeatbid()) - .ext(IxExtBidResponse.of(List.of(AuctionConfigExtBidResponse.of(impId, fledgeAuctionConfig)))) + .ext(IxExtBidResponse.of(List.of(AuctionConfigExtBidResponse.of(impId, auctionConfig)))) .build(); final BidderCall httpCall = givenHttpCall(bidRequest, mapper.writeValueAsString(bidResponseWithFledge)); @@ -787,14 +788,15 @@ public void makeBidderResponseShouldReturnFledgeAuctionConfig() throws JsonProce final CompositeBidderResponse result = target.makeBidderResponse(httpCall, bidRequest); // then + final ExtIgiIgs igs = ExtIgiIgs.builder() + .impId(impId) + .config(auctionConfig) + .build(); + assertThat(result.getErrors()).isEmpty(); assertThat(result.getBids()) .containsOnly(BidderBid.of(Bid.builder().impid(impId).mtype(1).build(), banner, bidResponse.getCur())); - final FledgeAuctionConfig expectedFledge = FledgeAuctionConfig.builder() - .impId(impId) - .config(fledgeAuctionConfig) - .build(); - assertThat(result.getFledgeAuctionConfigs()).containsExactly(expectedFledge); + assertThat(result.getIgi()).containsExactly(ExtIgi.builder().igs(singletonList(igs)).build()); } private static ExtRequest givenExtRequest(String pbjsv) { diff --git a/src/test/java/org/prebid/server/bidder/medianet/MedianetBidderTest.java b/src/test/java/org/prebid/server/bidder/medianet/MedianetBidderTest.java index 15e67bb5e25..03a3cba66f8 100644 --- a/src/test/java/org/prebid/server/bidder/medianet/MedianetBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/medianet/MedianetBidderTest.java @@ -21,7 +21,8 @@ import org.prebid.server.bidder.model.HttpResponse; import org.prebid.server.bidder.model.Result; import org.prebid.server.proto.openrtb.ext.ExtPrebid; -import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; +import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgs; import java.util.ArrayList; import java.util.List; @@ -215,13 +216,14 @@ public void makeBidsShouldReturnFledgeConfigIfBidIsPresent() throws JsonProcessi final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); // then + final ExtIgiIgs igs = ExtIgiIgs.builder() + .impId("imp_id") + .config(mapper.createObjectNode().put("someKey", "someValue")) + .build(); + assertThat(result.getErrors()).isEmpty(); assertThat(result.getBids()).hasSize(1); - assertThat(result.getFledgeAuctionConfigs()) - .containsOnly(FledgeAuctionConfig.builder() - .impId("imp_id") - .config(mapper.createObjectNode().put("someKey", "someValue")) - .build()); + assertThat(result.getIgi()).containsExactly(ExtIgi.builder().igs(singletonList(igs)).build()); } @Test @@ -235,13 +237,14 @@ public void makeBidsShouldReturnFledgeConfigIfBidIsAbsent() throws JsonProcessin final CompositeBidderResponse result = target.makeBidderResponse(httpCall, null); // then + final ExtIgiIgs igs = ExtIgiIgs.builder() + .impId("imp_id") + .config(mapper.createObjectNode().put("someKey", "someValue")) + .build(); + assertThat(result.getErrors()).isEmpty(); assertThat(result.getBids()).isEmpty(); - assertThat(result.getFledgeAuctionConfigs()) - .containsOnly(FledgeAuctionConfig.builder() - .impId("imp_id") - .config(mapper.createObjectNode().put("someKey", "someValue")) - .build()); + assertThat(result.getIgi()).containsExactly(ExtIgi.builder().igs(singletonList(igs)).build()); } private static MedianetBidResponse sampleBidResponse(Function Date: Wed, 8 Jan 2025 13:45:15 +0200 Subject: [PATCH 08/19] Added unit tests for BidResponseCreator and HttpBidderRequester --- .../auction/BidResponseCreatorTest.java | 44 +++++++++++++++++ .../bidder/HttpBidderRequesterTest.java | 49 +++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java index f9bade83d18..2256518bb80 100644 --- a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java +++ b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java @@ -97,6 +97,9 @@ import org.prebid.server.proto.openrtb.ext.response.ExtBidderError; import org.prebid.server.proto.openrtb.ext.response.ExtDebugTrace; import org.prebid.server.proto.openrtb.ext.response.ExtHttpCall; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; +import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgs; +import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgsExt; import org.prebid.server.proto.openrtb.ext.response.ExtResponseCache; import org.prebid.server.proto.openrtb.ext.response.ExtResponseDebug; import org.prebid.server.proto.openrtb.ext.response.ExtTraceActivityInfrastructure; @@ -3502,6 +3505,47 @@ public void shouldAddExtPrebidFledgeIfAvailable() { .build()); } + @Test + public void shouldAddExtIgiIfAvailable() { + // given + given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); + final Imp imp = givenImp("i1").toBuilder() + .ext(mapper.createObjectNode().put("ae", 1)) + .build(); + final BidRequest bidRequest = givenBidRequest(identity(), identity(), imp); + final ExtIgi igi = ExtIgi.builder() + .impid("impId") + .igs(singletonList(ExtIgiIgs.builder().config(mapper.createObjectNode()).build())) + .build(); + + final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("i1").build(); + final List bidderResponses = singletonList( + BidderResponse.of("bidder1", + BidderSeatBid.builder() + .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .igi(singletonList(igi)) + .build(), 100)); + + final AuctionContext auctionContext = givenAuctionContext( + bidRequest, + contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); + + // when + final BidResponse bidResponse = target + .create(auctionContext, CACHE_INFO, MULTI_BIDS) + .result(); + + // then + assertThat(bidResponse.getExt().getIgi()).containsExactly( + ExtIgi.builder() + .impid("impId") + .igs(singletonList(ExtIgiIgs.builder() + .config(mapper.createObjectNode()) + .ext(ExtIgiIgsExt.of("bidder1", "adapter1")) + .build())) + .build()); + } + @Test public void shouldAddExtPrebidFledgeIfAvailableEvenIfBidsEmpty() { // given diff --git a/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java b/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java index 179f2a1ceeb..6b8772dcbc7 100644 --- a/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java +++ b/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java @@ -37,6 +37,8 @@ import org.prebid.server.execution.timeout.TimeoutFactory; import org.prebid.server.model.CaseInsensitiveMultiMap; import org.prebid.server.proto.openrtb.ext.response.ExtHttpCall; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; +import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgs; import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; import org.prebid.server.util.HttpUtil; import org.prebid.server.vertx.httpclient.HttpClient; @@ -448,6 +450,53 @@ public void shouldReturnFledgeCreatedByBidder() { verify(bidRejectionTracker, never()).reject(anyList(), any()); } + @Test + public void shouldReturnExtIgiCreatedByBidder() { + // given + givenSuccessfulBidderMakeHttpRequests(); + + final List igi = List.of( + ExtIgi.builder() + .impid("impId") + .igs(singletonList(ExtIgiIgs.builder() + .config(mapper.createObjectNode()) + .build())) + .build()); + + final List bids = emptyList(); + + given(bidder.makeBidderResponse(any(), any())).willReturn( + CompositeBidderResponse.builder() + .bids(bids) + .igi(igi) + .build()); + + final BidderRequest bidderRequest = BidderRequest.builder() + .bidder("bidder") + .bidRequest(BidRequest.builder().build()) + .build(); + + // when + final BidderSeatBid bidderSeatBid = + target + .requestBids( + bidder, + bidderRequest, + bidRejectionTracker, + timeout, + CaseInsensitiveMultiMap.empty(), + bidderAliases, + false) + .result(); + + // then + assertThat(bidderSeatBid.getBids()).hasSameElementsAs(bids); + assertThat(bidderSeatBid.getIgi()).containsExactlyElementsOf(igi); + + verify(bidRejectionTracker, never()).reject(anyString(), any()); + verify(bidRejectionTracker, never()).reject(anyList(), any()); + } + @Test public void shouldCompressRequestBodyIfContentEncodingHeaderIsGzip() { // given From 5d6d88b21d499c11cf397f6dc69584b5cdcae21e Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Thu, 9 Jan 2025 16:07:47 +0200 Subject: [PATCH 09/19] Added igs.ae mapping. --- .../prebid/server/auction/ImpAdjuster.java | 31 ++++++++ .../server/auction/ImpAdjusterTest.java | 74 +++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/src/main/java/org/prebid/server/auction/ImpAdjuster.java b/src/main/java/org/prebid/server/auction/ImpAdjuster.java index 86e581b06e8..e34bee7d638 100644 --- a/src/main/java/org/prebid/server/auction/ImpAdjuster.java +++ b/src/main/java/org/prebid/server/auction/ImpAdjuster.java @@ -1,20 +1,26 @@ package org.prebid.server.auction; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.IntNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.iab.openrtb.request.Imp; import org.prebid.server.json.JacksonMapper; import org.prebid.server.json.JsonMerger; import org.prebid.server.validation.ImpValidator; +import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.stream.StreamSupport; public class ImpAdjuster { private static final String IMP_EXT = "ext"; + private static final String EXT_AE = "ae"; + private static final String EXT_IGS = "igs"; private static final String EXT_PREBID = "prebid"; private static final String EXT_PREBID_BIDDER = "bidder"; private static final String EXT_PREBID_IMP = "imp"; @@ -33,6 +39,8 @@ public ImpAdjuster(JacksonMapper jacksonMapper, } public Imp adjust(Imp originalImp, String bidder, BidderAliases bidderAliases, List debugMessages) { + setEaParams(originalImp.getExt()); + final JsonNode impExtPrebidImp = bidderParamsFromImpExtPrebidImp(originalImp.getExt()); if (impExtPrebidImp == null) { return originalImp; @@ -65,6 +73,29 @@ public Imp adjust(Imp originalImp, String bidder, BidderAliases bidderAliases, L } } + private void setEaParams(ObjectNode ext) { + final int extEa = Optional.ofNullable(ext) + .map(extNode -> extNode.get(EXT_AE)) + .filter(JsonNode::isInt) + .map(JsonNode::asInt) + .orElse(-1); + + boolean extIgsEaPresent = Optional.ofNullable(ext) + .map(extNode -> extNode.get(EXT_IGS)) + .filter(JsonNode::isArray) + .map(extNode -> StreamSupport.stream(extNode.spliterator(), false).toList()) + .stream() + .flatMap(Collection::stream) + .filter(Objects::nonNull) + .anyMatch(igsElementNode -> igsElementNode.has(EXT_AE)); + + if (!extIgsEaPresent && (extEa == 0 || extEa == 1)) { + final ArrayNode extIgs = jacksonMapper.mapper().createArrayNode(); + extIgs.add(jacksonMapper.mapper().createObjectNode().set(EXT_AE, IntNode.valueOf(extEa))); + ext.set(EXT_IGS, extIgs); + } + } + private static JsonNode bidderParamsFromImpExtPrebidImp(ObjectNode ext) { return Optional.ofNullable(ext) .map(extNode -> extNode.get(EXT_PREBID)) diff --git a/src/test/java/org/prebid/server/auction/ImpAdjusterTest.java b/src/test/java/org/prebid/server/auction/ImpAdjusterTest.java index 717ca62dedd..30148ed35b9 100644 --- a/src/test/java/org/prebid/server/auction/ImpAdjusterTest.java +++ b/src/test/java/org/prebid/server/auction/ImpAdjusterTest.java @@ -1,6 +1,7 @@ package org.prebid.server.auction; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.IntNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.iab.openrtb.request.Deal; import com.iab.openrtb.request.Imp; @@ -77,6 +78,79 @@ public void adjustShouldReturnOriginalImpWhenImpExtPrebidImpIsAbsent() { assertThat(debugMessages).isEmpty(); } + @Test + public void adjustShouldSetImpExtIgsAeWhenImpExtAeIsZero() { + // given + final ObjectNode ext = mapper.createObjectNode(); + ext.set("ae", IntNode.valueOf(0)); + + final Imp givenImp = Imp.builder().ext(ext).build(); + + final List debugMessages = new ArrayList<>(); + + // when + final Imp result = target.adjust(givenImp, "someBidder", bidderAliases, debugMessages); + + // then + assertThat(result.getExt().get("igs").get(0).get("ae")).isEqualTo(IntNode.valueOf(0)); + assertThat(debugMessages).isEmpty(); + } + + @Test + public void adjustShouldSetImpExtIgsAeWhenImpExtAeIsOne() { + // given + final ObjectNode ext = mapper.createObjectNode(); + ext.set("ae", IntNode.valueOf(1)); + + final Imp givenImp = Imp.builder().ext(ext).build(); + + final List debugMessages = new ArrayList<>(); + + // when + final Imp result = target.adjust(givenImp, "someBidder", bidderAliases, debugMessages); + + // then + assertThat(result.getExt().get("igs").get(0).get("ae")).isEqualTo(IntNode.valueOf(1)); + assertThat(debugMessages).isEmpty(); + } + + @Test + public void adjustShouldNotSetImpExtIgsAeWhenImpExtAeIsNotZeroOrOne() { + // given + final ObjectNode ext = mapper.createObjectNode(); + ext.set("ae", IntNode.valueOf(3)); + + final Imp givenImp = Imp.builder().ext(ext).build(); + + final List debugMessages = new ArrayList<>(); + + // when + final Imp result = target.adjust(givenImp, "someBidder", bidderAliases, debugMessages); + + // then + assertThat(result.getExt().get("igs")).isNull(); + assertThat(debugMessages).isEmpty(); + } + + @Test + public void adjustShouldNotModifyImpExtIgsAeWhenImpExtIgsAePresent() { + // given + final ObjectNode ext = mapper.createObjectNode(); + ext.set("ae", IntNode.valueOf(0)); + ext.set("igs", mapper.createArrayNode().add(mapper.createObjectNode().set("ae", IntNode.valueOf(123)))); + + final Imp givenImp = Imp.builder().ext(ext).build(); + + final List debugMessages = new ArrayList<>(); + + // when + final Imp result = target.adjust(givenImp, "someBidder", bidderAliases, debugMessages); + + // then + assertThat(result.getExt().get("igs").get(0).get("ae")).isEqualTo(IntNode.valueOf(123)); + assertThat(debugMessages).isEmpty(); + } + @Test public void adjustShouldRemoveExpImpFromOriginalImpWhenImpExtPrebidImpHasEmptyBidder() { // given From 4ca36ba489bf3e8469885767bc7fc6f0b196dd50 Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Thu, 9 Jan 2025 16:09:53 +0200 Subject: [PATCH 10/19] Removed TODOs. --- src/main/java/org/prebid/server/auction/BidResponseCreator.java | 2 +- 1 file changed, 1 insertion(+), 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 473c09fee39..691bc693a7e 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -1213,7 +1213,7 @@ private static PaaFormat resolvePaaFormat(AuctionContext auctionContext) { .or(() -> Optional.ofNullable(auctionContext.getAccount()) .map(Account::getAuction) .map(AccountAuctionConfig::getPaaFormat)) - .orElse(PaaFormat.IAB); // TODO: Decide what default value to use + .orElse(PaaFormat.IAB); } /** From 9e492ba442a850ca4fcb4889e83d4048b95482f6 Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Thu, 9 Jan 2025 16:13:41 +0200 Subject: [PATCH 11/19] Fixed styling. --- src/main/java/org/prebid/server/auction/ImpAdjuster.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/prebid/server/auction/ImpAdjuster.java b/src/main/java/org/prebid/server/auction/ImpAdjuster.java index e34bee7d638..c53a61a9896 100644 --- a/src/main/java/org/prebid/server/auction/ImpAdjuster.java +++ b/src/main/java/org/prebid/server/auction/ImpAdjuster.java @@ -80,7 +80,7 @@ private void setEaParams(ObjectNode ext) { .map(JsonNode::asInt) .orElse(-1); - boolean extIgsEaPresent = Optional.ofNullable(ext) + final boolean extIgsEaPresent = Optional.ofNullable(ext) .map(extNode -> extNode.get(EXT_IGS)) .filter(JsonNode::isArray) .map(extNode -> StreamSupport.stream(extNode.spliterator(), false).toList()) From 8333f7c9cde946e96c3187b201a049c3677bebaf Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Thu, 9 Jan 2025 16:16:00 +0200 Subject: [PATCH 12/19] Fixed naming. --- .../java/org/prebid/server/auction/ImpAdjuster.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/prebid/server/auction/ImpAdjuster.java b/src/main/java/org/prebid/server/auction/ImpAdjuster.java index c53a61a9896..6b03d006079 100644 --- a/src/main/java/org/prebid/server/auction/ImpAdjuster.java +++ b/src/main/java/org/prebid/server/auction/ImpAdjuster.java @@ -39,7 +39,7 @@ public ImpAdjuster(JacksonMapper jacksonMapper, } public Imp adjust(Imp originalImp, String bidder, BidderAliases bidderAliases, List debugMessages) { - setEaParams(originalImp.getExt()); + setAeParams(originalImp.getExt()); final JsonNode impExtPrebidImp = bidderParamsFromImpExtPrebidImp(originalImp.getExt()); if (impExtPrebidImp == null) { @@ -73,14 +73,14 @@ public Imp adjust(Imp originalImp, String bidder, BidderAliases bidderAliases, L } } - private void setEaParams(ObjectNode ext) { - final int extEa = Optional.ofNullable(ext) + private void setAeParams(ObjectNode ext) { + final int extAe = Optional.ofNullable(ext) .map(extNode -> extNode.get(EXT_AE)) .filter(JsonNode::isInt) .map(JsonNode::asInt) .orElse(-1); - final boolean extIgsEaPresent = Optional.ofNullable(ext) + final boolean extIgsAePresent = Optional.ofNullable(ext) .map(extNode -> extNode.get(EXT_IGS)) .filter(JsonNode::isArray) .map(extNode -> StreamSupport.stream(extNode.spliterator(), false).toList()) @@ -89,9 +89,9 @@ private void setEaParams(ObjectNode ext) { .filter(Objects::nonNull) .anyMatch(igsElementNode -> igsElementNode.has(EXT_AE)); - if (!extIgsEaPresent && (extEa == 0 || extEa == 1)) { + if (!extIgsAePresent && (extAe == 0 || extAe == 1)) { final ArrayNode extIgs = jacksonMapper.mapper().createArrayNode(); - extIgs.add(jacksonMapper.mapper().createObjectNode().set(EXT_AE, IntNode.valueOf(extEa))); + extIgs.add(jacksonMapper.mapper().createObjectNode().set(EXT_AE, IntNode.valueOf(extAe))); ext.set(EXT_IGS, extIgs); } } From b0c7f3162be3b705258386404e854042cb4c03b6 Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Fri, 10 Jan 2025 15:50:51 +0200 Subject: [PATCH 13/19] Fixes after merging master --- .../server/auction/model/BidRejectionTracker.java | 11 ----------- .../prebid/server/bidder/HttpBidderRequesterTest.java | 4 ++-- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/prebid/server/auction/model/BidRejectionTracker.java b/src/main/java/org/prebid/server/auction/model/BidRejectionTracker.java index 9810606ada3..476e61fac09 100644 --- a/src/main/java/org/prebid/server/auction/model/BidRejectionTracker.java +++ b/src/main/java/org/prebid/server/auction/model/BidRejectionTracker.java @@ -47,10 +47,6 @@ public BidRejectionTracker(String bidder, Set involvedImpIds, double log rejectedBids = new HashMap<>(); } - /** - * Restores ONLY imps from rejection, rejected bids are preserved for analytics. - * A bid can be rejected only once. - */ public void succeed(Collection bids) { bids.stream() .map(BidderBid::getBid) @@ -124,10 +120,6 @@ public void rejectAllImps(BidRejectionReason reason) { involvedImpIds.forEach(impId -> rejectImp(impId, reason)); } - /** - * If an impression has at least one valid bid, it's not considered rejected. - * If no valid bids are returned for the impression, only the first one rejected reason will be returned - */ public Map getRejectedImps() { final Map rejectedImpIds = new HashMap<>(); for (String impId : involvedImpIds) { @@ -144,9 +136,6 @@ public Map getRejectedImps() { return rejectedImpIds; } - /** - * Bid is absent for the non-bid code from 0 to 299 - */ public Map>> getRejectedBids() { final Map>> missingImpIds = new HashMap<>(); for (String impId : involvedImpIds) { diff --git a/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java b/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java index c4f81dd2713..2b067ab06d8 100644 --- a/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java +++ b/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java @@ -493,8 +493,8 @@ public void shouldReturnExtIgiCreatedByBidder() { assertThat(bidderSeatBid.getBids()).hasSameElementsAs(bids); assertThat(bidderSeatBid.getIgi()).containsExactlyElementsOf(igi); - verify(bidRejectionTracker, never()).reject(anyString(), any()); - verify(bidRejectionTracker, never()).reject(anyList(), any()); + verify(bidRejectionTracker, never()).rejectImp(anyString(), any()); + verify(bidRejectionTracker, never()).rejectImps(anyList(), any()); } @Test From 85208f5bc4a04c085e642eace242f66a48b1c9bc Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Fri, 10 Jan 2025 16:34:48 +0200 Subject: [PATCH 14/19] Fixed IxTest. --- .../prebid/server/it/openrtb2/ix/test-ix-bid-request.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-request.json index ef303b14b8e..5478c38a82b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-request.json @@ -16,6 +16,11 @@ }, "ext": { "ae": 1, + "igs": [ + { + "ae": 1 + } + ], "tid": "${json-unit.any-string}", "bidder": { "siteId": "10002" From 3882deb85f8fd67dc7861ae7279c0e62fe58b807 Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Tue, 14 Jan 2025 18:21:28 +0200 Subject: [PATCH 15/19] Made paa format default to original. --- .../server/auction/BidResponseCreator.java | 8 +-- .../auction/BidResponseCreatorTest.java | 49 ++++++++++++++++++- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index 20edcd38256..7bc9f9dae1e 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -898,9 +898,9 @@ private List toExtBidResponseIgi(List bidderResponse private ExtIgi extIgiWithBidder(ExtIgi extIgi, String bidder) { final List extIgiIgs = CollectionUtils.emptyIfNull(extIgi.getIgs()).stream() - .map(igs -> Optional.ofNullable(igs) - .map(ExtIgiIgs::toBuilder) - .orElseGet(ExtIgiIgs::builder) + .filter(Objects::nonNull) + .filter(igs -> StringUtils.isNotEmpty(igs.getImpId())) + .map(igs -> igs.toBuilder() .ext(ExtIgiIgsExt.of(bidder, bidderCatalog.resolveBaseBidder(bidder))) .build()) .toList(); @@ -1229,7 +1229,7 @@ private static PaaFormat resolvePaaFormat(AuctionContext auctionContext) { .or(() -> Optional.ofNullable(auctionContext.getAccount()) .map(Account::getAuction) .map(AccountAuctionConfig::getPaaFormat)) - .orElse(PaaFormat.IAB); + .orElse(PaaFormat.ORIGINAL); } /** diff --git a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java index 2a756324eb2..c00211452e9 100644 --- a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java +++ b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java @@ -44,6 +44,7 @@ import org.prebid.server.auction.model.CachedDebugLog; import org.prebid.server.auction.model.CategoryMappingResult; import org.prebid.server.auction.model.MultiBidConfig; +import org.prebid.server.auction.model.PaaFormat; import org.prebid.server.auction.model.TargetingInfo; import org.prebid.server.auction.model.TimeoutContext; import org.prebid.server.auction.model.debug.DebugContext; @@ -91,6 +92,7 @@ import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidVideo; import org.prebid.server.proto.openrtb.ext.response.ExtBidResponse; +import org.prebid.server.proto.openrtb.ext.response.ExtBidResponseFledge; import org.prebid.server.proto.openrtb.ext.response.ExtBidResponsePrebid; import org.prebid.server.proto.openrtb.ext.response.ExtBidderError; import org.prebid.server.proto.openrtb.ext.response.ExtDebugTrace; @@ -3520,7 +3522,7 @@ public void shouldAddExtIgiIfAvailable() { final Imp imp = givenImp("i1").toBuilder() .ext(mapper.createObjectNode().put("ae", 1)) .build(); - final BidRequest bidRequest = givenBidRequest(identity(), identity(), imp); + final BidRequest bidRequest = givenBidRequest(identity(), ext -> ext.paaFormat(PaaFormat.IAB), imp); final ExtIgi igi = ExtIgi.builder() .impid("impId") .igs(singletonList(ExtIgiIgs.builder().config(mapper.createObjectNode()).build())) @@ -3554,6 +3556,51 @@ public void shouldAddExtIgiIfAvailable() { .build()); } + @Test + public void shouldDefaultToOriginalPaaFormat() { + // given + given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); + final Imp imp = givenImp("i1").toBuilder() + .ext(mapper.createObjectNode().put("ae", 1)) + .build(); + final BidRequest bidRequest = givenBidRequest(identity(), identity(), imp); + final ExtIgi igi = ExtIgi.builder() + .impid("impId") + .igs(singletonList(ExtIgiIgs.builder().config(mapper.createObjectNode()).build())) + .build(); + + final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("i1").build(); + final List bidderResponses = singletonList( + BidderResponse.of("bidder1", + BidderSeatBid.builder() + .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .igi(singletonList(igi)) + .build(), 100)); + + final AuctionContext auctionContext = givenAuctionContext( + bidRequest, + contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); + + // when + final BidResponse bidResponse = target + .create(auctionContext, CACHE_INFO, MULTI_BIDS) + .result(); + + // then + assertThat(bidResponse.getExt()) + .extracting(ExtBidResponse::getPrebid) + .extracting(ExtBidResponsePrebid::getFledge) + .extracting(ExtBidResponseFledge::getAuctionConfigs) + .asList() + .containsExactly( + FledgeAuctionConfig.builder() + .impId("impId") + .config(mapper.createObjectNode()) + .bidder("bidder1") + .adapter("adapter1") + .build()); + } + @Test public void shouldAddExtPrebidFledgeIfAvailableEvenIfBidsEmpty() { // given From 0841723ea48d22f3de9154cda3e31fb25e52adaf Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Tue, 14 Jan 2025 19:47:53 +0200 Subject: [PATCH 16/19] Added missing validations. --- .../server/auction/BidResponseCreator.java | 123 ++++++--- .../spring/config/ServiceConfiguration.java | 2 + .../auction/BidResponseCreatorTest.java | 259 +++++++++++++++++- 3 files changed, 336 insertions(+), 48 deletions(-) diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index 7bc9f9dae1e..cbb63000c5c 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -62,6 +62,9 @@ import org.prebid.server.identity.IdGeneratorType; import org.prebid.server.json.DecodeException; import org.prebid.server.json.JacksonMapper; +import org.prebid.server.log.ConditionalLogger; +import org.prebid.server.log.Logger; +import org.prebid.server.log.LoggerFactory; import org.prebid.server.proto.openrtb.ext.request.ExtImp; import org.prebid.server.proto.openrtb.ext.request.ExtImpAuctionEnvironment; import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebid; @@ -122,6 +125,9 @@ public class BidResponseCreator { + private static final Logger logger = LoggerFactory.getLogger(BidResponseCreator.class); + private static final ConditionalLogger conditionalLogger = new ConditionalLogger(logger); + private static final String CACHE = "cache"; private static final String PREBID_EXT = "prebid"; private static final Integer DEFAULT_BID_LIMIT_MIN = 1; @@ -131,6 +137,7 @@ public class BidResponseCreator { private static final String TARGETING_ENV_APP_VALUE = "mobile-app"; private static final String TARGETING_ENV_AMP_VALUE = "amp"; + private final double logSamplingRate; private final CoreCacheService coreCacheService; private final BidderCatalog bidderCatalog; private final VastModifier vastModifier; @@ -150,7 +157,8 @@ public class BidResponseCreator { private final String cachePath; private final String cacheAssetUrlTemplate; - public BidResponseCreator(CoreCacheService coreCacheService, + public BidResponseCreator(double logSamplingRate, + CoreCacheService coreCacheService, BidderCatalog bidderCatalog, VastModifier vastModifier, EventsService eventsService, @@ -180,9 +188,11 @@ public BidResponseCreator(CoreCacheService coreCacheService, this.mediaTypeCacheTtl = Objects.requireNonNull(mediaTypeCacheTtl); this.cacheDefaultProperties = Objects.requireNonNull(cacheDefaultProperties); + this.logSamplingRate = logSamplingRate; + + cacheAssetUrlTemplate = Objects.requireNonNull(coreCacheService.getCachedAssetURLTemplate()); cacheHost = Objects.requireNonNull(coreCacheService.getEndpointHost()); cachePath = Objects.requireNonNull(coreCacheService.getEndpointPath()); - cacheAssetUrlTemplate = Objects.requireNonNull(coreCacheService.getCachedAssetURLTemplate()); } private static int validateTruncateAttrChars(int truncateAttrChars) { @@ -820,21 +830,20 @@ private ExtBidResponsePrebid toExtBidResponsePrebid(long auctionTimestamp, private PaaResult toPaaOutput(List bidderResponseInfos, AuctionContext auctionContext) { final PaaFormat paaFormat = resolvePaaFormat(auctionContext); - final List extIgi = paaFormat == PaaFormat.IAB ? toExtBidResponseIgi(bidderResponseInfos) : null; + final List igis = extractIgis(bidderResponseInfos); + final List extIgi = paaFormat == PaaFormat.IAB && !igis.isEmpty() ? igis : null; - final List imps = auctionContext.getBidRequest().getImp(); + final List fledgeConfigs = paaFormat == PaaFormat.ORIGINAL + ? toOriginalFledgeFormat(igis) + : Collections.emptyList(); // TODO: Remove after transition period - final Stream deprecatedFledgeConfigs = bidderResponseInfos.stream() - .flatMap(bidderResponseInfo -> toDeprecatedFledgeConfigs(bidderResponseInfo, imps)); - - final Stream fledgeConfigs = paaFormat == PaaFormat.ORIGINAL - ? bidderResponseInfos.stream().flatMap(this::toOriginalFledgeFormat) - : Stream.empty(); - - final List combinedFledgeConfigs = Stream.concat(deprecatedFledgeConfigs, fledgeConfigs) + final List imps = auctionContext.getBidRequest().getImp(); + final List deprecatedFledgeConfigs = bidderResponseInfos.stream() + .flatMap(bidderResponseInfo -> toDeprecatedFledgeConfigs(bidderResponseInfo, imps)) .toList(); + final List combinedFledgeConfigs = ListUtils.union(deprecatedFledgeConfigs, fledgeConfigs); final ExtBidResponseFledge extBidResponseFledge = combinedFledgeConfigs.isEmpty() ? null : ExtBidResponseFledge.of(combinedFledgeConfigs); @@ -842,20 +851,71 @@ private PaaResult toPaaOutput(List bidderResponseInfos, Auct return new PaaResult(extIgi, extBidResponseFledge); } - private Stream toOriginalFledgeFormat(BidderResponseInfo bidderResponseInfo) { - return Optional.ofNullable(bidderResponseInfo.getSeatBid().getIgi()).stream() - .flatMap(Collection::stream) + private List extractIgis(List bidderResponseInfos) { + return bidderResponseInfos.stream() + .flatMap(responseInfo -> responseInfo.getSeatBid().getIgi().stream() + .map(igi -> prepareExtIgi(igi, responseInfo.getBidder()))) .filter(Objects::nonNull) + .toList(); + } + + private ExtIgi prepareExtIgi(ExtIgi igi, String bidder) { + if (igi == null) { + return null; + } + + if (StringUtils.isEmpty(igi.getImpid())) { + conditionalLogger.warn("ExtIgi with absent impId", logSamplingRate); + return null; + } + + final List preparedIgs = prepareExtIgiIgs(igi.getIgs(), bidder); + return igi.toBuilder().igs(preparedIgs.isEmpty() ? null : preparedIgs).build(); + } + + private List prepareExtIgiIgs(List igiIgs, String bidder) { + if (igiIgs == null) { + return Collections.emptyList(); + } + + final List preparedIgiIgs = new ArrayList<>(); + for (ExtIgiIgs extIgiIgs : igiIgs) { + if (extIgiIgs == null) { + continue; + } + + if (StringUtils.isEmpty(extIgiIgs.getImpId())) { + conditionalLogger.warn("ExtIgiIgs with absent impId", logSamplingRate); + continue; + } + + if (extIgiIgs.getConfig() == null) { + conditionalLogger.warn("ExtIgiIgs with absent config", logSamplingRate); + continue; + } + + final ExtIgiIgs preparedExtIgiIgs = extIgiIgs.toBuilder() + .ext(ExtIgiIgsExt.of(bidder, bidderCatalog.resolveBaseBidder(bidder))) + .build(); + + preparedIgiIgs.add(preparedExtIgiIgs); + } + + return preparedIgiIgs; + } + + private List toOriginalFledgeFormat(List igis) { + return igis.stream() .map(ExtIgi::getIgs) - .filter(Objects::nonNull) .flatMap(Collection::stream) - .map(extIgiIgs -> extIgiIgsToFledgeConfig(extIgiIgs, bidderResponseInfo.getBidder())); + .map(BidResponseCreator::extIgiIgsToFledgeConfig) + .toList(); } - private FledgeAuctionConfig extIgiIgsToFledgeConfig(ExtIgiIgs extIgiIgs, String bidder) { + private static FledgeAuctionConfig extIgiIgsToFledgeConfig(ExtIgiIgs extIgiIgs) { return FledgeAuctionConfig.builder() - .bidder(bidder) - .adapter(bidderCatalog.resolveBaseBidder(bidder)) + .bidder(extIgiIgs.getExt().getBidder()) + .adapter(extIgiIgs.getExt().getAdapter()) .impId(extIgiIgs.getImpId()) .config(extIgiIgs.getConfig()) .build(); @@ -887,29 +947,6 @@ private FledgeAuctionConfig fledgeConfigWithBidder(FledgeAuctionConfig fledgeCon .build(); } - private List toExtBidResponseIgi(List bidderResponseInfos) { - final List extIgi = bidderResponseInfos.stream() - .flatMap(responseInfo -> responseInfo.getSeatBid().getIgi().stream() - .map(igi -> extIgiWithBidder(igi, responseInfo.getBidder()))) - .toList(); - - return extIgi.isEmpty() ? null : extIgi; - } - - private ExtIgi extIgiWithBidder(ExtIgi extIgi, String bidder) { - final List extIgiIgs = CollectionUtils.emptyIfNull(extIgi.getIgs()).stream() - .filter(Objects::nonNull) - .filter(igs -> StringUtils.isNotEmpty(igs.getImpId())) - .map(igs -> igs.toBuilder() - .ext(ExtIgiIgsExt.of(bidder, bidderCatalog.resolveBaseBidder(bidder))) - .build()) - .toList(); - - return extIgiIgs.isEmpty() - ? extIgi - : extIgi.toBuilder().igs(extIgiIgs).build(); - } - private static ExtResponseDebug toExtResponseDebug(List bidderResponseInfos, AuctionContext auctionContext, CacheServiceResult cacheResult, diff --git a/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java b/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java index deaa768320c..fa7cc267457 100644 --- a/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java @@ -807,6 +807,7 @@ CacheDefaultTtlProperties cacheDefaultTtlProperties( @Bean BidResponseCreator bidResponseCreator( + @Value("${logging.sampling-rate:0.01}") double logSamplingRate, CoreCacheService coreCacheService, BidderCatalog bidderCatalog, VastModifier vastModifier, @@ -824,6 +825,7 @@ BidResponseCreator bidResponseCreator( CacheDefaultTtlProperties cacheDefaultTtlProperties) { return new BidResponseCreator( + logSamplingRate, coreCacheService, bidderCatalog, vastModifier, diff --git a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java index c00211452e9..c3b19bcc491 100644 --- a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java +++ b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java @@ -1640,6 +1640,7 @@ public void shouldTruncateTargetingKeywordsByGlobalConfig() { contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); target = new BidResponseCreator( + 0, coreCacheService, bidderCatalog, vastModifier, @@ -3516,7 +3517,7 @@ public void shouldAddExtPrebidFledgeIfAvailable() { } @Test - public void shouldAddExtIgiIfAvailable() { + public void shouldAddExtIgiIfAvailableAndExtRequestPrebidPaaFormatIsIab() { // given given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); final Imp imp = givenImp("i1").toBuilder() @@ -3525,7 +3526,7 @@ public void shouldAddExtIgiIfAvailable() { final BidRequest bidRequest = givenBidRequest(identity(), ext -> ext.paaFormat(PaaFormat.IAB), imp); final ExtIgi igi = ExtIgi.builder() .impid("impId") - .igs(singletonList(ExtIgiIgs.builder().config(mapper.createObjectNode()).build())) + .igs(singletonList(ExtIgiIgs.builder().impId("impId").config(mapper.createObjectNode()).build())) .build(); final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("i1").build(); @@ -3550,26 +3551,167 @@ public void shouldAddExtIgiIfAvailable() { ExtIgi.builder() .impid("impId") .igs(singletonList(ExtIgiIgs.builder() + .impId("impId") .config(mapper.createObjectNode()) .ext(ExtIgiIgsExt.of("bidder1", "adapter1")) .build())) .build()); } + @Test + public void shouldAddExtPrebidFledgeIfAvailableAndExtRequestPrebidPaaFormatIsOriginal() { + // given + given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); + final Imp imp = givenImp("impId").toBuilder() + .ext(mapper.createObjectNode().put("ae", 1)) + .build(); + final BidRequest bidRequest = givenBidRequest(identity(), ext -> ext.paaFormat(PaaFormat.ORIGINAL), imp); + final ExtIgi igi = ExtIgi.builder() + .impid("impId") + .igs(singletonList(ExtIgiIgs.builder().impId("impId").config(mapper.createObjectNode()).build())) + .build(); + + final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("impId").build(); + final List bidderResponses = singletonList( + BidderResponse.of("bidder1", + BidderSeatBid.builder() + .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .igi(singletonList(igi)) + .build(), 100)); + + final AuctionContext auctionContext = givenAuctionContext( + bidRequest, + contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); + + // when + final BidResponse bidResponse = target + .create(auctionContext, CACHE_INFO, MULTI_BIDS) + .result(); + + // then + assertThat(bidResponse.getExt()) + .extracting(ExtBidResponse::getPrebid) + .extracting(ExtBidResponsePrebid::getFledge) + .extracting(ExtBidResponseFledge::getAuctionConfigs) + .asList() + .containsExactly( + FledgeAuctionConfig.builder() + .impId("impId") + .config(mapper.createObjectNode()) + .bidder("bidder1") + .adapter("adapter1") + .build()); + } + + @Test + public void shouldAddExtIgiIfAvailableAndExtRequestPrebidPaaFormatIsAbsentAndAccountConfigPaaFormatSetToIab() { + // given + given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); + final Imp imp = givenImp("impId").toBuilder() + .ext(mapper.createObjectNode().put("ae", 1)) + .build(); + final BidRequest bidRequest = givenBidRequest(identity(), identity(), imp); + final ExtIgi igi = ExtIgi.builder() + .impid("impId") + .igs(singletonList(ExtIgiIgs.builder().impId("impId").config(mapper.createObjectNode()).build())) + .build(); + + final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("impId").build(); + final List bidderResponses = singletonList( + BidderResponse.of("bidder1", + BidderSeatBid.builder() + .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .igi(singletonList(igi)) + .build(), 100)); + + final AuctionContext auctionContext = givenAuctionContext( + bidRequest, + contextBuilder -> contextBuilder + .auctionParticipations(toAuctionParticipant(bidderResponses)) + .account(Account.builder() + .auction(AccountAuctionConfig.builder().paaFormat(PaaFormat.IAB).build()) + .build())); + + // when + final BidResponse bidResponse = target + .create(auctionContext, CACHE_INFO, MULTI_BIDS) + .result(); + + // then + assertThat(bidResponse.getExt().getIgi()).containsExactly( + ExtIgi.builder() + .impid("impId") + .igs(singletonList(ExtIgiIgs.builder() + .impId("impId") + .config(mapper.createObjectNode()) + .ext(ExtIgiIgsExt.of("bidder1", "adapter1")) + .build())) + .build()); + } + + @Test + public void shouldAddExtPrebidFledgeIfAvailableAndRequestPaaFormatIsAbsentAndAccountConfigPaaFormatSetToOriginal() { + // given + given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); + final Imp imp = givenImp("impId").toBuilder() + .ext(mapper.createObjectNode().put("ae", 1)) + .build(); + final BidRequest bidRequest = givenBidRequest(identity(), identity(), imp); + final ExtIgi igi = ExtIgi.builder() + .impid("impId") + .igs(singletonList(ExtIgiIgs.builder().impId("impId").config(mapper.createObjectNode()).build())) + .build(); + + final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("impId").build(); + final List bidderResponses = singletonList( + BidderResponse.of("bidder1", + BidderSeatBid.builder() + .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .igi(singletonList(igi)) + .build(), 100)); + + final AuctionContext auctionContext = givenAuctionContext( + bidRequest, + contextBuilder -> contextBuilder + .auctionParticipations(toAuctionParticipant(bidderResponses)) + .account(Account.builder() + .auction(AccountAuctionConfig.builder().paaFormat(PaaFormat.ORIGINAL).build()) + .build())); + + // when + final BidResponse bidResponse = target + .create(auctionContext, CACHE_INFO, MULTI_BIDS) + .result(); + + // then + assertThat(bidResponse.getExt()) + .extracting(ExtBidResponse::getPrebid) + .extracting(ExtBidResponsePrebid::getFledge) + .extracting(ExtBidResponseFledge::getAuctionConfigs) + .asList() + .containsExactly( + FledgeAuctionConfig.builder() + .impId("impId") + .config(mapper.createObjectNode()) + .bidder("bidder1") + .adapter("adapter1") + .build()); + } + @Test public void shouldDefaultToOriginalPaaFormat() { // given given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); - final Imp imp = givenImp("i1").toBuilder() + final Imp imp = givenImp("impId").toBuilder() .ext(mapper.createObjectNode().put("ae", 1)) .build(); final BidRequest bidRequest = givenBidRequest(identity(), identity(), imp); final ExtIgi igi = ExtIgi.builder() .impid("impId") - .igs(singletonList(ExtIgiIgs.builder().config(mapper.createObjectNode()).build())) + .igs(singletonList(ExtIgiIgs.builder().impId("impId").config(mapper.createObjectNode()).build())) .build(); - final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("i1").build(); + final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("impId").build(); final List bidderResponses = singletonList( BidderResponse.of("bidder1", BidderSeatBid.builder() @@ -3601,6 +3743,112 @@ public void shouldDefaultToOriginalPaaFormat() { .build()); } + @Test + public void shouldDropExtIgiIfAvailableAndExtIgiImpIdIsAbsent() { + // given + final Imp imp = givenImp("impId").toBuilder() + .ext(mapper.createObjectNode().put("ae", 1)) + .build(); + final BidRequest bidRequest = givenBidRequest(identity(), ext -> ext.paaFormat(PaaFormat.IAB), imp); + final ExtIgi igi = ExtIgi.builder() + .igs(singletonList(ExtIgiIgs.builder().impId("impId").config(mapper.createObjectNode()).build())) + .build(); + + final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("impId").build(); + final List bidderResponses = singletonList( + BidderResponse.of("bidder1", + BidderSeatBid.builder() + .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .igi(singletonList(igi)) + .build(), 100)); + + final AuctionContext auctionContext = givenAuctionContext( + bidRequest, + contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); + + // when + final BidResponse bidResponse = target + .create(auctionContext, CACHE_INFO, MULTI_BIDS) + .result(); + + // then + assertThat(bidResponse.getExt()) + .extracting(ExtBidResponse::getIgi) + .isNull(); + } + + @Test + public void shouldDropExtIgiIgsIfAvailableAndExtIgiIgsImpIdIsAbsent() { + // given + final Imp imp = givenImp("impId").toBuilder() + .ext(mapper.createObjectNode().put("ae", 1)) + .build(); + final BidRequest bidRequest = givenBidRequest(identity(), ext -> ext.paaFormat(PaaFormat.IAB), imp); + final ExtIgi igi = ExtIgi.builder() + .impid("impId") + .igs(singletonList(ExtIgiIgs.builder().config(mapper.createObjectNode()).build())) + .build(); + + final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("impId").build(); + final List bidderResponses = singletonList( + BidderResponse.of("bidder1", + BidderSeatBid.builder() + .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .igi(singletonList(igi)) + .build(), 100)); + + final AuctionContext auctionContext = givenAuctionContext( + bidRequest, + contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); + + // when + final BidResponse bidResponse = target + .create(auctionContext, CACHE_INFO, MULTI_BIDS) + .result(); + + // then + assertThat(bidResponse.getExt()) + .extracting(ExtBidResponse::getIgi) + .asList() + .containsExactly(ExtIgi.builder().impid("impId").build()); + } + + @Test + public void shouldDropExtIgiIgsIfAvailableAndExtIgiIgsConfigIsAbsent() { + // given + final Imp imp = givenImp("impId").toBuilder() + .ext(mapper.createObjectNode().put("ae", 1)) + .build(); + final BidRequest bidRequest = givenBidRequest(identity(), ext -> ext.paaFormat(PaaFormat.IAB), imp); + final ExtIgi igi = ExtIgi.builder() + .impid("impId") + .igs(singletonList(ExtIgiIgs.builder().impId("impId").build())) + .build(); + + final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("impId").build(); + final List bidderResponses = singletonList( + BidderResponse.of("bidder1", + BidderSeatBid.builder() + .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .igi(singletonList(igi)) + .build(), 100)); + + final AuctionContext auctionContext = givenAuctionContext( + bidRequest, + contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); + + // when + final BidResponse bidResponse = target + .create(auctionContext, CACHE_INFO, MULTI_BIDS) + .result(); + + // then + assertThat(bidResponse.getExt()) + .extracting(ExtBidResponse::getIgi) + .asList() + .containsExactly(ExtIgi.builder().impid("impId").build()); + } + @Test public void shouldAddExtPrebidFledgeIfAvailableEvenIfBidsEmpty() { // given @@ -5114,6 +5362,7 @@ private static ExtBidPrebid toExtBidPrebid(ObjectNode ext) { private BidResponseCreator givenBidResponseCreator(int truncateAttrChars) { return new BidResponseCreator( + 0, coreCacheService, bidderCatalog, vastModifier, From 032f15f7a6552744dedf05b41c823527273edd0b Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Tue, 14 Jan 2025 20:04:11 +0200 Subject: [PATCH 17/19] Fixed inconsistent unit test. --- src/main/java/org/prebid/server/handler/SetuidHandler.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/prebid/server/handler/SetuidHandler.java b/src/main/java/org/prebid/server/handler/SetuidHandler.java index 1f6bed55e5f..f440c940a74 100644 --- a/src/main/java/org/prebid/server/handler/SetuidHandler.java +++ b/src/main/java/org/prebid/server/handler/SetuidHandler.java @@ -152,6 +152,7 @@ private static void validateUsersyncers(Stream usersyncers) { .filter(name -> name.getValue() > 1) .map(Map.Entry::getKey) .distinct() + .sorted() .toList(); if (CollectionUtils.isNotEmpty(cookieFamilyNameDuplicates)) { throw new IllegalArgumentException( From 7fd613ecc9b91718cf048d993804a0bc0e670679 Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Wed, 15 Jan 2025 14:53:06 +0200 Subject: [PATCH 18/19] Fixed igi validations. --- .../server/auction/BidResponseCreator.java | 20 ++++-- .../auction/BidResponseCreatorTest.java | 64 +++++++++++++++++-- 2 files changed, 73 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index cbb63000c5c..0ae43405432 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -87,6 +87,7 @@ import org.prebid.server.proto.openrtb.ext.response.ExtDebugTrace; import org.prebid.server.proto.openrtb.ext.response.ExtHttpCall; import org.prebid.server.proto.openrtb.ext.response.ExtIgi; +import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgb; import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgs; import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgsExt; import org.prebid.server.proto.openrtb.ext.response.ExtResponseCache; @@ -864,13 +865,18 @@ private ExtIgi prepareExtIgi(ExtIgi igi, String bidder) { return null; } - if (StringUtils.isEmpty(igi.getImpid())) { - conditionalLogger.warn("ExtIgi with absent impId", logSamplingRate); - return null; + boolean shouldDropIgb = StringUtils.isEmpty(igi.getImpid()); + if (shouldDropIgb) { + conditionalLogger.warn("ExtIgi with absent impId from bidder: " + bidder, logSamplingRate); } - final List preparedIgs = prepareExtIgiIgs(igi.getIgs(), bidder); - return igi.toBuilder().igs(preparedIgs.isEmpty() ? null : preparedIgs).build(); + final List updatedIgs = prepareExtIgiIgs(igi.getIgs(), bidder); + final List preparedIgs = updatedIgs.isEmpty() ? null : updatedIgs; + final List preparedIgb = shouldDropIgb ? null : igi.getIgb(); + + return ObjectUtils.anyNotNull(preparedIgs, preparedIgb) + ? igi.toBuilder().igs(preparedIgs).igb(preparedIgb).build() + : null; } private List prepareExtIgiIgs(List igiIgs, String bidder) { @@ -885,12 +891,12 @@ private List prepareExtIgiIgs(List igiIgs, String bidder) } if (StringUtils.isEmpty(extIgiIgs.getImpId())) { - conditionalLogger.warn("ExtIgiIgs with absent impId", logSamplingRate); + conditionalLogger.warn("ExtIgiIgs with absent impId from bidder: " + bidder, logSamplingRate); continue; } if (extIgiIgs.getConfig() == null) { - conditionalLogger.warn("ExtIgiIgs with absent config", logSamplingRate); + conditionalLogger.warn("ExtIgiIgs with absent config from bidder: " + bidder, logSamplingRate); continue; } diff --git a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java index c3b19bcc491..0b6d4b67b9f 100644 --- a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java +++ b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java @@ -98,6 +98,7 @@ import org.prebid.server.proto.openrtb.ext.response.ExtDebugTrace; import org.prebid.server.proto.openrtb.ext.response.ExtHttpCall; import org.prebid.server.proto.openrtb.ext.response.ExtIgi; +import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgb; import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgs; import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgsExt; import org.prebid.server.proto.openrtb.ext.response.ExtResponseCache; @@ -3744,14 +3745,16 @@ public void shouldDefaultToOriginalPaaFormat() { } @Test - public void shouldDropExtIgiIfAvailableAndExtIgiImpIdIsAbsent() { + public void shouldDropExtIgiIgbIfAvailableAndExtIgiImpIdIsAbsent() { // given + given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); final Imp imp = givenImp("impId").toBuilder() .ext(mapper.createObjectNode().put("ae", 1)) .build(); final BidRequest bidRequest = givenBidRequest(identity(), ext -> ext.paaFormat(PaaFormat.IAB), imp); final ExtIgi igi = ExtIgi.builder() .igs(singletonList(ExtIgiIgs.builder().impId("impId").config(mapper.createObjectNode()).build())) + .igb(singletonList(ExtIgiIgb.builder().build())) .build(); final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("impId").build(); @@ -3774,7 +3777,16 @@ public void shouldDropExtIgiIfAvailableAndExtIgiImpIdIsAbsent() { // then assertThat(bidResponse.getExt()) .extracting(ExtBidResponse::getIgi) - .isNull(); + .asList() + .containsExactly( + ExtIgi.builder() + .igs(singletonList( + ExtIgiIgs.builder() + .impId("impId") + .config(mapper.createObjectNode()) + .ext(ExtIgiIgsExt.of("bidder1", "adapter1")) + .build())) + .build()); } @Test @@ -3787,6 +3799,7 @@ public void shouldDropExtIgiIgsIfAvailableAndExtIgiIgsImpIdIsAbsent() { final ExtIgi igi = ExtIgi.builder() .impid("impId") .igs(singletonList(ExtIgiIgs.builder().config(mapper.createObjectNode()).build())) + .igb(singletonList(ExtIgiIgb.builder().build())) .build(); final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("impId").build(); @@ -3810,7 +3823,11 @@ public void shouldDropExtIgiIgsIfAvailableAndExtIgiIgsImpIdIsAbsent() { assertThat(bidResponse.getExt()) .extracting(ExtBidResponse::getIgi) .asList() - .containsExactly(ExtIgi.builder().impid("impId").build()); + .containsExactly( + ExtIgi.builder() + .impid("impId") + .igb(singletonList(ExtIgiIgb.builder().build())) + .build()); } @Test @@ -3823,6 +3840,7 @@ public void shouldDropExtIgiIgsIfAvailableAndExtIgiIgsConfigIsAbsent() { final ExtIgi igi = ExtIgi.builder() .impid("impId") .igs(singletonList(ExtIgiIgs.builder().impId("impId").build())) + .igb(singletonList(ExtIgiIgb.builder().build())) .build(); final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("impId").build(); @@ -3846,7 +3864,45 @@ public void shouldDropExtIgiIgsIfAvailableAndExtIgiIgsConfigIsAbsent() { assertThat(bidResponse.getExt()) .extracting(ExtBidResponse::getIgi) .asList() - .containsExactly(ExtIgi.builder().impid("impId").build()); + .containsExactly( + ExtIgi.builder() + .impid("impId") + .igb(singletonList(ExtIgiIgb.builder().build())) + .build()); + } + + @Test + public void shouldDropExtIgiIfAvailableAndExtIgiIgsAndExtIgiIgbAreAbsent() { + // given + final Imp imp = givenImp("impId").toBuilder() + .ext(mapper.createObjectNode().put("ae", 1)) + .build(); + final BidRequest bidRequest = givenBidRequest(identity(), ext -> ext.paaFormat(PaaFormat.IAB), imp); + final ExtIgi igi = ExtIgi.builder() + .impid("impId") + .build(); + + final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(2.37)).impid("impId").build(); + final List bidderResponses = singletonList( + BidderResponse.of("bidder1", + BidderSeatBid.builder() + .bids(List.of(BidderBid.of(bid, banner, "USD"))) + .igi(singletonList(igi)) + .build(), 100)); + + final AuctionContext auctionContext = givenAuctionContext( + bidRequest, + contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); + + // when + final BidResponse bidResponse = target + .create(auctionContext, CACHE_INFO, MULTI_BIDS) + .result(); + + // then + assertThat(bidResponse.getExt()) + .extracting(ExtBidResponse::getIgi) + .isNull(); } @Test From bfffd2ffe0efd3e3a773172bcccd28d8eca48924 Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Wed, 15 Jan 2025 14:55:04 +0200 Subject: [PATCH 19/19] Fixed styling. --- src/main/java/org/prebid/server/auction/BidResponseCreator.java | 2 +- 1 file changed, 1 insertion(+), 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 0ae43405432..2b2bc898374 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -865,7 +865,7 @@ private ExtIgi prepareExtIgi(ExtIgi igi, String bidder) { return null; } - boolean shouldDropIgb = StringUtils.isEmpty(igi.getImpid()); + final boolean shouldDropIgb = StringUtils.isEmpty(igi.getImpid()); if (shouldDropIgb) { conditionalLogger.warn("ExtIgi with absent impId from bidder: " + bidder, logSamplingRate); }