From 52c550fd33c5d1d26d65bc08931094523db6f711 Mon Sep 17 00:00:00 2001 From: Piotr Jaworski Date: Tue, 2 Dec 2025 16:37:30 +0100 Subject: [PATCH 1/5] RTBHouse: Extract tagid from Imp fields --- .../bidder/rtbhouse/RtbhouseBidder.java | 47 +++++++ .../bidder/rtbhouse/RtbhouseBidderTest.java | 125 ++++++++++++++++++ .../rtbhouse/test-rtbhouse-bid-request.json | 3 +- 3 files changed, 174 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java b/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java index f2228778feb..ef00953a097 100644 --- a/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java +++ b/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java @@ -185,13 +185,60 @@ private ExtImpRtbhouse parseImpExt(Imp imp) { } private static Imp modifyImp(Imp imp, Price bidFloorPrice) { + final String tagid = extractTagid(imp); return imp.toBuilder() + .tagid(tagid) .bidfloorcur(ObjectUtil.getIfNotNull(bidFloorPrice, Price::getCurrency)) .bidfloor(ObjectUtil.getIfNotNull(bidFloorPrice, Price::getValue)) .pmp(null) .build(); } + private static String extractTagid(Imp imp) { + final ObjectNode ext = imp.getExt(); + if (ext != null) { + // 1. imp.ext.gpid + final JsonNode gpid = ext.get("gpid"); + if (gpid != null && gpid.isTextual()) { + final String gpidValue = gpid.asText(); + if (StringUtils.isNotBlank(gpidValue)) { + return gpidValue; + } + } + // 2. imp.ext.data.adserver.adslot + final JsonNode data = ext.get("data"); + if (data != null && data.isObject()) { + final JsonNode adserver = data.get("adserver"); + if (adserver != null && adserver.isObject()) { + final JsonNode adslot = adserver.get("adslot"); + if (adslot != null && adslot.isTextual()) { + final String adslotValue = adslot.asText(); + if (StringUtils.isNotBlank(adslotValue)) { + return adslotValue; + } + } + } + } + // 3. imp.ext.data.pbadslot + if (data != null && data.isObject()) { + final JsonNode pbadslot = data.get("pbadslot"); + if (pbadslot != null && pbadslot.isTextual()) { + final String pbadslotValue = pbadslot.asText(); + if (StringUtils.isNotBlank(pbadslotValue)) { + return pbadslotValue; + } + } + } + } + // 4. imp.id + final String impId = imp.getId(); + if (StringUtils.isNotBlank(impId)) { + return impId; + } + // 5. empty (not set) + return null; + } + private Price resolveBidFloor(Imp imp, ExtImpRtbhouse impExt, BidRequest bidRequest) { final List brCur = bidRequest.getCur(); final Price initialBidFloorPrice = Price.of(imp.getBidfloorcur(), imp.getBidfloor()); diff --git a/src/test/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidderTest.java b/src/test/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidderTest.java index fe10dad45e3..fb8bdd69d6a 100644 --- a/src/test/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidderTest.java @@ -518,6 +518,123 @@ public void makeHttpRequestsShouldAlwaysRemovePmpField() { .containsOnlyNulls(); } + @Test + public void makeHttpRequestsShouldSetTagidFromGpid() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .id("imp123") + .ext(givenRtbhouseExt(node -> node.put("gpid", "gpid_value"))) + .build())) + .id("request_id") + .build(); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getTagid) + .containsExactly("gpid_value"); + } + + @Test + public void makeHttpRequestsShouldSetTagidFromAdserverAdslot() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .id("imp123") + .ext(givenRtbhouseExt(node -> node.set("data", mapper.createObjectNode() + .set("adserver", mapper.createObjectNode().put("adslot", "adslot_value"))))) + .build())) + .id("request_id") + .build(); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getTagid) + .containsExactly("adslot_value"); + } + + @Test + public void makeHttpRequestsShouldSetTagidFromPbadslot() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .id("imp123") + .ext(givenRtbhouseExt(node -> node.set("data", mapper.createObjectNode() + .put("pbadslot", "pbadslot_value")))) + .build())) + .id("request_id") + .build(); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getTagid) + .containsExactly("pbadslot_value"); + } + + @Test + public void makeHttpRequestsShouldSetTagidFromImpIdWhenNoOtherFields() { + // given + final BidRequest bidRequest = givenBidRequest( + bidReq -> bidReq.id("request_id"), + imp -> imp.id("imp123"), + identity()); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getTagid) + .containsExactly("imp123"); + } + + @Test + public void makeHttpRequestsShouldSetTagidToNullWhenNoFieldsAvailable() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .id(null) + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpRtbhouse.builder() + .publisherId("publisherId") + .region("region") + .build()))) + .build())) + .id("request_id") + .build(); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getTagid) + .containsOnlyNulls(); + } + private static BidResponse givenBidResponse(Function bidCustomizer) { return BidResponse.builder() .cur("USD") @@ -562,4 +679,12 @@ private static Imp givenImp(Function impCustomiz .build())))) .build(); } + + private static ObjectNode givenRtbhouseExt(Function extCustomizer) { + final ObjectNode extNode = (ObjectNode) mapper.valueToTree(ExtPrebid.of(null, ExtImpRtbhouse.builder() + .publisherId("publisherId") + .region("region") + .build())); + return extCustomizer.apply(extNode); + } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rtbhouse/test-rtbhouse-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/rtbhouse/test-rtbhouse-bid-request.json index e63afde3937..28d0438942f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/rtbhouse/test-rtbhouse-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/rtbhouse/test-rtbhouse-bid-request.json @@ -13,7 +13,8 @@ "bidder": { "publisherId": "publisherId" } - } + }, + "tagid": "imp_id" } ], "source": { From bc4cb7a8180aa2f16f2b8dec13c1b00e7a6d1901 Mon Sep 17 00:00:00 2001 From: Piotr Jaworski Date: Tue, 2 Dec 2025 17:44:35 +0100 Subject: [PATCH 2/5] RTBHouse: Preserve existing tagid in Imp when modifying requests --- .../bidder/rtbhouse/RtbhouseBidder.java | 3 ++- .../bidder/rtbhouse/RtbhouseBidderTest.java | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java b/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java index ef00953a097..afe429b1762 100644 --- a/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java +++ b/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java @@ -185,7 +185,8 @@ private ExtImpRtbhouse parseImpExt(Imp imp) { } private static Imp modifyImp(Imp imp, Price bidFloorPrice) { - final String tagid = extractTagid(imp); + final String existingTagid = imp.getTagid(); + final String tagid = StringUtils.isNotBlank(existingTagid) ? existingTagid : extractTagid(imp); return imp.toBuilder() .tagid(tagid) .bidfloorcur(ObjectUtil.getIfNotNull(bidFloorPrice, Price::getCurrency)) diff --git a/src/test/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidderTest.java b/src/test/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidderTest.java index fb8bdd69d6a..b0f5b7a247c 100644 --- a/src/test/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidderTest.java @@ -635,6 +635,30 @@ public void makeHttpRequestsShouldSetTagidToNullWhenNoFieldsAvailable() { .containsOnlyNulls(); } + @Test + public void makeHttpRequestsShouldPreserveExistingTagid() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .id("imp123") + .tagid("existing_tagid") + .ext(givenRtbhouseExt(node -> node.put("gpid", "gpid_value"))) + .build())) + .id("request_id") + .build(); + + // when + final Result>> result = target.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getTagid) + .containsExactly("existing_tagid"); + } + private static BidResponse givenBidResponse(Function bidCustomizer) { return BidResponse.builder() .cur("USD") From d30af842c8b9b04711a2b4c8d12ffe1065dc351d Mon Sep 17 00:00:00 2001 From: Piotr Jaworski Date: Mon, 5 Jan 2026 17:51:52 +0100 Subject: [PATCH 3/5] RTBHouse: refactor tag ID extraction logic --- .../bidder/rtbhouse/RtbhouseBidder.java | 89 +++++++++---------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java b/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java index afe429b1762..1e8c928eb48 100644 --- a/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java +++ b/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java @@ -185,59 +185,58 @@ private ExtImpRtbhouse parseImpExt(Imp imp) { } private static Imp modifyImp(Imp imp, Price bidFloorPrice) { - final String existingTagid = imp.getTagid(); - final String tagid = StringUtils.isNotBlank(existingTagid) ? existingTagid : extractTagid(imp); return imp.toBuilder() - .tagid(tagid) + .tagid(extractTagId(imp)) .bidfloorcur(ObjectUtil.getIfNotNull(bidFloorPrice, Price::getCurrency)) .bidfloor(ObjectUtil.getIfNotNull(bidFloorPrice, Price::getValue)) .pmp(null) .build(); } - private static String extractTagid(Imp imp) { - final ObjectNode ext = imp.getExt(); - if (ext != null) { - // 1. imp.ext.gpid - final JsonNode gpid = ext.get("gpid"); - if (gpid != null && gpid.isTextual()) { - final String gpidValue = gpid.asText(); - if (StringUtils.isNotBlank(gpidValue)) { - return gpidValue; - } - } - // 2. imp.ext.data.adserver.adslot - final JsonNode data = ext.get("data"); - if (data != null && data.isObject()) { - final JsonNode adserver = data.get("adserver"); - if (adserver != null && adserver.isObject()) { - final JsonNode adslot = adserver.get("adslot"); - if (adslot != null && adslot.isTextual()) { - final String adslotValue = adslot.asText(); - if (StringUtils.isNotBlank(adslotValue)) { - return adslotValue; - } - } - } - } - // 3. imp.ext.data.pbadslot - if (data != null && data.isObject()) { - final JsonNode pbadslot = data.get("pbadslot"); - if (pbadslot != null && pbadslot.isTextual()) { - final String pbadslotValue = pbadslot.asText(); - if (StringUtils.isNotBlank(pbadslotValue)) { - return pbadslotValue; - } - } - } - } - // 4. imp.id - final String impId = imp.getId(); - if (StringUtils.isNotBlank(impId)) { - return impId; + private static String extractTagId(Imp imp) { + final String existingTagid = imp.getTagid(); + if (StringUtils.isNotBlank(existingTagid)) { + return existingTagid; } - // 5. empty (not set) - return null; + + return extractTagIdFromExt(imp); + } + + private static String extractTagIdFromExt(Imp imp) { + return Optional.ofNullable(imp.getExt()) + .flatMap(ext -> extractGpid(ext)) + .orElseGet(() -> extractFromData(imp)); + } + + private static Optional extractGpid(JsonNode ext) { + return Optional.ofNullable(ext.get("gpid")) + .filter(JsonNode::isTextual) + .map(JsonNode::asText) + .filter(StringUtils::isNotBlank); + } + + private static String extractFromData(Imp imp) { + return Optional.ofNullable(imp.getExt()) + .map(ext -> ext.get("data")) + .filter(JsonNode::isObject) + .flatMap(data -> extractAdslot(data).or(() -> extractPbadslot(data))) + .orElseGet(() -> Optional.ofNullable(imp.getId()).filter(StringUtils::isNotBlank).orElse(null)); + } + + private static Optional extractAdslot(JsonNode data) { + return Optional.ofNullable(data.get("adserver")) + .filter(JsonNode::isObject) + .map(adserver -> adserver.get("adslot")) + .filter(JsonNode::isTextual) + .map(JsonNode::asText) + .filter(StringUtils::isNotBlank); + } + + private static Optional extractPbadslot(JsonNode data) { + return Optional.ofNullable(data.get("pbadslot")) + .filter(JsonNode::isTextual) + .map(JsonNode::asText) + .filter(StringUtils::isNotBlank); } private Price resolveBidFloor(Imp imp, ExtImpRtbhouse impExt, BidRequest bidRequest) { From 8828c64cab5d6af69f5ed9dc08debda4f86a94b1 Mon Sep 17 00:00:00 2001 From: Piotr Jaworski Date: Wed, 7 Jan 2026 09:26:45 +0100 Subject: [PATCH 4/5] RTBHouse: refactor main tag ID extraction method to use Optional --- .../prebid/server/bidder/rtbhouse/RtbhouseBidder.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java b/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java index 1e8c928eb48..a7a361e44d5 100644 --- a/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java +++ b/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java @@ -194,12 +194,9 @@ private static Imp modifyImp(Imp imp, Price bidFloorPrice) { } private static String extractTagId(Imp imp) { - final String existingTagid = imp.getTagid(); - if (StringUtils.isNotBlank(existingTagid)) { - return existingTagid; - } - - return extractTagIdFromExt(imp); + return Optional.ofNullable(imp.getTagid()) + .filter(StringUtils::isNotBlank) + .orElseGet(() -> extractTagIdFromExt(imp)); } private static String extractTagIdFromExt(Imp imp) { From d60dec3b688fc83f8fa5afd7f336fcac5149e136 Mon Sep 17 00:00:00 2001 From: Piotr Jaworski Date: Fri, 9 Jan 2026 09:21:24 +0100 Subject: [PATCH 5/5] RTBHouse: refactor tag id extraction logic for simplicity and improving readability; changed order of methods --- .../bidder/rtbhouse/RtbhouseBidder.java | 238 +++++++++--------- .../bidder/rtbhouse/RtbhouseBidderTest.java | 72 +++--- 2 files changed, 145 insertions(+), 165 deletions(-) diff --git a/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java b/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java index a7a361e44d5..8d45320cb9c 100644 --- a/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java +++ b/src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java @@ -94,6 +94,110 @@ public Result>> makeHttpRequests(BidRequest bidRequ return Result.withValue(BidderUtil.defaultRequest(outgoingRequest, endpointUrl, mapper)); } + private ExtImpRtbhouse parseImpExt(Imp imp) { + try { + return mapper.mapper().convertValue(imp.getExt(), RTBHOUSE_EXT_TYPE_REFERENCE).getBidder(); + } catch (IllegalArgumentException e) { + throw new PreBidException(e.getMessage()); + } + } + + private Price resolveBidFloor(Imp imp, ExtImpRtbhouse impExt, BidRequest bidRequest) { + final List brCur = bidRequest.getCur(); + final Price initialBidFloorPrice = Price.of(imp.getBidfloorcur(), imp.getBidfloor()); + + final BigDecimal impExtBidFloor = impExt.getBidFloor(); + final String impExtCurrency = impExtBidFloor != null && brCur != null && !brCur.isEmpty() + ? brCur.getFirst() : null; + final Price impExtBidFloorPrice = Price.of(impExtCurrency, impExtBidFloor); + final Price resolvedPrice = initialBidFloorPrice.getValue() == null + ? impExtBidFloorPrice : initialBidFloorPrice; + + return BidderUtil.isValidPrice(resolvedPrice) + && !StringUtils.equalsIgnoreCase(resolvedPrice.getCurrency(), BIDDER_CURRENCY) + ? convertBidFloor(resolvedPrice, imp.getId(), bidRequest) + : resolvedPrice; + } + + private Price convertBidFloor(Price bidFloorPrice, String impId, BidRequest bidRequest) { + final String bidFloorCur = bidFloorPrice.getCurrency(); + try { + final BigDecimal convertedPrice = currencyConversionService + .convertCurrency(bidFloorPrice.getValue(), bidRequest, bidFloorCur, BIDDER_CURRENCY); + + return Price.of(BIDDER_CURRENCY, convertedPrice); + } catch (PreBidException e) { + throw new PreBidException(String.format( + "Unable to convert provided bid floor currency from %s to %s for imp `%s`", + bidFloorCur, BIDDER_CURRENCY, impId)); + } + } + + private static Imp modifyImp(Imp imp, Price bidFloorPrice) { + return imp.toBuilder() + .tagid(extractTagId(imp)) + .bidfloorcur(ObjectUtil.getIfNotNull(bidFloorPrice, Price::getCurrency)) + .bidfloor(ObjectUtil.getIfNotNull(bidFloorPrice, Price::getValue)) + .pmp(null) + .build(); + } + + private static String extractTagId(Imp imp) { + return Optional.ofNullable(imp.getTagid()) + .filter(StringUtils::isNotBlank) + .or(() -> extractGpid(imp)) + .or(() -> extractAdslot(imp)) + .or(() -> extractPbadslot(imp)) + .or(() -> Optional.ofNullable(imp.getId()) + .filter(StringUtils::isNotBlank)) + .orElse(null); + } + + private static Optional extractGpid(Imp imp) { + return Optional.ofNullable(imp.getExt()) + .map(ext -> ext.get("gpid")) + .map(JsonNode::textValue) + .filter(StringUtils::isNotBlank); + } + + private static Optional extractAdslot(Imp imp) { + return Optional.ofNullable(imp.getExt()) + .map(ext -> ext.get("data")) + .map(data -> data.get("adserver")) + .map(adserver -> adserver.get("adslot")) + .map(JsonNode::textValue) + .filter(StringUtils::isNotBlank); + } + + private static Optional extractPbadslot(Imp imp) { + return Optional.ofNullable(imp.getExt()) + .map(ext -> ext.get("data")) + .map(data -> data.get("pbadslot")) + .map(JsonNode::textValue) + .filter(StringUtils::isNotBlank); + } + + private Site modifySite(Site site, String publisherId) { + final ObjectNode prebidNode = mapper.mapper().createObjectNode(); + prebidNode.put("publisherId", publisherId); + + final ExtPublisher extPublisher = ExtPublisher.empty(); + extPublisher.addProperty("prebid", prebidNode); + + final Publisher publisher = Optional.ofNullable(site) + .map(Site::getPublisher) + .map(Publisher::toBuilder) + .orElseGet(Publisher::builder) + .ext(extPublisher) + .build(); + + return Optional.ofNullable(site) + .map(Site::toBuilder) + .orElseGet(Site::builder) + .publisher(publisher) + .build(); + } + @Override public Result> makeBids(BidderCall httpCall, BidRequest bidRequest) { try { @@ -144,23 +248,6 @@ private BidderBid resolveBidderBid(Bid bid, .build(); } - private String resolveNativeAdm(String adm, List bidderErrors) { - final JsonNode admNode; - try { - admNode = mapper.mapper().readTree(adm); - } catch (JsonProcessingException e) { - bidderErrors.add(BidderError.badServerResponse("Unable to parse native adm: %s".formatted(adm))); - return null; - } - - final JsonNode nativeNode = admNode.get("native"); - if (nativeNode != null) { - return nativeNode.toString(); - } - - return adm; - } - private static BidType getBidType(String impId, List imps) { for (Imp imp : imps) { if (imp.getId().equals(impId)) { @@ -176,95 +263,21 @@ private static BidType getBidType(String impId, List imps) { return BidType.banner; } - private ExtImpRtbhouse parseImpExt(Imp imp) { + private String resolveNativeAdm(String adm, List bidderErrors) { + final JsonNode admNode; try { - return mapper.mapper().convertValue(imp.getExt(), RTBHOUSE_EXT_TYPE_REFERENCE).getBidder(); - } catch (IllegalArgumentException e) { - throw new PreBidException(e.getMessage()); + admNode = mapper.mapper().readTree(adm); + } catch (JsonProcessingException e) { + bidderErrors.add(BidderError.badServerResponse("Unable to parse native adm: %s".formatted(adm))); + return null; } - } - - private static Imp modifyImp(Imp imp, Price bidFloorPrice) { - return imp.toBuilder() - .tagid(extractTagId(imp)) - .bidfloorcur(ObjectUtil.getIfNotNull(bidFloorPrice, Price::getCurrency)) - .bidfloor(ObjectUtil.getIfNotNull(bidFloorPrice, Price::getValue)) - .pmp(null) - .build(); - } - - private static String extractTagId(Imp imp) { - return Optional.ofNullable(imp.getTagid()) - .filter(StringUtils::isNotBlank) - .orElseGet(() -> extractTagIdFromExt(imp)); - } - - private static String extractTagIdFromExt(Imp imp) { - return Optional.ofNullable(imp.getExt()) - .flatMap(ext -> extractGpid(ext)) - .orElseGet(() -> extractFromData(imp)); - } - - private static Optional extractGpid(JsonNode ext) { - return Optional.ofNullable(ext.get("gpid")) - .filter(JsonNode::isTextual) - .map(JsonNode::asText) - .filter(StringUtils::isNotBlank); - } - - private static String extractFromData(Imp imp) { - return Optional.ofNullable(imp.getExt()) - .map(ext -> ext.get("data")) - .filter(JsonNode::isObject) - .flatMap(data -> extractAdslot(data).or(() -> extractPbadslot(data))) - .orElseGet(() -> Optional.ofNullable(imp.getId()).filter(StringUtils::isNotBlank).orElse(null)); - } - - private static Optional extractAdslot(JsonNode data) { - return Optional.ofNullable(data.get("adserver")) - .filter(JsonNode::isObject) - .map(adserver -> adserver.get("adslot")) - .filter(JsonNode::isTextual) - .map(JsonNode::asText) - .filter(StringUtils::isNotBlank); - } - - private static Optional extractPbadslot(JsonNode data) { - return Optional.ofNullable(data.get("pbadslot")) - .filter(JsonNode::isTextual) - .map(JsonNode::asText) - .filter(StringUtils::isNotBlank); - } - - private Price resolveBidFloor(Imp imp, ExtImpRtbhouse impExt, BidRequest bidRequest) { - final List brCur = bidRequest.getCur(); - final Price initialBidFloorPrice = Price.of(imp.getBidfloorcur(), imp.getBidfloor()); - final BigDecimal impExtBidFloor = impExt.getBidFloor(); - final String impExtCurrency = impExtBidFloor != null && brCur != null && !brCur.isEmpty() - ? brCur.getFirst() : null; - final Price impExtBidFloorPrice = Price.of(impExtCurrency, impExtBidFloor); - final Price resolvedPrice = initialBidFloorPrice.getValue() == null - ? impExtBidFloorPrice : initialBidFloorPrice; - - return BidderUtil.isValidPrice(resolvedPrice) - && !StringUtils.equalsIgnoreCase(resolvedPrice.getCurrency(), BIDDER_CURRENCY) - ? convertBidFloor(resolvedPrice, imp.getId(), bidRequest) - : resolvedPrice; - } - - private Price convertBidFloor(Price bidFloorPrice, String impId, BidRequest bidRequest) { - final String bidFloorCur = bidFloorPrice.getCurrency(); - try { - final BigDecimal convertedPrice = currencyConversionService - .convertCurrency(bidFloorPrice.getValue(), bidRequest, bidFloorCur, BIDDER_CURRENCY); - - return Price.of(BIDDER_CURRENCY, convertedPrice); - } catch (PreBidException e) { - throw new PreBidException(String.format( - "Unable to convert provided bid floor currency from %s to %s for imp `%s`", - bidFloorCur, BIDDER_CURRENCY, impId)); + final JsonNode nativeNode = admNode.get("native"); + if (nativeNode != null) { + return nativeNode.toString(); } + + return adm; } private static Bid resolveMacros(Bid bid) { @@ -276,25 +289,4 @@ private static Bid resolveMacros(Bid bid) { .adm(StringUtils.replace(bid.getAdm(), PRICE_MACRO, priceAsString)) .build(); } - - private Site modifySite(Site site, String publisherId) { - final ObjectNode prebidNode = mapper.mapper().createObjectNode(); - prebidNode.put("publisherId", publisherId); - - final ExtPublisher extPublisher = ExtPublisher.empty(); - extPublisher.addProperty("prebid", prebidNode); - - final Publisher publisher = Optional.ofNullable(site) - .map(Site::getPublisher) - .map(Publisher::toBuilder) - .orElseGet(Publisher::builder) - .ext(extPublisher) - .build(); - - return Optional.ofNullable(site) - .map(Site::toBuilder) - .orElseGet(Site::builder) - .publisher(publisher) - .build(); - } } diff --git a/src/test/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidderTest.java b/src/test/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidderTest.java index b0f5b7a247c..6c66cf254c1 100644 --- a/src/test/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidderTest.java @@ -34,7 +34,9 @@ import java.math.BigDecimal; import java.util.List; +import java.util.Map; import java.util.function.Function; +import java.util.function.UnaryOperator; import static java.util.Collections.singletonList; import static java.util.function.Function.identity; @@ -521,13 +523,10 @@ public void makeHttpRequestsShouldAlwaysRemovePmpField() { @Test public void makeHttpRequestsShouldSetTagidFromGpid() { // given - final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(Imp.builder() - .id("imp123") - .ext(givenRtbhouseExt(node -> node.put("gpid", "gpid_value"))) - .build())) - .id("request_id") - .build(); + final BidRequest bidRequest = givenBidRequest( + bidReq -> bidReq.id("request_id"), + imp -> imp.id("imp123").ext(givenRtbhouseExt(node -> node.put("gpid", "gpid_value"))), + identity()); // when final Result>> result = target.makeHttpRequests(bidRequest); @@ -544,14 +543,13 @@ public void makeHttpRequestsShouldSetTagidFromGpid() { @Test public void makeHttpRequestsShouldSetTagidFromAdserverAdslot() { // given - final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(Imp.builder() - .id("imp123") - .ext(givenRtbhouseExt(node -> node.set("data", mapper.createObjectNode() - .set("adserver", mapper.createObjectNode().put("adslot", "adslot_value"))))) - .build())) - .id("request_id") - .build(); + final BidRequest bidRequest = givenBidRequest( + bidReq -> bidReq.id("request_id"), + imp -> imp.id("imp123") + .ext(givenRtbhouseExt(node -> + node.set("data", mapper.valueToTree( + Map.of("adserver", Map.of("adslot", "adslot_value")))))), + identity()); // when final Result>> result = target.makeHttpRequests(bidRequest); @@ -568,14 +566,12 @@ public void makeHttpRequestsShouldSetTagidFromAdserverAdslot() { @Test public void makeHttpRequestsShouldSetTagidFromPbadslot() { // given - final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(Imp.builder() - .id("imp123") - .ext(givenRtbhouseExt(node -> node.set("data", mapper.createObjectNode() - .put("pbadslot", "pbadslot_value")))) - .build())) - .id("request_id") - .build(); + final BidRequest bidRequest = givenBidRequest( + bidReq -> bidReq.id("request_id"), + imp -> imp.id("imp123") + .ext(givenRtbhouseExt(node -> + node.set("data", mapper.valueToTree(Map.of("pbadslot", "pbadslot_value"))))), + identity()); // when final Result>> result = target.makeHttpRequests(bidRequest); @@ -612,16 +608,10 @@ public void makeHttpRequestsShouldSetTagidFromImpIdWhenNoOtherFields() { @Test public void makeHttpRequestsShouldSetTagidToNullWhenNoFieldsAvailable() { // given - final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(Imp.builder() - .id(null) - .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpRtbhouse.builder() - .publisherId("publisherId") - .region("region") - .build()))) - .build())) - .id("request_id") - .build(); + final BidRequest bidRequest = givenBidRequest( + bidReq -> bidReq.id("request_id"), + imp -> imp.id(null), + identity()); // when final Result>> result = target.makeHttpRequests(bidRequest); @@ -638,14 +628,12 @@ public void makeHttpRequestsShouldSetTagidToNullWhenNoFieldsAvailable() { @Test public void makeHttpRequestsShouldPreserveExistingTagid() { // given - final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(Imp.builder() - .id("imp123") + final BidRequest bidRequest = givenBidRequest( + bidReq -> bidReq.id("request_id"), + imp -> imp.id("imp123") .tagid("existing_tagid") - .ext(givenRtbhouseExt(node -> node.put("gpid", "gpid_value"))) - .build())) - .id("request_id") - .build(); + .ext(givenRtbhouseExt(node -> node.put("gpid", "gpid_value"))), + identity()); // when final Result>> result = target.makeHttpRequests(bidRequest); @@ -704,8 +692,8 @@ private static Imp givenImp(Function impCustomiz .build(); } - private static ObjectNode givenRtbhouseExt(Function extCustomizer) { - final ObjectNode extNode = (ObjectNode) mapper.valueToTree(ExtPrebid.of(null, ExtImpRtbhouse.builder() + private static ObjectNode givenRtbhouseExt(UnaryOperator extCustomizer) { + final ObjectNode extNode = mapper.valueToTree(ExtPrebid.of(null, ExtImpRtbhouse.builder() .publisherId("publisherId") .region("region") .build()));