Skip to content

Commit

Permalink
Core: Support Bidder Specific Imp Level Params (#3254)
Browse files Browse the repository at this point in the history
  • Loading branch information
AntoxaAntoxic authored Aug 13, 2024
1 parent ef313c0 commit 8609e25
Show file tree
Hide file tree
Showing 23 changed files with 4,270 additions and 2,909 deletions.
13 changes: 8 additions & 5 deletions src/main/java/org/prebid/server/auction/ExchangeService.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,6 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* Executes an OpenRTB v2.5-2.6 Auction.
*/
public class ExchangeService {

private static final Logger logger = LoggerFactory.getLogger(ExchangeService.class);
Expand All @@ -174,6 +171,7 @@ public class ExchangeService {
private final StoredResponseProcessor storedResponseProcessor;
private final PrivacyEnforcementService privacyEnforcementService;
private final FpdResolver fpdResolver;
private final ImpAdjuster impAdjuster;
private final SupplyChainResolver supplyChainResolver;
private final DebugResolver debugResolver;
private final MediaTypeProcessor mediaTypeProcessor;
Expand Down Expand Up @@ -204,6 +202,7 @@ public ExchangeService(double logSamplingRate,
StoredResponseProcessor storedResponseProcessor,
PrivacyEnforcementService privacyEnforcementService,
FpdResolver fpdResolver,
ImpAdjuster impAdjuster,
SupplyChainResolver supplyChainResolver,
DebugResolver debugResolver,
MediaTypeProcessor mediaTypeProcessor,
Expand Down Expand Up @@ -234,6 +233,7 @@ public ExchangeService(double logSamplingRate,
this.storedResponseProcessor = Objects.requireNonNull(storedResponseProcessor);
this.privacyEnforcementService = Objects.requireNonNull(privacyEnforcementService);
this.fpdResolver = Objects.requireNonNull(fpdResolver);
this.impAdjuster = Objects.requireNonNull(impAdjuster);
this.supplyChainResolver = Objects.requireNonNull(supplyChainResolver);
this.debugResolver = Objects.requireNonNull(debugResolver);
this.mediaTypeProcessor = Objects.requireNonNull(mediaTypeProcessor);
Expand Down Expand Up @@ -299,7 +299,6 @@ private Future<AuctionContext> runAuction(AuctionContext receivedContext) {
.map(receivedContext::with))

.map(context -> updateRequestMetric(context, uidsCookie, aliases, account, requestTypeMetric))

.compose(context -> CompositeFuture.join(
context.getAuctionParticipations().stream()
.map(auctionParticipation -> processAndRequestBids(
Expand Down Expand Up @@ -528,7 +527,6 @@ private Future<List<AuctionParticipation>> extractAuctionParticipations(
.toList();
final Map<String, Map<String, String>> impBidderToStoredBidResponse =
storedResponseResult.getImpBidderToStoredBidResponse();

return makeAuctionParticipation(
bidders,
context,
Expand Down Expand Up @@ -852,6 +850,7 @@ private AuctionParticipation createAuctionParticipation(
bidderToMultiBid,
biddersToConfigs,
bidderToPrebidBidders,
bidderAliases,
context);

final BidderRequest bidderRequest = BidderRequest.builder()
Expand All @@ -878,6 +877,7 @@ private BidRequest prepareBidRequest(BidderPrivacyResult bidderPrivacyResult,
Map<String, MultiBidConfig> bidderToMultiBid,
Map<String, ExtBidderConfigOrtb> biddersToConfigs,
Map<String, JsonNode> bidderToPrebidBidders,
BidderAliases bidderAliases,
AuctionContext context) {

final String bidder = bidderPrivacyResult.getRequestBidder();
Expand Down Expand Up @@ -938,6 +938,7 @@ private BidRequest prepareBidRequest(BidderPrivacyResult bidderPrivacyResult,
transmitTid,
useFirstPartyData,
context.getAccount(),
bidderAliases,
context.getDebugWarnings());

return bidRequest.toBuilder()
Expand Down Expand Up @@ -975,10 +976,12 @@ private List<Imp> prepareImps(String bidder,
boolean transmitTid,
boolean useFirstPartyData,
Account account,
BidderAliases bidderAliases,
List<String> debugWarnings) {

return bidRequest.getImp().stream()
.filter(imp -> bidderParamsFromImpExt(imp.getExt()).hasNonNull(bidder))
.map(imp -> impAdjuster.adjust(imp, bidder, bidderAliases, debugWarnings))
.map(imp -> prepareImp(imp, bidder, bidRequest, transmitTid, useFirstPartyData, account, debugWarnings))
.toList();
}
Expand Down
99 changes: 99 additions & 0 deletions src/main/java/org/prebid/server/auction/ImpAdjuster.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package org.prebid.server.auction;

import com.fasterxml.jackson.databind.JsonNode;
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.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

public class ImpAdjuster {

private static final String IMP_EXT = "ext";
private static final String EXT_PREBID = "prebid";
private static final String EXT_PREBID_BIDDER = "bidder";
private static final String EXT_PREBID_IMP = "imp";

private final ImpValidator impValidator;
private final JacksonMapper jacksonMapper;
private final JsonMerger jsonMerger;

public ImpAdjuster(JacksonMapper jacksonMapper,
JsonMerger jsonMerger,
ImpValidator impValidator) {

this.impValidator = Objects.requireNonNull(impValidator);
this.jacksonMapper = Objects.requireNonNull(jacksonMapper);
this.jsonMerger = Objects.requireNonNull(jsonMerger);
}

public Imp adjust(Imp originalImp, String bidder, BidderAliases bidderAliases, List<String> debugMessages) {
final JsonNode impExtPrebidImp = bidderParamsFromImpExtPrebidImp(originalImp.getExt());
if (impExtPrebidImp == null) {
return originalImp;
}

final JsonNode bidderNode = getBidderNode(bidder, bidderAliases, impExtPrebidImp);

if (bidderNode == null || bidderNode.isEmpty()) {
return originalImp;
}

// remove circular references according to the requirements
removeExtPrebidBidder(bidderNode);

try {
final JsonNode originalImpNode = jacksonMapper.mapper().valueToTree(originalImp);
final JsonNode mergedImpNode = jsonMerger.merge(bidderNode, originalImpNode);

// clean up merged imp.ext.prebid.imp
removeImpExtPrebidImp(mergedImpNode);

final Imp resultImp = jacksonMapper.mapper().convertValue(mergedImpNode, Imp.class);

impValidator.validateImp(resultImp);
return resultImp;
} catch (Exception e) {
debugMessages.add("imp.ext.prebid.imp.%s can not be merged into original imp [id=%s], reason: %s"
.formatted(bidder, originalImp.getId(), e.getMessage()));
return originalImp;
}
}

private static JsonNode bidderParamsFromImpExtPrebidImp(ObjectNode ext) {
return Optional.ofNullable(ext)
.map(extNode -> extNode.get(EXT_PREBID))
.map(prebidNode -> prebidNode.get(EXT_PREBID_IMP))
.orElse(null);
}

private static JsonNode getBidderNode(String bidderName, BidderAliases bidderAliases, JsonNode node) {
final Iterator<String> fieldNames = node.fieldNames();
while (fieldNames.hasNext()) {
final String fieldName = fieldNames.next();
if (bidderAliases.isSame(fieldName, bidderName)) {
return node.get(fieldName);
}
}
return null;
}

private static void removeExtPrebidBidder(JsonNode bidderNode) {
Optional.ofNullable(bidderNode.get(IMP_EXT))
.map(extNode -> extNode.get(EXT_PREBID))
.map(ObjectNode.class::cast)
.ifPresent(ext -> ext.remove(EXT_PREBID_BIDDER));
}

private static void removeImpExtPrebidImp(JsonNode mergedImpNode) {
Optional.ofNullable(mergedImpNode.get(IMP_EXT))
.map(extNode -> extNode.get(EXT_PREBID))
.map(ObjectNode.class::cast)
.ifPresent(prebid -> prebid.remove(EXT_PREBID_IMP));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,9 @@ public class ExtImpPrebid {
* Defines the contract for bidrequest.imp[i].ext.prebid.passthrough
*/
JsonNode passthrough;

/**
* Defines the contract for bidrequest.imp[i].ext.prebid.imp
*/
ObjectNode imp;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.prebid.server.auction.ExchangeService;
import org.prebid.server.auction.FpdResolver;
import org.prebid.server.auction.GeoLocationServiceWrapper;
import org.prebid.server.auction.ImpAdjuster;
import org.prebid.server.auction.ImplicitParametersExtractor;
import org.prebid.server.auction.InterstitialProcessor;
import org.prebid.server.auction.IpAddressHelper;
Expand Down Expand Up @@ -111,6 +112,7 @@
import org.prebid.server.util.VersionInfo;
import org.prebid.server.util.system.CpuLoadAverageStats;
import org.prebid.server.validation.BidderParamValidator;
import org.prebid.server.validation.ImpValidator;
import org.prebid.server.validation.RequestValidator;
import org.prebid.server.validation.ResponseBidValidator;
import org.prebid.server.validation.VideoRequestValidator;
Expand Down Expand Up @@ -245,6 +247,11 @@ FpdResolver fpdResolver(JacksonMapper mapper, JsonMerger jsonMerger) {
return new FpdResolver(mapper, jsonMerger);
}

@Bean
ImpAdjuster impAdjuster(ImpValidator impValidator, JacksonMapper jacksonMapper, JsonMerger jsonMerger) {
return new ImpAdjuster(jacksonMapper, jsonMerger, impValidator);
}

@Bean
OrtbTypesResolver ortbTypesResolver(JacksonMapper jacksonMapper, JsonMerger jsonMerger) {
return new OrtbTypesResolver(logSamplingRate, jacksonMapper, jsonMerger);
Expand Down Expand Up @@ -819,6 +826,7 @@ ExchangeService exchangeService(
StoredResponseProcessor storedResponseProcessor,
PrivacyEnforcementService privacyEnforcementService,
FpdResolver fpdResolver,
ImpAdjuster impAdjuster,
SupplyChainResolver supplyChainResolver,
DebugResolver debugResolver,
CompositeMediaTypeProcessor mediaTypeProcessor,
Expand Down Expand Up @@ -850,6 +858,7 @@ ExchangeService exchangeService(
storedResponseProcessor,
privacyEnforcementService,
fpdResolver,
impAdjuster,
supplyChainResolver,
debugResolver,
mediaTypeProcessor,
Expand Down Expand Up @@ -989,18 +998,26 @@ VersionInfo versionInfo(JacksonMapper jacksonMapper) {
return VersionInfo.create("git-revision.json", jacksonMapper);
}

@Bean
ImpValidator impValidator(BidderParamValidator bidderParamValidator,
BidderCatalog bidderCatalog,
JacksonMapper mapper) {

return new ImpValidator(bidderParamValidator, bidderCatalog, mapper);
}

@Bean
RequestValidator requestValidator(
BidderCatalog bidderCatalog,
BidderParamValidator bidderParamValidator,
ImpValidator impValidator,
Metrics metrics,
JacksonMapper mapper,
@Value("${logging.sampling-rate:0.01}") double logSamplingRate,
@Value("${auction.strict-app-site-dooh:false}") boolean enabledStrictAppSiteDoohValidation) {

return new RequestValidator(
bidderCatalog,
bidderParamValidator,
impValidator,
metrics,
mapper,
logSamplingRate,
Expand Down
Loading

0 comments on commit 8609e25

Please sign in to comment.