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

Move prefmtype to ext.prebid.biddercontrols #2875

Merged
merged 6 commits into from
Jan 4, 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
4 changes: 3 additions & 1 deletion checkstyle.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

<module name="NewlineAtEndOfFile"/>
<module name="Translation"/>
<module name="FileLength"/>
<module name="FileLength">
<property name="max" value="2024"/>
</module>
<module name="FileTabCharacter"/>
<module name="RegexpSingleline">
<property name="format" value="\s+$"/>
Expand Down
4 changes: 1 addition & 3 deletions src/main/java/org/prebid/server/auction/ExchangeService.java
Original file line number Diff line number Diff line change
Expand Up @@ -1306,18 +1306,16 @@ private Future<BidderResponse> processAndRequestBids(AuctionContext auctionConte

final String bidderName = bidderRequest.getBidder();
final MediaTypeProcessingResult mediaTypeProcessingResult = mediaTypeProcessor.process(
bidderRequest.getBidRequest(), aliases.resolveBidder(bidderName), auctionContext.getAccount());
bidderRequest.getBidRequest(), bidderName, aliases, auctionContext.getAccount());

final List<BidderError> mediaTypeProcessingErrors = mediaTypeProcessingResult.getErrors();
if (mediaTypeProcessingResult.isRejected()) {
auctionContext.getBidRejectionTrackers()
.get(bidderName)
.rejectAll(BidRejectionReason.REJECTED_BY_MEDIA_TYPE);

final BidderSeatBid bidderSeatBid = BidderSeatBid.builder()
.warnings(mediaTypeProcessingErrors)
.build();

return Future.succeededFuture(BidderResponse.of(bidderName, bidderSeatBid, 0));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Imp;
import org.apache.commons.collections4.SetUtils;
import org.prebid.server.auction.BidderAliases;
import org.prebid.server.bidder.BidderCatalog;
import org.prebid.server.bidder.BidderInfo;
import org.prebid.server.bidder.model.BidderError;
Expand Down Expand Up @@ -35,8 +36,12 @@ public BidderMediaTypeProcessor(BidderCatalog bidderCatalog) {
}

@Override
public MediaTypeProcessingResult process(BidRequest bidRequest, String bidderName, Account account) {
final Set<MediaType> supportedMediaTypes = extractSupportedMediaTypes(bidRequest, bidderName);
public MediaTypeProcessingResult process(BidRequest bidRequest,
String bidderName,
BidderAliases aliases,
Account account) {
final String resolvedBidderName = aliases.resolveBidder(bidderName);
final Set<MediaType> supportedMediaTypes = extractSupportedMediaTypes(bidRequest, resolvedBidderName);
if (supportedMediaTypes.isEmpty()) {
return MediaTypeProcessingResult.rejected(Collections.singletonList(
BidderError.badInput("Bidder does not support any media types.")));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.prebid.server.auction.mediatypeprocessor;

import com.iab.openrtb.request.BidRequest;
import org.prebid.server.auction.BidderAliases;
import org.prebid.server.bidder.model.BidderError;
import org.prebid.server.settings.model.Account;

Expand All @@ -17,12 +18,19 @@ public CompositeMediaTypeProcessor(List<MediaTypeProcessor> mediaTypeProcessors)
}

@Override
public MediaTypeProcessingResult process(BidRequest originalBidRequest, String bidderName, Account account) {
public MediaTypeProcessingResult process(BidRequest originalBidRequest,
String bidderName,
BidderAliases aliases,
Account account) {
BidRequest bidRequest = originalBidRequest;
final List<BidderError> errors = new ArrayList<>();

for (MediaTypeProcessor mediaTypeProcessor : mediaTypeProcessors) {
final MediaTypeProcessingResult result = mediaTypeProcessor.process(bidRequest, bidderName, account);
final MediaTypeProcessingResult result = mediaTypeProcessor.process(
bidRequest,
bidderName,
aliases,
account);

bidRequest = result.getBidRequest();
errors.addAll(result.getErrors());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package org.prebid.server.auction.mediatypeprocessor;

import com.iab.openrtb.request.BidRequest;
import org.prebid.server.auction.BidderAliases;
import org.prebid.server.settings.model.Account;

public interface MediaTypeProcessor {

MediaTypeProcessingResult process(BidRequest bidRequest, String bidderName, Account account);
MediaTypeProcessingResult process(BidRequest bidRequest, String bidderName, BidderAliases aliases, Account account);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package org.prebid.server.auction.mediatypeprocessor;

import com.fasterxml.jackson.core.JsonPointer;
import com.fasterxml.jackson.databind.JsonNode;
import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Imp;
import org.prebid.server.auction.BidderAliases;
import org.prebid.server.bidder.BidderCatalog;
import org.prebid.server.bidder.model.BidderError;
import org.prebid.server.proto.openrtb.ext.request.ExtRequest;
Expand All @@ -20,7 +20,7 @@

public class MultiFormatMediaTypeProcessor implements MediaTypeProcessor {

private static final JsonPointer PREF_MTYPE_FIELD = JsonPointer.compile("/bidder/prefmtype");
private static final String PREF_MTYPE_FIELD = "prefmtype";

private final BidderCatalog bidderCatalog;

Expand All @@ -29,14 +29,31 @@ public MultiFormatMediaTypeProcessor(BidderCatalog bidderCatalog) {
}

@Override
public MediaTypeProcessingResult process(BidRequest bidRequest, String bidderName, Account account) {
if (isMultiFormatSupported(bidderName)) {
return MediaTypeProcessingResult.succeeded(bidRequest, Collections.emptyList());
public MediaTypeProcessingResult process(BidRequest bidRequest,
String bidderName,
BidderAliases aliases,
Account account) {
final String resolvedBidderName = aliases.resolveBidder(bidderName);
//todo: ext.prebid.biddercontrols clean-up should NOT be here
// Suggestion: keep biddercontrols in the Auction Context
// and clean it up on the extraction auction participants step
final BidRequest.BidRequestBuilder bidRequestBuilder = Optional.ofNullable(bidRequest.getExt())
.map(ExtRequest::getPrebid)
.map(prebid -> prebid.toBuilder().biddercontrols(null).build())
.map(prebid -> {
final ExtRequest extRequest = ExtRequest.of(prebid);
extRequest.addProperties(bidRequest.getExt().getProperties());
return extRequest;
})
.map(extRequest -> bidRequest.toBuilder().ext(extRequest))
.orElse(bidRequest.toBuilder());
AntoxaAntoxic marked this conversation as resolved.
Show resolved Hide resolved
if (isMultiFormatSupported(resolvedBidderName)) {
return MediaTypeProcessingResult.succeeded(bidRequestBuilder.build(), Collections.emptyList());
}

final MediaType preferredMediaType = preferredMediaType(bidRequest, account, bidderName);
final MediaType preferredMediaType = preferredMediaType(bidRequest, account, bidderName, resolvedBidderName);
if (preferredMediaType == null) {
return MediaTypeProcessingResult.succeeded(bidRequest, Collections.emptyList());
return MediaTypeProcessingResult.succeeded(bidRequestBuilder.build(), Collections.emptyList());
}

final List<BidderError> errors = new ArrayList<>();
Expand All @@ -50,24 +67,28 @@ public MediaTypeProcessingResult process(BidRequest bidRequest, String bidderNam
return MediaTypeProcessingResult.rejected(errors);
}

return MediaTypeProcessingResult.succeeded(bidRequest.toBuilder().imp(updatedImps).build(), errors);
return MediaTypeProcessingResult.succeeded(bidRequestBuilder.imp(updatedImps).build(), errors);
}

private boolean isMultiFormatSupported(String bidder) {
return bidderCatalog.bidderInfoByName(bidder).getOrtb().isMultiFormatSupported();
}

private MediaType preferredMediaType(BidRequest bidRequest, Account account, String bidderName) {
private MediaType preferredMediaType(BidRequest bidRequest,
Account account,
String originalBidderName,
String resolvedBidderName) {
return Optional.ofNullable(bidRequest.getExt())
.map(ExtRequest::getPrebid)
.map(ExtRequestPrebid::getBidders)
.map(bidders -> bidders.at(PREF_MTYPE_FIELD))
.map(ExtRequestPrebid::getBiddercontrols)
.map(bidders -> bidders.get(originalBidderName))
.map(bidder -> bidder.get(PREF_MTYPE_FIELD))
.filter(JsonNode::isTextual)
.map(JsonNode::textValue)
.map(MediaType::of)
.or(() -> Optional.ofNullable(account.getAuction())
.map(AccountAuctionConfig::getPreferredMediaTypes)
.map(preferredMediaTypes -> preferredMediaTypes.get(bidderName)))
.map(preferredMediaTypes -> preferredMediaTypes.get(resolvedBidderName)))
.orElse(null);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ public class ExtRequestPrebid {
*/
ObjectNode bidders;

/**
* Defines the contract for bidrequest.ext.prebid.biddercontrols
*/
ObjectNode biddercontrols;

/**
* Defines the contract for bidrequest.ext.prebid.amp
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ package org.prebid.server.functional.model.request.auction
import groovy.transform.ToString

@ToString(includeNames = true, ignoreNulls = true)
class PreferredBidders {
class BidderControls {

GenericPreferredBidder generic
GenericPreferredBidder bidder
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class Prebid {
Boolean createTids
Sdk sdk
List<AdServerTargeting> adServerTargeting
PreferredBidders bidders
BidderControls bidderControls

static class Channel {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import org.prebid.server.functional.model.request.auction.Banner
import org.prebid.server.functional.model.request.auction.BidRequest
import org.prebid.server.functional.model.request.auction.GenericPreferredBidder
import org.prebid.server.functional.model.request.auction.Native
import org.prebid.server.functional.model.request.auction.PreferredBidders
import org.prebid.server.functional.model.request.auction.BidderControls

import static org.prebid.server.functional.model.response.auction.ErrorType.GENERIC
import static org.prebid.server.functional.model.response.auction.MediaType.AUDIO
Expand Down Expand Up @@ -52,7 +52,7 @@ class FilterMultiFormatSpec extends BaseSpec {
def bidRequest = BidRequest.defaultBidRequest.tap {
imp[0].banner = Banner.defaultBanner
imp[0].audio = Audio.defaultAudio
ext.prebid.bidders = new PreferredBidders(generic: new GenericPreferredBidder(preferredMediaType: BANNER))
ext.prebid.bidderControls = new BidderControls(generic: new GenericPreferredBidder(preferredMediaType: BANNER))
}

when: "PBS processes auction request"
Expand Down Expand Up @@ -98,7 +98,7 @@ class FilterMultiFormatSpec extends BaseSpec {
def bidRequest = BidRequest.defaultBidRequest.tap {
imp[0].banner = Banner.defaultBanner
imp[0].audio = Audio.defaultAudio
ext.prebid.bidders = new PreferredBidders(generic: new GenericPreferredBidder(preferredMediaType: BANNER))
ext.prebid.bidderControls = new BidderControls(generic: new GenericPreferredBidder(preferredMediaType: BANNER))
}

when: "PBS processes auction request"
Expand All @@ -119,7 +119,7 @@ class FilterMultiFormatSpec extends BaseSpec {
def bidRequest = BidRequest.defaultBidRequest.tap {
imp[0].banner = Banner.defaultBanner
imp[0].audio = Audio.defaultAudio
ext.prebid.bidders = new PreferredBidders(generic: new GenericPreferredBidder(preferredMediaType: BANNER))
ext.prebid.bidderControls = new BidderControls(generic: new GenericPreferredBidder(preferredMediaType: BANNER))
}

when: "PBS processes auction request"
Expand Down Expand Up @@ -190,7 +190,7 @@ class FilterMultiFormatSpec extends BaseSpec {
def bidRequest = BidRequest.defaultBidRequest.tap {
imp[0].banner = Banner.defaultBanner
imp[0].audio = Audio.defaultAudio
ext.prebid.bidders = new PreferredBidders(generic: new GenericPreferredBidder(preferredMediaType: BANNER))
ext.prebid.bidderControls = new BidderControls(generic: new GenericPreferredBidder(preferredMediaType: BANNER))
}

when: "PBS processes auction request"
Expand Down Expand Up @@ -241,7 +241,7 @@ class FilterMultiFormatSpec extends BaseSpec {
imp[0].banner = null
imp[0].audio = Audio.defaultAudio
imp[0].nativeObj = Native.defaultNative
ext.prebid.bidders = new PreferredBidders(generic: new GenericPreferredBidder(preferredMediaType: BANNER))
ext.prebid.bidderControls = new BidderControls(generic: new GenericPreferredBidder(preferredMediaType: BANNER))
}

when: "PBS processes auction request"
Expand Down Expand Up @@ -292,7 +292,7 @@ class FilterMultiFormatSpec extends BaseSpec {
def bidRequest = BidRequest.defaultBidRequest.tap {
imp[0].banner = null
imp[0].audio = Audio.defaultAudio
ext.prebid.bidders = new PreferredBidders(generic: new GenericPreferredBidder(preferredMediaType: BANNER))
ext.prebid.bidderControls = new BidderControls(generic: new GenericPreferredBidder(preferredMediaType: BANNER))
}

when: "PBS processes auction request"
Expand All @@ -315,7 +315,7 @@ class FilterMultiFormatSpec extends BaseSpec {
def bidRequest = BidRequest.defaultBidRequest.tap {
imp[0].banner = Banner.getDefaultBanner()
imp[0].audio = Audio.defaultAudio
ext.prebid.bidders = new PreferredBidders(generic: new GenericPreferredBidder(preferredMediaType: NULL))
ext.prebid.bidderControls = new BidderControls(generic: new GenericPreferredBidder(preferredMediaType: NULL))
}

when: "PBS processes auction request"
Expand Down Expand Up @@ -364,7 +364,7 @@ class FilterMultiFormatSpec extends BaseSpec {
def bidRequest = BidRequest.defaultBidRequest.tap {
imp[0].banner = Banner.defaultBanner
imp[0].audio = Audio.defaultAudio
ext.prebid.bidders = new PreferredBidders(generic: new GenericPreferredBidder(preferredMediaType: BANNER))
ext.prebid.bidderControls = new BidderControls(generic: new GenericPreferredBidder(preferredMediaType: BANNER))
}

and: "Account in the DB with preferred media type"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ public void setUp() {
false,
AuctionResponsePayloadImpl.of(invocation.getArgument(0)))));

given(mediaTypeProcessor.process(any(), anyString(), any()))
given(mediaTypeProcessor.process(any(), anyString(), any(), any()))
.willAnswer(invocation -> MediaTypeProcessingResult.succeeded(invocation.getArgument(0), emptyList()));

given(responseBidValidator.validate(any(), any(), any(), any())).willReturn(ValidationResult.success());
Expand Down Expand Up @@ -4758,7 +4758,7 @@ public void shouldResponseWithEmptySeatBidIfBidderNotSupportProvidedMediaTypes()
final BidRequest bidRequest = givenBidRequest(singletonList(imp), identity());
final AuctionContext auctionContext = givenRequestContext(bidRequest).toBuilder().build();

given(mediaTypeProcessor.process(any(), anyString(), any()))
given(mediaTypeProcessor.process(any(), anyString(), any(), any()))
.willReturn(MediaTypeProcessingResult.rejected(Collections.singletonList(
BidderError.badInput("MediaTypeProcessor error."))));
given(bidResponseCreator.create(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.prebid.server.VertxTest;
import org.prebid.server.auction.BidderAliases;
import org.prebid.server.auction.versionconverter.OrtbVersion;
import org.prebid.server.bidder.BidderCatalog;
import org.prebid.server.bidder.BidderInfo;
Expand All @@ -32,7 +33,9 @@
import static java.util.Collections.singletonList;
import static java.util.function.UnaryOperator.identity;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.when;
import static org.prebid.server.spring.config.bidder.model.MediaType.AUDIO;
import static org.prebid.server.spring.config.bidder.model.MediaType.BANNER;
import static org.prebid.server.spring.config.bidder.model.MediaType.NATIVE;
Expand All @@ -47,12 +50,15 @@ public class BidderMediaTypeProcessorTest extends VertxTest {

@Mock
private BidderCatalog bidderCatalog;
@Mock
private BidderAliases bidderAliases;

private BidderMediaTypeProcessor target;

@Before
public void setUp() {
target = new BidderMediaTypeProcessor(bidderCatalog);
when(bidderAliases.resolveBidder(anyString())).thenAnswer(invocation -> invocation.getArgument(0));
}

@Test
Expand All @@ -63,7 +69,7 @@ public void processShouldReturnRejectedResultAndErrorIfBidderNotSupportAnyMediaT
final BidRequest bidRequest = givenBidRequest(identity(), givenImp(BANNER));

// when
final MediaTypeProcessingResult result = target.process(bidRequest, BIDDER, null);
final MediaTypeProcessingResult result = target.process(bidRequest, BIDDER, bidderAliases, null);

// then
assertThat(result.isRejected()).isTrue();
Expand All @@ -79,7 +85,7 @@ public void processShouldUseAppMediaTypesIfAppPresent() {
.willReturn(givenBidderInfo(singletonList(BANNER), singletonList(AUDIO), singletonList(NATIVE)));

// when
final MediaTypeProcessingResult result = target.process(bidRequest, BIDDER, null);
final MediaTypeProcessingResult result = target.process(bidRequest, BIDDER, bidderAliases, null);

// then
assertThat(result.getBidRequest()).isEqualTo(bidRequest);
Expand All @@ -97,7 +103,7 @@ public void processShouldRemoveUnsupportedMediaTypes() {
givenImp(BANNER, VIDEO));

// when
final MediaTypeProcessingResult result = target.process(bidRequest, BIDDER, null);
final MediaTypeProcessingResult result = target.process(bidRequest, BIDDER, bidderAliases, null);

// then
assertThat(result.getBidRequest())
Expand All @@ -118,7 +124,7 @@ public void processShouldRemoveImpWithOnlyUnsupportedMediaTypes() {
givenImp(BANNER, AUDIO));

// when
final MediaTypeProcessingResult result = target.process(bidRequest, BIDDER, null);
final MediaTypeProcessingResult result = target.process(bidRequest, BIDDER, bidderAliases, null);

// then
assertThat(result.getBidRequest())
Expand All @@ -141,7 +147,7 @@ public void processShouldReturnRejectedResultIfRequestDoesNotContainsAnyImpWithS
givenImp(NATIVE));

// when
final MediaTypeProcessingResult result = target.process(bidRequest, BIDDER, null);
final MediaTypeProcessingResult result = target.process(bidRequest, BIDDER, bidderAliases, null);

// then
assertThat(result.isRejected()).isTrue();
Expand Down
Loading
Loading