diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index 86fe28fdcbe..2b2bc898374 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; @@ -61,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; @@ -82,6 +86,10 @@ 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.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; import org.prebid.server.proto.openrtb.ext.response.ExtResponseDebug; import org.prebid.server.proto.openrtb.ext.response.ExtTraceActivityInfrastructure; @@ -118,6 +126,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; @@ -127,6 +138,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; @@ -146,7 +158,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, @@ -176,9 +189,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) { @@ -418,7 +433,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())); } @@ -778,9 +794,12 @@ private ExtBidResponse toExtBidResponse(List bidderResponseI final Map responseTimeMillis = toResponseTimes(bidderResponseInfos, cacheResult); - 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) @@ -788,6 +807,7 @@ private ExtBidResponse toExtBidResponse(List bidderResponseI .warnings(warnings) .responsetimemillis(responseTimeMillis) .tmaxrequest(auctionContext.getBidRequest().getTmax()) + .igi(igi) .prebid(prebid) .build(); } @@ -809,17 +829,107 @@ 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 igis = extractIgis(bidderResponseInfos); + final List extIgi = paaFormat == PaaFormat.IAB && !igis.isEmpty() ? igis : null; + + final List fledgeConfigs = paaFormat == PaaFormat.ORIGINAL + ? toOriginalFledgeFormat(igis) + : Collections.emptyList(); + // TODO: Remove after transition period final List imps = auctionContext.getBidRequest().getImp(); - final List fledgeConfigs = bidderResponseInfos.stream() - .flatMap(bidderResponseInfo -> fledgeConfigsForBidder(bidderResponseInfo, imps)) + 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); + + return new PaaResult(extIgi, extBidResponseFledge); + } + + 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; + } + + final boolean shouldDropIgb = StringUtils.isEmpty(igi.getImpid()); + if (shouldDropIgb) { + conditionalLogger.warn("ExtIgi with absent impId from bidder: " + bidder, logSamplingRate); + } + + 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) { + 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 from bidder: " + bidder, logSamplingRate); + continue; + } + + if (extIgiIgs.getConfig() == null) { + conditionalLogger.warn("ExtIgiIgs with absent config from bidder: " + bidder, 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) + .flatMap(Collection::stream) + .map(BidResponseCreator::extIgiIgsToFledgeConfig) .toList(); - return !fledgeConfigs.isEmpty() ? ExtBidResponseFledge.of(fledgeConfigs) : null; } - private Stream fledgeConfigsForBidder(BidderResponseInfo bidderResponseInfo, List imps) { + private static FledgeAuctionConfig extIgiIgsToFledgeConfig(ExtIgiIgs extIgiIgs) { + return FledgeAuctionConfig.builder() + .bidder(extIgiIgs.getExt().getBidder()) + .adapter(extIgiIgs.getExt().getAdapter()) + .impId(extIgiIgs.getImpId()) + .config(extIgiIgs.getConfig()) + .build(); + } + + private Stream toDeprecatedFledgeConfigs(BidderResponseInfo bidderResponseInfo, + List imps) { + return Optional.ofNullable(bidderResponseInfo.getSeatBid().getFledgeAuctionConfigs()) .stream() .flatMap(Collection::stream) @@ -836,10 +946,10 @@ 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(); } @@ -1154,6 +1264,17 @@ private static Map toResponseTimes(Collection Optional.ofNullable(auctionContext.getAccount()) + .map(Account::getAuction) + .map(AccountAuctionConfig::getPaaFormat)) + .orElse(PaaFormat.ORIGINAL); + } + /** * Returns {@link BidResponse} based on list of {@link BidderResponse}s and {@link CacheServiceResult}. */ @@ -1800,4 +1921,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/ImpAdjuster.java b/src/main/java/org/prebid/server/auction/ImpAdjuster.java index 86e581b06e8..6b03d006079 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) { + setAeParams(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 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 extIgsAePresent = 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 (!extIgsAePresent && (extAe == 0 || extAe == 1)) { + final ArrayNode extIgs = jacksonMapper.mapper().createArrayNode(); + extIgs.add(jacksonMapper.mapper().createObjectNode().set(EXT_AE, IntNode.valueOf(extAe))); + 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/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/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/HttpBidderRequester.java b/src/main/java/org/prebid/server/bidder/HttpBidderRequester.java index 0345aa4c29e..3a24683c774 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(); } 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..be29b4d1d4a 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 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 d184aefc297..a82d6a72e63 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(igiIgs -> ExtIgiIgs.builder().impId(igiIgs.getImpId()).config(igiIgs.getConfig()).build()) .toList(); + + return igs.isEmpty() ? null : 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..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,15 +1,14 @@ 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; +import org.prebid.server.proto.openrtb.ext.response.ExtIgi; import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; import java.util.List; -@AllArgsConstructor(staticName = "of") -@Value +@Value(staticConstructor = "of") public class BidderSeatBidInfo { List bidsInfos; @@ -20,9 +19,18 @@ public class BidderSeatBidInfo { List warnings; + @Deprecated(forRemoval = true) 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 7e5a31f16b0..75a71e0864a 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,19 +27,12 @@ public class CompositeBidderResponse { */ List fledgeAuctionConfigs; + List igi; + 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 6cdae97b5cb..f37547e90cf 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; @@ -88,9 +89,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())); } @@ -312,14 +317,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(ext -> ExtIgiIgs.builder().impId(ext.getKey()).config(ext.getValue()).build()) .toList(); + + 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 d84465416f8..4a9e9818688 100644 --- a/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java +++ b/src/main/java/org/prebid/server/bidder/pubmatic/PubmaticBidder.java @@ -43,7 +43,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; @@ -496,11 +497,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())); } @@ -609,14 +613,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(config -> ExtIgiIgs.builder().impId(config.getKey()).config(config.getValue()).build()) .toList(); + + return igs.isEmpty() ? null : Collections.singletonList(ExtIgi.builder().igs(igs).build()); } } diff --git a/src/main/java/org/prebid/server/handler/SetuidHandler.java b/src/main/java/org/prebid/server/handler/SetuidHandler.java index 728285fb0f6..450cc1f7efa 100644 --- a/src/main/java/org/prebid/server/handler/SetuidHandler.java +++ b/src/main/java/org/prebid/server/handler/SetuidHandler.java @@ -138,6 +138,7 @@ private static void validateUsersyncersDuplicates(BidderCatalog bidderCatalog) { .map(Usersyncer::getCookieFamilyName) .filter(Predicate.not(StreamUtil.distinctBy(Function.identity()))) .distinct() + .sorted() .toList(); if (!duplicatedCookieFamilyNames.isEmpty()) { 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/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..49e84d9739f --- /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 + */ +@Builder(toBuilder = true) +@Value(staticConstructor = "of") +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..a243380bb4e --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtIgiIgs.java @@ -0,0 +1,18 @@ +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; + +@Builder(toBuilder = true) +@Value(staticConstructor = "of") +public class ExtIgiIgs { + + @JsonProperty("impid") + 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; +} 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; } 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 19181bf3503..0b6d4b67b9f 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,10 +92,15 @@ 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; 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; import org.prebid.server.proto.openrtb.ext.response.ExtResponseDebug; import org.prebid.server.proto.openrtb.ext.response.ExtTraceActivityInfrastructure; @@ -1635,6 +1641,7 @@ public void shouldTruncateTargetingKeywordsByGlobalConfig() { contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); target = new BidResponseCreator( + 0, coreCacheService, bidderCatalog, vastModifier, @@ -3476,6 +3483,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(); @@ -3505,13 +3513,402 @@ public void shouldAddExtPrebidFledgeIfAvailable() { .usingRecursiveComparison() .isEqualTo(fledgeAuctionConfig.toBuilder() .bidder("bidder1") - .adapter("bidder1") + .adapter("adapter1") .build()); } + @Test + public void shouldAddExtIgiIfAvailableAndExtRequestPrebidPaaFormatIsIab() { + // 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(), ext -> ext.paaFormat(PaaFormat.IAB), 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("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() + .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("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))); + + // 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 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(); + 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() + .igs(singletonList( + ExtIgiIgs.builder() + .impId("impId") + .config(mapper.createObjectNode()) + .ext(ExtIgiIgsExt.of("bidder1", "adapter1")) + .build())) + .build()); + } + + @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())) + .igb(singletonList(ExtIgiIgb.builder().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") + .igb(singletonList(ExtIgiIgb.builder().build())) + .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())) + .igb(singletonList(ExtIgiIgb.builder().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") + .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 public void shouldAddExtPrebidFledgeIfAvailableEvenIfBidsEmpty() { // given + given(bidderCatalog.resolveBaseBidder("bidder1")).willReturn("adapter1"); final Imp imp = givenImp("i1").toBuilder() .ext(mapper.createObjectNode().put("ae", 1)) .build(); @@ -3540,7 +3937,7 @@ public void shouldAddExtPrebidFledgeIfAvailableEvenIfBidsEmpty() { .usingRecursiveComparison() .isEqualTo(fledgeAuctionConfig.toBuilder() .bidder("bidder1") - .adapter("bidder1") + .adapter("adapter1") .build()); } @@ -5021,6 +5418,7 @@ private static ExtBidPrebid toExtBidPrebid(ObjectNode ext) { private BidResponseCreator givenBidResponseCreator(int truncateAttrChars) { return new BidResponseCreator( + 0, coreCacheService, bidderCatalog, vastModifier, 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 diff --git a/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java b/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java index d2ce145e7ef..2b067ab06d8 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; @@ -196,7 +198,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 +348,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 +381,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 +418,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") @@ -446,6 +450,53 @@ public void shouldReturnFledgeCreatedByBidder() { verify(bidRejectionTracker, never()).rejectImps(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()).rejectImp(anyString(), any()); + verify(bidRejectionTracker, never()).rejectImps(anyList(), any()); + } + @Test public void shouldCompressRequestBodyIfContentEncodingHeaderIsGzip() { // given @@ -555,8 +606,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 +655,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 +788,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/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(FunctionThis 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 @@ -753,13 +757,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 66a1888a2a4..ae22bb5a300 100644 --- a/src/test/java/org/prebid/server/bidder/pubmatic/PubmaticBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/pubmatic/PubmaticBidderTest.java @@ -42,7 +42,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; @@ -1273,11 +1274,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)); @@ -1289,11 +1290,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 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-response.json b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-response.json index 1ecdc0136a1..c2c8e90c3f5 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-response.json @@ -28,47 +28,7 @@ "ix": "{{ ix.response_time_ms }}" }, "prebid": { - "auctiontimestamp": 0, - "fledge": { - "auctionconfigs": [ - { - "impid": "imp_id", - "bidder": "ix", - "adapter": "ix", - "config": { - "seller": "https://test.casalemedia.com", - "decisionLogicUrl": "https://test.casalemedia.com/decision-logic.js", - "trustedScoringSignalsURL": "https://test.casalemedia.com/123", - "interestGroupBuyers": [ - "https://test.com" - ], - "sellerSignals": { - "callbackURL": "https://test.casalemedia.com/callback/1", - "debugURL": "https://test.casalemedia.com/debug/1", - "width": 300, - "height": 250 - }, - "sellerTimeout": 150, - "perBuyerSignals": { - "https://test.com": [ - { - "key": "value" - } - ] - }, - "perBuyerCurrencies": { - "*": "USD" - }, - "sellerCurrency": "USD", - "requestedSize": { - "width": 300, - "height": 250 - }, - "maxTrustedBiddingSignalsURLLength": 1000 - } - } - ] - } + "auctiontimestamp": 0 }, "tmaxrequest": 5000 } 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" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-response.json index c62e7c626b9..9d9d7035ed7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-response.json @@ -13,43 +13,5 @@ ], "seat": "seatId6" } - ], - "ext": { - "protectedAudienceAuctionConfigs": [ - { - "bidId": "imp_id", - "config": { - "seller": "https://test.casalemedia.com", - "decisionLogicUrl": "https://test.casalemedia.com/decision-logic.js", - "trustedScoringSignalsURL": "https://test.casalemedia.com/123", - "interestGroupBuyers": [ - "https://test.com" - ], - "sellerSignals": { - "callbackURL": "https://test.casalemedia.com/callback/1", - "debugURL": "https://test.casalemedia.com/debug/1", - "width": 300, - "height": 250 - }, - "sellerTimeout": 150, - "perBuyerSignals": { - "https://test.com": [ - { - "key": "value" - } - ] - }, - "perBuyerCurrencies": { - "*": "USD" - }, - "sellerCurrency": "USD", - "requestedSize": { - "width": 300, - "height": 250 - }, - "maxTrustedBiddingSignalsURLLength": 1000 - } - } - ] - } + ] }