Skip to content

Commit cd771c0

Browse files
authored
Fix prebid#3592. Bad Input Error if pbjs s2s config contains alias configuration for a disabled adapter (prebid#3650)
1 parent 6363e1d commit cd771c0

File tree

17 files changed

+299
-119
lines changed

17 files changed

+299
-119
lines changed

docs/config-app.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,10 @@ Preconfigured application settings can be obtained from multiple data sources co
303303

304304
Warning! Application will not start in case of no one data source is defined and you'll get an exception in logs.
305305

306+
For requests validation mode available next options:
307+
- `settings.fail-on-unknown-bidders` - fail with validation error or just make warning for unknown bidders.
308+
- `settings.fail-on-disabled-bidders` - fail with validation error or just make warning for disabled bidders.
309+
306310
For filesystem data source available next options:
307311
- `settings.filesystem.settings-filename` - location of file settings.
308312
- `settings.filesystem.stored-requests-dir` - directory with stored requests.

docs/metrics.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ where `[DATASOURCE]` is a data source name, `DEFAULT_DS` by defaul.
4545
- `imps_video` - number of video impressions
4646
- `imps_native` - number of native impressions
4747
- `imps_audio` - number of audio impressions
48+
- `disabled_bidder` - number of disabled bidders received within requests
49+
- `unknown_bidder` - number of unknown bidders received within requests
4850
- `requests.(ok|badinput|err|networkerr|blocklisted_account|blocklisted_app).(openrtb2-web|openrtb-app|amp|legacy)` - number of requests broken down by status and type
4951
- `bidder-cardinality.<cardinality>.requests` - number of requests targeting `<cardinality>` of bidders
5052
- `connection_accept_errors` - number of errors occurred while establishing HTTP connection
@@ -92,6 +94,8 @@ Following metrics are collected and submitted if account is configured with `det
9294
- `account.<account-id>.requests.type.(openrtb2-web,openrtb-app,amp,legacy)` - number of requests received from account with `<account-id>` broken down by type of incoming request
9395
- `account.<account-id>.debug_requests` - number of requests received from account with `<account-id>` broken down by type of incoming request (when debug mode is enabled)
9496
- `account.<account-id>.requests.rejected` - number of rejected requests caused by incorrect `accountId`
97+
- `account.<account-id>.requests.disabled_bidder` - number of disabled bidders received within requests from account with `<account-id>`
98+
- `account.<account-id>.requests.unknown_bidder` - number of unknown bidder names received within requests from account with `<account-id>`
9599
- `account.<account-id>.adapter.<bidder-name>.request_time` - timer tracking how long did it take to make a request to `<bidder-name>` when incoming request was from `<account-id>`
96100
- `account.<account-id>.adapter.<bidder-name>.bids_received` - number of bids received from `<bidder-name>` when incoming request was from `<account-id>`
97101
- `account.<account-id>.adapter.<bidder-name>.requests.(gotbids|nobid)` - number of requests made to `<bidder-name>` broken down by result status when incoming request was from `<account-id>`

src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ private Future<BidRequest> updateBidRequest(AuctionContext auctionContext) {
415415
.map(bidRequest -> paramsResolver.resolve(bidRequest, auctionContext, ENDPOINT, true))
416416
.map(bidRequest -> ortb2RequestFactory.removeEmptyEids(bidRequest, auctionContext.getDebugWarnings()))
417417
.compose(resolvedBidRequest -> ortb2RequestFactory.validateRequest(
418+
account,
418419
resolvedBidRequest,
419420
auctionContext.getHttpRequest(),
420421
auctionContext.getDebugContext(),

src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ private Future<BidRequest> updateAndValidateBidRequest(AuctionContext auctionCon
242242
return storedRequestProcessor.processAuctionRequest(account.getId(), auctionContext.getBidRequest())
243243
.compose(auctionStoredResult -> updateBidRequest(auctionStoredResult, auctionContext))
244244
.compose(bidRequest -> ortb2RequestFactory.validateRequest(
245-
bidRequest, httpRequest, auctionContext.getDebugContext(), debugWarnings))
245+
account, bidRequest, httpRequest, auctionContext.getDebugContext(), debugWarnings))
246246
.map(interstitialProcessor::process);
247247
}
248248

src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,13 +192,14 @@ public Future<ActivityInfrastructure> activityInfrastructureFrom(AuctionContext
192192
auctionContext.getDebugContext().getTraceLevel()));
193193
}
194194

195-
public Future<BidRequest> validateRequest(BidRequest bidRequest,
195+
public Future<BidRequest> validateRequest(Account account,
196+
BidRequest bidRequest,
196197
HttpRequestContext httpRequestContext,
197198
DebugContext debugContext,
198199
List<String> warnings) {
199200

200201
final ValidationResult validationResult = requestValidator.validate(
201-
bidRequest, httpRequestContext, debugContext);
202+
account, bidRequest, httpRequestContext, debugContext);
202203

203204
if (validationResult.hasWarnings()) {
204205
warnings.addAll(validationResult.getWarnings());

src/main/java/org/prebid/server/auction/requestfactory/VideoRequestFactory.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ public Future<WithPodErrors<AuctionContext>> fromRequest(RoutingContext routingC
120120
.map(auctionContext -> auctionContext.with(debugResolver.debugContextFrom(auctionContext)))
121121

122122
.compose(auctionContext -> ortb2RequestFactory.validateRequest(
123+
auctionContext.getAccount(),
123124
auctionContext.getBidRequest(),
124125
auctionContext.getHttpRequest(),
125126
auctionContext.getDebugContext(),

src/main/java/org/prebid/server/metric/MetricName.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ public enum MetricName {
6363
nobid,
6464
gotbids,
6565
badinput,
66+
disabled_bidder,
67+
unknown_bidder,
6668
blocklisted_account,
6769
blocklisted_app,
6870
badserverresponse,

src/main/java/org/prebid/server/metric/Metrics.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,22 @@ public void updateAdapterRequestErrorMetric(String bidder, MetricName errorMetri
336336
forAdapter(bidder).request().incCounter(errorMetric);
337337
}
338338

339+
public void updateDisabledBidderMetric(Account account) {
340+
incCounter(MetricName.disabled_bidder);
341+
if (accountMetricsVerbosityResolver.forAccount(account)
342+
.isAtLeast(AccountMetricsVerbosityLevel.detailed)) {
343+
forAccount(account.getId()).requests().incCounter(MetricName.disabled_bidder);
344+
}
345+
}
346+
347+
public void updateUnknownBidderMetric(Account account) {
348+
incCounter(MetricName.unknown_bidder);
349+
if (accountMetricsVerbosityResolver.forAccount(account)
350+
.isAtLeast(AccountMetricsVerbosityLevel.detailed)) {
351+
forAccount(account.getId()).requests().incCounter(MetricName.unknown_bidder);
352+
}
353+
}
354+
339355
public void updateAnalyticEventMetric(String analyticCode, MetricName eventType, MetricName result) {
340356
forAnalyticReporter(analyticCode).forEventType(eventType).incCounter(result);
341357
}

src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,15 +1033,19 @@ RequestValidator requestValidator(
10331033
Metrics metrics,
10341034
JacksonMapper mapper,
10351035
@Value("${logging.sampling-rate:0.01}") double logSamplingRate,
1036-
@Value("${auction.strict-app-site-dooh:false}") boolean enabledStrictAppSiteDoohValidation) {
1036+
@Value("${auction.strict-app-site-dooh:false}") boolean enabledStrictAppSiteDoohValidation,
1037+
@Value("${settings.fail-on-disabled-bidders:true}") boolean failOnDisabledBidders,
1038+
@Value("${settings.fail-on-unknown-bidders:true}") boolean failOnUnknownBidders) {
10371039

10381040
return new RequestValidator(
10391041
bidderCatalog,
10401042
impValidator,
10411043
metrics,
10421044
mapper,
10431045
logSamplingRate,
1044-
enabledStrictAppSiteDoohValidation);
1046+
enabledStrictAppSiteDoohValidation,
1047+
failOnDisabledBidders,
1048+
failOnUnknownBidders);
10451049
}
10461050

10471051
@Bean

src/main/java/org/prebid/server/validation/RequestValidator.java

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.prebid.server.proto.openrtb.ext.request.ExtUserPrebid;
4242
import org.prebid.server.proto.openrtb.ext.request.ImpMediaType;
4343
import org.prebid.server.proto.openrtb.ext.response.BidType;
44+
import org.prebid.server.settings.model.Account;
4445
import org.prebid.server.util.HttpUtil;
4546
import org.prebid.server.validation.model.ValidationResult;
4647

@@ -74,6 +75,8 @@ public class RequestValidator {
7475
private final JacksonMapper mapper;
7576
private final double logSamplingRate;
7677
private final boolean enabledStrictAppSiteDoohValidation;
78+
private final boolean failOnDisabledBidders;
79+
private final boolean failOnUnknownBidders;
7780

7881
/**
7982
* Constructs a RequestValidator that will use the BidderParamValidator passed in order to validate all critical
@@ -83,21 +86,26 @@ public RequestValidator(BidderCatalog bidderCatalog,
8386
ImpValidator impValidator, Metrics metrics,
8487
JacksonMapper mapper,
8588
double logSamplingRate,
86-
boolean enabledStrictAppSiteDoohValidation) {
89+
boolean enabledStrictAppSiteDoohValidation,
90+
boolean failOnDisabledBidders,
91+
boolean failOnUnknownBidders) {
8792

8893
this.bidderCatalog = Objects.requireNonNull(bidderCatalog);
8994
this.impValidator = Objects.requireNonNull(impValidator);
9095
this.metrics = Objects.requireNonNull(metrics);
9196
this.mapper = Objects.requireNonNull(mapper);
9297
this.logSamplingRate = logSamplingRate;
9398
this.enabledStrictAppSiteDoohValidation = enabledStrictAppSiteDoohValidation;
99+
this.failOnDisabledBidders = failOnDisabledBidders;
100+
this.failOnUnknownBidders = failOnUnknownBidders;
94101
}
95102

96103
/**
97104
* Validates the {@link BidRequest} against a list of validation checks, however, reports only one problem
98105
* at a time.
99106
*/
100-
public ValidationResult validate(BidRequest bidRequest,
107+
public ValidationResult validate(Account account,
108+
BidRequest bidRequest,
101109
HttpRequestContext httpRequestContext,
102110
DebugContext debugContext) {
103111

@@ -126,7 +134,7 @@ public ValidationResult validate(BidRequest bidRequest,
126134
validateTargeting(targeting);
127135
}
128136
aliases = ObjectUtils.defaultIfNull(extRequestPrebid.getAliases(), Collections.emptyMap());
129-
validateAliases(aliases);
137+
validateAliases(aliases, warnings, account);
130138
validateAliasesGvlIds(extRequestPrebid, aliases);
131139
validateBidAdjustmentFactors(extRequestPrebid.getBidadjustmentfactors(), aliases);
132140
validateExtBidPrebidData(extRequestPrebid.getData(), aliases, isDebugEnabled, warnings);
@@ -505,18 +513,34 @@ private static void validateGranularityRangeIncrement(ExtGranularityRange range)
505513
* Validates aliases. Throws {@link ValidationException} in cases when alias points to invalid bidder or when alias
506514
* is equals to itself.
507515
*/
508-
private void validateAliases(Map<String, String> aliases) throws ValidationException {
516+
private void validateAliases(Map<String, String> aliases, List<String> warnings,
517+
Account account) throws ValidationException {
518+
509519
for (final Map.Entry<String, String> aliasToBidder : aliases.entrySet()) {
510520
final String alias = aliasToBidder.getKey();
511521
final String coreBidder = aliasToBidder.getValue();
512522
if (!bidderCatalog.isValidName(coreBidder)) {
513-
throw new ValidationException(
514-
"request.ext.prebid.aliases.%s refers to unknown bidder: %s".formatted(alias, coreBidder));
515-
}
516-
if (!bidderCatalog.isActive(coreBidder)) {
517-
throw new ValidationException(
518-
"request.ext.prebid.aliases.%s refers to disabled bidder: %s".formatted(alias, coreBidder));
523+
metrics.updateUnknownBidderMetric(account);
524+
525+
final String message = "request.ext.prebid.aliases.%s refers to unknown bidder: %s".formatted(alias,
526+
coreBidder);
527+
if (failOnUnknownBidders) {
528+
throw new ValidationException(message);
529+
} else {
530+
warnings.add(message);
531+
}
532+
} else if (!bidderCatalog.isActive(coreBidder)) {
533+
metrics.updateDisabledBidderMetric(account);
534+
535+
final String message = "request.ext.prebid.aliases.%s refers to disabled bidder: %s".formatted(alias,
536+
coreBidder);
537+
if (failOnDisabledBidders) {
538+
throw new ValidationException(message);
539+
} else {
540+
warnings.add(message);
541+
}
519542
}
543+
520544
if (alias.equals(coreBidder)) {
521545
throw new ValidationException("""
522546
request.ext.prebid.aliases.%s defines a no-op alias. \

0 commit comments

Comments
 (0)