Skip to content

Commit

Permalink
Medianet: Using mtype for getting bidtype (#3048)
Browse files Browse the repository at this point in the history
* Adds gpp, gdpr params for usersync and gzip compression for medianet adapter

* Updates medianet adapter to read bidtype from mtype and ext.prebid.type

* retrigger checks

* Fixed checkstyle errors

* Fixes invalid mtype exception handling

---------

Co-authored-by: Aman Jain <[email protected]>
Co-authored-by: rajatgoyal2510 <[email protected]>
  • Loading branch information
3 people authored Apr 2, 2024
1 parent 2516654 commit f5a365c
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Imp;
import com.iab.openrtb.response.Bid;
import com.iab.openrtb.response.BidResponse;
import com.iab.openrtb.response.SeatBid;
import org.apache.commons.collections4.CollectionUtils;
Expand All @@ -11,12 +12,14 @@
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.exception.PreBidException;
import org.prebid.server.json.DecodeException;
import org.prebid.server.json.JacksonMapper;
import org.prebid.server.proto.openrtb.ext.response.BidType;
import org.prebid.server.util.BidderUtil;
import org.prebid.server.util.HttpUtil;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
Expand All @@ -39,15 +42,21 @@ public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest bidRequ

@Override
public final Result<List<BidderBid>> makeBids(BidderCall<BidRequest> httpCall, BidRequest bidRequest) {
final BidResponse bidResponse;
try {
final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class);
return Result.withValues(extractBids(httpCall.getRequest().getPayload(), bidResponse));
bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class);
} catch (DecodeException e) {
return Result.withError(BidderError.badServerResponse(e.getMessage()));
}

final List<BidderError> errors = new ArrayList<>();
final List<BidderBid> bids = extractBids(httpCall.getRequest().getPayload(), bidResponse, errors);

return Result.of(bids, errors);
}

private static List<BidderBid> extractBids(BidRequest bidRequest, BidResponse bidResponse) {
private static List<BidderBid> extractBids(BidRequest bidRequest, BidResponse bidResponse,
List<BidderError> errors) {
if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) {
return Collections.emptyList();
}
Expand All @@ -59,11 +68,41 @@ private static List<BidderBid> extractBids(BidRequest bidRequest, BidResponse bi
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.filter(Objects::nonNull)
.map(bid -> BidderBid.of(bid, resolveBidType(bid.getImpid(), bidRequest.getImp()), currency))
.map(bid -> makeBidderBid(bid, bidRequest.getImp(), currency, errors))
.filter(Objects::nonNull)
.toList();
}

private static BidType resolveBidType(String impId, List<Imp> imps) {
private static BidType resolveBidType(Bid bid, List<Imp> imps) {
final Integer markupType = bid.getMtype();
if (markupType == null) {
return resolveBidTypeFromImpId(bid.getImpid(), imps);
}

return switch (markupType) {
case 1 -> BidType.banner;
case 2 -> BidType.video;
case 3 -> BidType.audio;
case 4 -> BidType.xNative;
default ->
throw new PreBidException("Unable to fetch mediaType: %s"
.formatted(bid.getImpid()));
};
}

private static BidderBid makeBidderBid(Bid bid, List<Imp> imps, String cur, List<BidderError> errors) {
final BidType bidType;
try {
bidType = resolveBidType(bid, imps);
} catch (PreBidException e) {
errors.add(BidderError.badServerResponse(e.getMessage()));
return null;
}

return BidderBid.of(bid, bidType, cur);
}

private static BidType resolveBidTypeFromImpId(String impId, List<Imp> imps) {
for (Imp imp : imps) {
if (Objects.equals(impId, imp.getId())) {
if (imp.getBanner() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Imp;
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 @@ -16,13 +17,17 @@
import org.prebid.server.bidder.model.Result;
import org.prebid.server.proto.openrtb.ext.ExtPrebid;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.prebid.server.proto.openrtb.ext.response.BidType.audio;
import static org.prebid.server.proto.openrtb.ext.response.BidType.banner;
import static org.prebid.server.proto.openrtb.ext.response.BidType.video;
import static org.prebid.server.proto.openrtb.ext.response.BidType.xNative;

public class MedianetBidderTest extends VertxTest {

Expand Down Expand Up @@ -110,6 +115,88 @@ public void makeBidsShouldReturnBannerBidIfBannerIsPresent() throws JsonProcessi
.containsExactly(BidderBid.of(Bid.builder().impid("123").build(), banner, "USD"));
}

@Test
public void makeBidsShouldReturnCorrespondingMtypesAndAdTypes() throws JsonProcessingException {
final List<Bid> bids = new ArrayList<>();
final Bid bid1 = Bid.builder().impid("imp_id").mtype(1).build();
final Bid bid2 = Bid.builder().impid("imp_id").mtype(2).build();
final Bid bid3 = Bid.builder().impid("imp_id").mtype(3).build();
final Bid bid4 = Bid.builder().impid("imp_id").mtype(4).build();
bids.add(bid1);
bids.add(bid2);
bids.add(bid3);
bids.add(bid4);

// given
final BidderCall<BidRequest> httpCall = sampleHttpCall(
givenBidRequest(),
mapper.writeValueAsString(sampleMultiFormatBidResponse(bids)));

// when
final Result<List<BidderBid>> result = target.makeBids(httpCall, null);

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue()).hasSize(4);
final BidderBid bannerBid = BidderBid.of(bid1, banner, "USD");
final BidderBid videoBid = BidderBid.of(bid2, video, "USD");
final BidderBid audioBid = BidderBid.of(bid3, audio, "USD");
final BidderBid xNativeBid = BidderBid.of(bid4, xNative, "USD");
assertThat(result.getValue()).containsExactlyInAnyOrder(bannerBid, videoBid, audioBid, xNativeBid);
}

@Test
public void makeBidsShouldReturnAdTypeAccordingToImpressionIfMtypeIsAbsent() throws JsonProcessingException {
// given
final BidderCall<BidRequest> httpCall = sampleHttpCall(
givenVideoBidRequest(),
mapper.writeValueAsString(sampleBidResponse(bidBuilder -> bidBuilder.impid("imp_id"))));

// when
final Result<List<BidderBid>> result = target.makeBids(httpCall, null);

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue()).hasSize(1);
final BidderBid videoBid = BidderBid.of(Bid.builder().impid("imp_id").build(), video, "USD");
assertThat(result.getValue()).containsExactly(videoBid);
}

@Test
public void makeBidsShouldReturnBannerAdTypeIfMtypeIsAbsentAndIfNoImpressionIdMatches()
throws JsonProcessingException {
// given
final BidderCall<BidRequest> httpCall = sampleHttpCall(
givenVideoBidRequest(),
mapper.writeValueAsString(sampleBidResponse(bidBuilder -> bidBuilder.impid("imp_id2"))));

// when
final Result<List<BidderBid>> result = target.makeBids(httpCall, null);

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue()).hasSize(1);
final BidderBid bannerBid = BidderBid.of(Bid.builder().impid("imp_id2").build(), banner, "USD");
assertThat(result.getValue()).containsExactly(bannerBid);
}

@Test
public void makeBidsShouldReturnErrorIfMtypeIsWrong() throws JsonProcessingException {
// given
final BidderCall<BidRequest> httpCall = sampleHttpCall(
givenVideoBidRequest(),
mapper.writeValueAsString(sampleBidResponse(bidBuilder -> bidBuilder.impid("imp_id").mtype(5))));

// when
final Result<List<BidderBid>> result = target.makeBids(httpCall, null);

// then
assertThat(result.getErrors()).hasSize(1);
assertThat(result.getValue()).isEmpty();
final BidderError error = BidderError.badServerResponse("Unable to fetch mediaType: imp_id");
assertThat(result.getErrors()).containsExactly(error);
}

private static BidResponse sampleBidResponse(Function<Bid.BidBuilder,
Bid.BidBuilder> bidCustomizer) {
return BidResponse.builder()
Expand All @@ -120,6 +207,15 @@ private static BidResponse sampleBidResponse(Function<Bid.BidBuilder,
.build();
}

private static BidResponse sampleMultiFormatBidResponse(List<Bid> bids) {
return BidResponse.builder()
.cur("USD")
.seatbid(singletonList(SeatBid.builder()
.bid(bids)
.build()))
.build();
}

private static BidderCall<BidRequest> sampleHttpCall(BidRequest bidRequest, String body) {
return BidderCall.succeededHttp(
HttpRequest.<BidRequest>builder().payload(bidRequest).build(),
Expand All @@ -136,4 +232,15 @@ private static BidRequest givenBidRequest() {
.build()))
.build();
}

private static BidRequest givenVideoBidRequest() {
return BidRequest.builder()
.id("request_id")
.imp(singletonList(Imp.builder()
.id("imp_id")
.video(Video.builder().build())
.ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createObjectNode())))
.build()))
.build();
}
}

0 comments on commit f5a365c

Please sign in to comment.