Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core: Remove Empty EIDs + add new ortb fields #3465

Merged
merged 5 commits into from
Oct 1, 2024
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
27 changes: 9 additions & 18 deletions src/main/java/com/iab/openrtb/request/Eid.java
Original file line number Diff line number Diff line change
@@ -1,33 +1,24 @@
package com.iab.openrtb.request;

import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.Builder;
import lombok.Value;

import java.util.List;

/**
* Extended identifiers support in the OpenRTB specification allows buyers
* to use audience data in real-time bidding. This object can contain one
* or more {@link Uid}s from a single source or a technology provider. The
* exchange should ensure that business agreements allow for the sending
* of this data.
*/
@Value(staticConstructor = "of")
@Value
@Builder(toBuilder = true)
public class Eid {

/**
* Source or technology provider responsible for the set of included IDs. Expressed as a top-level domain.
*/
String source;

/**
* Array of extended ID {@link Uid} objects from the given source.
* Refer to 3.2.28 Extended Identifier UIDs
*/
List<Uid> uids;

/**
* Placeholder for vendor specific extensions to this object
*/
String inserter;

String matcher;

Integer mm;

ObjectNode ext;
}
4 changes: 3 additions & 1 deletion src/main/java/com/iab/openrtb/request/Uid.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package com.iab.openrtb.request;

import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.Builder;
import lombok.Value;

/**
* This object contains a single user identifier provided as part of
* extended identifiers. The exchange should ensure that business
* agreements allow for the sending of this data.
*/
@Value(staticConstructor = "of")
@Value
@Builder(toBuilder = true)
public class Uid {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ private Future<BidRequest> updateBidRequest(AuctionContext auctionContext) {
.map(this::fillExplicitParameters)
.map(bidRequest -> overrideParameters(bidRequest, httpRequest, auctionContext.getPrebidErrors()))
.map(bidRequest -> paramsResolver.resolve(bidRequest, auctionContext, ENDPOINT, true))
.map(bidRequest -> ortb2RequestFactory.removeEmptyEids(bidRequest, auctionContext.getDebugWarnings()))
.compose(resolvedBidRequest -> ortb2RequestFactory.validateRequest(
resolvedBidRequest,
auctionContext.getHttpRequest(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,8 @@ private Future<BidRequest> updateBidRequest(AuctionStoredResult auctionStoredRes
.map(ortbVersionConversionManager::convertToAuctionSupportedVersion)
.map(bidRequest -> gppService.updateBidRequest(bidRequest, auctionContext))
.map(bidRequest -> paramsResolver.resolve(bidRequest, auctionContext, ENDPOINT, hasStoredBidRequest))
.map(bidRequest -> cookieDeprecationService.updateBidRequestDevice(bidRequest, auctionContext));
.map(bidRequest -> cookieDeprecationService.updateBidRequestDevice(bidRequest, auctionContext))
.map(bidRequest -> ortb2RequestFactory.removeEmptyEids(bidRequest, auctionContext.getDebugWarnings()));
}

private static MetricName requestTypeMetric(BidRequest bidRequest) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Device;
import com.iab.openrtb.request.Dooh;
import com.iab.openrtb.request.Eid;
import com.iab.openrtb.request.Geo;
import com.iab.openrtb.request.Publisher;
import com.iab.openrtb.request.Regs;
import com.iab.openrtb.request.Site;
import com.iab.openrtb.request.Uid;
import com.iab.openrtb.request.User;
import io.vertx.core.Future;
import io.vertx.core.MultiMap;
import io.vertx.ext.web.RoutingContext;
Expand All @@ -32,7 +35,6 @@
import org.prebid.server.exception.UnauthorizedAccountException;
import org.prebid.server.execution.Timeout;
import org.prebid.server.execution.TimeoutFactory;
import org.prebid.server.floors.PriceFloorProcessor;
import org.prebid.server.geolocation.CountryCodeMapper;
import org.prebid.server.geolocation.model.GeoInfo;
import org.prebid.server.hooks.execution.HookStageExecutor;
Expand All @@ -51,11 +53,11 @@
import org.prebid.server.model.UpdateResult;
import org.prebid.server.privacy.model.PrivacyContext;
import org.prebid.server.proto.openrtb.ext.FlexibleExtension;
import org.prebid.server.proto.openrtb.ext.request.DsaTransparency;
import org.prebid.server.proto.openrtb.ext.request.ExtPublisher;
import org.prebid.server.proto.openrtb.ext.request.ExtPublisherPrebid;
import org.prebid.server.proto.openrtb.ext.request.ExtRegs;
import org.prebid.server.proto.openrtb.ext.request.ExtRegsDsa;
import org.prebid.server.proto.openrtb.ext.request.DsaTransparency;
import org.prebid.server.proto.openrtb.ext.request.ExtRequest;
import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid;
import org.prebid.server.proto.openrtb.ext.request.ExtRequestTargeting;
Expand All @@ -73,12 +75,14 @@
import org.prebid.server.validation.model.ValidationResult;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.stream.Stream;

public class Ortb2RequestFactory {

Expand All @@ -99,7 +103,6 @@ public class Ortb2RequestFactory {
private final ApplicationSettings applicationSettings;
private final IpAddressHelper ipAddressHelper;
private final HookStageExecutor hookStageExecutor;
private final PriceFloorProcessor priceFloorProcessor;
private final CountryCodeMapper countryCodeMapper;
private final Metrics metrics;

Expand All @@ -115,7 +118,6 @@ public Ortb2RequestFactory(int timeoutAdjustmentFactor,
ApplicationSettings applicationSettings,
IpAddressHelper ipAddressHelper,
HookStageExecutor hookStageExecutor,
PriceFloorProcessor priceFloorProcessor,
CountryCodeMapper countryCodeMapper,
Metrics metrics) {

Expand All @@ -135,7 +137,6 @@ public Ortb2RequestFactory(int timeoutAdjustmentFactor,
this.applicationSettings = Objects.requireNonNull(applicationSettings);
this.ipAddressHelper = Objects.requireNonNull(ipAddressHelper);
this.hookStageExecutor = Objects.requireNonNull(hookStageExecutor);
this.priceFloorProcessor = Objects.requireNonNull(priceFloorProcessor);
this.countryCodeMapper = Objects.requireNonNull(countryCodeMapper);
this.metrics = Objects.requireNonNull(metrics);
}
Expand Down Expand Up @@ -206,6 +207,40 @@ public Future<BidRequest> validateRequest(BidRequest bidRequest,
: Future.succeededFuture(bidRequest);
}

public BidRequest removeEmptyEids(BidRequest bidRequest, List<String> warnings) {
final User user = bidRequest.getUser();

if (user == null) {
return bidRequest;
}

final List<Eid> eids = Stream.ofNullable(user.getEids())
.flatMap(Collection::stream)
.map(eid -> eid.toBuilder().uids(removeEmptyUids(eid, warnings)).build())
.filter(eid -> CollectionUtils.isNotEmpty(eid.getUids()))
.toList();

if (CollectionUtils.isEmpty(eids) && CollectionUtils.isNotEmpty(user.getEids())) {
warnings.add("removed empty EID array");
}

final User modifiedUser = user.toBuilder().eids(CollectionUtils.isEmpty(eids) ? null : eids).build();
return bidRequest.toBuilder().user(modifiedUser).build();
}

private List<Uid> removeEmptyUids(Eid eid, List<String> warnings) {
return CollectionUtils.emptyIfNull(eid.getUids()).stream()
.filter(uid -> {
if (StringUtils.isBlank(uid.getId())) {
warnings.add("removed EID %s due to empty ID".formatted(eid.getSource()));
return false;
}

return true;
})
.toList();
}

public Future<BidRequest> enrichBidRequestWithGeolocationData(AuctionContext auctionContext) {
final BidRequest bidRequest = auctionContext.getBidRequest();
final Device device = bidRequest.getDevice();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,19 +108,18 @@ public Future<WithPodErrors<AuctionContext>> fromRequest(RoutingContext routingC
Endpoint.openrtb2_video, MetricName.video);

return ortb2RequestFactory.executeEntrypointHooks(routingContext, body, initialAuctionContext)
.compose(httpRequest ->
createBidRequest(httpRequest)
.compose(httpRequest -> createBidRequest(httpRequest)
.map(bidRequest -> removeEmptyEids(bidRequest, initialAuctionContext.getDebugWarnings()))
.compose(bidRequest -> validateRequest(
bidRequest,
httpRequest,
initialAuctionContext.getDebugWarnings()))

.compose(bidRequest -> validateRequest(
bidRequest,
httpRequest,
initialAuctionContext.getDebugWarnings()))
.map(bidRequestWithErrors -> populatePodErrors(
bidRequestWithErrors.getPodErrors(), podErrors, bidRequestWithErrors))

.map(bidRequestWithErrors -> populatePodErrors(
bidRequestWithErrors.getPodErrors(), podErrors, bidRequestWithErrors))

.map(bidRequestWithErrors -> ortb2RequestFactory.enrichAuctionContext(
initialAuctionContext, httpRequest, bidRequestWithErrors.getData(), startTime)))
.map(bidRequestWithErrors -> ortb2RequestFactory.enrichAuctionContext(
initialAuctionContext, httpRequest, bidRequestWithErrors.getData(), startTime)))

.compose(auctionContext -> ortb2RequestFactory.fetchAccountWithoutStoredRequestLookup(auctionContext)
.map(auctionContext::with))
Expand Down Expand Up @@ -154,6 +153,14 @@ public Future<WithPodErrors<AuctionContext>> fromRequest(RoutingContext routingC
.map(auctionContext -> WithPodErrors.of(auctionContext, podErrors));
}

private WithPodErrors<BidRequest> removeEmptyEids(WithPodErrors<BidRequest> requestWithPodErrors,
List<String> debugWarnings) {

return WithPodErrors.of(
ortb2RequestFactory.removeEmptyEids(requestWithPodErrors.getData(), debugWarnings),
requestWithPodErrors.getPodErrors());
}

private String extractAndValidateBody(RoutingContext routingContext) {
final String body = routingContext.getBodyAsString();
if (body == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1230,7 +1230,7 @@ private static Eid prepareExtUserEid(Eid extUserEid) {
.filter(Objects::nonNull)
.map(RubiconBidder::cleanExtUserEidUidStype)
.toList();
return Eid.of(extUserEid.getSource(), extUserEidUids, extUserEid.getExt());
return extUserEid.toBuilder().uids(extUserEidUids).build();
}

private static Uid cleanExtUserEidUidStype(Uid extUserEidUid) {
Expand All @@ -1242,10 +1242,7 @@ private static Uid cleanExtUserEidUidStype(Uid extUserEidUid) {
final ObjectNode extUserEidUidExtCopy = extUserEidUidExt.deepCopy();
extUserEidUidExtCopy.remove(STYPE_FIELD);

return Uid.of(
extUserEidUid.getId(),
extUserEidUid.getAtype(),
extUserEidUidExtCopy);
return extUserEidUid.toBuilder().ext(extUserEidUidExtCopy).build();
}

private RubiconUserExtRp rubiconUserExtRp(User user, ExtImpRubicon rubiconImpExt) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,6 @@ Ortb2RequestFactory openRtb2RequestFactory(
IpAddressHelper ipAddressHelper,
HookStageExecutor hookStageExecutor,
CountryCodeMapper countryCodeMapper,
PriceFloorProcessor priceFloorProcessor,
Metrics metrics) {

final List<String> blocklistedAccounts = splitToList(blocklistedAccountsString);
Expand All @@ -402,7 +401,6 @@ Ortb2RequestFactory openRtb2RequestFactory(
applicationSettings,
ipAddressHelper,
hookStageExecutor,
priceFloorProcessor,
countryCodeMapper,
metrics);
}
Expand Down
14 changes: 0 additions & 14 deletions src/main/java/org/prebid/server/validation/RequestValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import com.iab.openrtb.request.Imp;
import com.iab.openrtb.request.Regs;
import com.iab.openrtb.request.Site;
import com.iab.openrtb.request.Uid;
import com.iab.openrtb.request.User;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
Expand Down Expand Up @@ -572,19 +571,6 @@ private void validateUser(User user, Map<String, String> aliases) throws Validat
throw new ValidationException(
"request.user.eids[%d] missing required field: \"source\"", index);
}
final List<Uid> eidUids = eid.getUids();
if (CollectionUtils.isEmpty(eidUids)) {
throw new ValidationException(
"request.user.eids[%d].uids must contain at least one element", index);
}
for (int uidsIndex = 0; uidsIndex < eidUids.size(); uidsIndex++) {
final Uid uid = eidUids.get(uidsIndex);
if (StringUtils.isBlank(uid.getId())) {
throw new ValidationException(
"request.user.eids[%d].uids[%d] missing required field: \"id\"", index,
uidsIndex);
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.prebid.server.functional.model.request.auction

import com.fasterxml.jackson.annotation.JsonProperty
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import org.prebid.server.functional.util.PBSUtils
Expand All @@ -10,11 +11,18 @@ class Eid {

String source
List<Uid> uids
String inserter
String matcher
@JsonProperty("mm")
Integer matchMethod

static Eid getDefaultEid(String source = PBSUtils.randomString) {
new Eid().tap {
it.source = source
it.uids = [Uid.defaultUid]
it.inserter = PBSUtils.randomString
it.matcher = PBSUtils.randomString
it.matchMethod = PBSUtils.randomNumber
}
}
}
Loading
Loading