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
26 changes: 18 additions & 8 deletions src/main/java/org/prebid/server/auction/ExchangeService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.iab.openrtb.request.App;
import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Content;
import com.iab.openrtb.request.Device;
import com.iab.openrtb.request.Dooh;
import com.iab.openrtb.request.Eid;
import com.iab.openrtb.request.Imp;
Expand Down Expand Up @@ -97,6 +98,7 @@
import org.prebid.server.util.ListUtil;
import org.prebid.server.util.PbsUtil;
import org.prebid.server.util.StreamUtil;
import org.apache.commons.lang3.tuple.Pair;

import java.math.BigDecimal;
import java.time.Clock;
Expand Down Expand Up @@ -502,10 +504,10 @@ private Future<List<AuctionParticipation>> makeAuctionParticipation(
final ExtRequestPrebid prebid = requestExt == null ? null : requestExt.getPrebid();
final Map<String, ExtBidderConfigOrtb> biddersToConfigs = getBiddersToConfigs(prebid);
final Map<String, List<String>> eidPermissions = getEidPermissions(prebid);
final Map<String, User> bidderToUser =
prepareUsers(bidders, context, aliases, biddersToConfigs, eidPermissions);
final Map<String, Pair<User, Device>> bidderToUserAndDevice =
prepareUsersAndDevices(bidders, context, aliases, biddersToConfigs, eidPermissions);

return privacyEnforcementService.mask(context, bidderToUser, aliases)
return privacyEnforcementService.mask(context, bidderToUserAndDevice, aliases)
.map(bidderToPrivacyResult -> getAuctionParticipation(
bidderToPrivacyResult,
bidRequest,
Expand Down Expand Up @@ -557,7 +559,7 @@ private static List<String> firstPartyDataBidders(ExtRequest requestExt) {
return data == null ? null : data.getBidders();
}

private Map<String, User> prepareUsers(List<String> bidders,
private Map<String, Pair<User, Device>> prepareUsersAndDevices(List<String> bidders,
AuctionContext context,
BidderAliases aliases,
Map<String, ExtBidderConfigOrtb> biddersToConfigs,
Expand All @@ -566,17 +568,19 @@ private Map<String, User> prepareUsers(List<String> bidders,
final BidRequest bidRequest = context.getBidRequest();
final List<String> firstPartyDataBidders = firstPartyDataBidders(bidRequest.getExt());

final Map<String, User> bidderToUser = new HashMap<>();
final Map<String, Pair<User, Device>> bidderToUserAndDevice = new HashMap<>();
for (String bidder : bidders) {
final ExtBidderConfigOrtb fpdConfig = ObjectUtils.defaultIfNull(biddersToConfigs.get(bidder),
biddersToConfigs.get(ALL_BIDDERS_CONFIG));
final boolean useFirstPartyData = firstPartyDataBidders == null || firstPartyDataBidders.stream()
.anyMatch(fpdBidder -> StringUtils.equalsIgnoreCase(fpdBidder, bidder));
final User preparedUser = prepareUser(
bidder, context, aliases, useFirstPartyData, fpdConfig, eidPermissions);
bidderToUser.put(bidder, preparedUser);
final Device preparedDevice = prepareDevice(
bidRequest.getDevice(), fpdConfig, useFirstPartyData);
bidderToUserAndDevice.put(bidder, Pair.of(preparedUser, preparedDevice));
}
return bidderToUser;
return bidderToUserAndDevice;
}

private User prepareUser(String bidder,
Expand Down Expand Up @@ -813,7 +817,6 @@ private BidRequest prepareBidRequest(BidderPrivacyResult bidderPrivacyResult,
final boolean isApp = preparedApp != null;
final boolean isDooh = !isApp && preparedDooh != null;
final boolean isSite = !isApp && !isDooh && preparedSite != null;

final List<Imp> preparedImps = prepareImps(
bidder,
bidRequest,
Expand Down Expand Up @@ -945,6 +948,13 @@ private App prepareApp(App app, ObjectNode fpdApp, boolean useFirstPartyData) {
return useFirstPartyData ? fpdResolver.resolveApp(maskedApp, fpdApp) : maskedApp;
}

private Device prepareDevice(Device device, ExtBidderConfigOrtb fpdConfig, boolean useFirstPartyData) {
if (fpdConfig == null) {
return device;
}
return useFirstPartyData ? fpdResolver.resolveDevice(device, fpdConfig.getDevice()) : device;
}

private static ExtApp maskExtApp(ExtApp appExt) {
final ExtApp maskedExtApp = ExtApp.of(appExt.getPrebid(), null);
return maskedExtApp.isEmpty() ? null : maskedExtApp;
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/org/prebid/server/auction/FpdResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.fasterxml.jackson.databind.node.NullNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.iab.openrtb.request.App;
import com.iab.openrtb.request.Device;
import com.iab.openrtb.request.Dooh;
import com.iab.openrtb.request.Site;
import com.iab.openrtb.request.User;
Expand All @@ -23,7 +24,8 @@ public class FpdResolver {
private static final String BIDDERS = "bidders";
private static final String APP = "app";
private static final String DOOH = "dooh";
private static final Set<String> KNOWN_FPD_ATTRIBUTES = Set.of(USER, SITE, APP, DOOH, BIDDERS);
private static final String DEVICE = "device";
private static final Set<String> KNOWN_FPD_ATTRIBUTES = Set.of(USER, SITE, APP, DOOH, DEVICE, BIDDERS);
private static final String CONTEXT = "context";
private static final String DATA = "data";

Expand Down Expand Up @@ -51,6 +53,10 @@ public Dooh resolveDooh(Dooh originDooh, ObjectNode fpdDooh) {
return mergeFpd(originDooh, fpdDooh, Dooh.class);
}

public Device resolveDevice(Device originDevice, ObjectNode fpdDevice) {
return mergeFpd(originDevice, fpdDevice, Device.class);
}

private <T> T mergeFpd(T original, ObjectNode fpd, Class<T> tClass) {
if (fpd == null || fpd.isNull() || fpd.isMissingNode()) {
return original;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,7 @@ public class GppModelWrapper extends GppModel {
private IntObjectMap<String> sectionIdToEncodedString;

public GppModelWrapper(String encodedString) throws DecodingException {
super(padSections(encodedString));
}

private static String padSections(String gpp) {
final StringBuilder gppBuilder = new StringBuilder(gpp);

int subsectionStart = 0;
int offset = 0;
for (int i = 1; i < gpp.length(); i++) {
final char currentChar = gpp.charAt(i);

if (currentChar == '~' || currentChar == '.') {
if ((i - subsectionStart) % 4 != 0 && gpp.charAt(i - 1) != '=') {
gppBuilder.insert(i + offset, "A");
offset++;
}

subsectionStart = i + 1;
}
}

final int lastSubsectionLength = gpp.length() - subsectionStart;
if (lastSubsectionLength > 0 && lastSubsectionLength % 4 != 0 && !gpp.endsWith("=")) {
gppBuilder.append("A");
}

return gppBuilder.toString();
super(encodedString);
}

private void init() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package org.prebid.server.auction.privacy.enforcement;

import com.iab.openrtb.request.Device;
import com.iab.openrtb.request.User;
import io.vertx.core.Future;
import org.prebid.server.auction.aliases.BidderAliases;
import org.prebid.server.auction.model.AuctionContext;
import org.prebid.server.auction.model.BidderPrivacyResult;
import org.apache.commons.lang3.tuple.Pair;

import java.util.List;
import java.util.Map;
Expand All @@ -22,14 +24,14 @@ public PrivacyEnforcementService(final List<PrivacyEnforcement> enforcements) {
}

public Future<List<BidderPrivacyResult>> mask(AuctionContext auctionContext,
Map<String, User> bidderToUser,
Map<String, Pair<User, Device>> bidderToUserAndDevice,
BidderAliases aliases) {

final List<BidderPrivacyResult> initialResults = bidderToUser.entrySet().stream()
final List<BidderPrivacyResult> initialResults = bidderToUserAndDevice.entrySet().stream()
.map(entry -> BidderPrivacyResult.builder()
.requestBidder(entry.getKey())
.user(entry.getValue())
.device(auctionContext.getBidRequest().getDevice())
.user(entry.getValue().getLeft())
.device(entry.getValue().getRight())
.build())
.toList();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ private static String resolveWidth(Device device) {
}

private static String resolveHost(Integer domainId) {
if (domainId == 0 || domainId == 1 || domainId == 1001) {
if (domainId == null || domainId == 0 || domainId == 1 || domainId == 1001) {
return "bid";
} else if (domainId < 1002) {
return "bid" + domainId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import com.iab.openrtb.response.BidResponse;
import com.iab.openrtb.response.SeatBid;
import io.vertx.core.MultiMap;
import io.vertx.core.http.HttpMethod;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
Expand All @@ -22,17 +21,22 @@
import org.prebid.server.bidder.model.BidderError;
import org.prebid.server.bidder.model.HttpRequest;
import org.prebid.server.bidder.model.Result;
import org.prebid.server.bidder.nextmillennium.proto.NextMillenniumExt;
import org.prebid.server.bidder.nextmillennium.proto.NextMillenniumExtBidder;
import org.prebid.server.exception.PreBidException;
import org.prebid.server.json.DecodeException;
import org.prebid.server.json.JacksonMapper;
import org.prebid.server.proto.openrtb.ext.ExtPrebid;
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.ExtRequestPrebidServer;
import org.prebid.server.proto.openrtb.ext.request.ExtStoredRequest;
import org.prebid.server.proto.openrtb.ext.request.nextmillennium.ExtImpNextMillennium;
import org.prebid.server.proto.openrtb.ext.response.BidType;
import org.prebid.server.util.BidderUtil;
import org.prebid.server.util.HttpUtil;
import org.prebid.server.util.ObjectUtil;
import org.prebid.server.version.PrebidVersionProvider;

import java.util.ArrayList;
import java.util.Collection;
Expand All @@ -46,15 +50,22 @@ public class NextMillenniumBidder implements Bidder<BidRequest> {
new TypeReference<>() {
};

private static final String NM_ADAPTER_VERSION = "v1.0.0";

private final String endpointUrl;
private final JacksonMapper mapper;
private final List<String> nmmFlags;
private final PrebidVersionProvider versionProvider;

public NextMillenniumBidder(String endpointUrl,
JacksonMapper mapper,
List<String> nmmFlags,
PrebidVersionProvider versionProvider) {

public NextMillenniumBidder(String endpointUrl, JacksonMapper mapper, List<String> nmmFlags) {
this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl));
this.mapper = Objects.requireNonNull(mapper);
this.nmmFlags = nmmFlags;

this.versionProvider = Objects.requireNonNull(versionProvider);
}

@Override
Expand All @@ -70,7 +81,12 @@ public final Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest b
errors.add(BidderError.badInput(e.getMessage()));
continue;
}
httpRequests.add(makeHttpRequest(updateBidRequest(bidRequest, extImpNextMillennium)));
final BidRequest updatedRequest = updateBidRequest(bidRequest, extImpNextMillennium);
httpRequests.add(BidderUtil.defaultRequest(
updatedRequest,
headers(),
endpointUrl,
mapper));
}

return errors.isEmpty() ? Result.withValues(httpRequests) : Result.withErrors(errors);
Expand All @@ -84,31 +100,19 @@ private ExtImpNextMillennium convertExt(ObjectNode impExt) {
}
}

private BidRequest updateBidRequest(BidRequest bidRequest, ExtImpNextMillennium ext) {
final ExtStoredRequest storedRequest = ExtStoredRequest.of(resolveStoredRequestId(bidRequest, ext));

final ExtRequestPrebid createdExtRequestPrebid = ExtRequestPrebid.builder()
.storedrequest(storedRequest)
.build();

final ExtRequestPrebid extRequestPrebid = Optional.of(bidRequest)
.map(BidRequest::getExt)
private BidRequest updateBidRequest(BidRequest bidRequest, ExtImpNextMillennium extImp) {
final String soredRequestId = resolveStoredRequestId(bidRequest, extImp);
final ExtRequestPrebidServer extRequestPrebidServer = Optional.ofNullable(bidRequest.getExt())
.map(ExtRequest::getPrebid)
.map(prebid -> prebid.toBuilder().storedrequest(storedRequest).build())
.orElse(createdExtRequestPrebid);
.map(ExtRequestPrebid::getServer)
.orElse(null);

return bidRequest.toBuilder()
.imp(updateImps(bidRequest, createdExtRequestPrebid))
.ext(ExtRequest.of(extRequestPrebid))
.imp(modifyFirstImp(bidRequest.getImp(), soredRequestId))
.ext(createExtRequest(soredRequestId, extRequestPrebidServer))
.build();
}

private List<Imp> updateImps(BidRequest bidRequest, ExtRequestPrebid extRequestPrebid) {
return bidRequest.getImp().stream()
.map(imp -> imp.toBuilder().ext(createImpExt(extRequestPrebid)).build())
.toList();
}

private static String resolveStoredRequestId(BidRequest bidRequest, ExtImpNextMillennium extImpNextMillennium) {
final String groupId = extImpNextMillennium.getGroupId();
if (StringUtils.isEmpty(groupId)) {
Expand Down Expand Up @@ -146,24 +150,38 @@ private static String formatSize(Integer w, Integer h) {
: null;
}

private ObjectNode createImpExt(ExtRequestPrebid prebid) {
final ObjectNode impExt = mapper.mapper().createObjectNode();
impExt.set("prebid", mapper.mapper().valueToTree(prebid));
if (CollectionUtils.isNotEmpty(nmmFlags)) {
impExt.putObject("nextMillennium")
.set("nmmFlags", mapper.mapper().valueToTree(nmmFlags));
}
return impExt;
private List<Imp> modifyFirstImp(List<Imp> imps, String storedRequestId) {
final ExtRequestPrebid extRequestPrebid = ExtRequestPrebid.builder()
.storedrequest(ExtStoredRequest.of(storedRequestId))
.build();

final NextMillenniumExt nextMillenniumExt = NextMillenniumExt.of(
NextMillenniumExtBidder.of(nmmFlags, null, null));

final ExtRequest extRequest = ExtRequest.of(extRequestPrebid);
mapper.fillExtension(extRequest, nextMillenniumExt);

final ObjectNode impExt = mapper.mapper().valueToTree(extRequest);

final List<Imp> modifiedImps = new ArrayList<>(imps);
modifiedImps.set(0, imps.getFirst().toBuilder().ext(impExt).build());

return modifiedImps;
}

private HttpRequest<BidRequest> makeHttpRequest(BidRequest bidRequest) {
return HttpRequest.<BidRequest>builder()
.method(HttpMethod.POST)
.uri(endpointUrl)
.headers(headers())
.payload(bidRequest)
.body(mapper.encodeToBytes(bidRequest))
private ExtRequest createExtRequest(String storedRequestId, ExtRequestPrebidServer extRequestPrebidServer) {
final ExtRequestPrebid extRequestPrebid = ExtRequestPrebid.builder()
.storedrequest(ExtStoredRequest.of(storedRequestId))
.server(extRequestPrebidServer)
.build();

final NextMillenniumExt nextMillenniumExt = NextMillenniumExt.of(
NextMillenniumExtBidder.of(nmmFlags, NM_ADAPTER_VERSION, versionProvider.getNameVersionRecord()));

final ExtRequest extRequest = ExtRequest.of(extRequestPrebid);
mapper.fillExtension(extRequest, nextMillenniumExt);

return extRequest;
}

private static MultiMap headers() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.prebid.server.bidder.nextmillennium.proto;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Value;

@Value(staticConstructor = "of")
public class NextMillenniumExt {

@JsonProperty("nextMillennium")
NextMillenniumExtBidder nextMillennium;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.prebid.server.bidder.nextmillennium.proto;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Value;

import java.util.List;

@Value(staticConstructor = "of")
public class NextMillenniumExtBidder {

@JsonProperty("nmmFlags")
List<String> nmmFlags;

String nmVersion;

String serverVersion;
}
Loading
Loading