Skip to content

Commit

Permalink
DMX: Enforcing w and h in imp
Browse files Browse the repository at this point in the history
  • Loading branch information
RodionOrets committed Apr 26, 2021
1 parent 800573c commit 8b2a46f
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 28 deletions.
103 changes: 76 additions & 27 deletions src/main/java/org/prebid/server/bidder/dmx/DmxBidder.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
import com.iab.openrtb.request.App;
import com.iab.openrtb.request.Banner;
import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Device;
import com.iab.openrtb.request.Format;
import com.iab.openrtb.request.Imp;
import com.iab.openrtb.request.Publisher;
import com.iab.openrtb.request.Site;
import com.iab.openrtb.request.User;
import com.iab.openrtb.request.Video;
import com.iab.openrtb.response.Bid;
import com.iab.openrtb.response.BidResponse;
import com.iab.openrtb.response.SeatBid;
Expand All @@ -35,6 +38,7 @@

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
Expand All @@ -51,6 +55,7 @@ public class DmxBidder implements Bidder<BidRequest> {
private static final int SECURE = 1;
private static final String IMP = "</Impression><Impression><![CDATA[%s]]></Impression>";
private static final String SEARCH = "</Impression>";
private static final List<Integer> VIDEO_PROTOCOLS = Arrays.asList(2, 3, 5, 6, 7, 8);

private final String endpointUrl;
private final JacksonMapper mapper;
Expand All @@ -63,7 +68,7 @@ public DmxBidder(String endpointUrl, JacksonMapper mapper) {
@Override
public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request) {
try {
validateUserAndApp(request.getApp(), request.getUser());
validateRequest(request);
} catch (PreBidException e) {
return Result.withError(BidderError.badInput(e.getMessage()));
}
Expand Down Expand Up @@ -102,7 +107,7 @@ public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request
final BidRequest outgoingRequest = request.toBuilder()
.imp(validImps)
.site(modifySite(request.getSite(), updatedPublisherId))
.app(modifyApp(request.getApp(), updatedPublisherId))
.app(modifyApp(request.getApp(), request.getDevice(), updatedPublisherId))
.build();

final String urlParameter = StringUtils.isNotBlank(updatedSellerId)
Expand All @@ -121,6 +126,38 @@ public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request
errors);
}

private static void validateRequest(BidRequest bidRequest) {
final User user = bidRequest.getUser();
final App app = bidRequest.getApp();
final Device device = bidRequest.getDevice();

if (user == null && app == null) {
throw new PreBidException("No user id or app id found. Could not send request to DMX.");
}

if (app != null) {
if (StringUtils.isNotBlank(app.getId())) {
return;
} else if (device != null && StringUtils.isNotBlank(device.getIfa())) {
return;
}
}

if (user != null) {
if (StringUtils.isNotBlank(user.getId())) {
return;
}

final ExtUser userExt = user.getExt();
// Notice that digitrust is absent to keep prebid convention
if (userExt != null && CollectionUtils.isNotEmpty(userExt.getEids())) {
return;
}
}

throw new PreBidException("This request contained no identifier");
}

private ExtImpDmx parseImpExt(Imp imp) {
try {
return mapper.mapper().convertValue(imp.getExt(), DMX_EXT_TYPE_REFERENCE).getBidder();
Expand Down Expand Up @@ -157,41 +194,52 @@ private static Imp fetchParams(Imp imp, ExtImpDmx extImp) {
return null;
}

BigDecimal bidFloor = imp.getBidfloor();
final BigDecimal extBidFloor = extImp.getBidFloor();
if (extBidFloor != null && extBidFloor.compareTo(BigDecimal.ZERO) > 0) {
bidFloor = extBidFloor;
}

return imp.toBuilder()
.tagid(tagId)
.secure(StringUtils.isAllBlank(extTagId, dmxId) ? imp.getSecure() : SECURE)
.bidfloor(bidFloor)
.bidfloor(resolveBidFloor(extImp, imp.getBidfloor()))
.banner(resolveBanner(imp.getBanner()))
.video(resolveVideo(imp.getVideo()))
.build();
}

private static void validateUserAndApp(App app, User user) {
if (user == null && app == null) {
throw new PreBidException("No user id or app id found. Could not send request to DMX.");
}
private static BigDecimal resolveBidFloor(ExtImpDmx extImp, BigDecimal bidFloor) {
final BigDecimal extBidFloor = extImp.getBidFloor();
return extBidFloor != null && extBidFloor.compareTo(BigDecimal.ZERO) > 0
? extBidFloor
: bidFloor;
}

if (app != null && StringUtils.isNotBlank(app.getId())) {
return;
private static Banner resolveBanner(Banner banner) {
if (banner != null) {
if (banner.getH() == null || banner.getW() == null) {
if (CollectionUtils.isNotEmpty(banner.getFormat())) {
Format bannerFormat = banner.getFormat().get(0);
if (bannerFormat != null) {
return banner.toBuilder()
.w(bannerFormat.getW())
.h(bannerFormat.getH())
.build();
}
}
}
}
return banner;
}

if (user != null) {
if (StringUtils.isNotBlank(user.getId())) {
return;
}
private static Video resolveVideo(Video video) {
return video == null
? video
: video.toBuilder()
.protocols(resolveVideoProtocols(video.getProtocols()))
.build();

final ExtUser userExt = user.getExt();
// Notice that digitrust is absent to keep prebid convention
if (userExt != null && CollectionUtils.isNotEmpty(userExt.getEids())) {
return;
}
}
}

throw new PreBidException("This request contained no identifier");
private static List<Integer> resolveVideoProtocols(List<Integer> videoProtocols) {
return CollectionUtils.isNotEmpty(videoProtocols)
? videoProtocols
: VIDEO_PROTOCOLS;
}

private Site modifySite(Site site, String updatedPublisherId) {
Expand All @@ -202,10 +250,11 @@ private Site modifySite(Site site, String updatedPublisherId) {
.build();
}

private App modifyApp(App app, String updatedPublisherId) {
private App modifyApp(App app, Device device, String updatedPublisherId) {
return app == null
? null
: app.toBuilder()
.id(StringUtils.isNotBlank(app.getId()) ? app.getId() : device.getIfa())
.publisher(modifyPublisher(app.getPublisher(), updatedPublisherId, true))
.build();
}
Expand Down
82 changes: 82 additions & 0 deletions src/test/java/org/prebid/server/bidder/dmx/DmxBidderTest.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.Banner;
import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Device;
import com.iab.openrtb.request.Format;
import com.iab.openrtb.request.Imp;
import com.iab.openrtb.request.Publisher;
Expand All @@ -30,6 +31,8 @@
import org.prebid.server.proto.openrtb.ext.request.dmx.ExtImpDmx;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

Expand Down Expand Up @@ -77,6 +80,7 @@ public void makeHttpRequestsShouldReturnErrorWhenRequestContainsNoIdentifierIdIs
final BidRequest bidRequest = givenBidRequest(
builder -> builder
.app(App.builder().id(null).build())
.device(Device.builder().ifa(null).build())
.user(User.builder().id(null).ext(ExtUser.builder().eids(emptyList()).build()).build()),
identity());

Expand All @@ -88,6 +92,24 @@ public void makeHttpRequestsShouldReturnErrorWhenRequestContainsNoIdentifierIdIs
.containsExactly(BidderError.badInput("This request contained no identifier"));
}

@Test
public void makeHttpRequestsShouldReturnErrorWhenRequestContainsNoIdentifierAndDeviceIsNull() {
// given
final BidRequest bidRequest = givenBidRequest(
builder -> builder
.app(App.builder().id(null).build())
.user(User.builder().id(null).ext(ExtUser.builder().eids(emptyList()).build()).build())
.device(null),
identity());

// when
final Result<List<HttpRequest<BidRequest>>> result = dmxBidder.makeHttpRequests(bidRequest);

// then
assertThat(result.getErrors())
.containsExactly(BidderError.badInput("This request contained no identifier"));
}

@Test
public void makeHttpRequestsShouldReturnErrorIfImpExtCouldNotBeParsed() {
// given
Expand Down Expand Up @@ -137,6 +159,24 @@ public void makeHttpRequestsShouldModifyImpWhenBannerFormatIsNotEmpty() {
.containsOnly(tuple("dmxId", 1, BigDecimal.ONE));
}

@Test
public void makeHttpRequestsShouldGetSizeForBannerFromFirstFormatIfAnyOfBannerSizesAreMissed() {
// given
final BidRequest bidRequest = givenBidRequest(identity());

// when
final Result<List<HttpRequest<BidRequest>>> result = dmxBidder.makeHttpRequests(bidRequest);

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue()).hasSize(1)
.extracting(HttpRequest::getPayload)
.flatExtracting(BidRequest::getImp)
.extracting(Imp::getBanner)
.extracting(Banner::getH, Banner::getW)
.containsOnly(tuple(500, 300));
}

@Test
public void makeHttpRequestsShouldModifyImpWhenVideoIsNotEmpty() {
// given
Expand Down Expand Up @@ -225,6 +265,27 @@ public void makeHttpRequestsShouldUpdateImpTagIdFromDmxIdWhenExtTagIdAndDmxIdIsP
.containsExactly("dmxId");
}

@Test
public void makeHttpRequestsShouldEnrichVideoWithNeededProtocolsIfProtocolsAreMissed() {
// given
final BidRequest bidRequest = givenBidRequest(
builder -> builder.video(Video.builder().protocols(null).build()));

// when
final Result<List<HttpRequest<BidRequest>>> result = dmxBidder.makeHttpRequests(bidRequest);

final List<Integer> expectedProtocols = new ArrayList<>(Arrays.asList(2, 3, 5, 6, 7, 8));

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue()).hasSize(1)
.extracting(HttpRequest::getPayload)
.flatExtracting(BidRequest::getImp)
.extracting(Imp::getVideo)
.flatExtracting(Video::getProtocols)
.containsAll(Arrays.asList(2, 3, 5, 6, 7, 8));
}

@Test
public void makeHttpRequestsShouldUpdateAppPublisherWhenAppAndExtImpPublisherIdIsPresent() {
// given
Expand Down Expand Up @@ -264,6 +325,27 @@ public void makeHttpRequestsShouldUpdateAppPublisherWhenAppAndMemberIdPresentAnd
.containsExactly(expectedPublisher("memberId", true));
}

@Test
public void makeHttpRequestsShouldReplaceAppIdWithDeviceIfa() {
// given
final BidRequest bidRequest = givenBidRequest(
builder -> builder
.app(App.builder().id(null).build())
.device(Device.builder().ifa("ifa").build()),
identity());

// when
final Result<List<HttpRequest<BidRequest>>> result = dmxBidder.makeHttpRequests(bidRequest);

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue()).hasSize(1)
.extracting(HttpRequest::getPayload)
.extracting(BidRequest::getApp)
.flatExtracting(App::getId)
.containsExactly("ifa");
}

@Test
public void makeHttpRequestsShouldUpdateSitePublisherWhenSiteAndExtImpPublisherIdIsPresent() {
// given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
"w": 300,
"h": 250
}
]
],
"w": 300,
"h": 250
},
"tagid": "1007",
"secure": 1,
Expand Down

0 comments on commit 8b2a46f

Please sign in to comment.