Skip to content

Commit

Permalink
Consolidate Unruly Adapter: Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
marki1an committed Jan 21, 2022
1 parent 573fa33 commit d9ab2f8
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 28 deletions.
52 changes: 35 additions & 17 deletions src/main/java/org/prebid/server/bidder/unruly/UnrulyBidder.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
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 io.vertx.core.MultiMap;
import io.vertx.core.http.HttpMethod;
import org.apache.commons.collections4.CollectionUtils;
import org.prebid.server.bidder.Bidder;
Expand Down Expand Up @@ -56,6 +56,7 @@ public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request
modifiedImps.add(modifyImp(imp, extImpUnruly));
} catch (PreBidException e) {
errors.add(BidderError.badInput(e.getMessage()));
return Result.withErrors(errors);
}
}

Expand All @@ -70,13 +71,14 @@ private ExtImpUnruly parseImpExt(Imp imp) {
try {
return mapper.mapper().convertValue(imp.getExt(), UNRULY_EXT_TYPE_REFERENCE).getBidder();
} catch (IllegalArgumentException e) {
throw new PreBidException(e.getMessage(), e);
throw new PreBidException(String.format("ext data not provided in imp id=%s. Abort all Request",
imp.getId()));
}
}

private Imp modifyImp(Imp imp, ExtImpUnruly extImpUnruly) {
final ObjectNode modifiedExt = mapper.mapper().createObjectNode();
modifiedExt.set("unruly", mapper.mapper().convertValue(extImpUnruly, JsonNode.class));
modifiedExt.set("bidder", mapper.mapper().convertValue(extImpUnruly, JsonNode.class));
return imp.toBuilder().ext(modifiedExt).build();
}

Expand All @@ -86,44 +88,58 @@ private HttpRequest<BidRequest> createSingleRequest(Imp modifiedImp, BidRequest
return HttpRequest.<BidRequest>builder()
.method(HttpMethod.POST)
.uri(endpointUrl)
.headers(getHeaders())
.headers(HttpUtil.headers())
.body(mapper.encodeToBytes(outgoingRequest))
.payload(outgoingRequest)
.build();
}

private static MultiMap getHeaders() {
return HttpUtil.headers()
.add("X-Unruly-Origin", "Prebid-Server");
}

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

private static List<BidderBid> extractBids(BidRequest bidRequest, BidResponse bidResponse) {
private static List<BidderBid> extractBids(BidRequest bidRequest, BidResponse bidResponse,
List<BidderError> errors) {
return bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())
? Collections.emptyList()
: bidsFromResponse(bidRequest, bidResponse);
: bidsFromResponse(bidRequest, bidResponse, errors);
}

private static List<BidderBid> bidsFromResponse(BidRequest bidRequest, BidResponse bidResponse) {
return bidResponse.getSeatbid().stream()
private static List<BidderBid> bidsFromResponse(BidRequest bidRequest, BidResponse bidResponse,
List<BidderError> errors) {
return bidResponse.getSeatbid()
.stream()
.filter(Objects::nonNull)
.map(SeatBid::getBid)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), bidRequest.getImp()), bidResponse.getCur()))
.filter(Objects::nonNull)
.map(bid -> resolveBidderBid(bid, bidResponse.getCur(), bidRequest.getImp(), errors))
.filter(Objects::nonNull)
.collect(Collectors.toList());
}

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

private static BidType getBidType(String impId, List<Imp> imps) {
final List<String> noMatchingImps = new ArrayList<>();

for (Imp imp : imps) {
if (imp.getId().equals(impId)) {
if (imp.getBanner() != null) {
Expand All @@ -134,9 +150,11 @@ private static BidType getBidType(String impId, List<Imp> imps) {
return BidType.banner;
}
} else {
throw new PreBidException(String.format("Unknown impression type for ID: %s", impId));
noMatchingImps.add(imp.getId());
}
}
throw new PreBidException(String.format("Failed to find impression %s", impId));

throw new PreBidException(String
.format("Bid response imp ID %s not found in bid request containing imps %s", impId, noMatchingImps));
}
}
26 changes: 16 additions & 10 deletions src/test/java/org/prebid/server/bidder/unruly/UnrulyBidderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.tuple;
import static org.prebid.server.bidder.model.BidderError.Type.bad_input;
import static org.prebid.server.bidder.model.BidderError.Type.bad_server_response;
import static org.prebid.server.proto.openrtb.ext.response.BidType.banner;
import static org.prebid.server.proto.openrtb.ext.response.BidType.video;

Expand Down Expand Up @@ -60,9 +62,11 @@ public void makeHttpRequestsShouldReturnErrorIfImpExtCouldNotBeParsed() {
final Result<List<HttpRequest<BidRequest>>> result = unrulyBidder.makeHttpRequests(bidRequest);

// then
assertThat(result.getErrors()).hasSize(1);
assertThat(result.getErrors().get(0).getMessage()).startsWith("Cannot deserialize value");
assertThat(result.getValue()).isEmpty();
assertThat(result.getErrors()).hasSize(1)
.allSatisfy(error -> {
assertThat(error.getMessage()).startsWith("ext data not provided in imp id=123");
assertThat(error.getType()).isEqualTo(bad_input);
});
}

@Test
Expand All @@ -81,8 +85,7 @@ public void makeHttpRequestsShouldReturnOneRequestPerImpWithExpectedHeaders() {
.extracting(Map.Entry::getKey, Map.Entry::getValue)
.containsOnly(
tuple("Content-Type", "application/json;charset=utf-8"),
tuple("Accept", "application/json"),
tuple("X-Unruly-Origin", "Prebid-Server"));
tuple("Accept", "application/json"));
}

@Test
Expand Down Expand Up @@ -186,22 +189,25 @@ public void makeBidsShouldReturnBannerBid() throws JsonProcessingException {
}

@Test
public void makeBidsShouldReturnErrorIfImpressionWasNotFound() throws JsonProcessingException {
public void makeBidsShouldReturnErrorNotFoundBidRequest() throws JsonProcessingException {
// given
final HttpCall<BidRequest> httpCall = givenHttpCall(
BidRequest.builder()
.imp(singletonList(Imp.builder().id("321").build()))
.imp(singletonList(Imp.builder().id("112").build()))
.build(),
mapper.writeValueAsString(
givenBidResponse(bidBuilder -> bidBuilder.impid("123"))));
givenBidResponse(bidBuilder -> bidBuilder.impid("111"))));

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

// then
assertThat(result.getValue()).isEmpty();
assertThat(result.getErrors()).hasSize(1)
.containsExactly(BidderError.badServerResponse("Failed to find impression 123"));
assertThat(result.getErrors())
.allSatisfy(error -> {
assertThat(error.getMessage()).startsWith("Bid response imp ID 111 not found");
assertThat(error.getType()).isEqualTo(bad_server_response);
});
}

private static BidRequest givenBidRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"h": 600
},
"ext": {
"unruly": {
"bidder": {
"siteid": 123
}
}
Expand Down

0 comments on commit d9ab2f8

Please sign in to comment.