Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/main/java/org/prebid/server/auction/BidResponseCreator.java
Original file line number Diff line number Diff line change
Expand Up @@ -1566,7 +1566,15 @@ private Bid toBid(BidInfo bidInfo,
final String categoryDuration = bidInfo.getCategory();
targetingKeywords = keywordsCreator != null
? keywordsCreator.makeFor(
bid, seat, isWinningBid, cacheId, bidType.getName(), videoCacheId, categoryDuration, account)
bid,
seat,
isWinningBid,
cacheId,
bidType.getName(),
videoCacheId,
categoryDuration,
account,
bidWarnings)
: null;
} else {
targetingKeywords = null;
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/org/prebid/server/auction/CpmRange.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.prebid.server.auction;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.prebid.server.proto.openrtb.ext.request.ExtGranularityRange;
import org.prebid.server.settings.model.Account;
import org.prebid.server.settings.model.AccountAuctionConfig;
Expand All @@ -19,6 +18,8 @@
*/
public class CpmRange {

public static final String DEFAULT_CPM = "0.0";

private static final Locale LOCALE = Locale.US;
private static final int DEFAULT_PRECISION = 2;

Expand All @@ -30,7 +31,7 @@ private CpmRange() {
*/
public static String fromCpm(BigDecimal cpm, PriceGranularity priceGranularity, Account account) {
final BigDecimal value = fromCpmAsNumber(cpm, priceGranularity, account);
return value != null ? format(value, priceGranularity.getPrecision()) : StringUtils.EMPTY;
return value != null ? format(value, priceGranularity.getPrecision()) : DEFAULT_CPM;
}

/**
Expand Down
6 changes: 1 addition & 5 deletions src/main/java/org/prebid/server/auction/ExchangeService.java
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,6 @@ private AuctionParticipation createAuctionParticipation(
bidderToMultiBid,
biddersToConfigs,
bidderToPrebidBidders,
bidderAliases,
context);

final Map<String, Price> originalPriceFloors = enrichedWithPriceFloors.getImp().stream()
Expand Down Expand Up @@ -815,7 +814,6 @@ 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 @@ -869,7 +867,6 @@ private BidRequest prepareBidRequest(BidderPrivacyResult bidderPrivacyResult,
transmitTid,
useFirstPartyData,
context.getAccount(),
bidderAliases,
context.getDebugWarnings());

return bidRequest.toBuilder()
Expand Down Expand Up @@ -907,13 +904,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 -> imp.toBuilder().ext(imp.getExt().deepCopy()).build())
.map(imp -> impAdjuster.adjust(imp, bidder, bidderAliases, debugWarnings))
.map(imp -> impAdjuster.adjust(imp, bidder, debugWarnings))
.map(imp -> prepareImp(imp, bidder, bidRequest, transmitTid, useFirstPartyData, account, debugWarnings))
.toList();
}
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/org/prebid/server/auction/ImpAdjuster.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.fasterxml.jackson.databind.node.IntNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.iab.openrtb.request.Imp;
import org.prebid.server.auction.aliases.BidderAliases;
import org.apache.commons.lang3.StringUtils;
import org.prebid.server.json.JacksonMapper;
import org.prebid.server.json.JsonMerger;
import org.prebid.server.validation.ImpValidator;
Expand Down Expand Up @@ -36,15 +36,15 @@ public ImpAdjuster(JacksonMapper jacksonMapper,
this.jsonMerger = Objects.requireNonNull(jsonMerger);
}

public Imp adjust(Imp originalImp, String bidder, BidderAliases bidderAliases, List<String> debugMessages) {
public Imp adjust(Imp originalImp, String bidder, List<String> debugMessages) {
setAeParams(originalImp.getExt());

final JsonNode impExtPrebidImp = bidderParamsFromImpExtPrebidImp(originalImp.getExt());
if (impExtPrebidImp == null) {
return originalImp;
}

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

if (bidderNode == null || bidderNode.isEmpty()) {
removeImpExtPrebidImp(originalImp.getExt());
Expand Down Expand Up @@ -98,11 +98,11 @@ private static JsonNode bidderParamsFromImpExtPrebidImp(ObjectNode ext) {
.orElse(null);
}

private static JsonNode getBidderNode(String bidderName, BidderAliases bidderAliases, JsonNode node) {
private static JsonNode getBidderNode(String bidderName, JsonNode node) {
final Iterator<String> fieldNames = node.fieldNames();
while (fieldNames.hasNext()) {
final String fieldName = fieldNames.next();
if (bidderAliases.isSame(fieldName, bidderName)) {
if (StringUtils.equalsIgnoreCase(fieldName, bidderName)) {
return node.get(fieldName);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import com.iab.openrtb.response.Bid;
import org.apache.commons.lang3.StringUtils;
import org.prebid.server.bidder.model.BidderError;
import org.prebid.server.proto.openrtb.ext.request.ExtPriceGranularity;
import org.prebid.server.proto.openrtb.ext.response.ExtBidderError;
import org.prebid.server.settings.model.Account;

import java.math.BigDecimal;
Expand All @@ -12,7 +14,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
* Used throughout Prebid to create targeting keys as keys which can be used in an ad server like DFP.
Expand Down Expand Up @@ -77,8 +78,6 @@ public class TargetingKeywordsCreator {
*/
private static final String FORMAT_KEY = "_format";

private static final String DEFAULT_CPM = "0.0";

private final PriceGranularity priceGranularity;
private final boolean includeWinners;
private final boolean includeBidderKeys;
Expand Down Expand Up @@ -154,7 +153,8 @@ Map<String, String> makeFor(Bid bid,
String format,
String vastCacheId,
String categoryDuration,
Account account) {
Account account,
Map<String, List<ExtBidderError>> bidWarnings) {

final Map<String, String> keywords = makeFor(
bidder,
Expand All @@ -170,13 +170,13 @@ Map<String, String> makeFor(Bid bid,
account);

if (resolver == null) {
return truncateKeys(keywords);
return truncateKeys(keywords, bidWarnings);
}

final Map<String, String> augmentedKeywords = new HashMap<>(keywords);
augmentedKeywords.putAll(resolver.resolve(bid, bidder));

return truncateKeys(augmentedKeywords);
return truncateKeys(augmentedKeywords, bidWarnings);
}

/**
Expand Down Expand Up @@ -204,7 +204,7 @@ private Map<String, String> makeFor(String bidder,

final String roundedCpm = isPriceGranularityValid()
? CpmRange.fromCpm(price, priceGranularity, account)
: DEFAULT_CPM;
: CpmRange.DEFAULT_CPM;

keywordMap.put(this.keyPrefix + PB_KEY, roundedCpm);

Expand Down Expand Up @@ -261,12 +261,33 @@ private static String sizeFrom(Integer width, Integer height) {
: null;
}

private Map<String, String> truncateKeys(Map<String, String> keyValues) {
return truncateAttrChars > 0
? keyValues.entrySet().stream()
.collect(Collectors
.toMap(keyValue -> truncateKey(keyValue.getKey()), Map.Entry::getValue, (key1, key2) -> key1))
: keyValues;
private Map<String, String> truncateKeys(Map<String, String> keyValues,
Map<String, List<ExtBidderError>> bidWarnings) {

if (truncateAttrChars <= 0) {
return keyValues;
}

final Map<String, String> keys = new HashMap<>();
final List<String> truncatedKeys = new ArrayList<>();
for (Map.Entry<String, String> entry : keyValues.entrySet()) {
final String key = entry.getKey();
final String truncatedKey = truncateKey(key);
keys.putIfAbsent(truncatedKey, entry.getValue());

if (truncatedKey.length() != key.length()) {
truncatedKeys.add(key);
}
}

if (!truncatedKeys.isEmpty()) {
final String errorMessage = "The following keys have been truncated: %s"
.formatted(String.join(", ", truncatedKeys));
bidWarnings.computeIfAbsent("targeting", ignored -> new ArrayList<>())
.add(ExtBidderError.of(BidderError.Type.bad_input.getCode(), errorMessage));
}

return keys;
}

private String truncateKey(String key) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,5 +145,9 @@ LIMIT 1
"currency-converter.external-rates.refresh-period-ms" : "900000"]
}

static Map<String,String> getTargetingConfig() {
["settings.targeting.truncate-attr-chars": '255']
}

private PbsConfig() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class PrebidServerContainer extends GenericContainer<PrebidServerContainer> {
<< PbsConfig.bidderAliasConfig
<< PbsConfig.prebidCacheConfig
<< PbsConfig.mySqlConfig
<< PbsConfig.targetingConfig
withConfig(commonConfig)
withConfig(customConfig)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ class CacheSpec extends BaseSpec {
private static final String PBS_API_HEADER = 'x-pbc-api-key'
private static final Integer MAX_DATACENTER_REGION_LENGTH = 4
private static final Integer DEFAULT_UUID_LENGTH = 36
private static final Integer TARGETING_PARAM_NAME_MAX_LENGTH = 20

private static final String XML_CREATIVE_SIZE_ACCOUNT_METRIC = "account.%s.prebid_cache.creative_size.xml"
private static final String JSON_CREATIVE_SIZE_ACCOUNT_METRIC = "account.%s.prebid_cache.creative_size.json"
Expand Down Expand Up @@ -612,8 +611,8 @@ class CacheSpec extends BaseSpec {
it.get("hb_cache_id_generic")
it.get("hb_cache_path") == CACHE_PATH
it.get("hb_cache_host") == CACHE_HOST
it.get("hb_cache_path_generic".substring(0, TARGETING_PARAM_NAME_MAX_LENGTH)) == CACHE_PATH
it.get("hb_cache_host_generic".substring(0, TARGETING_PARAM_NAME_MAX_LENGTH)) == CACHE_HOST
it.get("hb_cache_path_generic") == CACHE_PATH
it.get("hb_cache_host_generic") == CACHE_HOST
}

and: "Debug should contain http call"
Expand Down Expand Up @@ -648,8 +647,8 @@ class CacheSpec extends BaseSpec {
it.get("hb_cache_id_generic")
it.get("hb_cache_path") == INTERNAL_CACHE_PATH
it.get("hb_cache_host") == networkServiceContainer.hostAndPort.toString()
it.get("hb_cache_path_generic".substring(0, TARGETING_PARAM_NAME_MAX_LENGTH)) == INTERNAL_CACHE_PATH
it.get("hb_cache_host_generic".substring(0, TARGETING_PARAM_NAME_MAX_LENGTH)) == networkServiceContainer.hostAndPort.toString()
it.get("hb_cache_path_generic") == INTERNAL_CACHE_PATH
it.get("hb_cache_host_generic") == networkServiceContainer.hostAndPort.toString()
}

and: "Debug should contain http call"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import static org.prebid.server.functional.model.bidder.BidderName.OPENX
import static org.prebid.server.functional.model.bidder.BidderName.RUBICON
import static org.prebid.server.functional.model.bidder.BidderName.UNKNOWN
import static org.prebid.server.functional.model.bidder.BidderName.WILDCARD
import static org.prebid.server.functional.model.bidder.BidderName.GENER_X
import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID
import static org.prebid.server.functional.testcontainers.Dependencies.getNetworkServiceContainer

Expand Down Expand Up @@ -131,6 +132,42 @@ class ImpRequestSpec extends BaseSpec {
ALIAS_CAMEL_CASE | GENERIC_CAMEL_CASE
}

def "PBS should update imp fields only for specific alias when request has multiple aliases"() {
given: "Default basic BidRequest"
def storedPmp = Pmp.defaultPmp
def originalPmp = Pmp.defaultPmp
def bidRequest = BidRequest.defaultBidRequest.tap {
imp.first.tap {
pmp = originalPmp
ext.prebid.imp = [(aliasName): new Imp(pmp: storedPmp)]
ext.prebid.bidder.generic = null
ext.prebid.bidder.generX = new Generic()
ext.prebid.bidder.alias = new Generic()
}
ext.prebid.aliases = [(GENER_X.value) : bidderName,
(aliasName.value): bidderName,
]
}

when: "Requesting PBS auction"
def response = defaultPbsService.sendAuctionRequest(bidRequest)

then: "BidderRequest should update imp information for specific alias"
def bidderRequests = getRequests(response)
assert bidderRequests.size() == 2
assert bidderRequests[ALIAS.value].imp.pmp.flatten() == [storedPmp]

and: "Left original information for other"
assert bidderRequests[GENER_X.value].imp.pmp.flatten() == [originalPmp]

where:
aliasName | bidderName
ALIAS | GENERIC
ALIAS_CAMEL_CASE | GENERIC
ALIAS | GENERIC_CAMEL_CASE
ALIAS_CAMEL_CASE | GENERIC_CAMEL_CASE
}

def "PBS shouldn't update imp fields when imp.ext.prebid.imp contain only bidder with invalid name"() {
given: "Default basic BidRequest"
def impPmp = Pmp.defaultPmp
Expand Down
Loading
Loading