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
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.iab.openrtb.request.Banner;
import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Device;
import com.iab.openrtb.request.User;
import com.iab.openrtb.request.Format;
import com.iab.openrtb.request.Imp;
import com.iab.openrtb.response.Bid;
Expand All @@ -16,6 +17,7 @@
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.URIBuilder;
import org.prebid.server.bidder.Bidder;
import org.prebid.server.bidder.model.BidderBid;
import org.prebid.server.bidder.model.BidderCall;
Expand All @@ -35,6 +37,7 @@
import org.prebid.server.util.HttpUtil;

import java.math.BigDecimal;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand Down Expand Up @@ -74,6 +77,13 @@ public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request
return Result.withError(BidderError.badInput("Device IP is required"));
}

final String optimalEndpointUrl;
try {
optimalEndpointUrl = getOptimalEndpointUrl(request);
} catch (PreBidException e) {
return Result.withError(BidderError.badInput(e.getMessage()));
}

final String displayManagerVer = buildDisplayManagerVersion(request);
final MultiMap headers = resolveHeaders(device);

Expand All @@ -85,7 +95,7 @@ public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request
final ExtImpConnatix extImpConnatix = parseExtImp(imp);
final Imp modifiedImp = modifyImp(imp, extImpConnatix, displayManagerVer, request);

httpRequests.add(makeHttpRequest(request, modifiedImp, headers));
httpRequests.add(makeHttpRequest(request, modifiedImp, headers, optimalEndpointUrl));
} catch (PreBidException e) {
errors.add(BidderError.badInput(e.getMessage()));
}
Expand All @@ -94,6 +104,42 @@ public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request
return Result.of(httpRequests, errors);
}

private String getOptimalEndpointUrl(BidRequest request) {
final Optional<String> dataCenterCode = getUserId(request).map(ConnatixBidder::getDataCenterCode);

if (dataCenterCode.isEmpty()) {
return endpointUrl;
}

try {
return new URIBuilder(endpointUrl)
.addParameter("dc", dataCenterCode.get())
.build()
.toString();
} catch (URISyntaxException e) {
throw new PreBidException(e.getMessage());
}
}

private static Optional<String> getUserId(BidRequest request) {
return Optional.ofNullable(request.getUser())
.map(User::getBuyeruid)
.filter(StringUtils::isNotBlank)
.map(String::trim);
}

private static String getDataCenterCode(String usedId) {
if (usedId.startsWith("1-")) {
return "us-east-2";
} else if (usedId.startsWith("2-")) {
return "us-west-2";
} else if (usedId.startsWith("3-")) {
return "eu-west-1";
}

return null;
}

private static String buildDisplayManagerVersion(BidRequest request) {
return Optional.ofNullable(request.getApp())
.map(App::getExt)
Expand Down Expand Up @@ -171,12 +217,13 @@ private Banner modifyImpBanner(Banner banner) {
return banner;
}

private HttpRequest<BidRequest> makeHttpRequest(BidRequest request, Imp imp, MultiMap headers) {
final BidRequest outgoingRequest = request.toBuilder()
.imp(List.of(imp))
.build();
private HttpRequest<BidRequest> makeHttpRequest(BidRequest request,
Imp imp,
MultiMap headers,
String optimalEndpointUrl) {

return BidderUtil.defaultRequest(outgoingRequest, headers, endpointUrl, mapper);
final BidRequest outgoingRequest = request.toBuilder().imp(List.of(imp)).build();
return BidderUtil.defaultRequest(outgoingRequest, headers, optimalEndpointUrl, mapper);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.iab.openrtb.request.Device;
import com.iab.openrtb.request.Format;
import com.iab.openrtb.request.Imp;
import com.iab.openrtb.request.User;
import com.iab.openrtb.response.Bid;
import com.iab.openrtb.response.BidResponse;
import com.iab.openrtb.response.SeatBid;
Expand Down Expand Up @@ -268,6 +269,86 @@ public void makeHttpRequestsShouldIncludeResolvedHttpHeadersFromDevice() {
tuple(HttpUtil.ACCEPT_HEADER.toString(), HttpHeaderValues.APPLICATION_JSON.toString()));
}

@Test
public void makeHttpRequestsShouldUseDataCenterUsEast2WhenUserIdStartsWith1() {
// given
final BidRequest bidRequest = givenBidRequest(
request -> request.user(User.builder().buyeruid("1-UserId").build()),
givenImp(impBuilder -> impBuilder
.ext(mapper.valueToTree(ExtImpConnatix.of("placementId", null)))));

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

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue()).extracting(HttpRequest::getUri).containsOnly("https://test-url.com/?dc=us-east-2");
}

@Test
public void makeHttpRequestsShouldUseDataCenterUsWest2WhenUserIdStartsWith2() {
// given
final BidRequest bidRequest = givenBidRequest(
request -> request.user(User.builder().buyeruid("2-UserId").build()),
givenImp(impBuilder -> impBuilder
.ext(mapper.valueToTree(ExtImpConnatix.of("placementId", null)))));

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

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue()).extracting(HttpRequest::getUri).containsOnly("https://test-url.com/?dc=us-west-2");
}

@Test
public void makeHttpRequestsShouldUseDataCenterEuWest1WhenUserIdStartsWith3() {
// given
final BidRequest bidRequest = givenBidRequest(
request -> request.user(User.builder().buyeruid("3-UserId").build()),
givenImp(impBuilder -> impBuilder
.ext(mapper.valueToTree(ExtImpConnatix.of("placementId", null)))));

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

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue()).extracting(HttpRequest::getUri).containsOnly("https://test-url.com/?dc=eu-west-1");
}

@Test
public void makeHttpRequestsShouldExcludeDataCenterWhenUserIdPrefixDoesNotMatch() {
// given
final BidRequest bidRequest = givenBidRequest(
request -> request.user(User.builder().buyeruid("4-UserId").build()),
givenImp(impBuilder -> impBuilder
.ext(mapper.valueToTree(ExtImpConnatix.of("placementId", null)))));

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

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue()).extracting(HttpRequest::getUri).containsOnly(CONNATIX_ENDPOINT);
}

@Test
public void makeHttpRequestsShouldExcludeDataCenterWhenUserIdIsMissing() {
// given
final BidRequest bidRequest = givenBidRequest(
UnaryOperator.identity(),
givenImp(impBuilder -> impBuilder
.ext(mapper.valueToTree(ExtImpConnatix.of("placementId", null)))));

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

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getValue()).extracting(HttpRequest::getUri).containsOnly(CONNATIX_ENDPOINT);
}

@Test
public void makeBidsShouldErrorIfResponseBodyCannotBeParsed() {
// given
Expand Down
Loading