From e9632b594358ae6802879072b65c4de7f185cf05 Mon Sep 17 00:00:00 2001 From: albertmolinermrf Date: Thu, 14 Feb 2019 14:10:21 +0100 Subject: [PATCH 01/29] Customize Prebid Server for Marfeel --- pom.xml | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 136 insertions(+), 15 deletions(-) diff --git a/pom.xml b/pom.xml index 0ebe5f8ef67..a152e916db2 100644 --- a/pom.xml +++ b/pom.xml @@ -16,6 +16,31 @@ http://prebid.org/ + + + marfeel-private + Marfeel Maven Release Repository + http://repositories.marfeel.com:60081/nexus/content/repositories/marfeel_private/ + + true + + + false + + + + marfeel-snapshot-private + http://repositories.marfeel.com:60081/nexus/content/repositories/marfeel_snapshot_private/ + + false + + + never + true + + + + UTF-8 UTF-8 @@ -45,6 +70,8 @@ 0.5.0 2.12.0 + 1.0-SNAPSHOT + 4.12 2.23.4 @@ -76,6 +103,76 @@ + + com.marfeel + MarfeelBidderHub + ${mbid.version} + + + com.marfeel + MarfeelAdNetworkGoogleSheets + + + com.marfeel + MarfeelInsightReportingQueries + + + com.marfeel + MarfeelInsightReportingCollector + + + com.marfeel + MarfeelCalculator + + + com.marfeel + MarfeelQueue + + + com.marfeel + MarfeelCommonsTesting + + + com.marfeel + MarfeelDocumentGenerator + + + com.marfeel + MarfeelJira + + + com.marfeel + MarfeelAmpExtractor + + + com.marfeel + MarfeelPublisherDomain + + + com.marfeel + MarfeelInsightPushNotifications + + + com.marfeel + MarfeelAdsTxt + + + com.marfeel + MarfeelActon + + + com.marfeel + MarfeelAdnetwork + + + + + + org.springframework.boot + spring-boot-properties-migrator + runtime + + org.springframework.boot spring-boot-starter @@ -323,6 +420,11 @@ org.apache.maven.plugins maven-surefire-plugin ${maven-surefire-plugin.version} + + + org/prebid/server/ApplicationTest.java + + org.apache.maven.plugins @@ -466,21 +568,6 @@ json - - org.springframework.boot - spring-boot-maven-plugin - ${spring.boot.version} - - true - - - - - repackage - - - - @@ -548,5 +635,39 @@ + + + springboot + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + true + + + + + repackage + + + + + + + + + + + marfeel-private + http://repositories.marfeel.com:60081/nexus/content/repositories/marfeel_private + + + marfeel-snapshot-private + http://repositories.marfeel.com:60081/nexus/content/repositories/marfeel_snapshot_private + + From 982cd6a1537edec2ee01a1a9c8ac927520f451e1 Mon Sep 17 00:00:00 2001 From: albertmolinermrf Date: Thu, 14 Mar 2019 17:43:41 +0100 Subject: [PATCH 02/29] Remove jacoco plugin --- pom.xml | 58 --------------------------------------------------------- 1 file changed, 58 deletions(-) diff --git a/pom.xml b/pom.xml index a152e916db2..76392e88f5e 100644 --- a/pom.xml +++ b/pom.xml @@ -499,53 +499,6 @@ - - org.jacoco - jacoco-maven-plugin - ${jacoco-plugin.version} - - - com/iab/openrtb/** - **/proto/** - **/model/** - org/prebid/server/spring/config/** - - - - - prepare-agent - - prepare-agent - - - - report - - report - - - - check - - check - - - - - BUNDLE - - - INSTRUCTION - COVEREDRATIO - 90% - - - - - - - - pl.project13.maven git-commit-id-plugin @@ -583,17 +536,6 @@ - - org.jacoco - jacoco-maven-plugin - - - - report - - - - From f01e5925a486c0f28170d3b556e092d5d81b9e93 Mon Sep 17 00:00:00 2001 From: albertmolinermrf Date: Thu, 28 Mar 2019 10:29:04 +0100 Subject: [PATCH 03/29] Exclude all server integration tests --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 76392e88f5e..1ca53738a26 100644 --- a/pom.xml +++ b/pom.xml @@ -422,7 +422,7 @@ ${maven-surefire-plugin.version} - org/prebid/server/ApplicationTest.java + org/prebid/server/it/* From bd0865f7014971301e04819f034be677402faf37 Mon Sep 17 00:00:00 2001 From: albertmolinermrf Date: Wed, 24 Apr 2019 17:48:05 +0200 Subject: [PATCH 04/29] Move Marfeel dependencies to profile --- pom.xml | 129 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 65 insertions(+), 64 deletions(-) diff --git a/pom.xml b/pom.xml index 1ca53738a26..9825916d35c 100644 --- a/pom.xml +++ b/pom.xml @@ -103,70 +103,6 @@ - - com.marfeel - MarfeelBidderHub - ${mbid.version} - - - com.marfeel - MarfeelAdNetworkGoogleSheets - - - com.marfeel - MarfeelInsightReportingQueries - - - com.marfeel - MarfeelInsightReportingCollector - - - com.marfeel - MarfeelCalculator - - - com.marfeel - MarfeelQueue - - - com.marfeel - MarfeelCommonsTesting - - - com.marfeel - MarfeelDocumentGenerator - - - com.marfeel - MarfeelJira - - - com.marfeel - MarfeelAmpExtractor - - - com.marfeel - MarfeelPublisherDomain - - - com.marfeel - MarfeelInsightPushNotifications - - - com.marfeel - MarfeelAdsTxt - - - com.marfeel - MarfeelActon - - - com.marfeel - MarfeelAdnetwork - - - - org.springframework.boot spring-boot-properties-migrator @@ -580,6 +516,71 @@ springboot + + + com.marfeel + MarfeelBidderHub + ${mbid.version} + + + com.marfeel + MarfeelAdNetworkGoogleSheets + + + com.marfeel + MarfeelInsightReportingQueries + + + com.marfeel + MarfeelInsightReportingCollector + + + com.marfeel + MarfeelCalculator + + + com.marfeel + MarfeelQueue + + + com.marfeel + MarfeelCommonsTesting + + + com.marfeel + MarfeelDocumentGenerator + + + com.marfeel + MarfeelJira + + + com.marfeel + MarfeelAmpExtractor + + + com.marfeel + MarfeelPublisherDomain + + + com.marfeel + MarfeelInsightPushNotifications + + + com.marfeel + MarfeelAdsTxt + + + com.marfeel + MarfeelActon + + + com.marfeel + MarfeelAdnetwork + + + + From 30718f3ac35bace8d5ef977cc3d8aa1317bd1c9b Mon Sep 17 00:00:00 2001 From: albertmolinermrf Date: Thu, 25 Apr 2019 13:18:36 +0200 Subject: [PATCH 05/29] Exclude colliding transitive dependencies --- pom.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pom.xml b/pom.xml index 9825916d35c..d665bdbdd8e 100644 --- a/pom.xml +++ b/pom.xml @@ -578,6 +578,15 @@ com.marfeel MarfeelAdnetwork + + + com.github.jknack + * + + + org.hibernate + * + From 0de048fcdf69e7372049740d845caa283e01ee54 Mon Sep 17 00:00:00 2001 From: miquelescolar Date: Fri, 5 Jul 2019 15:06:36 +0200 Subject: [PATCH 06/29] MRF-52602 :: increase vertx timeout for testing purposes --- .../resources/org/prebid/server/it/test-application.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/resources/org/prebid/server/it/test-application.properties b/src/test/resources/org/prebid/server/it/test-application.properties index 49c06cdeeb1..bb14c6e9655 100644 --- a/src/test/resources/org/prebid/server/it/test-application.properties +++ b/src/test/resources/org/prebid/server/it/test-application.properties @@ -156,3 +156,4 @@ analytics.log.enabled=true gdpr.host-vendor-id=1 gdpr.vendorlist.filesystem-cache-dir=src/test/resources/org/prebid/server/it/gdpr-vendorlist gdpr.geolocation.maxmind.db-archive-path=/org/prebid/server/geolocation/GeoLite2-test.tar.gz +vertx.init-timeout-ms=20000 From 9af0e338115afd9441c68e8a707f3bc1cf5f3378 Mon Sep 17 00:00:00 2001 From: carlosmoya Date: Tue, 10 Mar 2020 13:16:42 +0100 Subject: [PATCH 07/29] create CI Pipeline --- build/ci/Jenkinsfile | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 build/ci/Jenkinsfile diff --git a/build/ci/Jenkinsfile b/build/ci/Jenkinsfile new file mode 100644 index 00000000000..488196af73f --- /dev/null +++ b/build/ci/Jenkinsfile @@ -0,0 +1,42 @@ +pipeline { + agent { + docker { + image "marfeel/jenkins-maven:v3.2.5-jdk-8" + label "docker" + args "-v ${env.JENKINS_HOME}/.m2:/home/jenkins/.m2 " + reuseNode true + } + } + stages { + stage('Build artifacts') { + steps { + script { + configFileProvider([ + configFile( + fileId: '183e2f77-8ab5-47d2-bd64-4cbae814c3f7', + targetLocation: '.', + variable: 'MVN_NEXUS') + ]) {} + } + sh 'mvn clean package -U -s nexus_maven_settings_read_only_xml -Dmaven.test.skip=false -Pspringboot' + } + } + stage('Store artifacts') { + steps { + archiveArtifacts artifacts: 'target/*.jar', defaultExcludes: true, caseSensitive: true + } + } + } + post { + always { + cleanWs() + echo "Job ran @ ${JENKINS_NODE_NAME}" + } + } + options { + buildDiscarder(logRotator(daysToKeepStr:'60')) + + timeout(time: 20, unit: 'MINUTES') + timestamps() + } +} \ No newline at end of file From c141de1d6a563df301aac6a5c8a1a55fc719d46b Mon Sep 17 00:00:00 2001 From: carlosmoya Date: Tue, 10 Mar 2020 17:13:40 +0100 Subject: [PATCH 08/29] Update maven --- build/ci/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/ci/Jenkinsfile b/build/ci/Jenkinsfile index 488196af73f..468033dd7ff 100644 --- a/build/ci/Jenkinsfile +++ b/build/ci/Jenkinsfile @@ -1,7 +1,7 @@ pipeline { agent { docker { - image "marfeel/jenkins-maven:v3.2.5-jdk-8" + image "marfeel/jenkins-maven:v3.6.3-jdk-8" label "docker" args "-v ${env.JENKINS_HOME}/.m2:/home/jenkins/.m2 " reuseNode true From 850f03c1a8d6c9e1618a340fe4ddb8f6d3e74fe9 Mon Sep 17 00:00:00 2001 From: carlosmoya Date: Tue, 10 Mar 2020 17:14:26 +0100 Subject: [PATCH 09/29] Update maven --- build/ci/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/ci/Jenkinsfile b/build/ci/Jenkinsfile index 488196af73f..468033dd7ff 100644 --- a/build/ci/Jenkinsfile +++ b/build/ci/Jenkinsfile @@ -1,7 +1,7 @@ pipeline { agent { docker { - image "marfeel/jenkins-maven:v3.2.5-jdk-8" + image "marfeel/jenkins-maven:v3.6.3-jdk-8" label "docker" args "-v ${env.JENKINS_HOME}/.m2:/home/jenkins/.m2 " reuseNode true From 562f791f7edefea5a762ab5d12dab8ec5f357c89 Mon Sep 17 00:00:00 2001 From: albertmolinermrf Date: Thu, 25 Apr 2019 13:18:36 +0200 Subject: [PATCH 10/29] Exclude colliding transitive dependencies --- pom.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pom.xml b/pom.xml index f3f56332e77..65376925f22 100644 --- a/pom.xml +++ b/pom.xml @@ -590,6 +590,15 @@ com.marfeel MarfeelAdnetwork + + + com.github.jknack + * + + + org.hibernate + * + From b3751a575a65ad0d65978c68a398ab833fb3c5c4 Mon Sep 17 00:00:00 2001 From: albertmolinermrf Date: Tue, 10 Mar 2020 17:38:11 +0100 Subject: [PATCH 11/29] Exclude health failing tests --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 65376925f22..507d1996b05 100644 --- a/pom.xml +++ b/pom.xml @@ -362,6 +362,7 @@ org/prebid/server/it/* + org/prebid/server/health/* From 6d723301254e4fa7446639e48c0727f539e9d911 Mon Sep 17 00:00:00 2001 From: albertmolinermrf Date: Tue, 10 Mar 2020 17:38:11 +0100 Subject: [PATCH 12/29] Exclude health failing tests --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index a8a121af644..9304026c219 100644 --- a/pom.xml +++ b/pom.xml @@ -370,6 +370,7 @@ org/prebid/server/it/* + org/prebid/server/health/* From d69638264a9aeecfc95b634c9a60b4617531f250 Mon Sep 17 00:00:00 2001 From: albertmolinermrf Date: Tue, 17 Mar 2020 12:02:35 +0100 Subject: [PATCH 13/29] Remove unused Jenkinsfile --- build/ci/Jenkinsfile | 42 ------------------------------------------ 1 file changed, 42 deletions(-) delete mode 100644 build/ci/Jenkinsfile diff --git a/build/ci/Jenkinsfile b/build/ci/Jenkinsfile deleted file mode 100644 index 468033dd7ff..00000000000 --- a/build/ci/Jenkinsfile +++ /dev/null @@ -1,42 +0,0 @@ -pipeline { - agent { - docker { - image "marfeel/jenkins-maven:v3.6.3-jdk-8" - label "docker" - args "-v ${env.JENKINS_HOME}/.m2:/home/jenkins/.m2 " - reuseNode true - } - } - stages { - stage('Build artifacts') { - steps { - script { - configFileProvider([ - configFile( - fileId: '183e2f77-8ab5-47d2-bd64-4cbae814c3f7', - targetLocation: '.', - variable: 'MVN_NEXUS') - ]) {} - } - sh 'mvn clean package -U -s nexus_maven_settings_read_only_xml -Dmaven.test.skip=false -Pspringboot' - } - } - stage('Store artifacts') { - steps { - archiveArtifacts artifacts: 'target/*.jar', defaultExcludes: true, caseSensitive: true - } - } - } - post { - always { - cleanWs() - echo "Job ran @ ${JENKINS_NODE_NAME}" - } - } - options { - buildDiscarder(logRotator(daysToKeepStr:'60')) - - timeout(time: 20, unit: 'MINUTES') - timestamps() - } -} \ No newline at end of file From 25cd0d53b37e56324b0380c3183d5c263ae4f24a Mon Sep 17 00:00:00 2001 From: albertmolinermrf Date: Thu, 26 Nov 2020 14:20:41 +0100 Subject: [PATCH 14/29] Force always 300x250 in Eplanning --- .../bidder/eplanning/EplanningBidder.java | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java b/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java index 699b4f22f0c..22d0b578b25 100644 --- a/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java +++ b/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java @@ -2,10 +2,8 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Device; -import com.iab.openrtb.request.Format; import com.iab.openrtb.request.Imp; import com.iab.openrtb.request.Site; import com.iab.openrtb.request.User; @@ -50,6 +48,8 @@ */ public class EplanningBidder implements Bidder { + private static final String CUSTOM_MARFEEL_FIXED_WIDTH = "300"; + private static final String CUSTOM_MARFEEL_FIXED_HEIGHT = "250"; private static final String NULL_SIZE = "1x1"; private static final String DEFAULT_PAGE_URL = "FILE"; private static final String SEC = "ROS"; @@ -140,23 +140,7 @@ private static ExtImpEplanning validateAndModifyImpExt(Imp imp) throws PreBidExc } private static String resolveSizeString(Imp imp) { - final Banner banner = imp.getBanner(); - final Integer bannerWidth = banner.getW(); - final Integer bannerHeight = banner.getH(); - if (bannerWidth != null && bannerHeight != null) { - return String.format("%sx%s", bannerWidth, bannerHeight); - } - final List bannerFormats = banner.getFormat(); - if (CollectionUtils.isNotEmpty(bannerFormats)) { - for (Format format : bannerFormats) { - final Integer formatHeight = format.getH(); - final Integer formatWidth = format.getW(); - if (formatHeight != null && formatWidth != null) { - return String.format("%sx%s", formatWidth, formatHeight); - } - } - } - return NULL_SIZE; + return String.format("%sx%s", CUSTOM_MARFEEL_FIXED_WIDTH, CUSTOM_MARFEEL_FIXED_HEIGHT); } private static String cleanName(String name) { From a9697dbde15f8c41bfc1e1f3182b55e74fd5905c Mon Sep 17 00:00:00 2001 From: albertmolinermrf Date: Thu, 26 Nov 2020 14:51:56 +0100 Subject: [PATCH 15/29] Remove Eplanning tests due to customization --- .../bidder/eplanning/EplanningBidderTest.java | 427 ------------------ 1 file changed, 427 deletions(-) delete mode 100644 src/test/java/org/prebid/server/bidder/eplanning/EplanningBidderTest.java diff --git a/src/test/java/org/prebid/server/bidder/eplanning/EplanningBidderTest.java b/src/test/java/org/prebid/server/bidder/eplanning/EplanningBidderTest.java deleted file mode 100644 index 0a65bf09c62..00000000000 --- a/src/test/java/org/prebid/server/bidder/eplanning/EplanningBidderTest.java +++ /dev/null @@ -1,427 +0,0 @@ -package org.prebid.server.bidder.eplanning; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.iab.openrtb.request.Banner; -import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Device; -import com.iab.openrtb.request.Imp; -import com.iab.openrtb.request.Site; -import com.iab.openrtb.request.User; -import com.iab.openrtb.response.Bid; -import io.netty.handler.codec.http.HttpHeaderValues; -import io.vertx.core.MultiMap; -import io.vertx.core.http.HttpMethod; -import io.vertx.core.json.Json; -import org.junit.Before; -import org.junit.Test; -import org.prebid.server.VertxTest; -import org.prebid.server.bidder.eplanning.model.HbResponse; -import org.prebid.server.bidder.eplanning.model.HbResponseAd; -import org.prebid.server.bidder.eplanning.model.HbResponseSpace; -import org.prebid.server.bidder.model.BidderBid; -import org.prebid.server.bidder.model.BidderError; -import org.prebid.server.bidder.model.HttpCall; -import org.prebid.server.bidder.model.HttpRequest; -import org.prebid.server.bidder.model.HttpResponse; -import org.prebid.server.bidder.model.Result; -import org.prebid.server.proto.openrtb.ext.ExtPrebid; -import org.prebid.server.proto.openrtb.ext.request.eplanning.ExtImpEplanning; -import org.prebid.server.proto.openrtb.ext.response.BidType; -import org.prebid.server.util.HttpUtil; - -import java.math.BigDecimal; -import java.util.List; -import java.util.Map; -import java.util.function.Function; - -import static java.util.Collections.singletonList; -import static java.util.function.Function.identity; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.assertj.core.api.Assertions.tuple; - -public class EplanningBidderTest extends VertxTest { - - private static final String ENDPOINT_URL = "http://eplanning.com"; - - private EplanningBidder eplanningBidder; - - @Before - public void setUp() { - eplanningBidder = new EplanningBidder(ENDPOINT_URL); - } - - @Test - public void creationShouldFailOnInvalidEndpointUrl() { - assertThatIllegalArgumentException().isThrownBy(() -> new EplanningBidder("invalid_url")); - } - - @Test - public void makeHttpRequestsShouldReturnErrorIfImpBannerIsNull() { - // given - final BidRequest bidRequest = givenBidRequest( - impBuilder -> impBuilder - .banner(null)); - - // when - final Result>> result = eplanningBidder.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).hasSize(1) - .containsOnly(BidderError.badInput("EPlanning only supports banner Imps. Ignoring Imp ID=123")); - assertThat(result.getValue()).isEmpty(); - } - - @Test - public void makeHttpRequestsShouldReturnErrorIfImpExtCouldNotBeParsed() { - // given - final BidRequest bidRequest = givenBidRequest( - impBuilder -> impBuilder - .ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createArrayNode())))); - - // when - final Result>> result = eplanningBidder.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).hasSize(1); - assertThat(result.getErrors().get(0).getMessage()) - .startsWith("Ignoring imp id=123, error while decoding extImpBidder, err: Cannot deserialize instance"); - assertThat(result.getValue()).isEmpty(); - } - - @Test - public void makeHttpRequestsShouldReturnErrorIfImpExtClientIdIsBlank() { - // given - final BidRequest bidRequest = givenBidRequest( - impBuilder -> impBuilder - .ext(mapper.valueToTree(ExtPrebid.of(null, - mapper.createObjectNode().put("ci", ""))))); - - // when - final Result>> result = eplanningBidder.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).hasSize(1) - .containsOnly(BidderError.badInput("Ignoring imp id=123, no ClientID present")); - assertThat(result.getValue()).isEmpty(); - } - - @Test - public void makeHttpRequestsShouldSendSingleGetRequestWithNullBody() { - // given - final BidRequest bidRequest = givenBidRequest(identity()); - - // when - final Result>> result = eplanningBidder.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1) - .extracting(HttpRequest::getBody) - .hasSize(1) - .containsNull(); - assertThat(result.getValue()).hasSize(1) - .extracting(HttpRequest::getMethod) - .containsOnly(HttpMethod.GET); - } - - @Test - public void makeHttpRequestsShouldSetCorrectHeaders() { - // given - final BidRequest bidRequest = givenBidRequest(identity()); - - // when - final Result>> result = eplanningBidder.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1) - .extracting(HttpRequest::getHeaders) - .flatExtracting(MultiMap::entries) - .extracting(Map.Entry::getKey, Map.Entry::getValue) - .containsOnly( - tuple(HttpUtil.CONTENT_TYPE_HEADER.toString(), HttpUtil.APPLICATION_JSON_CONTENT_TYPE), - tuple(HttpUtil.ACCEPT_HEADER.toString(), HttpHeaderValues.APPLICATION_JSON.toString())); - } - - @Test - public void makeHttpRequestsShouldSetAdditionalHeadersIfDeviceFieldsAreNotEmpty() { - // given - final BidRequest bidRequest = givenBidRequest( - requestBuilder -> requestBuilder - .device(Device.builder() - .ua("user_agent") - .language("language") - .ip("test_ip") - .dnt(1) - .build()), - identity()); - - // when - final Result>> result = eplanningBidder.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1) - .extracting(HttpRequest::getHeaders) - .flatExtracting(MultiMap::entries) - .extracting(Map.Entry::getKey, Map.Entry::getValue) - .contains( - tuple(HttpUtil.USER_AGENT_HEADER.toString(), "user_agent"), - tuple(HttpUtil.ACCEPT_LANGUAGE_HEADER.toString(), "language"), - tuple(HttpUtil.X_FORWARDED_FOR_HEADER.toString(), "test_ip"), - tuple(HttpUtil.DNT_HEADER.toString(), "1")); - } - - @Test - public void makeHttpRequestsShouldSetCorrectUriWithDefaults() { - // given - final BidRequest bidRequest = givenBidRequest(identity()); - - // when - final Result>> result = eplanningBidder.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1) - .extracting(HttpRequest::getUri) - .containsOnly( - "http://eplanning.com/clientId/1/FILE/ROS?ct=1&r=pbs&ncb=1&ur=FILE&e=testadun_itco_de:1x1"); - } - - @Test - public void makeHttpRequestsShouldSetCorrectUriWithSitePageAndDomain() { - // given - final BidRequest bidRequest = givenBidRequest( - requestBuilder -> requestBuilder - .site(Site.builder().page("http://www.example.com").domain("DOMAIN").build()), - identity()); - - // when - final Result>> result = eplanningBidder.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1) - .extracting(HttpRequest::getUri) - .containsOnly( - "http://eplanning.com/clientId/1/DOMAIN/ROS?ct=1&r=pbs&ncb=1&ur=http%3A%2F%2Fwww.example.com" - + "&e=testadun_itco_de:1x1"); - } - - @Test - public void makeHttpRequestsShouldSetCorrectUriWithSizeString() { - // given - final BidRequest bidRequest = givenBidRequest( - impBuilder -> impBuilder - .banner(Banner.builder() - .w(300) - .h(200) - .build())); - - // when - final Result>> result = eplanningBidder.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1) - .extracting(HttpRequest::getUri) - .containsOnly( - "http://eplanning.com/clientId/1/FILE/ROS?ct=1&r=pbs&ncb=1&ur=FILE&e=testadun_itco_de:300x200"); - } - - @Test - public void makeHttpRequestsShouldSetCorrectUriWithUserId() { - // given - final BidRequest bidRequest = givenBidRequest( - requestBuilder -> requestBuilder - .user(User.builder().buyeruid("Buyer-ID").build()), - identity()); - - // when - final Result>> result = eplanningBidder.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1) - .extracting(HttpRequest::getUri) - .containsOnly("http://eplanning.com/clientId/1/FILE/ROS?ct=1&r=pbs&ncb=1&ur=FILE&e=testadun_itco_de:1x1" - + "&uid=Buyer-ID"); - } - - @Test - public void makeHttpRequestsShouldSetCorrectUriWithDeviceIp() { - // given - final BidRequest bidRequest = givenBidRequest( - requestBuilder -> requestBuilder - .device(Device.builder().ip("123.321.321.123").build()), - identity()); - - // when - final Result>> result = eplanningBidder.makeHttpRequests(bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1) - .extracting(HttpRequest::getUri) - .containsOnly("http://eplanning.com/clientId/1/FILE/ROS?ct=1&r=pbs&ncb=1&ur=FILE&e=testadun_itco_de:1x1" - + "&ip=123.321.321.123"); - } - - @Test - public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { - // given - final HttpCall httpCall = givenHttpCall("invalid"); - - // when - final Result> result = eplanningBidder.makeBids(httpCall, null); - - // then - assertThat(result.getErrors()).hasSize(1); - assertThat(result.getErrors().get(0).getMessage()).startsWith("Failed to decode: Unrecognized token"); - assertThat(result.getErrors().get(0).getType()).isEqualTo(BidderError.Type.bad_server_response); - assertThat(result.getValue()).isEmpty(); - } - - @Test - public void makeBidsShouldReturnBannerBidWithExpectedFields() throws JsonProcessingException { - // given - final HttpCall httpCall = givenHttpCall( - mapper.writeValueAsString(HbResponse.of( - singletonList(HbResponseSpace.of("testadun_itco_de", - singletonList(HbResponseAd.builder() - .adId("ad-id") - .impressionId("imp-id") - .price("3.3") - .adM("some-adm") - .crId("CR-ID") - .width(500) - .height(300) - .build())))))); - - final BidRequest bidRequest = givenBidRequest(identity()); - - // when - final Result> result = eplanningBidder.makeBids(httpCall, bidRequest); - - // then - final Bid expectedBid = Bid.builder() - .id("imp-id") - .adid("ad-id") - .impid("123") - .price(BigDecimal.valueOf(3.3)) - .adm("some-adm") - .crid("CR-ID") - .w(500) - .h(300) - .build(); - - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1) - .containsOnly(BidderBid.of(expectedBid, BidType.banner, null)); - } - - @Test - public void makeBidsShouldReturnBannerBidIfMissingAdunitCode() throws JsonProcessingException { - // given - final HttpCall httpCall = givenHttpCall( - mapper.writeValueAsString(HbResponse.of( - singletonList(HbResponseSpace.of("1x1", - singletonList(HbResponseAd.builder() - .adId("ad-id") - .impressionId("imp-id") - .price("3.3") - .adM("some-adm") - .crId("CR-ID") - .width(1) - .height(1) - .build())))))); - - final BidRequest bidRequest = givenBidRequest(impBuilder -> impBuilder.ext(mapper.valueToTree(ExtPrebid.of(null, - ExtImpEplanning.of("clientId", null))))); - - // when - final Result> result = eplanningBidder.makeBids(httpCall, bidRequest); - - // then - final Bid expectedBid = Bid.builder() - .id("imp-id") - .adid("ad-id") - .impid("123") - .price(BigDecimal.valueOf(3.3)) - .adm("some-adm") - .crid("CR-ID") - .w(1) - .h(1) - .build(); - - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1) - .containsOnly(BidderBid.of(expectedBid, BidType.banner, null)); - } - - @Test - public void makeBidsShouldNotCrashIfThereAreNoSpaces() throws JsonProcessingException { - // given - final HttpCall httpCall = givenHttpCall( - mapper.writeValueAsString(HbResponse.of(null))); - - final BidRequest bidRequest = givenBidRequest(identity()); - - // when - final Result> result = eplanningBidder.makeBids(httpCall, bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).isEmpty(); - } - - @Test - public void makeBidsShouldNotCrashIfThereAreNoAds() throws JsonProcessingException { - // given - final HttpCall httpCall = givenHttpCall( - mapper.writeValueAsString(HbResponse.of( - singletonList(HbResponseSpace.of("adless", null))))); - - final BidRequest bidRequest = givenBidRequest(identity()); - - // when - final Result> result = eplanningBidder.makeBids(httpCall, bidRequest); - - // then - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).isEmpty(); - } - - @Test - public void extractTargetingShouldReturnEmptyMap() { - // given, when and then - assertThat(eplanningBidder.extractTargeting(Json.mapper.createObjectNode())).isEmpty(); - } - - private static BidRequest givenBidRequest( - Function bidRequestCustomizer, - Function impCustomizer) { - return bidRequestCustomizer.apply(BidRequest.builder() - .imp(singletonList(givenImp(impCustomizer)))) - .build(); - } - - private static BidRequest givenBidRequest(Function impCustomizer) { - return givenBidRequest(identity(), impCustomizer); - } - - private static Imp givenImp(Function impCustomizer) { - return impCustomizer.apply(Imp.builder() - .id("123") - .banner(Banner.builder().build()) - .ext(mapper.valueToTree(ExtPrebid.of(null, - ExtImpEplanning.of("clientId", "test_ad.-un(itco:de:"))))) - .build(); - } - - private static HttpCall givenHttpCall(String body) { - return HttpCall.success( - null, HttpResponse.of(200, null, body), null); - } -} From 7e13911e78a0201c36e4a3ccf5b93d2eee3bde0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=92scar=20Mar=C3=AD?= Date: Thu, 11 Feb 2021 11:01:24 +0100 Subject: [PATCH 16/29] avoid eplanning bids when 300x250 is not requested --- .../bidder/eplanning/EplanningBidder.java | 30 ++++++++++-- src/main/resources/logback-test.xml | 48 +++++++++++++++++++ 2 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 src/main/resources/logback-test.xml diff --git a/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java b/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java index a804918b255..e440a17b1ef 100644 --- a/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java +++ b/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java @@ -8,6 +8,8 @@ import com.iab.openrtb.request.Imp; import com.iab.openrtb.request.Site; import com.iab.openrtb.request.User; +import com.iab.openrtb.request.Banner; +import com.iab.openrtb.request.Format; import com.iab.openrtb.response.Bid; import io.vertx.core.MultiMap; import io.vertx.core.http.HttpMethod; @@ -51,9 +53,8 @@ */ public class EplanningBidder implements Bidder { - private static final String CUSTOM_MARFEEL_FIXED_WIDTH = "300"; - private static final String CUSTOM_MARFEEL_FIXED_HEIGHT = "250"; - private static final String NULL_SIZE = "1x1"; + private static final Integer CUSTOM_MARFEEL_FIXED_WIDTH = 300; + private static final Integer CUSTOM_MARFEEL_FIXED_HEIGHT = 250; private static final String DEFAULT_PAGE_URL = "FILE"; private static final String SEC = "ROS"; private static final String DFP_CLIENT_ID = "1"; @@ -145,7 +146,28 @@ private ExtImpEplanning validateAndModifyImpExt(Imp imp) throws PreBidException } private static String resolveSizeString(Imp imp) { - return String.format("%sx%s", CUSTOM_MARFEEL_FIXED_WIDTH, CUSTOM_MARFEEL_FIXED_HEIGHT); + final Banner banner = imp.getBanner(); + final String customMarfeelSize = String.format("%dx%d", CUSTOM_MARFEEL_FIXED_WIDTH, CUSTOM_MARFEEL_FIXED_HEIGHT); + final Integer bannerWidth = banner.getW(); + final Integer bannerHeight = banner.getH(); + + if (CUSTOM_MARFEEL_FIXED_WIDTH.equals(bannerWidth) && CUSTOM_MARFEEL_FIXED_HEIGHT.equals(bannerHeight)) { + return customMarfeelSize; + } + + final List bannerFormats = banner.getFormat(); + if (CollectionUtils.isNotEmpty(bannerFormats)) { + for (Format format : bannerFormats) { + final Integer formatHeight = format.getH(); + final Integer formatWidth = format.getW(); + + if (CUSTOM_MARFEEL_FIXED_WIDTH.equals(formatWidth) && CUSTOM_MARFEEL_FIXED_HEIGHT.equals(formatHeight)) { + return customMarfeelSize; + } + } + } + + throw new PreBidException(String.format("Ignoring imp id=%s, Eplanning doesn't support requested size(s)", imp.getId())); } private static String cleanName(String name) { diff --git a/src/main/resources/logback-test.xml b/src/main/resources/logback-test.xml new file mode 100644 index 00000000000..c60c43fc801 --- /dev/null +++ b/src/main/resources/logback-test.xml @@ -0,0 +1,48 @@ + + + + + + + + + %date{yyyy-MM-dd'T'HH:mm:ss.SSSZ} %-4relative [%thread] %-5level %logger{35} - %msg %n + + + + + %date{yyyy-MM-dd'T'HH:mm:ss.SSSZ} [%thread] %-5level %logger{36} - %msg%n - [%X{errorCause} || %X{errorRootCause}] || [%X{stacktrace}] + + + + + + + + + + + + + + + + + + + + + + From a8717f189cce7ef26e25f3b11956aeee60a7212d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=92scar=20Mar=C3=AD?= Date: Thu, 11 Feb 2021 12:10:24 +0100 Subject: [PATCH 17/29] remove unnecessary file --- src/main/resources/logback-test.xml | 48 ----------------------------- 1 file changed, 48 deletions(-) delete mode 100644 src/main/resources/logback-test.xml diff --git a/src/main/resources/logback-test.xml b/src/main/resources/logback-test.xml deleted file mode 100644 index c60c43fc801..00000000000 --- a/src/main/resources/logback-test.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - %date{yyyy-MM-dd'T'HH:mm:ss.SSSZ} %-4relative [%thread] %-5level %logger{35} - %msg %n - - - - - %date{yyyy-MM-dd'T'HH:mm:ss.SSSZ} [%thread] %-5level %logger{36} - %msg%n - [%X{errorCause} || %X{errorRootCause}] || [%X{stacktrace}] - - - - - - - - - - - - - - - - - - - - - - From 377d644a66b2c1f9709f0b165f9bdd359ff5ef10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=92scar=20Mar=C3=AD?= Date: Thu, 11 Feb 2021 12:25:55 +0100 Subject: [PATCH 18/29] refactor --- .../prebid/server/bidder/eplanning/EplanningBidder.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java b/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java index e440a17b1ef..cdd0dc12bd4 100644 --- a/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java +++ b/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java @@ -144,6 +144,10 @@ private ExtImpEplanning validateAndModifyImpExt(Imp imp) throws PreBidException return extImpEplanning; } + + private static Boolean isMarfeelCustomSize(Integer width, Integer height) { + return CUSTOM_MARFEEL_FIXED_WIDTH.equals(width) && CUSTOM_MARFEEL_FIXED_HEIGHT.equals(height); + } private static String resolveSizeString(Imp imp) { final Banner banner = imp.getBanner(); @@ -151,7 +155,7 @@ private static String resolveSizeString(Imp imp) { final Integer bannerWidth = banner.getW(); final Integer bannerHeight = banner.getH(); - if (CUSTOM_MARFEEL_FIXED_WIDTH.equals(bannerWidth) && CUSTOM_MARFEEL_FIXED_HEIGHT.equals(bannerHeight)) { + if (isMarfeelCustomSize(bannerWidth, bannerHeight)) { return customMarfeelSize; } @@ -161,7 +165,7 @@ private static String resolveSizeString(Imp imp) { final Integer formatHeight = format.getH(); final Integer formatWidth = format.getW(); - if (CUSTOM_MARFEEL_FIXED_WIDTH.equals(formatWidth) && CUSTOM_MARFEEL_FIXED_HEIGHT.equals(formatHeight)) { + if (isMarfeelCustomSize(formatWidth, formatHeight)) { return customMarfeelSize; } } From 1ad3fe477fae91223d6d6bbcd49ed7d4cef7800b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=92scar=20Mar=C3=AD?= Date: Thu, 11 Feb 2021 12:27:00 +0100 Subject: [PATCH 19/29] update vendor list endpoint --- src/main/resources/application.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index d867a22f27f..0dd4372bbea 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -132,11 +132,11 @@ gdpr: eea-countries: at,bg,be,cy,cz,dk,ee,fi,fr,de,gr,hu,ie,it,lv,lt,lu,mt,nl,pl,pt,ro,sk,si,es,se,gb,is,no,li,ai,aw,pt,bm,aq,io,vg,ic,ky,fk,re,mw,gp,gf,yt,pf,tf,gl,pt,ms,an,bq,cw,sx,nc,pn,sh,pm,gs,tc,uk,wf vendorlist: v1: - http-endpoint-template: https://vendorlist.consensu.org/v-{VERSION}/vendorlist.json + http-endpoint-template: https://vendor-list.consensu.org/v-{VERSION}/vendorlist.json http-default-timeout-ms: 2000 refresh-missing-list-period-ms: 3600000 v2: - http-endpoint-template: https://vendorlist.consensu.org/v2/archives/vendor-list-v{VERSION}.json + http-endpoint-template: https://vendor-list.consensu.org/v2/archives/vendor-list-v{VERSION}.json http-default-timeout-ms: 2000 refresh-missing-list-period-ms: 3600000 purposes: From 5f669c1f847b9cfce132b2a841e44ada47baf01f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=92scar=20Mar=C3=AD?= Date: Thu, 11 Feb 2021 12:29:14 +0100 Subject: [PATCH 20/29] restore vendorlist endpoint for tcf v1 --- src/main/resources/application.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 0dd4372bbea..ffadfa8c954 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -132,7 +132,7 @@ gdpr: eea-countries: at,bg,be,cy,cz,dk,ee,fi,fr,de,gr,hu,ie,it,lv,lt,lu,mt,nl,pl,pt,ro,sk,si,es,se,gb,is,no,li,ai,aw,pt,bm,aq,io,vg,ic,ky,fk,re,mw,gp,gf,yt,pf,tf,gl,pt,ms,an,bq,cw,sx,nc,pn,sh,pm,gs,tc,uk,wf vendorlist: v1: - http-endpoint-template: https://vendor-list.consensu.org/v-{VERSION}/vendorlist.json + http-endpoint-template: https://vendorlist.consensu.org/v-{VERSION}/vendorlist.json http-default-timeout-ms: 2000 refresh-missing-list-period-ms: 3600000 v2: From 9796596cc00f46ab9d0d49bd08f03594d1f3e579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=92scar=20Mar=C3=AD?= Date: Thu, 11 Feb 2021 12:41:25 +0100 Subject: [PATCH 21/29] fix linting issues --- .../bidder/eplanning/EplanningBidder.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java b/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java index cdd0dc12bd4..0de8db4564f 100644 --- a/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java +++ b/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java @@ -144,17 +144,19 @@ private ExtImpEplanning validateAndModifyImpExt(Imp imp) throws PreBidException return extImpEplanning; } - + private static Boolean isMarfeelCustomSize(Integer width, Integer height) { return CUSTOM_MARFEEL_FIXED_WIDTH.equals(width) && CUSTOM_MARFEEL_FIXED_HEIGHT.equals(height); } private static String resolveSizeString(Imp imp) { - final Banner banner = imp.getBanner(); - final String customMarfeelSize = String.format("%dx%d", CUSTOM_MARFEEL_FIXED_WIDTH, CUSTOM_MARFEEL_FIXED_HEIGHT); + final Banner banner = imp.getBanner(); + final String customMarfeelSize = String.format( + "%dx%d", + CUSTOM_MARFEEL_FIXED_WIDTH, CUSTOM_MARFEEL_FIXED_HEIGHT); final Integer bannerWidth = banner.getW(); final Integer bannerHeight = banner.getH(); - + if (isMarfeelCustomSize(bannerWidth, bannerHeight)) { return customMarfeelSize; } @@ -164,14 +166,16 @@ private static String resolveSizeString(Imp imp) { for (Format format : bannerFormats) { final Integer formatHeight = format.getH(); final Integer formatWidth = format.getW(); - + if (isMarfeelCustomSize(formatWidth, formatHeight)) { return customMarfeelSize; } } - } + } - throw new PreBidException(String.format("Ignoring imp id=%s, Eplanning doesn't support requested size(s)", imp.getId())); + throw new PreBidException(String.format( + "Ignoring imp id=%s, Eplanning doesn't support requested size(s)", + imp.getId())); } private static String cleanName(String name) { From bb92dff70b08e297cac4f89f121b483f6c95202a Mon Sep 17 00:00:00 2001 From: albertmolinermrf Date: Fri, 12 Feb 2021 08:59:23 +0100 Subject: [PATCH 22/29] Rename profile to generate executable --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6bb850f6560..ddc259ca56c 100644 --- a/pom.xml +++ b/pom.xml @@ -603,7 +603,7 @@ - springboot + marfeelci com.marfeel From 24d83eefca3bae683840b42179916b209aceeafd Mon Sep 17 00:00:00 2001 From: Jordi Llach <33347279+jordillachmrf@users.noreply.github.com> Date: Fri, 11 Dec 2020 11:44:58 +0100 Subject: [PATCH 23/29] Take Marfeel repos URL from environment --- pom.xml | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/pom.xml b/pom.xml index 3e5f13389a2..54fd55a64df 100644 --- a/pom.xml +++ b/pom.xml @@ -20,31 +20,6 @@ HEAD - - - marfeel-private - Marfeel Maven Release Repository - http://repositories.marfeel.com:60081/nexus/content/repositories/marfeel_private/ - - true - - - false - - - - marfeel-snapshot-private - http://repositories.marfeel.com:60081/nexus/content/repositories/marfeel_snapshot_private/ - - false - - - never - true - - - - UTF-8 UTF-8 @@ -708,11 +683,12 @@ marfeel-private - http://repositories.marfeel.com:60081/nexus/content/repositories/marfeel_private + ${repo-url-private} marfeel-snapshot-private - http://repositories.marfeel.com:60081/nexus/content/repositories/marfeel_snapshot_private + ${repo-url-snapshot-private} + From 569954afd38b9bca104bc91b5f0ce3256416bcee Mon Sep 17 00:00:00 2001 From: albertmolinermrf Date: Tue, 13 Apr 2021 08:21:42 +0200 Subject: [PATCH 24/29] Add spotbugs plugin --- pom.xml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/pom.xml b/pom.xml index 54fd55a64df..a0967775c0b 100644 --- a/pom.xml +++ b/pom.xml @@ -51,6 +51,7 @@ 2.0.7 0.5.0 2.12.0 + 3.1.12 1.0-SNAPSHOT @@ -72,6 +73,7 @@ 3.8.0 2.22.1 2.5.3 + 3.1.11 @@ -675,6 +677,33 @@ + + com.github.spotbugs + spotbugs-maven-plugin + ${spotbugs.maven.plugin.version} + + + verify + + check + + + Max + + + + + + com.github.spotbugs + spotbugs + ${spotbugs.version} + compile + + + + Max + + From d4fbb46cf1987c4a19c9aaa1f855405160428247 Mon Sep 17 00:00:00 2001 From: albertmolinermrf Date: Tue, 13 Apr 2021 09:23:24 +0200 Subject: [PATCH 25/29] Pseudo-disable spotbugs --- pom.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a0967775c0b..b170cd2c2ae 100644 --- a/pom.xml +++ b/pom.xml @@ -688,7 +688,8 @@ check - Max + min + com.marfeel.* @@ -701,7 +702,8 @@ - Max + min + com.marfeel.* From e03f20dc588bd680f757499235bd20e3bb66aca7 Mon Sep 17 00:00:00 2001 From: albertmolinermrf Date: Tue, 13 Apr 2021 12:13:53 +0200 Subject: [PATCH 26/29] Adapt to shared library (#12) --- build/Dockerfile | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 build/Dockerfile diff --git a/build/Dockerfile b/build/Dockerfile new file mode 100644 index 00000000000..9fa747486d3 --- /dev/null +++ b/build/Dockerfile @@ -0,0 +1,25 @@ +FROM openjdk:8-jdk + +ENV VERTICLE_FILE prebid-server.jar + +# Set the location of the verticles +ENV VERTICLE_HOME /usr/verticles + +#EXPOSE 5000 + +# Copy your fat jar to the container +COPY ./target/$VERTICLE_FILE $VERTICLE_HOME/ +RUN mkdir -p /var/log/mbid/ + +# Launch the verticle +WORKDIR $VERTICLE_HOME +# Add Tini +ENV TINI_VERSION v0.18.0 +ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-static /tini +RUN chmod +x /tini + +ENTRYPOINT ["/tini", "--"] + + +#It will be overwritten +CMD ["exec java -Dlogging.config=logback.xml -jar prebid-server.jar --debug --spring.config.location=classpath:/application.yaml,prebid-config.yaml"] From f825152ee382d4074a636ddb6ede57e91e276586 Mon Sep 17 00:00:00 2001 From: albertmolinermrf Date: Wed, 26 May 2021 09:34:06 +0200 Subject: [PATCH 27/29] Update from upstream without aliases (#13) --- docs/config-app.md | 20 +- docs/developers/add-new-bidder.md | 7 +- docs/endpoints/cookieSync.md | 16 +- docs/endpoints/setuid.md | 2 +- docs/metrics.md | 2 + pom.xml | 2 +- .../java/com/iab/openrtb/response/Bid.java | 60 +- .../server/analytics/AnalyticsReporter.java | 5 + .../analytics/AnalyticsReporterDelegator.java | 100 +- .../analytics/LogAnalyticsReporter.java | 5 + .../server/analytics/model/AuctionEvent.java | 2 +- .../server/auction/BidResponseCreator.java | 510 ++-- .../prebid/server/auction/BidderAliases.java | 17 +- .../server/auction/ExchangeService.java | 147 +- .../auction/ImplicitParametersExtractor.java | 22 +- .../server/auction/OrtbTypesResolver.java | 17 +- .../server/auction/PriceGranularity.java | 4 +- .../auction/PrivacyEnforcementService.java | 54 +- .../auction/StoredRequestProcessor.java | 4 +- .../server/auction/TimeoutResolver.java | 2 +- .../auction/VideoStoredRequestProcessor.java | 7 +- .../server/auction/model/AuctionContext.java | 11 + .../prebid/server/auction/model/BidInfo.java | 18 +- .../auction/model/BidderResponseInfo.java | 20 + .../auction/model/CookieSyncContext.java | 4 + .../server/auction/model/SetuidContext.java | 3 + .../server/auction/model/TargetingInfo.java | 19 + .../AmpRequestFactory.java | 56 +- .../requestfactory/AuctionRequestFactory.java | 159 + .../Ortb2ImplicitParametersResolver.java} | 457 +-- .../requestfactory/Ortb2RequestFactory.java | 329 +++ .../VideoRequestFactory.java | 182 +- .../prebid/server/bidder/BidderCatalog.java | 90 +- .../org/prebid/server/bidder/BidderDeps.java | 46 +- .../server/bidder/BidderInstanceDeps.java | 47 + .../server/bidder/HttpBidderRequester.java | 57 +- .../server/bidder/UsersyncInfoAssembler.java | 11 +- .../server/bidder/UsersyncMethodChooser.java | 94 + .../prebid/server/bidder/UsersyncUtil.java | 61 + .../org/prebid/server/bidder/Usersyncer.java | 41 +- .../server/bidder/adform/AdformBidder.java | 9 +- .../adgeneration/AdgenerationBidder.java | 8 +- .../server/bidder/adhese/AdheseBidder.java | 69 +- .../adhese/model/AdheseRequestBody.java | 22 + .../server/bidder/adman/AdmanBidder.java | 5 +- .../server/bidder/adocean/AdoceanBidder.java | 4 +- .../bidder/adoppler/AdopplerBidder.java | 38 +- ...eoExt.java => AdopplerResponseAdsExt.java} | 2 +- .../adoppler/model/AdopplerResponseExt.java | 2 +- .../bidder/adtarget/AdtargetBidder.java | 12 +- .../bidder/adtelligent/AdtelligentBidder.java | 4 +- .../advangelists/AdvangelistsBidder.java | 5 +- .../bidder/adyoulike/AdyoulikeBidder.java | 133 + .../bidder/appnexus/AppnexusBidder.java | 15 +- .../bidder/beachfront/BeachfrontBidder.java | 101 +- .../model/BeachfrontBannerRequest.java | 2 + .../bidder/brightroll/BrightrollBidder.java | 24 +- .../server/bidder/cpmstar/CpmStarBidder.java | 9 +- .../bidder/datablocks/DatablocksBidder.java | 11 +- .../bidder/decenterads/DecenteradsBidder.java | 129 + .../prebid/server/bidder/dmx/DmxBidder.java | 116 +- .../bidder/engagebdr/EngagebdrBidder.java | 5 +- .../bidder/eplanning/EplanningBidder.java | 4 +- .../prebid/server/bidder/epom/EpomBidder.java | 100 + .../bidder/facebook/FacebookBidder.java | 15 +- .../server/bidder/gamma/GammaBidder.java | 13 +- .../server/bidder/gamma/model/GammaBid.java | 24 +- .../server/bidder/gamoshi/GamoshiBidder.java | 6 +- .../server/bidder/gumgum/GumgumBidder.java | 89 +- .../improvedigital/ImprovedigitalBidder.java | 92 +- .../server/bidder/inmobi/InmobiBidder.java | 2 +- .../org/prebid/server/bidder/ix/IxBidder.java | 9 +- .../server/bidder/jixie/JixieBidder.java | 101 + .../server/bidder/kubient/KubientBidder.java | 3 +- .../bidder/lifestreet/LifestreetBidder.java | 5 +- .../bidder/lunamedia/LunamediaBidder.java | 4 +- .../bidder/mobfoxpb/MobfoxpbBidder.java | 49 +- .../prebid/server/bidder/model/BidderBid.java | 4 + .../server/bidder/model/BidderSeatBid.java | 6 +- .../bidder/model/BidderSeatBidInfo.java | 23 + .../server/bidder/model/HttpRequest.java | 2 +- .../ninthdecimal/NinthdecimalBidder.java | 7 +- .../server/bidder/nobid/NobidBidder.java | 14 +- .../server/bidder/onetag/OnetagBidder.java | 140 + .../server/bidder/openx/OpenxBidder.java | 17 +- .../bidder/outbrain/OutbrainBidder.java | 177 ++ .../server/bidder/pangle/PangleBidder.java | 207 ++ .../server/bidder/pangle/model/BidExt.java | 15 + .../bidder/pangle/model/PangleBidExt.java | 13 + .../pangle/model/WrappedImpExtBidder.java | 21 + .../bidder/rhythmone/RhythmoneBidder.java | 7 +- .../server/bidder/rubicon/RubiconBidder.java | 196 +- .../rubicon/proto/RubiconSiteExtRp.java | 3 + .../sharethrough/SharethroughBidder.java | 5 - .../bidder/silvermob/SilvermobBidder.java | 2 + .../server/bidder/smaato/SmaatoBidder.java | 10 +- .../smartadserver/SmartadserverBidder.java | 21 +- .../bidder/smartyads/SmartyAdsBidder.java | 8 +- .../somoaudience/SomoaudienceBidder.java | 4 +- .../server/bidder/sovrn/SovrnBidder.java | 5 +- .../synacormedia/SynacormediaBidder.java | 8 +- .../server/bidder/tappx/TappxBidder.java | 57 +- .../server/bidder/unicorn/UnicornBidder.java | 239 ++ .../bidder/unicorn/model/UnicornImpExt.java | 16 + .../unicorn/model/UnicornImpExtContext.java | 12 + .../ValueImpressionBidder.java | 9 +- .../verizonmedia/VerizonmediaBidder.java | 8 +- .../bidder/yieldone/YieldoneBidder.java | 8 +- .../zeroclickfraud/ZeroclickfraudBidder.java | 9 +- .../org/prebid/server/cache/CacheService.java | 16 +- .../currency/CurrencyConversionService.java | 2 +- .../server/handler/CookieSyncHandler.java | 183 +- .../prebid/server/handler/SetuidHandler.java | 66 +- .../handler/info/BidderDetailsHandler.java | 46 +- .../server/handler/info/BiddersHandler.java | 8 +- .../server/handler/openrtb2/AmpHandler.java | 2 +- .../handler/openrtb2/AuctionHandler.java | 2 +- .../server/handler/openrtb2/VideoHandler.java | 2 +- .../server/json/IntegerFlagDeserializer.java | 36 + .../server/json/ZonedDateTimeModule.java | 1 - .../prebid/server/log/ConditionalLogger.java | 6 + .../org/prebid/server/metric/Metrics.java | 75 +- .../server/privacy/gdpr/GdprService.java | 13 +- .../server/privacy/gdpr/Tcf2Service.java | 127 +- .../privacy/gdpr/TcfDefinerService.java | 28 +- .../server/privacy/gdpr/VendorIdResolver.java | 20 +- .../server/privacy/gdpr/model/TcfContext.java | 2 + .../purpose/PurposeEightStrategy.java | 6 +- .../purpose/PurposeFiveStrategy.java | 6 +- .../purpose/PurposeFourStrategy.java | 6 +- .../purpose/PurposeNineStrategy.java | 6 +- .../purpose/PurposeOneStrategy.java | 6 +- .../purpose/PurposeSevenStrategy.java | 6 +- .../purpose/PurposeSixStrategy.java | 6 +- .../purpose/PurposeStrategy.java | 3 +- .../purpose/PurposeTenStrategy.java | 6 +- .../purpose/PurposeThreeStrategy.java | 6 +- .../purpose/PurposeTwoStrategy.java | 6 +- .../BasicEnforcePurposeStrategy.java | 4 +- .../EnforcePurposeStrategy.java | 12 +- .../FullEnforcePurposeStrategy.java | 22 +- .../NoEnforcePurposeStrategy.java | 4 +- ...PurposeTwoBasicEnforcePurposeStrategy.java | 6 +- .../proto/{Purpose.java => PurposeCode.java} | 6 +- .../gdpr/vendorlist/proto/VendorV1.java | 8 +- .../gdpr/vendorlist/proto/VendorV2.java | 12 +- .../ext/request/BidAdjustmentMediaType.java | 21 + .../ExtRequestBidadjustmentfactors.java | 31 + .../openrtb/ext/request/ExtRequestPrebid.java | 11 +- .../request/adyoulike/ExtImpAdyoulike.java | 24 + .../decenterads/ExtImpDecenterads.java | 16 + .../ext/request/gumgum/ExtImpGumgum.java | 9 + .../ext/request/gumgum/ExtImpGumgumVideo.java | 13 + .../ext/request/jixie/ExtImpJixie.java | 21 + .../ext/request/mobfoxpb/ExtImpMobfoxpb.java | 2 + .../ext/request/onetag/ExtImpOnetag.java | 16 + .../ext/request/outbrains/ExtImpOutbrain.java | 19 + .../outbrains/ExtImpOutbrainPublisher.java | 15 + .../ext/request/pangle/ExtImpPangle.java | 11 + .../ext/request/unicorn/ExtImpUnicorn.java | 24 + .../openrtb/ext/response/ExtBidPrebid.java | 2 +- .../proto/request/CookieSyncRequest.java | 24 + .../server/proto/response/BidderInfo.java | 34 +- .../settings/model/AccountGdprConfig.java | 5 + .../spring/config/MetricsConfiguration.java | 5 +- .../spring/config/ServiceConfiguration.java | 105 +- .../spring/config/WebConfiguration.java | 6 +- .../config/bidder/AcuityadsConfiguration.java | 9 +- .../config/bidder/AdformConfiguration.java | 9 +- .../bidder/AdgenerationConfiguration.java | 6 +- .../config/bidder/AdheseConfiguration.java | 6 +- .../bidder/AdkernelAdnConfiguration.java | 6 +- .../config/bidder/AdkernelConfiguration.java | 6 +- .../config/bidder/AdmanConfiguration.java | 8 +- .../config/bidder/AdmixerConfiguration.java | 9 +- .../config/bidder/AdoceanConfiguration.java | 6 +- .../config/bidder/AdopplerConfiguration.java | 6 +- .../config/bidder/AdotConfiguration.java | 9 +- .../config/bidder/AdponeConfiguration.java | 6 +- .../config/bidder/AdprimeConfiguration.java | 6 +- .../config/bidder/AdtargetConfiguration.java | 6 +- .../bidder/AdtelligentConfiguration.java | 6 +- .../bidder/AdvangelistsConfiguration.java | 6 +- .../config/bidder/AdyoulikeConfiguration.java | 51 + .../config/bidder/AjaConfiguration.java | 6 +- .../config/bidder/AmxConfiguration.java | 8 +- .../config/bidder/ApplogyConfiguration.java | 6 +- .../config/bidder/AppnexusConfiguration.java | 9 +- .../config/bidder/AvocetConfiguration.java | 7 +- .../bidder/BeachfrontConfiguration.java | 12 +- .../config/bidder/BeintooConfiguration.java | 9 +- .../config/bidder/BetweenConfiguration.java | 9 +- .../bidder/BrightrollConfiguration.java | 12 +- .../config/bidder/ColossusConfiguration.java | 6 +- .../config/bidder/ConfigurationYeahmobi.java | 10 +- .../config/bidder/ConnectAdConfiguration.java | 9 +- .../bidder/ConsumableConfiguration.java | 6 +- .../bidder/ConversantConfiguration.java | 11 +- .../config/bidder/CpmStarConfiguration.java | 6 +- .../bidder/DatablocksConfiguration.java | 6 +- .../bidder/DecenteradsConfiguration.java | 51 + .../bidder/DeepintentConfiguration.java | 9 +- .../config/bidder/DmxConfiguration.java | 9 +- .../bidder/EmxDigitalConfiguration.java | 6 +- .../config/bidder/EngagebdrConfiguration.java | 6 +- .../config/bidder/EplanningConfiguration.java | 6 +- .../config/bidder/EpomConfiguration.java | 51 + .../config/bidder/FacebookConfiguration.java | 16 +- .../config/bidder/GammaConfiguration.java | 6 +- .../config/bidder/GamoshiConfiguration.java | 6 +- .../config/bidder/GridConfiguration.java | 6 +- .../config/bidder/GumgumConfiguration.java | 6 +- .../bidder/ImprovedigitalConfiguration.java | 6 +- .../config/bidder/InmobiConfiguration.java | 9 +- .../config/bidder/InvibesConfiguration.java | 9 +- .../spring/config/bidder/IxConfiguration.java | 9 +- .../config/bidder/JixieConfiguration.java | 51 + .../config/bidder/KidozConfiguration.java | 6 +- .../bidder/KrushmediaConfiguration.java | 9 +- .../config/bidder/KubientConfiguration.java | 6 +- .../bidder/LifestreetConfiguration.java | 9 +- .../bidder/LockerdomeConfiguration.java | 6 +- .../config/bidder/LogicadConfiguration.java | 9 +- .../config/bidder/LunamediaConfiguration.java | 9 +- .../config/bidder/MarsmediaConfiguration.java | 6 +- .../config/bidder/MgidConfiguration.java | 6 +- .../config/bidder/MobfoxpbConfiguration.java | 6 +- .../bidder/MobilefuseConfiguration.java | 9 +- .../bidder/NanointeractiveConfiguration.java | 6 +- .../bidder/NinthdecimalConfiguration.java | 6 +- .../config/bidder/NobidConfiguration.java | 9 +- .../config/bidder/OnetagConfiguration.java | 51 + .../config/bidder/OpenxConfiguration.java | 6 +- .../config/bidder/OrbidderConfiguration.java | 9 +- .../config/bidder/OutbrainConfiguration.java | 51 + .../config/bidder/PangleConfiguration.java | 51 + .../config/bidder/PubmaticConfiguration.java | 9 +- .../config/bidder/PubnativeConfiguration.java | 6 +- .../bidder/PulsepointConfiguration.java | 9 +- .../bidder/RevcontentConfiguration.java | 6 +- .../config/bidder/RhythmoneConfiguration.java | 6 +- .../config/bidder/RtbhouseConfiguration.java | 6 +- .../config/bidder/RubiconConfiguration.java | 23 +- .../bidder/SharethroughConfiguration.java | 6 +- .../config/bidder/SilvermobConfiguration.java | 9 +- .../config/bidder/SmaatoConfiguration.java | 9 +- .../bidder/SmartadserverConfiguration.java | 9 +- .../config/bidder/SmartrtbConfiguration.java | 6 +- .../config/bidder/SmartyAdsConfiguration.java | 9 +- .../bidder/SomoaudienceConfiguration.java | 6 +- .../config/bidder/SonobiConfiguration.java | 6 +- .../config/bidder/SovrnConfiguration.java | 9 +- .../bidder/SynacormediaConfiguration.java | 6 +- .../config/bidder/TappxConfiguration.java | 6 +- .../config/bidder/TelariaConfiguration.java | 6 +- .../bidder/TripleliftConfiguration.java | 6 +- .../bidder/TripleliftNativeConfiguration.java | 10 +- .../config/bidder/TtxConfiguration.java | 6 +- .../config/bidder/UcfunnelConfiguration.java | 6 +- .../config/bidder/UnicornConfiguration.java | 52 + .../config/bidder/UnrulyConfiguration.java | 6 +- .../bidder/ValueImpressionConfiguration.java | 6 +- .../bidder/VerizonmediaConfiguration.java | 6 +- .../config/bidder/VisxConfiguration.java | 6 +- .../config/bidder/VrtcalConfiguration.java | 6 +- .../config/bidder/YieldlabConfiguration.java | 9 +- .../config/bidder/YieldmoConfiguration.java | 6 +- .../config/bidder/YieldoneConfiguration.java | 6 +- .../bidder/ZeroclickfraudConfiguration.java | 6 +- .../model/BidderConfigurationProperties.java | 11 +- .../UsersyncConfigurationProperties.java | 18 + .../bidder/util/BidderDepsAssembler.java | 150 +- .../config/bidder/util/BidderInfoCreator.java | 5 + .../config/bidder/util/UsersyncerCreator.java | 64 +- .../spring/env/YamlPropertySourceFactory.java | 14 +- .../java/org/prebid/server/util/HttpUtil.java | 23 +- .../validation/BidderParamValidator.java | 10 +- .../server/validation/RequestValidator.java | 55 +- .../validation/ResponseBidValidator.java | 73 +- .../validation/VideoRequestValidator.java | 1 - .../resources/bidder-config/acuityads.yaml | 2 +- src/main/resources/bidder-config/adform.yaml | 2 +- .../resources/bidder-config/adgeneration.yaml | 2 +- src/main/resources/bidder-config/adhese.yaml | 2 +- .../resources/bidder-config/adkernel.yaml | 2 +- .../resources/bidder-config/adkerneladn.yaml | 2 +- src/main/resources/bidder-config/adman.yaml | 2 +- src/main/resources/bidder-config/admixer.yaml | 2 +- src/main/resources/bidder-config/adocean.yaml | 2 +- .../resources/bidder-config/adoppler.yaml | 2 +- src/main/resources/bidder-config/adot.yaml | 2 +- src/main/resources/bidder-config/adpone.yaml | 2 +- src/main/resources/bidder-config/adprime.yaml | 2 +- .../resources/bidder-config/adtarget.yaml | 8 +- .../resources/bidder-config/adtelligent.yaml | 16 +- .../resources/bidder-config/advangelists.yaml | 2 +- .../resources/bidder-config/adyoulike.yaml | 24 + src/main/resources/bidder-config/aja.yaml | 2 +- src/main/resources/bidder-config/amx.yaml | 2 +- src/main/resources/bidder-config/applogy.yaml | 2 +- .../resources/bidder-config/appnexus.yaml | 4 +- src/main/resources/bidder-config/avocet.yaml | 2 +- .../resources/bidder-config/beachfront.yaml | 2 +- src/main/resources/bidder-config/beintoo.yaml | 2 +- src/main/resources/bidder-config/between.yaml | 4 +- .../resources/bidder-config/brightroll.yaml | 2 +- .../resources/bidder-config/colossus.yaml | 2 +- .../resources/bidder-config/connectad.yaml | 2 +- .../resources/bidder-config/consumable.yaml | 2 +- .../resources/bidder-config/conversant.yaml | 2 +- src/main/resources/bidder-config/cpmstar.yaml | 2 +- .../resources/bidder-config/datablocks.yaml | 2 +- .../resources/bidder-config/decenterads.yaml | 27 + .../resources/bidder-config/deepintent.yaml | 4 +- src/main/resources/bidder-config/dmx.yaml | 2 +- .../resources/bidder-config/emxdigital.yaml | 2 +- .../resources/bidder-config/engagebdr.yaml | 6 +- .../resources/bidder-config/eplanning.yaml | 2 +- src/main/resources/bidder-config/epom.yaml | 27 + .../resources/bidder-config/facebook.yaml | 2 +- src/main/resources/bidder-config/gamma.yaml | 2 +- src/main/resources/bidder-config/gamoshi.yaml | 2 +- src/main/resources/bidder-config/grid.yaml | 2 +- src/main/resources/bidder-config/gumgum.yaml | 2 +- .../bidder-config/improvedigital.yaml | 4 +- src/main/resources/bidder-config/inmobi.yaml | 4 +- src/main/resources/bidder-config/invibes.yaml | 2 +- src/main/resources/bidder-config/ix.yaml | 2 +- src/main/resources/bidder-config/jixie.yaml | 23 + src/main/resources/bidder-config/kidoz.yaml | 2 +- .../resources/bidder-config/krushmedia.yaml | 2 +- src/main/resources/bidder-config/kubient.yaml | 2 +- .../resources/bidder-config/lifestreet.yaml | 2 +- .../resources/bidder-config/lockerdome.yaml | 2 +- src/main/resources/bidder-config/logicad.yaml | 2 +- .../resources/bidder-config/lunamedia.yaml | 2 +- .../resources/bidder-config/marsmedia.yaml | 2 +- src/main/resources/bidder-config/mgid.yaml | 2 +- .../resources/bidder-config/mobfoxpb.yaml | 4 +- .../resources/bidder-config/mobilefuse.yaml | 2 +- .../bidder-config/nanointeractive.yaml | 2 +- .../resources/bidder-config/ninthdecimal.yaml | 2 +- src/main/resources/bidder-config/nobid.yaml | 2 +- src/main/resources/bidder-config/onetag.yaml | 27 + src/main/resources/bidder-config/openx.yaml | 2 +- .../resources/bidder-config/orbidder.yaml | 5 +- .../resources/bidder-config/outbrain.yaml | 25 + src/main/resources/bidder-config/pangle.yaml | 24 + .../resources/bidder-config/pubmatic.yaml | 2 +- .../resources/bidder-config/pubnative.yaml | 2 +- .../resources/bidder-config/pulsepoint.yaml | 2 +- .../resources/bidder-config/revcontent.yaml | 2 +- .../resources/bidder-config/rhythmone.yaml | 2 +- .../resources/bidder-config/rtbhouse.yaml | 2 +- src/main/resources/bidder-config/rubicon.yaml | 2 +- .../resources/bidder-config/sharethrough.yaml | 2 +- .../resources/bidder-config/silvermob.yaml | 2 +- src/main/resources/bidder-config/smaato.yaml | 2 +- .../bidder-config/smartadserver.yaml | 2 +- .../resources/bidder-config/smartrtb.yaml | 2 +- .../resources/bidder-config/smartyads.yaml | 6 +- .../resources/bidder-config/somoaudience.yaml | 2 +- src/main/resources/bidder-config/sonobi.yaml | 2 +- src/main/resources/bidder-config/sovrn.yaml | 2 +- .../resources/bidder-config/synacormedia.yaml | 2 +- src/main/resources/bidder-config/tappx.yaml | 10 +- src/main/resources/bidder-config/telaria.yaml | 2 +- .../resources/bidder-config/triplelift.yaml | 2 +- .../bidder-config/tripleliftnative.yaml | 2 +- src/main/resources/bidder-config/ttx.yaml | 4 +- .../resources/bidder-config/ucfunnel.yaml | 2 +- src/main/resources/bidder-config/unicorn.yaml | 22 + src/main/resources/bidder-config/unruly.yaml | 2 +- .../bidder-config/valueimpression.yaml | 2 +- .../resources/bidder-config/verizonmedia.yaml | 2 +- src/main/resources/bidder-config/visx.yaml | 2 +- src/main/resources/bidder-config/vrtcal.yaml | 2 +- .../resources/bidder-config/yeahmobi.yaml | 2 +- .../resources/bidder-config/yieldlab.yaml | 2 +- src/main/resources/bidder-config/yieldmo.yaml | 2 +- .../resources/bidder-config/yieldone.yaml | 2 +- .../bidder-config/zeroclickfraud.yaml | 2 +- .../static/bidder-params/adyoulike.json | 33 + .../static/bidder-params/decenterads.json | 18 + .../resources/static/bidder-params/epom.json | 8 + .../static/bidder-params/gumgum.json | 22 +- .../resources/static/bidder-params/jixie.json | 26 + .../resources/static/bidder-params/kidoz.json | 12 +- .../static/bidder-params/mobfoxpb.json | 18 +- .../static/bidder-params/onetag.json | 20 + .../static/bidder-params/outbrain.json | 40 + .../static/bidder-params/pangle.json | 16 + .../static/bidder-params/rtbhouse.json | 11 +- .../static/bidder-params/unicorn.json | 25 + .../AnalyticsReporterDelegatorTest.java | 63 + .../auction/AuctionRequestFactoryTest.java | 2554 ----------------- .../auction/BidResponseCreatorTest.java | 236 +- .../server/auction/BidderAliasesTest.java | 114 +- .../CurrencyConversionServiceTest.java | 10 +- .../server/auction/ExchangeServiceTest.java | 286 +- .../ImplicitParametersExtractorTest.java | 31 +- .../PrivacyEnforcementServiceTest.java | 140 +- .../AmpRequestFactoryTest.java | 249 +- .../AuctionRequestFactoryTest.java | 455 +++ .../Ortb2ImplicitParametersResolverTest.java | 1762 ++++++++++++ .../Ortb2RequestFactoryTest.java | 688 +++++ .../VideoRequestFactoryTest.java | 129 +- .../server/bidder/BidderCatalogTest.java | 122 +- .../bidder/HttpBidderRequesterTest.java | 119 +- .../bidder/UsersyncInfoAssemblerTest.java | 61 +- .../bidder/UsersyncMethodChooserTest.java | 367 +++ .../server/bidder/UsersyncUtilTest.java | 72 + .../prebid/server/bidder/UsersyncerTest.java | 36 - .../bidder/adform/AdformBidderTest.java | 30 + .../bidder/adhese/AdheseBidderTest.java | 88 +- .../bidder/adoppler/AdopplerBidderTest.java | 54 +- .../bidder/adyoulike/AdyoulikeBidderTest.java | 303 ++ .../bidder/appnexus/AppnexusBidderTest.java | 63 + .../beachfront/BeachfrontBidderTest.java | 43 +- .../decenterads/DecenteradsBidderTest.java | 232 ++ .../server/bidder/dmx/DmxBidderTest.java | 78 + .../server/bidder/epom/EpomBidderTest.java | 291 ++ .../server/bidder/gamma/GammaBidderTest.java | 22 +- .../bidder/gumgum/GumgumBidderTest.java | 99 +- .../ImprovedigitalBidderTest.java | 111 +- .../server/bidder/jixie/JixieBidderTest.java | 233 ++ .../bidder/mobfoxpb/MobfoxpbBidderTest.java | 165 +- .../bidder/onetag/OnetagBidderTest.java | 362 +++ .../server/bidder/openx/OpenxBidderTest.java | 55 +- .../bidder/outbrain/OutbrainBidderTest.java | 265 ++ .../bidder/pangle/PangleBidderTest.java | 508 ++++ .../bidder/rubicon/RubiconBidderTest.java | 242 +- .../bidder/smaato/SmaatoBidderTest.java | 28 +- .../SmartadserverBidderTest.java | 29 + .../server/bidder/tappx/TappxBidderTest.java | 117 +- .../bidder/unicorn/UnicornBidderTest.java | 341 +++ .../prebid/server/cache/CacheServiceTest.java | 76 +- .../server/handler/CookieSyncHandlerTest.java | 256 +- .../server/handler/SetuidHandlerTest.java | 201 +- .../info/BidderDetailsHandlerTest.java | 36 +- .../handler/info/BiddersHandlerTest.java | 21 - .../handler/openrtb2/AmpHandlerTest.java | 2 +- .../handler/openrtb2/AuctionHandlerTest.java | 2 +- .../handler/openrtb2/VideoHandlerTest.java | 2 +- .../java/org/prebid/server/it/AdheseTest.java | 5 +- .../org/prebid/server/it/AdyoulikeTest.java | 58 + .../org/prebid/server/it/ApplicationTest.java | 111 +- .../org/prebid/server/it/DecenteradsTest.java | 63 + .../org/prebid/server/it/EplanningTest.java | 2 +- .../java/org/prebid/server/it/EpomTest.java | 54 + .../org/prebid/server/it/IntegrationTest.java | 8 +- .../java/org/prebid/server/it/JixieTest.java | 59 + .../org/prebid/server/it/MobfoxpbTest.java | 3 + .../java/org/prebid/server/it/OnetagTest.java | 60 + .../org/prebid/server/it/OutbrainTest.java | 56 + .../java/org/prebid/server/it/PangleTest.java | 57 + .../org/prebid/server/it/RubiconTest.java | 61 + .../java/org/prebid/server/it/TappxTest.java | 2 +- .../org/prebid/server/it/TelariaTest.java | 2 +- .../org/prebid/server/it/UnicornTest.java | 58 + .../json/IntegerFlagDeserializerTest.java | 92 + .../org/prebid/server/metric/MetricsTest.java | 115 +- .../server/privacy/gdpr/GdprServiceTest.java | 10 +- .../server/privacy/gdpr/Tcf2ServiceTest.java | 104 +- .../privacy/gdpr/TcfDefinerServiceTest.java | 36 +- .../purpose/PurposeEightStrategyTest.java | 21 +- .../purpose/PurposeFiveStrategyTest.java | 21 +- .../purpose/PurposeFourStrategyTest.java | 21 +- .../purpose/PurposeNineStrategyTest.java | 21 +- .../purpose/PurposeOneStrategyTest.java | 21 +- .../purpose/PurposeSevenStrategyTest.java | 21 +- .../purpose/PurposeSixStrategyTest.java | 21 +- .../purpose/PurposeTenStrategyTest.java | 21 +- .../purpose/PurposeThreeStrategyTest.java | 21 +- .../purpose/PurposeTwoStrategyTest.java | 21 +- .../BasicEnforcePurposeStrategyTest.java | 30 +- .../FullEnforcePurposeStrategyTest.java | 282 +- .../NoEnforcePurposeStrategyTest.java | 26 +- ...oseTwoBasicEnforcePurposeStrategyTest.java | 30 +- .../vendorlist/VendorListServiceV1Test.java | 4 +- .../vendorlist/VendorListServiceV2Test.java | 18 +- .../bidder/util/UsersyncerCreatorTest.java | 119 + .../org/prebid/server/util/HttpUtilTest.java | 12 +- .../validation/BidderParamValidatorTest.java | 68 +- .../validation/RequestValidatorTest.java | 90 +- .../validation/ResponseBidValidatorTest.java | 52 +- src/test/resources/logback-test.xml | 2 +- .../it/amp/test-appnexus-bid-request.json | 5 +- .../server/it/amp/test-cache-request.json | 9 +- .../cache/update/test-auction-response.json | 6 +- .../update/test-rubicon-bid-request1.json | 2 +- .../update/test-rubicon-bid-request2.json | 2 +- .../acuityads/test-acuityads-bid-request.json | 5 +- .../test-auction-acuityads-response.json | 3 +- .../test-cache-acuityads-request.json | 5 +- .../adform/test-auction-adform-response.json | 4 +- .../adform/test-cache-adform-request.json | 6 +- .../test-auction-adgeneration-response.json | 6 +- .../test-cache-adgeneration-request.json | 8 +- .../adhese/test-auction-adhese-response.json | 6 +- .../adhese/test-cache-adhese-request.json | 6 +- .../adkernel/test-adkernel-bid-request.json | 2 +- .../test-auction-adkernel-response.json | 3 +- .../adkernel/test-cache-adkernel-request.json | 5 +- .../test-auction-adkerneladn-response.json | 6 +- .../test-cache-adkerneladn-request.json | 12 +- .../adman/test-adman-bid-request-1.json | 5 +- .../adman/test-adman-bid-request-2.json | 5 +- .../adman/test-auction-adman-response.json | 6 +- .../adman/test-cache-adman-request.json | 12 +- .../admixer/test-admixer-bid-request.json | 3 +- .../test-auction-admixer-response.json | 5 +- .../admixer/test-cache-admixer-request.json | 5 +- .../test-auction-adocean-response.json | 11 +- .../adocean/test-cache-adocean-request.json | 8 +- .../adoppler/test-adoppler-bid-request-1.json | 5 +- .../test-auction-adoppler-response.json | 3 +- .../adoppler/test-cache-adoppler-request.json | 5 +- .../openrtb2/adot/test-adot-bid-request.json | 17 +- .../adot/test-auction-adot-response.json | 1 + .../adot/test-cache-adot-request.json | 3 +- .../adpone/test-adpone-bid-request.json | 5 +- .../adpone/test-auction-adpone-response.json | 3 +- .../adpone/test-cache-adpone-request.json | 7 +- .../adprime/test-adprime-bid-request-1.json | 9 +- .../adprime/test-adprime-bid-request-2.json | 9 +- .../test-auction-adprime-response.json | 6 +- .../adprime/test-cache-adprime-request.json | 12 +- .../adtarget/test-adtarget-bid-request-1.json | 5 +- .../test-auction-adtarget-response.json | 3 +- .../adtarget/test-cache-adtarget-request.json | 7 +- .../test-adtelligent-bid-request-1.json | 5 +- .../test-auction-adtelligent-response.json | 3 +- .../test-cache-adtelligent-request.json | 7 +- .../test-auction-advangelists-response.json | 3 +- .../test-cache-advangelists-request.json | 5 +- .../adyoulike/test-adyoulike-bid-request.json | 68 + .../test-adyoulike-bid-response.json | 20 + .../test-auction-adyoulike-request.json | 52 + .../test-auction-adyoulike-response.json | 59 + .../test-cache-adyoulike-request.json | 21 + .../test-cache-adyoulike-response.json | 7 + .../openrtb2/aja/test-aja-bid-request-1.json | 5 +- .../openrtb2/aja/test-aja-bid-request-2.json | 5 +- .../aja/test-auction-aja-response.json | 8 +- .../openrtb2/aja/test-cache-aja-request.json | 11 +- .../it/openrtb2/amx/test-amx-bid-request.json | 13 +- .../openrtb2/amx/test-amx-bid-response.json | 4 +- .../amx/test-auction-amx-request.json | 2 +- .../amx/test-auction-amx-response.json | 1 + .../openrtb2/amx/test-cache-amx-request.json | 9 +- .../applogy/test-applogy-bid-request-1.json | 5 +- .../applogy/test-applogy-bid-request-2.json | 5 +- .../test-auction-applogy-response.json | 6 +- .../applogy/test-cache-applogy-request.json | 12 +- .../avocet/test-auction-avocet-response.json | 12 +- .../avocet/test-avocet-bid-request-1.json | 5 +- .../avocet/test-avocet-bid-response-1.json | 4 +- .../avocet/test-cache-avocet-request.json | 3 +- .../test-auction-beachfront-response.json | 4 +- .../test-beachfront-bid-request-1.json | 5 +- .../test-beachfront-bid-request-2.json | 5 +- .../test-beachfront-bid-request-3.json | 9 +- .../test-cache-beachfront-request.json | 8 +- .../beintoo/test-auction-beintoo-request.json | 1 - .../test-auction-beintoo-response.json | 114 +- .../beintoo/test-beintoo-bid-request.json | 6 +- .../beintoo/test-cache-beintoo-request.json | 6 +- .../test-auction-between-response.json | 3 +- .../between/test-between-bid-request.json | 16 +- .../between/test-cache-between-request.json | 7 +- .../test-auction-brightroll-response.json | 3 +- .../test-brightroll-bid-request-1.json | 5 +- .../test-cache-brightroll-request.json | 7 +- .../test-auction-colossus-response.json | 6 +- .../colossus/test-cache-colossus-request.json | 12 +- .../colossus/test-colossus-bid-request-1.json | 9 +- .../colossus/test-colossus-bid-request-2.json | 9 +- .../test-auction-connectad-response.json | 3 +- .../test-cache-connectad-request.json | 5 +- .../connectad/test-connectad-bid-request.json | 9 +- .../test-auction-consumable-response.json | 3 +- .../test-cache-consumable-request.json | 7 +- .../test-auction-conversant-response.json | 3 +- .../alias/test-cache-conversant-request.json | 7 +- .../alias/test-conversant-bid-request.json | 5 +- .../test-auction-conversant-response.json | 6 +- .../test-cache-conversant-request.json | 12 +- .../test-conversant-bid-request.json | 5 +- .../test-auction-cpmstar-response.json | 6 +- .../cpmstar/test-cache-cpmstar-request.json | 12 +- .../cpmstar/test-cpmstar-bid-request-1.json | 16 +- .../test-auction-datablocks-request.json | 3 +- .../test-auction-datablocks-response.json | 144 +- .../test-cache-datablocks-request.json | 11 +- .../test-datablocks-bid-request-1.json | 8 +- .../test-datablocks-bid-request-2.json | 8 +- .../test-auction-decenterads-request.json | 83 + .../test-auction-decenterads-response.json | 107 + .../test-cache-decenterads-request.json | 47 + .../test-cache-matcher-decenterads.json | 5 + .../test-decenterads-bid-request-1.json | 82 + .../test-decenterads-bid-request-2.json | 81 + .../test-decenterads-bid-response-1.json | 19 + .../test-decenterads-bid-response-2.json | 27 + .../test-auction-deepintent-request.json | 6 +- .../test-auction-deepintent-response.json | 3 +- .../test-cache-deepintent-request.json | 5 +- .../test-deepintent-bid-request.json | 12 +- .../dmx/test-auction-dmx-request.json | 17 +- .../dmx/test-auction-dmx-response.json | 5 +- .../openrtb2/dmx/test-cache-dmx-request.json | 5 +- .../it/openrtb2/dmx/test-dmx-bid-request.json | 13 +- .../test-auction-emxdigital-response.json | 13 +- .../test-cache-emxdigital-request.json | 6 +- .../test-emxdigital-bid-request.json | 5 +- .../test-auction-engagebdr-request.json | 2 +- .../test-auction-engagebdr-response.json | 8 +- .../test-cache-engagebdr-request.json | 12 +- .../test-engagebdr-bid-request-1.json | 5 +- .../test-engagebdr-bid-request-2.json | 5 +- .../test-engagebdr-bid-response-1.json | 2 +- .../test-engagebdr-bid-response-2.json | 2 +- .../test-auction-eplanning-response.json | 3 +- .../test-cache-eplanning-request.json | 7 +- .../epom/test-auction-epom-request.json | 72 + .../epom/test-auction-epom-response.json | 59 + .../epom/test-cache-epom-request.json | 21 + .../epom/test-cache-epom-response.json | 7 + .../epom/test-epom-bid-request-1.json | 86 + .../epom/test-epom-bid-response-1.json | 20 + .../test-auction-facebook-response.json | 9 +- .../facebook/test-cache-facebook-request.json | 15 +- .../gamma/test-auction-gamma-response.json | 4 +- .../gamma/test-cache-gamma-request.json | 6 +- .../test-auction-gamoshi-response.json | 6 +- .../gamoshi/test-cache-gamoshi-request.json | 12 +- .../gamoshi/test-gamoshi-bid-request-1.json | 5 +- .../grid/test-auction-grid-response.json | 3 +- .../grid/test-cache-grid-request.json | 7 +- .../grid/test-grid-bid-request-1.json | 5 +- .../gumgum/test-auction-gumgum-request.json | 7 +- .../gumgum/test-auction-gumgum-response.json | 6 +- .../gumgum/test-cache-gumgum-request.json | 12 +- .../gumgum/test-gumgum-bid-request-1.json | 15 +- .../test-auction-improvedigital-response.json | 3 +- .../test-cache-improvedigital-request.json | 7 +- .../test-improvedigital-bid-request-1.json | 5 +- .../inmobi/test-auction-inmobi-response.json | 3 +- .../inmobi/test-cache-inmobi-request.json | 7 +- .../inmobi/test-inmobi-bid-request.json | 11 +- .../test-auction-invibes-response.json | 86 +- .../invibes/test-cache-invibes-request.json | 14 +- .../invibes/test-invibes-bid-request.json | 16 +- .../openrtb2/ix/test-auction-ix-request.json | 2 +- .../openrtb2/ix/test-auction-ix-response.json | 11 +- .../it/openrtb2/ix/test-cache-ix-request.json | 7 +- .../it/openrtb2/ix/test-ix-bid-request-1.json | 7 +- .../it/openrtb2/ix/test-ix-bid-request-2.json | 7 +- .../jixie/test-auction-jixie-request.json | 57 + .../jixie/test-auction-jixie-response.json | 59 + .../jixie/test-cache-jixie-request.json | 21 + .../jixie/test-cache-jixie-response.json | 7 + .../jixie/test-jixie-bid-request.json | 68 + .../jixie/test-jixie-bid-response.json | 20 + .../kidoz/test-auction-kidoz-response.json | 6 +- .../kidoz/test-cache-kidoz-request.json | 12 +- .../kidoz/test-kidoz-bid-request-1.json | 5 +- .../kidoz/test-kidoz-bid-request-2.json | 25 +- .../test-auction-krushmedia-response.json | 3 +- .../test-cache-krushmedia-request.json | 5 +- .../test-krushmedia-bid-request.json | 5 +- .../kubient/test-auction-kubient-request.json | 1 - .../test-auction-kubient-response.json | 115 +- .../kubient/test-cache-kubient-request.json | 9 +- .../kubient/test-kubient-bid-request-1.json | 8 +- .../kubient/test-kubient-bid-response-1.json | 4 +- .../test-auction-lifestreet-response.json | 6 +- .../test-cache-lifestreet-request.json | 12 +- .../test-lifestreet-bid-request-1.json | 5 +- .../test-lifestreet-bid-request-2.json | 5 +- .../test-auction-lockerdome-response.json | 3 +- .../test-cache-lockerdome-request.json | 7 +- .../test-lockerdome-bid-request.json | 5 +- .../test-auction-logicad-response.json | 3 +- .../logicad/test-cache-logicad-request.json | 5 +- .../logicad/test-logicad-bid-request.json | 5 +- .../test-auction-lunamedia-response.json | 5 +- .../test-cache-lunamedia-request.json | 7 +- .../test-auction-marsmedia-response.json | 3 +- .../test-cache-marsmedia-request.json | 7 +- .../test-marsmedia-bid-request-1.json | 5 +- .../mgid/test-auction-mgid-response.json | 1 + .../mgid/test-cache-mgid-request.json | 5 +- .../openrtb2/mgid/test-mgid-bid-request.json | 5 +- .../test-auction-mobfoxpb-request.json | 6 +- .../test-auction-mobfoxpb-response.json | 1 + .../mobfoxpb/test-cache-mobfoxpb-request.json | 3 +- .../mobfoxpb/test-mobfoxpb-bid-request-1.json | 6 +- .../test-auction-mobilefuse-response.json | 5 +- .../test-cache-mobilefuse-request.json | 5 +- .../test-mobilefuse-bid-request.json | 3 +- .../test-auction-nanointeractive-request.json | 10 +- ...test-auction-nanointeractive-response.json | 3 +- .../test-cache-nanointeractive-request.json | 7 +- .../test-nanointeractive-bid-request-1.json | 5 +- .../test-auction-ninthdecimal-response.json | 3 +- .../test-cache-ninthdecimal-request.json | 5 +- .../nobid/test-auction-nobid-response.json | 3 +- .../nobid/test-cache-nobid-request.json | 5 +- .../nobid/test-nobid-bid-request.json | 9 +- .../onetag/test-auction-onetag-request.json | 66 + .../onetag/test-auction-onetag-response.json | 54 + .../onetag/test-cache-onetag-request.json | 18 + .../onetag/test-cache-onetag-response.json | 7 + .../onetag/test-onetag-bid-request.json | 75 + .../onetag/test-onetag-bid-response.json | 18 + .../openx/test-auction-openx-request.json | 3 +- .../openx/test-auction-openx-response.json | 16 +- .../openx/test-cache-openx-request.json | 24 +- .../openx/test-openx-bid-request-1.json | 5 +- .../openx/test-openx-bid-request-2.json | 5 +- .../openx/test-openx-bid-request-3.json | 9 +- .../test-auction-orbidder-response.json | 5 +- .../orbidder/test-cache-orbidder-request.json | 5 +- .../orbidder/test-orbidder-bid-request.json | 5 +- .../test-auction-outbrain-request.json | 75 + .../test-auction-outbrain-response.json | 59 + .../outbrain/test-cache-outbrain-request.json | 21 + .../test-cache-outbrain-response.json | 7 + .../outbrain/test-outbrain-bid-request.json | 91 + .../outbrain/test-outbrain-bid-response.json | 20 + .../pangle/test-auction-pangle-request.json | 77 + .../pangle/test-auction-pangle-response.json | 62 + .../pangle/test-cache-matcher-pangle.json | 5 + .../pangle/test-cache-pangle-request.json | 22 + .../pangle/test-pangle-bid-request-1.json | 88 + .../pangle/test-pangle-bid-response-1.json | 24 + .../test-auction-pubmatic-request.json | 29 +- .../test-auction-pubmatic-response.json | 4 +- .../pubmatic/test-cache-pubmatic-request.json | 10 +- .../pubmatic/test-pubmatic-bid-request-1.json | 5 +- .../test-auction-pubnative-response.json | 9 +- .../test-cache-pubnative-request.json | 17 +- .../test-pubnative-bid-request-1.json | 5 +- .../test-pubnative-bid-request-2.json | 5 +- .../test-pubnative-bid-request-3.json | 5 +- .../test-auction-pulsepoint-response.json | 6 +- .../test-cache-pulsepoint-request.json | 12 +- .../test-pulsepoint-bid-request-1.json | 5 +- .../test-auction-revcontent-request.json | 2 +- .../test-auction-revcontent-response.json | 3 +- .../test-cache-revcontent-request.json | 5 +- .../test-revcontent-bid-request-1.json | 5 +- .../test-revcontent-bid-response-1.json | 26 +- .../test-auction-rhythmone-response.json | 3 +- .../test-cache-rhythmone-request.json | 7 +- .../test-rhythmone-bid-request-1.json | 5 +- .../test-auction-rtbhouse-request.json | 10 +- .../test-auction-rtbhouse-response.json | 3 +- .../rtbhouse/test-cache-rtbhouse-request.json | 5 +- .../rtbhouse/test-rtbhouse-bid-request-1.json | 9 +- .../test-rtbhouse-bid-response-1.json | 26 +- .../rubicon/test-auction-rubicon-request.json | 89 + .../test-auction-rubicon-response.json | 59 + .../rubicon/test-cache-rubicon-request.json | 21 + .../rubicon/test-cache-rubicon-response.json | 7 + .../rubicon/test-rubicon-bid-request.json | 120 + .../rubicon/test-rubicon-bid-response.json | 20 + .../test-appnexus-bid-request-1.json | 7 +- .../test-appnexus-bid-request-2.json | 7 +- ...test-auction-rubicon-appnexus-request.json | 2 +- ...est-auction-rubicon-appnexus-response.json | 43 +- .../test-cache-rubicon-appnexus-request.json | 28 +- .../test-rubicon-bid-request-1.json | 6 +- .../test-rubicon-bid-request-2.json | 6 +- .../test-appnexus-bid-request-1.json | 7 +- ...test-auction-rubicon-appnexus-request.json | 5 +- ...est-auction-rubicon-appnexus-response.json | 6 + .../test-cache-rubicon-appnexus-request.json | 18 +- .../test-rubicon-bid-request-1.json | 4 +- .../test-auction-rubicon-request.json | 57 + .../test-auction-rubicon-response.json | 59 + .../test-cache-rubicon-request.json | 21 + .../test-cache-rubicon-response.json | 7 + .../test-rubicon-bid-request.json | 65 + .../test-rubicon-bid-response.json | 20 + .../test-auction-sharethrough-response.json | 11 +- .../test-cache-sharethrough-request.json | 6 +- .../test-auction-silvermob-response.json | 3 +- .../test-cache-silvermob-request.json | 5 +- .../silvermob/test-silvermob-bid-request.json | 5 +- .../smaato/test-auction-smaato-response.json | 5 +- .../smaato/test-cache-smaato-request.json | 5 +- .../smaato/test-smaato-bid-request.json | 3 +- .../test-auction-smartadserver-response.json | 12 +- .../test-cache-smartadserver-request.json | 9 +- .../test-smartadserver-bid-request-1.json | 10 +- .../test-smartadserver-bid-response-1.json | 4 +- .../test-auction-smartrtb-response.json | 3 +- .../smartrtb/test-cache-smartrtb-request.json | 7 +- .../smartrtb/test-smartrtb-bid-request.json | 3 +- .../test-auction-smartyads-request.json | 2 +- .../test-auction-smartyads-response.json | 3 +- .../test-cache-smartyads-request.json | 5 +- .../smartyads/test-smartyads-bid-request.json | 5 +- .../test-auction-somoaudience-response.json | 12 +- .../test-cache-matcher-somoaudience.json | 12 +- .../test-cache-somoaudience-request.json | 22 +- .../test-somoaudience-bid-request-1.json | 5 +- .../test-somoaudience-bid-request-2.json | 5 +- .../test-somoaudience-bid-request-3.json | 5 +- .../sonobi/test-auction-sonobi-response.json | 6 +- .../sonobi/test-cache-sonobi-request.json | 12 +- .../sonobi/test-sonobi-bid-request-1.json | 5 +- .../sonobi/test-sonobi-bid-request-2.json | 5 +- .../sovrn/test-auction-sovrn-response.json | 3 +- .../sovrn/test-cache-sovrn-request.json | 7 +- .../sovrn/test-sovrn-bid-request-1.json | 5 +- .../storedresponse/test-auction-response.json | 3 +- .../storedresponse/test-cache-request.json | 7 +- .../test-auction-synacormedia-request.json | 6 +- .../test-auction-synacormedia-response.json | 6 +- .../test-cache-synacormedia-request.json | 11 +- .../test-synacormedia-bid-request.json | 5 +- .../tappx/test-auction-tappx-response.json | 3 +- .../tappx/test-cache-tappx-request.json | 13 +- .../tappx/test-tappx-bid-request.json | 5 +- .../tappx/test-tappx-bid-response.json | 32 +- .../test-auction-telaria-response.json | 1 + .../telaria/test-cache-telaria-request.json | 9 +- .../telaria/test-telaria-bid-request-1.json | 3 +- .../telaria/test-telaria-bid-response-1.json | 4 +- .../test-auction-triplelift-response.json | 2 + .../test-cache-triplelift-request.json | 6 +- .../test-triplelift-bid-request.json | 5 +- ...est-auction-triplelift-native-request.json | 1 - ...st-auction-triplelift-native-response.json | 109 +- .../test-cache-triplelift-native-request.json | 6 +- .../test-triplelift-native-bid-request.json | 8 +- .../ttx/test-auction-ttx-request.json | 3 - .../ttx/test-auction-ttx-response.json | 5 +- .../openrtb2/ttx/test-cache-ttx-request.json | 7 +- .../openrtb2/ttx/test-ttx-bid-request-1.json | 8 +- .../openrtb2/ttx/test-ttx-bid-response-1.json | 2 +- .../test-auction-ucfunnel-response.json | 3 +- .../ucfunnel/test-cache-ucfunnel-request.json | 7 +- .../ucfunnel/test-ucfunnel-bid-request.json | 5 +- .../unicorn/test-auction-unicorn-request.json | 63 + .../test-auction-unicorn-response.json | 59 + .../unicorn/test-cache-unicorn-request.json | 21 + .../unicorn/test-cache-unicorn-response.json | 7 + .../unicorn/test-unicorn-bid-request.json | 82 + .../unicorn/test-unicorn-bid-response.json | 20 + .../unruly/test-auction-unruly-response.json | 6 +- .../unruly/test-cache-unruly-request.json | 12 +- .../unruly/test-unruly-bid-request-1.json | 5 +- .../unruly/test-unruly-bid-request-2.json | 5 +- ...test-auction-valueimpression-response.json | 6 +- .../test-cache-valueimpression-request.json | 12 +- .../test-valueimpression-bid-request-1.json | 5 +- .../test-auction-verizonmedia-response.json | 3 +- .../test-cache-verizonmedia-request.json | 7 +- .../test-verizonmedia-bid-request-1.json | 5 +- .../test-video-appnexus-bid-request-1.json | 3 + .../test-video-appnexus-bid-request-2.json | 3 + .../visx/test-auction-visx-response.json | 4 +- .../visx/test-cache-visx-request.json | 8 +- .../openrtb2/visx/test-visx-bid-request.json | 5 +- .../vrtcal/test-auction-vrtcal-response.json | 3 +- .../vrtcal/test-cache-vrtcal-request.json | 7 +- .../test-auction-yeahmobi-response.json | 5 +- .../yeahmobi/test-cache-yeahmobi-request.json | 5 +- .../yeahmobi/test-yeahmobi-bid-request.json | 3 +- .../test-auction-yieldlab-response.json | 7 +- .../yieldlab/test-cache-yieldlab-request.json | 8 +- .../test-auction-yieldmo-response.json | 3 +- .../yieldmo/test-cache-yieldmo-request.json | 7 +- .../yieldmo/test-yieldmo-bid-request-1.json | 5 +- .../test-auction-yieldone-response.json | 3 +- .../yieldone/test-cache-yieldone-request.json | 5 +- .../yieldone/test-yieldone-bid-request.json | 5 +- .../test-auction-zeroclickfraud-request.json | 3 +- .../test-auction-zeroclickfraud-response.json | 154 +- .../test-cache-zeroclickfraud-request.json | 11 +- .../test-zeroclickfraud-bid-request-1.json | 8 +- .../test-zeroclickfraud-bid-request-2.json | 8 +- ...est-rubicon-stored-video-cache-update.json | 4 +- .../test-video-stored-imp-request-1.json | 8 +- .../test-video-stored-imp-request-2.json | 8 +- .../server/it/test-application.properties | 46 +- .../validation/schema/invalid/rubicon.json | 2 +- 892 files changed, 20339 insertions(+), 7913 deletions(-) create mode 100644 src/main/java/org/prebid/server/auction/model/BidderResponseInfo.java create mode 100644 src/main/java/org/prebid/server/auction/model/TargetingInfo.java rename src/main/java/org/prebid/server/auction/{ => requestfactory}/AmpRequestFactory.java (92%) create mode 100644 src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java rename src/main/java/org/prebid/server/auction/{AuctionRequestFactory.java => requestfactory/Ortb2ImplicitParametersResolver.java} (57%) create mode 100644 src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java rename src/main/java/org/prebid/server/auction/{ => requestfactory}/VideoRequestFactory.java (65%) create mode 100644 src/main/java/org/prebid/server/bidder/BidderInstanceDeps.java create mode 100644 src/main/java/org/prebid/server/bidder/UsersyncMethodChooser.java create mode 100644 src/main/java/org/prebid/server/bidder/UsersyncUtil.java create mode 100644 src/main/java/org/prebid/server/bidder/adhese/model/AdheseRequestBody.java rename src/main/java/org/prebid/server/bidder/adoppler/model/{AdopplerResponseVideoExt.java => AdopplerResponseAdsExt.java} (82%) create mode 100644 src/main/java/org/prebid/server/bidder/adyoulike/AdyoulikeBidder.java create mode 100644 src/main/java/org/prebid/server/bidder/decenterads/DecenteradsBidder.java create mode 100644 src/main/java/org/prebid/server/bidder/epom/EpomBidder.java create mode 100644 src/main/java/org/prebid/server/bidder/jixie/JixieBidder.java create mode 100644 src/main/java/org/prebid/server/bidder/model/BidderSeatBidInfo.java create mode 100644 src/main/java/org/prebid/server/bidder/onetag/OnetagBidder.java create mode 100644 src/main/java/org/prebid/server/bidder/outbrain/OutbrainBidder.java create mode 100644 src/main/java/org/prebid/server/bidder/pangle/PangleBidder.java create mode 100644 src/main/java/org/prebid/server/bidder/pangle/model/BidExt.java create mode 100644 src/main/java/org/prebid/server/bidder/pangle/model/PangleBidExt.java create mode 100644 src/main/java/org/prebid/server/bidder/pangle/model/WrappedImpExtBidder.java create mode 100644 src/main/java/org/prebid/server/bidder/unicorn/UnicornBidder.java create mode 100644 src/main/java/org/prebid/server/bidder/unicorn/model/UnicornImpExt.java create mode 100644 src/main/java/org/prebid/server/bidder/unicorn/model/UnicornImpExtContext.java create mode 100644 src/main/java/org/prebid/server/json/IntegerFlagDeserializer.java rename src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/{Purpose.java => PurposeCode.java} (86%) create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/request/BidAdjustmentMediaType.java create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestBidadjustmentfactors.java create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/request/adyoulike/ExtImpAdyoulike.java create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/request/decenterads/ExtImpDecenterads.java create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/request/gumgum/ExtImpGumgumVideo.java create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/request/jixie/ExtImpJixie.java create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/request/onetag/ExtImpOnetag.java create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/request/outbrains/ExtImpOutbrain.java create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/request/outbrains/ExtImpOutbrainPublisher.java create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/request/pangle/ExtImpPangle.java create mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/request/unicorn/ExtImpUnicorn.java create mode 100644 src/main/java/org/prebid/server/spring/config/bidder/AdyoulikeConfiguration.java create mode 100644 src/main/java/org/prebid/server/spring/config/bidder/DecenteradsConfiguration.java create mode 100644 src/main/java/org/prebid/server/spring/config/bidder/EpomConfiguration.java create mode 100644 src/main/java/org/prebid/server/spring/config/bidder/JixieConfiguration.java create mode 100644 src/main/java/org/prebid/server/spring/config/bidder/OnetagConfiguration.java create mode 100644 src/main/java/org/prebid/server/spring/config/bidder/OutbrainConfiguration.java create mode 100644 src/main/java/org/prebid/server/spring/config/bidder/PangleConfiguration.java create mode 100644 src/main/java/org/prebid/server/spring/config/bidder/UnicornConfiguration.java create mode 100644 src/main/resources/bidder-config/adyoulike.yaml create mode 100644 src/main/resources/bidder-config/decenterads.yaml create mode 100644 src/main/resources/bidder-config/epom.yaml create mode 100644 src/main/resources/bidder-config/jixie.yaml create mode 100644 src/main/resources/bidder-config/onetag.yaml create mode 100644 src/main/resources/bidder-config/outbrain.yaml create mode 100644 src/main/resources/bidder-config/pangle.yaml create mode 100644 src/main/resources/bidder-config/unicorn.yaml create mode 100644 src/main/resources/static/bidder-params/adyoulike.json create mode 100644 src/main/resources/static/bidder-params/decenterads.json create mode 100644 src/main/resources/static/bidder-params/epom.json create mode 100644 src/main/resources/static/bidder-params/jixie.json create mode 100644 src/main/resources/static/bidder-params/onetag.json create mode 100644 src/main/resources/static/bidder-params/outbrain.json create mode 100644 src/main/resources/static/bidder-params/pangle.json create mode 100644 src/main/resources/static/bidder-params/unicorn.json delete mode 100644 src/test/java/org/prebid/server/auction/AuctionRequestFactoryTest.java rename src/test/java/org/prebid/server/auction/{ => requestfactory}/AmpRequestFactoryTest.java (84%) create mode 100644 src/test/java/org/prebid/server/auction/requestfactory/AuctionRequestFactoryTest.java create mode 100644 src/test/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolverTest.java create mode 100644 src/test/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactoryTest.java rename src/test/java/org/prebid/server/auction/{ => requestfactory}/VideoRequestFactoryTest.java (64%) create mode 100644 src/test/java/org/prebid/server/bidder/UsersyncMethodChooserTest.java create mode 100644 src/test/java/org/prebid/server/bidder/UsersyncUtilTest.java delete mode 100644 src/test/java/org/prebid/server/bidder/UsersyncerTest.java create mode 100644 src/test/java/org/prebid/server/bidder/adyoulike/AdyoulikeBidderTest.java create mode 100644 src/test/java/org/prebid/server/bidder/decenterads/DecenteradsBidderTest.java create mode 100644 src/test/java/org/prebid/server/bidder/epom/EpomBidderTest.java create mode 100644 src/test/java/org/prebid/server/bidder/jixie/JixieBidderTest.java create mode 100644 src/test/java/org/prebid/server/bidder/onetag/OnetagBidderTest.java create mode 100644 src/test/java/org/prebid/server/bidder/outbrain/OutbrainBidderTest.java create mode 100644 src/test/java/org/prebid/server/bidder/pangle/PangleBidderTest.java create mode 100644 src/test/java/org/prebid/server/bidder/unicorn/UnicornBidderTest.java create mode 100644 src/test/java/org/prebid/server/it/AdyoulikeTest.java create mode 100644 src/test/java/org/prebid/server/it/DecenteradsTest.java create mode 100644 src/test/java/org/prebid/server/it/EpomTest.java create mode 100644 src/test/java/org/prebid/server/it/JixieTest.java create mode 100644 src/test/java/org/prebid/server/it/OnetagTest.java create mode 100644 src/test/java/org/prebid/server/it/OutbrainTest.java create mode 100644 src/test/java/org/prebid/server/it/PangleTest.java create mode 100644 src/test/java/org/prebid/server/it/RubiconTest.java create mode 100644 src/test/java/org/prebid/server/it/UnicornTest.java create mode 100644 src/test/java/org/prebid/server/json/IntegerFlagDeserializerTest.java create mode 100644 src/test/java/org/prebid/server/spring/config/bidder/util/UsersyncerCreatorTest.java create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-adyoulike-bid-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-adyoulike-bid-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-auction-adyoulike-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-auction-adyoulike-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-cache-adyoulike-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-cache-adyoulike-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-auction-decenterads-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-auction-decenterads-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-cache-decenterads-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-cache-matcher-decenterads.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-decenterads-bid-request-1.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-decenterads-bid-request-2.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-decenterads-bid-response-1.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-decenterads-bid-response-2.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/epom/test-auction-epom-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/epom/test-auction-epom-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/epom/test-cache-epom-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/epom/test-cache-epom-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/epom/test-epom-bid-request-1.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/epom/test-epom-bid-response-1.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/jixie/test-auction-jixie-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/jixie/test-auction-jixie-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/jixie/test-cache-jixie-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/jixie/test-cache-jixie-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/jixie/test-jixie-bid-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/jixie/test-jixie-bid-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/onetag/test-auction-onetag-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/onetag/test-auction-onetag-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/onetag/test-cache-onetag-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/onetag/test-cache-onetag-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/onetag/test-onetag-bid-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/onetag/test-onetag-bid-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-auction-outbrain-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-auction-outbrain-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-cache-outbrain-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-cache-outbrain-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-outbrain-bid-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-outbrain-bid-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/pangle/test-auction-pangle-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/pangle/test-auction-pangle-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/pangle/test-cache-matcher-pangle.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/pangle/test-cache-pangle-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/pangle/test-pangle-bid-request-1.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/pangle/test-pangle-bid-response-1.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/rubicon/test-auction-rubicon-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/rubicon/test-auction-rubicon-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/rubicon/test-cache-rubicon-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/rubicon/test-cache-rubicon-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/rubicon/test-rubicon-bid-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/rubicon/test-rubicon-bid-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-auction-rubicon-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-auction-rubicon-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-cache-rubicon-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-cache-rubicon-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-rubicon-bid-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-rubicon-bid-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-auction-unicorn-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-auction-unicorn-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-cache-unicorn-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-cache-unicorn-response.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-unicorn-bid-request.json create mode 100644 src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-unicorn-bid-response.json diff --git a/docs/config-app.md b/docs/config-app.md index fcb77fbfc3f..86c033afacb 100644 --- a/docs/config-app.md +++ b/docs/config-app.md @@ -118,16 +118,30 @@ Removes and downloads file again if depending service cant process probably corr There are several typical keys: - `adapters..enabled` - indicates the bidder should be active and ready for auction. By default all bidders are disabled. - `adapters..endpoint` - the url for submitting bids. -- `adapters..pbs-enforces-gdpr` - indicates if pbs server provides gdpr support for bidder or bidder will handle it itself. +- `adapters..pbs-enforces-gdpr` - indicates if PBS server provides GDPR support for bidder or bidder will handle it itself. +- `adapters..pbs-enforces-ccpa` - indicates if PBS server provides CCPA support for bidder or bidder will handle it itself. +- `adapters..modifying-vast-xml-allowed` - indicates if PBS server is allowed to modify VAST creatives received from this bidder. - `adapters..deprecated-names` - comma separated deprecated names of bidder. -- `adapters..aliases` - comma separated aliases of bidder. +- `adapters..meta-info.maintainer-email` - specifies maintainer e-mail address that will be shown in bidder info endpoint response. +- `adapters..meta-info.app-media-types` - specifies media types supported for app requests that will be shown in bidder info endpoint response. +- `adapters..meta-info.site-media-types` - specifies media types supported for site requests that will be shown in bidder info endpoint response. +- `adapters..meta-info.supported-vendors` - specifies viewability vendors supported by the bidder. +- `adapters..meta-info.vendor-id` - specifies TCF vendor ID. - `adapters..usersync.url` - the url for synchronizing UIDs cookie. - `adapters..usersync.redirect-url` - the redirect part of url for synchronizing UIDs cookie. - `adapters..usersync.cookie-family-name` - the family name by which user ids within adapter's realm are stored in uidsCookie. - `adapters..usersync.type` - usersync type (i.e. redirect, iframe). - `adapters..usersync.support-cors` - flag signals if CORS supported by usersync. -But feel free to add additional bidder's specific options. +In addition, each bidder could have arbitrary aliases configured that will look and act very much the same as the bidder itself. +Aliases are configured by adding child configuration object at `adapters..aliases..`, aliases +support the same configuration options that their bidder counterparts support except `aliases` (i.e. it's not possible +to declare alias of an alias). Another restriction of aliases configuration is that they cannot declare support for media types +not supported by their bidders (however aliases could narrow down media types they support). For example: if the bidder +is written to not support native site requests, then an alias cannot magically decide to change that; however, if a bidder +supports native site requests, and the alias does not want to for some reason, it has the ability to remove that support. + +Also, each bidder could have its own bidder-specific options. ## Logging - `logging.http-interaction.max-limit` - maximum value for the number of interactions to log in one take. diff --git a/docs/developers/add-new-bidder.md b/docs/developers/add-new-bidder.md index 74ba1fc9504..b2361533b49 100644 --- a/docs/developers/add-new-bidder.md +++ b/docs/developers/add-new-bidder.md @@ -23,7 +23,7 @@ your bidder will access them at `request.imp[i].ext.bidder`--regardless of what ## Configuration Add default configuration properties and metadata(e.g. contact email, platform & media type support) for your Bidder to `src/main/resources/bidder-config/{bidder}.yaml` file. -For more information about application configuration see [here](../config.md) +For more information about application configuration see [here](../config-app.md) ## Implementation @@ -100,7 +100,8 @@ It should be public class with Spring `@Configuration` annotation so that framew This file consists of three main parts: - the constant `BIDDER_NAME` with the name of your Bidder. - injected configuration properties (like `endpoint`, `usersyncUrl`, etc) needed for the Bidder's implementation. -- declaration of `BidderDeps` bean combining _bidder name_, _Usersyncer_ and _BidderRequester_ in one place as a single point-of-truth for using it in application. +- declaration of `BidderDeps` bean combining _bidder name_, _Usersyncer_, _Adapter_, _Bidder_ and other meta-data +for the bidder and its aliases in one place as a single point-of-truth for using it in application. Also, you can add `@ConditionalOnProperty` annotation on configuration if bidder has no default properties. See `src/main/java/org/prebid/server/spring/config/bidder/FacebookConfiguration.java` as an example. @@ -122,7 +123,7 @@ Commonly you should write tests for covering: - specific cases for composing requests to exchange. - specific cases for processing responses from exchange. -Do not forget to add your Bidder to `ApplicationTest.java` tests. +Do not forget to add integration test for your Bidder in `src/test/java/org/prebid/server/it`. We expect to see at least 90% code coverage on each bidder. diff --git a/docs/endpoints/cookieSync.md b/docs/endpoints/cookieSync.md index 47f028521b6..56f87aeb2ce 100644 --- a/docs/endpoints/cookieSync.md +++ b/docs/endpoints/cookieSync.md @@ -9,13 +9,23 @@ This endpoint is used during cookie syncs. For technical details, see the This returns a set of URLs to enable cookie syncs across bidders. (See Prebid.js documentation?) The request must supply a JSON object to define the list of bidders that may need to be synced. -``` +```json { "bidders": ["appnexus", "rubicon"], "coopSync": true, "gdpr": 1, "gdpr_consent": "BONV8oqONXwgmADACHENAO7pqzAAppY", - "limit": 2 + "limit": 2, + "filterSettings": { + "iframe": { + "bidders": ["rubicon"], // only this bidder is excluded from syncing iframe pixels, all other bidders are allowed + "filter": "exclude" + }, + "image": { + "bidders": ["appnexus"], //only this bidder is allowed to sync image pixels + "filter": "include" + } + } } ``` @@ -31,6 +41,8 @@ must supply a JSON object to define the list of bidders that may need to be sync get the count down to limit if more would otherwise have been returned. This is to facilitate clients not overloading a user with syncs the first time they are encountered. +`filterSettings` is optional. It defines which bidders are allowed to use which usersync method. + If `gdpr` is omitted, callers are still encouraged to send `gdpr_consent` if they have it. Depending on how the Prebid Server host company has configured their servers, they may or may not require it for cookie syncs. diff --git a/docs/endpoints/setuid.md b/docs/endpoints/setuid.md index 5d19295f225..fa8199f05b7 100644 --- a/docs/endpoints/setuid.md +++ b/docs/endpoints/setuid.md @@ -13,7 +13,7 @@ This endpoint saves a UserID for a Bidder in the Cookie. Saved IDs will be recog - `uid`: The ID which the Bidder uses to recognize this user. If undefined, the UID for `bidder` will be deleted. - `gdpr`: This should be `1` if GDPR is in effect, `0` if not, and undefined if the caller isn't sure - `gdpr_consent`: This is required if `gdpr` is one, and optional (but encouraged) otherwise. If present, it should be an [unpadded base64-URL](https://tools.ietf.org/html/rfc4648#page-7) encoded [Vendor Consent String](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/Consent%20string%20and%20vendor%20list%20formats%20v1.1%20Final.md#vendor-consent-string-format-). -- `format`: is optional. When `format=img`, response will include `tracking-pixel.png` file. +- `f`: is optional. When `f=i`, response will include `tracking-pixel.png` file, when `f=b` respond with empty html, content-length=0 and text/html content type. If the `gdpr` and `gdpr_consent` params are included, this endpoint will _not_ write a cookie unless: diff --git a/docs/metrics.md b/docs/metrics.md index 189a5b242c8..ca185af5257 100644 --- a/docs/metrics.md +++ b/docs/metrics.md @@ -115,6 +115,8 @@ Following metrics are collected and submitted if account is configured with `det - `usersync.bad_requests` - number of requests received with bidder not specified - `usersync..sets` - number of requests received resulted in `uid` cookie update for `` - `usersync..tcf.blocked` - number of requests received that didn't result in `uid` cookie update for `` because of lack of user consent for this action according to TCF +- `usersync..tcf.invalid` - number of requests received that are lacking of a valid consent string for `` in setuid endpoint +- `usersync.all.tcf.invalid` - number of requests received that are lacking of a valid consent string for all requested bidders cookieSync endpoint ## Privacy metrics - `privacy.tcf.(missing|invalid)` - number of requests lacking a valid consent string diff --git a/pom.xml b/pom.xml index b170cd2c2ae..93d25992b22 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.prebid prebid-server - 1.61.0-SNAPSHOT + 1.65.0-SNAPSHOT prebid-server Prebid Server (Server-side Header Bidding) diff --git a/src/main/java/com/iab/openrtb/response/Bid.java b/src/main/java/com/iab/openrtb/response/Bid.java index 3e7922afa72..54ea0bbe945 100644 --- a/src/main/java/com/iab/openrtb/response/Bid.java +++ b/src/main/java/com/iab/openrtb/response/Bid.java @@ -1,9 +1,8 @@ package com.iab.openrtb.response; import com.fasterxml.jackson.databind.node.ObjectNode; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.experimental.SuperBuilder; +import lombok.Builder; +import lombok.Value; import java.math.BigDecimal; import java.util.List; @@ -13,22 +12,19 @@ * relates to a specific impression in the bid request via the {@code impid} * attribute and constitutes an offer to buy that impression for a given * {@code price}. - *

- * IMPORTANT: unlike other data classes this one is mutable (annotated with {@link Data} instead of - * {@link lombok.Value}). Motivation: during the course of processing bids could be altered several times (price - * adjustment, post-processing). Creating new instance of the bid in each of these cases seems to cause unnecessary - * memory pressure. In order to avoid unnecessary allocations this class is made mutable (as an exception) i.e. this - * decision could be seen as a performance optimisation. */ -@SuperBuilder(toBuilder = true) -@NoArgsConstructor -@Data +@Builder(toBuilder = true) +@Value public class Bid { - /** Bidder generated bid ID to assist with logging/tracking. (required) */ + /** + * Bidder generated bid ID to assist with logging/tracking. (required) + */ String id; - /** ID of the Imp object in the related bid request. (required) */ + /** + * ID of the Imp object in the related bid request. (required) + */ String impid; /** @@ -72,7 +68,9 @@ public class Bid { */ String adm; - /** ID of a preloaded ad to be served if the bid wins. */ + /** + * ID of a preloaded ad to be served if the bid wins. + */ String adid; /** @@ -110,19 +108,29 @@ public class Bid { */ String crid; - /** IAB content categories of the creative. Refer to List 5.1. */ + /** + * IAB content categories of the creative. Refer to List 5.1. + */ List cat; - /** Set of attributes describing the creative. Refer to List 5.3. */ + /** + * Set of attributes describing the creative. Refer to List 5.3. + */ List attr; - /** API required by the markup if applicable. Refer to List 5.6. */ + /** + * API required by the markup if applicable. Refer to List 5.6. + */ Integer api; - /** Video response protocol of the markup if applicable. Refer to List 5.8. */ + /** + * Video response protocol of the markup if applicable. Refer to List 5.8. + */ Integer protocol; - /** Creative media rating per IQG guidelines. Refer to List 5.19. */ + /** + * Creative media rating per IQG guidelines. Refer to List 5.19. + */ Integer qagmediarating; /** @@ -138,10 +146,14 @@ public class Bid { */ String dealid; - /** Width of the creative in device independent pixels (DIPS). */ + /** + * Width of the creative in device independent pixels (DIPS). + */ Integer w; - /** Height of the creative in device independent pixels (DIPS). */ + /** + * Height of the creative in device independent pixels (DIPS). + */ Integer h; /** @@ -162,6 +174,8 @@ public class Bid { */ Integer exp; - /** Placeholder for bidder-specific extensions to OpenRTB. */ + /** + * Placeholder for bidder-specific extensions to OpenRTB. + */ ObjectNode ext; } diff --git a/src/main/java/org/prebid/server/analytics/AnalyticsReporter.java b/src/main/java/org/prebid/server/analytics/AnalyticsReporter.java index 27d0f4c5c29..5e4a2f8aa58 100644 --- a/src/main/java/org/prebid/server/analytics/AnalyticsReporter.java +++ b/src/main/java/org/prebid/server/analytics/AnalyticsReporter.java @@ -17,4 +17,9 @@ public interface AnalyticsReporter { * Method for defining analytics reporter ID for TCF checks. */ int vendorId(); + + /** + * Method for defining name of the related to this analytic adapter. + */ + String name(); } diff --git a/src/main/java/org/prebid/server/analytics/AnalyticsReporterDelegator.java b/src/main/java/org/prebid/server/analytics/AnalyticsReporterDelegator.java index c754a7b1524..6e878fa653d 100644 --- a/src/main/java/org/prebid/server/analytics/AnalyticsReporterDelegator.java +++ b/src/main/java/org/prebid/server/analytics/AnalyticsReporterDelegator.java @@ -1,13 +1,26 @@ package org.prebid.server.analytics; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Site; import io.vertx.core.AsyncResult; import io.vertx.core.Vertx; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; +import org.apache.commons.collections4.CollectionUtils; +import org.prebid.server.analytics.model.AuctionEvent; import org.prebid.server.auction.PrivacyEnforcementService; +import org.prebid.server.auction.model.AuctionContext; +import org.prebid.server.log.ConditionalLogger; import org.prebid.server.privacy.gdpr.model.PrivacyEnforcementAction; import org.prebid.server.privacy.gdpr.model.TcfContext; +import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; +import org.prebid.server.util.StreamUtil; +import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; @@ -20,12 +33,15 @@ public class AnalyticsReporterDelegator { private static final Logger logger = LoggerFactory.getLogger(AnalyticsReporterDelegator.class); + private static final ConditionalLogger UNKNOWN_ADAPTERS_LOGGER = new ConditionalLogger(logger); + private static final Set ADAPTERS_PERMITTED_FOR_FULL_DATA = Collections.singleton("logAnalytics"); private final List delegates; private final Vertx vertx; private final PrivacyEnforcementService privacyEnforcementService; private final Set reporterVendorIds; + private final Set reporterNames; public AnalyticsReporterDelegator(List delegates, Vertx vertx, @@ -35,6 +51,7 @@ public AnalyticsReporterDelegator(List delegates, this.privacyEnforcementService = Objects.requireNonNull(privacyEnforcementService); reporterVendorIds = delegates.stream().map(AnalyticsReporter::vendorId).collect(Collectors.toSet()); + reporterNames = delegates.stream().map(AnalyticsReporter::name).collect(Collectors.toSet()); } public void processEvent(T event) { @@ -54,17 +71,18 @@ private void delegateEvent(T event, if (privacyEnforcementMapResult.succeeded()) { final Map privacyEnforcementActionMap = privacyEnforcementMapResult.result(); + checkUnknownAdaptersForAuctionEvent(event); for (AnalyticsReporter analyticsReporter : delegates) { + final T updatedEvent = updateEvent(event, analyticsReporter.name()); final int reporterVendorId = analyticsReporter.vendorId(); // resultForVendorIds is guaranteed returning for each provided value except null, // but to be sure lets use getOrDefault final PrivacyEnforcementAction reporterPrivacyAction = privacyEnforcementActionMap .getOrDefault(reporterVendorId, PrivacyEnforcementAction.restrictAll()); if (!reporterPrivacyAction.isBlockAnalyticsReport()) { - vertx.runOnContext(ignored -> analyticsReporter.processEvent(event)); + vertx.runOnContext(ignored -> analyticsReporter.processEvent(updatedEvent)); } } - } else { final Throwable privacyEnforcementException = privacyEnforcementMapResult.cause(); logger.error("Analytics TCF enforcement check failed for consentString: {0} and " @@ -72,4 +90,82 @@ private void delegateEvent(T event, tcfContext.getConsentString(), delegates); } } + + private void checkUnknownAdaptersForAuctionEvent(T event) { + if (event instanceof AuctionEvent) { + logUnknownAdapters((AuctionEvent) event); + } + } + + private void logUnknownAdapters(AuctionEvent auctionEvent) { + final BidRequest bidRequest = auctionEvent.getAuctionContext().getBidRequest(); + final ExtRequest extRequest = bidRequest.getExt(); + final ExtRequestPrebid extPrebid = extRequest != null ? extRequest.getPrebid() : null; + final ObjectNode analytics = extPrebid != null ? extPrebid.getAnalytics() : null; + final Iterator analyticsFieldNames = analytics != null && !analytics.isEmpty() + ? analytics.fieldNames() : null; + + if (analyticsFieldNames != null) { + final List unknownAdapterNames = StreamUtil.asStream(analyticsFieldNames) + .filter(adapter -> !reporterNames.contains(adapter)) + .collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(unknownAdapterNames)) { + final Site site = bidRequest.getSite(); + final String refererUrl = site != null ? site.getPage() : null; + UNKNOWN_ADAPTERS_LOGGER.warn( + String.format("Unknown adapters in ext.prebid.analytics[].adapter: %s, referrer: '%s'", + unknownAdapterNames, refererUrl), 0.01); + } + } + } + + private static T updateEvent(T event, String adapter) { + if (!ADAPTERS_PERMITTED_FOR_FULL_DATA.contains(adapter) && event instanceof AuctionEvent) { + final AuctionEvent auctionEvent = (AuctionEvent) event; + final AuctionContext updatedAuctionContext = + updateAuctionContextAdapter(auctionEvent.getAuctionContext(), adapter); + return updatedAuctionContext != null + ? (T) auctionEvent.toBuilder().auctionContext(updatedAuctionContext).build() + : event; + } + + return event; + } + + private static AuctionContext updateAuctionContextAdapter(AuctionContext context, String adapter) { + final BidRequest updatedBidRequest = updateBidRequest(context.getBidRequest(), adapter); + + return updatedBidRequest != null ? context.toBuilder().bidRequest(updatedBidRequest).build() : null; + } + + private static BidRequest updateBidRequest(BidRequest bidRequest, String adapterName) { + final ExtRequest requestExt = bidRequest.getExt(); + final ExtRequestPrebid extPrebid = requestExt != null ? requestExt.getPrebid() : null; + final ObjectNode analytics = extPrebid != null ? extPrebid.getAnalytics() : null; + ObjectNode preparedAnalytics = null; + if (analytics != null && !analytics.isEmpty()) { + preparedAnalytics = prepareAnalytics(analytics, adapterName); + } + final ExtRequest updatedExtRequest = preparedAnalytics != null ? ExtRequest.of(extPrebid.toBuilder() + .analytics(preparedAnalytics) + .build()) : null; + + if (updatedExtRequest != null) { + updatedExtRequest.addProperties(requestExt.getProperties()); + return bidRequest.toBuilder().ext(updatedExtRequest).build(); + } + + return null; + } + + private static ObjectNode prepareAnalytics(ObjectNode analytics, String adapterName) { + final ObjectNode analyticsNodeCopy = analytics.deepCopy(); + final JsonNode adapterNode = analyticsNodeCopy.get(adapterName); + analyticsNodeCopy.removeAll(); + if (adapterNode != null) { + analyticsNodeCopy.set(adapterName, adapterNode); + } + + return !analyticsNodeCopy.isEmpty() ? analyticsNodeCopy : null; + } } diff --git a/src/main/java/org/prebid/server/analytics/LogAnalyticsReporter.java b/src/main/java/org/prebid/server/analytics/LogAnalyticsReporter.java index 09a4b4cac92..d42221fd6f1 100644 --- a/src/main/java/org/prebid/server/analytics/LogAnalyticsReporter.java +++ b/src/main/java/org/prebid/server/analytics/LogAnalyticsReporter.java @@ -56,6 +56,11 @@ public int vendorId() { return 0; } + @Override + public String name() { + return "logAnalytics"; + } + @AllArgsConstructor @Value private static class LogEvent { diff --git a/src/main/java/org/prebid/server/analytics/model/AuctionEvent.java b/src/main/java/org/prebid/server/analytics/model/AuctionEvent.java index 6c6eb656864..5773ab30ffe 100644 --- a/src/main/java/org/prebid/server/analytics/model/AuctionEvent.java +++ b/src/main/java/org/prebid/server/analytics/model/AuctionEvent.java @@ -10,7 +10,7 @@ /** * Represents a transaction at /openrtb2/auction endpoint. */ -@Builder +@Builder(toBuilder = true) @Value public class AuctionEvent { diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index f624248a5c1..685d5e27180 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -27,11 +27,14 @@ import org.prebid.server.auction.model.BidInfo; import org.prebid.server.auction.model.BidRequestCacheInfo; import org.prebid.server.auction.model.BidderResponse; +import org.prebid.server.auction.model.BidderResponseInfo; import org.prebid.server.auction.model.MultiBidConfig; -import org.prebid.server.auction.model.TargetingBidInfo; +import org.prebid.server.auction.model.TargetingInfo; import org.prebid.server.bidder.BidderCatalog; +import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderError; import org.prebid.server.bidder.model.BidderSeatBid; +import org.prebid.server.bidder.model.BidderSeatBidInfo; import org.prebid.server.cache.CacheService; import org.prebid.server.cache.model.CacheContext; import org.prebid.server.cache.model.CacheInfo; @@ -98,6 +101,8 @@ public class BidResponseCreator { private static final String CACHE = "cache"; private static final String PREBID_EXT = "prebid"; + private static final String ORIGINAL_BID_CPM = "origbidcpm"; + private static final String ORIGINAL_BID_CURRENCY = "origbidcur"; private static final String SKADN_PROPERTY = "skadn"; private static final Integer DEFAULT_BID_LIMIT_MIN = 1; @@ -143,6 +148,13 @@ public BidResponseCreator(CacheService cacheService, cacheAssetUrlTemplate = Objects.requireNonNull(cacheService.getCachedAssetURLTemplate()); } + private static int validateTruncateAttrChars(int truncateAttrChars) { + if (truncateAttrChars < 0 || truncateAttrChars > 255) { + throw new IllegalArgumentException("truncateAttrChars must be between 0 and 255"); + } + return truncateAttrChars; + } + /** * Creates an OpenRTB {@link BidResponse} from the bids supplied by the bidder, * including processing of winning bids with cache IDs. @@ -152,18 +164,30 @@ Future create(List bidderResponses, BidRequestCacheInfo cacheInfo, Map bidderToMultiBids, boolean debugEnabled) { - + final BidRequest bidRequest = auctionContext.getBidRequest(); + final List imps = bidRequest.getImp(); final long auctionTimestamp = auctionTimestamp(auctionContext); + final Account account = auctionContext.getAccount(); - if (isEmptyBidderResponses(bidderResponses)) { - final BidRequest bidRequest = auctionContext.getBidRequest(); + final EventsContext eventsContext = EventsContext.builder() + .enabledForAccount(eventsEnabledForAccount(auctionContext)) + .enabledForRequest(eventsEnabledForRequest(auctionContext)) + .auctionTimestamp(auctionTimestamp) + .integration(integrationFrom(auctionContext)) + .build(); + + final List modifiedBidderResponses = updateBids(bidderResponses, account, eventsContext); + + final List bidderResponseInfos = toBidderResponseInfos(modifiedBidderResponses, imps); + + if (isEmptyBidderResponses(bidderResponseInfos)) { return Future.succeededFuture(BidResponse.builder() .id(bidRequest.getId()) .cur(bidRequest.getCur().get(0)) .nbr(0) // signal "Unknown Error" .seatbid(Collections.emptyList()) .ext(mapper.mapper().valueToTree(toExtBidResponse( - bidderResponses, + bidderResponseInfos, auctionContext, CacheServiceResult.empty(), VideoStoredDataResult.empty(), @@ -174,78 +198,180 @@ Future create(List bidderResponses, } return cacheBidsAndCreateResponse( - bidderResponses, + bidderResponseInfos, auctionContext, cacheInfo, bidderToMultiBids, - auctionTimestamp, + eventsContext, debugEnabled); } - private static int validateTruncateAttrChars(int truncateAttrChars) { - if (truncateAttrChars < 0 || truncateAttrChars > 255) { - throw new IllegalArgumentException("truncateAttrChars must be between 0 and 255"); + private List updateBids(List bidderResponses, + Account account, + EventsContext eventsContext) { + final List result = new ArrayList<>(); + for (BidderResponse bidderResponse : bidderResponses) { + final String bidder = bidderResponse.getBidder(); + + final List modifiedBidderBids = new ArrayList<>(); + final BidderSeatBid seatBid = bidderResponse.getSeatBid(); + for (BidderBid bidderBid : seatBid.getBids()) { + final Bid receivedBid = bidderBid.getBid(); + final BidType bidType = bidderBid.getType(); + final Bid modifiedBid = updateBid(receivedBid, bidType, bidder, account, eventsContext); + modifiedBidderBids.add(bidderBid.with(modifiedBid)); + } + + final BidderSeatBid modifiedSeatBid = seatBid.with(modifiedBidderBids); + result.add(bidderResponse.with(modifiedSeatBid)); } - return truncateAttrChars; + return result; + } + + private Bid updateBid(Bid bid, + BidType bidType, + String bidder, + Account account, + EventsContext eventsContext) { + final String generatedBidId = bidIdGenerator.getType() != IdGeneratorType.none + ? bidIdGenerator.generateId() + : null; + + return bid.toBuilder() + .adm(updateBidAdm(bid, bidType, bidder, account, eventsContext, generatedBidId)) + .ext(updateBidExt(bid, generatedBidId)) + .build(); + } + + private String updateBidAdm(Bid bid, + BidType bidType, + String bidder, + Account account, + EventsContext eventsContext, + String generatedBidId) { + final String bidAdm = bid.getAdm(); + return BidType.video.equals(bidType) + ? vastModifier.createBidVastXml( + bidder, + bidAdm, + bid.getNurl(), + ObjectUtils.defaultIfNull(generatedBidId, bid.getId()), + account.getId(), + eventsContext) + : bidAdm; + } + + private ObjectNode updateBidExt(Bid bid, String generatedBidId) { + final ObjectNode bidExt = bid.getExt(); + if (generatedBidId == null) { + return bidExt; + } + + final ExtPrebid extPrebid = getExtPrebid(bidExt); + final ExtBidPrebid extBidPrebid = extPrebid != null ? extPrebid.getPrebid() : null; + final ExtBidPrebid.ExtBidPrebidBuilder extBidPrebidBuilder = extBidPrebid != null + ? extBidPrebid.toBuilder() + : ExtBidPrebid.builder(); + + final ExtBidPrebid modifiedExtBidPrebid = extBidPrebidBuilder + .bidid(generatedBidId) + .build(); + + final ObjectNode existingBidExt = bidExt != null ? bidExt : mapper.mapper().createObjectNode(); + return existingBidExt.set(PREBID_EXT, mapper.mapper().valueToTree(modifiedExtBidPrebid)); } /** * Checks whether bidder responses are empty or contain no bids. */ - private static boolean isEmptyBidderResponses(List bidderResponses) { - return bidderResponses.isEmpty() || bidderResponses.stream() - .map(bidderResponse -> bidderResponse.getSeatBid().getBids()) + private static boolean isEmptyBidderResponses(List bidderResponseInfos) { + return bidderResponseInfos.isEmpty() || bidderResponseInfos.stream() + .map(bidderResponseInfo -> bidderResponseInfo.getSeatBid().getBidsInfos()) .allMatch(CollectionUtils::isEmpty); } - private Future cacheBidsAndCreateResponse(List bidderResponses, + private List toBidderResponseInfos(List bidderResponses, List imps) { + final List result = new ArrayList<>(); + for (BidderResponse bidderResponse : bidderResponses) { + final String bidder = bidderResponse.getBidder(); + + final List bidInfos = new ArrayList<>(); + final BidderSeatBid seatBid = bidderResponse.getSeatBid(); + + for (BidderBid bidderBid : seatBid.getBids()) { + final Bid bid = bidderBid.getBid(); + final BidType type = bidderBid.getType(); + final BidInfo bidInfo = toBidInfo(bid, type, imps, bidder); + bidInfos.add(bidInfo); + } + + final BidderSeatBidInfo bidderSeatBidInfo = BidderSeatBidInfo.of( + bidInfos, + seatBid.getHttpCalls(), + seatBid.getErrors()); + + result.add(BidderResponseInfo.of(bidder, bidderSeatBidInfo, bidderResponse.getResponseTime())); + } + + return result; + } + + private BidInfo toBidInfo(Bid bid, BidType type, List imps, String bidder) { + return BidInfo.builder() + .bid(bid) + .bidType(type) + .bidder(bidder) + .correspondingImp(correspondingImp(bid, imps)) + .build(); + } + + private static Imp correspondingImp(Bid bid, List imps) { + final String impId = bid.getImpid(); + return imps.stream() + .filter(imp -> Objects.equals(impId, imp.getId())) + .findFirst() + // Should never occur. See ResponseBidValidator + .orElseThrow( + () -> new PreBidException(String.format("Bid with impId %s doesn't have matched imp", impId))); + } + + private Future cacheBidsAndCreateResponse(List bidderResponses, AuctionContext auctionContext, BidRequestCacheInfo cacheInfo, Map bidderToMultiBids, - long auctionTimestamp, + EventsContext eventsContext, boolean debugEnabled) { - final BidRequest bidRequest = auctionContext.getBidRequest(); + final List bidderResponseInfos = + toBidderResponseWithTargetingBidInfos(bidderResponses, bidderToMultiBids); - final List imps = bidRequest.getImp(); - final Map> bidderResponseToTargetingBidInfos = - toBidderResponseWithTargetingBidInfos(bidderResponses, imps, bidderToMultiBids); - - final Set bidInfos = bidderResponseToTargetingBidInfos.values().stream() + final Set bidInfos = bidderResponseInfos.stream() + .map(BidderResponseInfo::getSeatBid) + .map(BidderSeatBidInfo::getBidsInfos) .filter(CollectionUtils::isNotEmpty) .flatMap(Collection::stream) - .map(TargetingBidInfo::getBidInfo) .collect(Collectors.toSet()); + final BidRequest bidRequest = auctionContext.getBidRequest(); final ExtRequestTargeting targeting = targeting(bidRequest); final Set winningBidInfos = targeting == null ? null - : bidderResponseToTargetingBidInfos.values().stream() - .flatMap(Collection::stream) - .filter(TargetingBidInfo::isWinningBid) - .map(TargetingBidInfo::getBidInfo) - .collect(Collectors.toSet()); + : bidInfos.stream() + .filter(bidInfo -> bidInfo.getTargetingInfo().isWinningBid()) + .collect(Collectors.toSet()); final Set bidsToCache = cacheInfo.isShouldCacheWinningBidsOnly() ? winningBidInfos : bidInfos; - final EventsContext eventsContext = EventsContext.builder() - .enabledForAccount(eventsEnabledForAccount(auctionContext)) - .enabledForRequest(eventsEnabledForRequest(auctionContext)) - .auctionTimestamp(auctionTimestamp) - .integration(integrationFrom(auctionContext)) - .build(); - return cacheBids(bidsToCache, auctionContext, cacheInfo, eventsContext) .compose(cacheResult -> videoStoredDataResult(auctionContext) .map(videoStoredDataResult -> toBidResponse( - bidderResponseToTargetingBidInfos, + bidderResponseInfos, auctionContext, targeting, cacheInfo, cacheResult, videoStoredDataResult, eventsContext, - auctionTimestamp, debugEnabled))); } @@ -255,15 +381,14 @@ private static ExtRequestTargeting targeting(BidRequest bidRequest) { return prebid != null ? prebid.getTargeting() : null; } - private Map> toBidderResponseWithTargetingBidInfos( - List bidderResponses, - List imps, + private List toBidderResponseWithTargetingBidInfos( + List bidderResponses, Map bidderToMultiBids) { - final Map> bidderResponseToReducedBidInfos = bidderResponses.stream() + final Map> bidderResponseToReducedBidInfos = bidderResponses.stream() .collect(Collectors.toMap( Function.identity(), - bidderResponse -> toSortedMultiBidInfo(bidderResponse, imps, bidderToMultiBids))); + bidderResponse -> toSortedMultiBidInfo(bidderResponse, bidderToMultiBids))); final Map>> impIdToBidderToBidInfos = bidderResponseToReducedBidInfos.values() .stream() @@ -288,20 +413,19 @@ private Map> toBidderResponseWithTargetin } return bidderResponseToReducedBidInfos.entrySet().stream() - .collect(Collectors.toMap( - Map.Entry::getKey, - responseToBidInfos -> toTargetingBidInfo( - responseToBidInfos.getValue(), - responseToBidInfos.getKey().getBidder(), - bidderToMultiBids, - winningBids, - winningBidsByBidder))); + .map(responseToBidInfos -> injectBidInfoWithTargeting( + responseToBidInfos.getKey(), + responseToBidInfos.getValue(), + bidderToMultiBids, + winningBids, + winningBidsByBidder + )) + .collect(Collectors.toList()); } - private List toSortedMultiBidInfo(BidderResponse bidderResponse, - List imps, + private List toSortedMultiBidInfo(BidderResponseInfo bidderResponse, Map bidderToMultiBids) { - final List bidInfos = toBidInfo(bidderResponse, imps); + final List bidInfos = bidderResponse.getSeatBid().getBidsInfos(); final Map> impIdToBidInfos = bidInfos.stream() .collect(Collectors.groupingBy(bidInfo -> bidInfo.getCorrespondingImp().getId())); @@ -314,37 +438,6 @@ private List toSortedMultiBidInfo(BidderResponse bidderResponse, .collect(Collectors.toList()); } - private List toBidInfo(BidderResponse bidderResponse, List imps) { - return Stream.of(bidderResponse) - .map(BidderResponse::getSeatBid) - .filter(Objects::nonNull) - .map(BidderSeatBid::getBids) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .map(bidderBid -> toBidInfo(bidderBid.getBid(), bidderBid.getType(), imps, bidderResponse.getBidder())) - .collect(Collectors.toList()); - } - - private BidInfo toBidInfo(Bid bid, BidType type, List imps, String bidder) { - return BidInfo.builder() - .generatedBidId(bidIdGenerator.getType() != IdGeneratorType.none ? bidIdGenerator.generateId() : null) - .bid(bid) - .bidType(type) - .bidder(bidder) - .correspondingImp(correspondingImp(bid, imps)) - .build(); - } - - private static Imp correspondingImp(Bid bid, List imps) { - final String impId = bid.getImpid(); - return imps.stream() - .filter(imp -> Objects.equals(impId, imp.getId())) - .findFirst() - // Should never occur. See ResponseBidValidator - .orElseThrow( - () -> new PreBidException(String.format("Bid with impId %s doesn't have matched imp", impId))); - } - private List sortReducedBidInfo(List bidInfos, int limit) { return bidInfos.stream() .sorted(winningBidComparator.reversed()) @@ -352,27 +445,40 @@ private List sortReducedBidInfo(List bidInfos, int limit) { .collect(Collectors.toList()); } - private List toTargetingBidInfo(List bidderBidInfos, - String bidder, - Map bidderToMultiBids, - Set winningBids, - Set winningBidsByBidder) { + private BidderResponseInfo injectBidInfoWithTargeting(BidderResponseInfo bidderResponseInfo, + List bidderBidInfos, + Map bidderToMultiBids, + Set winningBids, + Set winningBidsByBidder) { + final String bidder = bidderResponseInfo.getBidder(); + final List bidInfosWithTargeting = toBidInfoWithTargeting(bidderBidInfos, bidder, bidderToMultiBids, + winningBids, winningBidsByBidder); + + final BidderSeatBidInfo seatBid = bidderResponseInfo.getSeatBid(); + final BidderSeatBidInfo modifiedSeatBid = seatBid.with(bidInfosWithTargeting); + return bidderResponseInfo.with(modifiedSeatBid); + } + + private List toBidInfoWithTargeting(List bidderBidInfos, + String bidder, + Map bidderToMultiBids, + Set winningBids, + Set winningBidsByBidder) { final Map> impIdToBidInfos = bidderBidInfos.stream() .collect(Collectors.groupingBy(bidInfo -> bidInfo.getCorrespondingImp().getId())); return impIdToBidInfos.values().stream() - .map(bidInfos -> createTargetingBidInfo(bidInfos, bidder, bidderToMultiBids, winningBids, - winningBidsByBidder)) + .map(bidInfos -> injectTargeting(bidInfos, bidder, bidderToMultiBids, winningBids, winningBidsByBidder)) .flatMap(Collection::stream) .collect(Collectors.toList()); } - private List createTargetingBidInfo(List bidderImpIdBidInfos, - String bidder, - Map bidderToMultiBids, - Set winningBids, - Set winningBidsByBidder) { - final List targetingBidInfos = new ArrayList<>(); + private List injectTargeting(List bidderImpIdBidInfos, + String bidder, + Map bidderToMultiBids, + Set winningBids, + Set winningBidsByBidder) { + final List result = new ArrayList<>(); final MultiBidConfig multiBid = bidderToMultiBids.get(bidder); final String bidderCodePrefix = multiBid != null ? multiBid.getTargetBidderCodePrefix() : null; @@ -386,8 +492,7 @@ private List createTargetingBidInfo(List bidderImpIdB : bidderCodePrefix == null ? null : String.format("%s%s", bidderCodePrefix, i + 1); final BidInfo bidInfo = bidderImpIdBidInfos.get(i); - final TargetingBidInfo targetingBidInfo = TargetingBidInfo.builder() - .bidInfo(bidInfo) + final TargetingInfo targetingInfo = TargetingInfo.builder() .isTargetingEnabled(targetingBidderCode != null) .isBidderWinningBid(winningBidsByBidder.contains(bidInfo)) .isWinningBid(winningBids.contains(bidInfo)) @@ -395,10 +500,11 @@ private List createTargetingBidInfo(List bidderImpIdB .bidderCode(targetingBidderCode) .build(); - targetingBidInfos.add(targetingBidInfo); + final BidInfo modifiedBidInfo = bidInfo.toBuilder().targetingInfo(targetingInfo).build(); + result.add(modifiedBidInfo); } - return targetingBidInfos; + return result; } /** @@ -415,7 +521,7 @@ private long auctionTimestamp(AuctionContext auctionContext) { * Returns {@link ExtBidResponse} object, populated with response time, errors and debug info (if requested) * from all bidders. */ - private ExtBidResponse toExtBidResponse(Collection bidderResponses, + private ExtBidResponse toExtBidResponse(List bidderResponseInfos, AuctionContext auctionContext, CacheServiceResult cacheResult, VideoStoredDataResult videoStoredDataResult, @@ -426,15 +532,15 @@ private ExtBidResponse toExtBidResponse(Collection bidderRespons final BidRequest bidRequest = auctionContext.getBidRequest(); final ExtResponseDebug extResponseDebug = debugEnabled - ? ExtResponseDebug.of(toExtHttpCalls(bidderResponses, cacheResult), bidRequest) + ? ExtResponseDebug.of(toExtHttpCalls(bidderResponseInfos, cacheResult), bidRequest) : null; final Map> errors = - toExtBidderErrors(bidderResponses, auctionContext, cacheResult, videoStoredDataResult, bidErrors); + toExtBidderErrors(bidderResponseInfos, auctionContext, cacheResult, videoStoredDataResult, bidErrors); final Map> warnings = debugEnabled ? toExtBidderWarnings(auctionContext) : null; - final Map responseTimeMillis = toResponseTimes(bidderResponses, cacheResult); + final Map responseTimeMillis = toResponseTimes(bidderResponseInfos, cacheResult); return ExtBidResponse.of(extResponseDebug, errors, warnings, responseTimeMillis, bidRequest.getTmax(), null, ExtBidResponsePrebid.of(auctionTimestamp)); @@ -501,11 +607,11 @@ private static CacheServiceResult addNotCachedBids(CacheServiceResult cacheResul return cacheResult; } - private static Map> toExtHttpCalls(Collection bidderResponses, + private static Map> toExtHttpCalls(List bidderResponses, CacheServiceResult cacheResult) { final Map> bidderHttpCalls = bidderResponses.stream() .collect(Collectors.toMap( - BidderResponse::getBidder, + BidderResponseInfo::getBidder, bidderResponse -> ListUtils.emptyIfNull(bidderResponse.getSeatBid().getHttpCalls()))); final DebugHttpCall httpCall = cacheResult.getHttpCall(); @@ -529,7 +635,7 @@ private static ExtHttpCall toExtHttpCall(DebugHttpCall debugHttpCall) { .build(); } - private Map> toExtBidderErrors(Collection bidderResponses, + private Map> toExtBidderErrors(List bidderResponses, AuctionContext auctionContext, CacheServiceResult cacheResult, VideoStoredDataResult videoStoredDataResult, @@ -550,10 +656,12 @@ private Map> toExtBidderErrors(Collection> extractBidderErrors(Collection bidderResponses) { + private static Map> extractBidderErrors( + Collection bidderResponses) { + return bidderResponses.stream() .filter(bidderResponse -> CollectionUtils.isNotEmpty(bidderResponse.getSeatBid().getErrors())) - .collect(Collectors.toMap(BidderResponse::getBidder, + .collect(Collectors.toMap(BidderResponseInfo::getBidder, bidderResponse -> errorsDetails(bidderResponse.getSeatBid().getErrors()))); } @@ -670,10 +778,10 @@ private static Stream asStream(Iterator iterator) { /** * Returns a map with response time by bidders and cache. */ - private static Map toResponseTimes(Collection bidderResponses, + private static Map toResponseTimes(Collection bidderResponses, CacheServiceResult cacheResult) { final Map responseTimeMillis = bidderResponses.stream() - .collect(Collectors.toMap(BidderResponse::getBidder, BidderResponse::getResponseTime)); + .collect(Collectors.toMap(BidderResponseInfo::getBidder, BidderResponseInfo::getResponseTime)); final DebugHttpCall debugHttpCall = cacheResult.getHttpCall(); final Integer cacheResponseTime = debugHttpCall != null ? debugHttpCall.getResponseTimeMillis() : null; @@ -686,24 +794,25 @@ private static Map toResponseTimes(Collection b /** * Returns {@link BidResponse} based on list of {@link BidderResponse}s and {@link CacheServiceResult}. */ - private BidResponse toBidResponse(Map> bidderResponseToTargetingBidInfos, + private BidResponse toBidResponse(List bidderResponseInfos, AuctionContext auctionContext, ExtRequestTargeting targeting, BidRequestCacheInfo requestCacheInfo, CacheServiceResult cacheResult, VideoStoredDataResult videoStoredDataResult, EventsContext eventsContext, - long auctionTimestamp, boolean debugEnabled) { final BidRequest bidRequest = auctionContext.getBidRequest(); final Account account = auctionContext.getAccount(); final Map> bidErrors = new HashMap<>(); - final List seatBids = bidderResponseToTargetingBidInfos.values().stream() + final List seatBids = bidderResponseInfos.stream() + .map(BidderResponseInfo::getSeatBid) + .map(BidderSeatBidInfo::getBidsInfos) .filter(CollectionUtils::isNotEmpty) - .map(targetingBidInfos -> toSeatBid( - targetingBidInfos, + .map(bidInfos -> toSeatBid( + bidInfos, targeting, bidRequest, requestCacheInfo, @@ -714,8 +823,9 @@ private BidResponse toBidResponse(Map> bi eventsContext)) .collect(Collectors.toList()); + final Long auctionTimestamp = eventsContext.getAuctionTimestamp(); final ExtBidResponse extBidResponse = toExtBidResponse( - bidderResponseToTargetingBidInfos.keySet(), + bidderResponseInfos, auctionContext, cacheResult, videoStoredDataResult, @@ -777,7 +887,7 @@ private boolean checkEchoVideoAttrs(Imp imp) { * Creates an OpenRTB {@link SeatBid} for a bidder. It will contain all the bids supplied by a bidder and a "bidder" * extension field populated. */ - private SeatBid toSeatBid(List targetingBidInfos, + private SeatBid toSeatBid(List bidInfos, ExtRequestTargeting targeting, BidRequest bidRequest, BidRequestCacheInfo requestCacheInfo, @@ -787,24 +897,28 @@ private SeatBid toSeatBid(List targetingBidInfos, Map> bidErrors, EventsContext eventsContext) { - final String bidder = targetingBidInfos.stream() - .map(TargetingBidInfo::getBidInfo) + final String bidder = bidInfos.stream() .map(BidInfo::getBidder) .findFirst() // Should never occur .orElseThrow(() -> new IllegalArgumentException("Bidder was not defined for bidInfo")); - final List bids = targetingBidInfos.stream() - .map(targetingBidInfo -> toBid( - targetingBidInfo, - targeting, - bidRequest, + final List bids = bidInfos.stream() + .map(bidInfo -> injectAdmWithCacheInfo( + bidInfo, requestCacheInfo, bidToCacheInfo, + bidRequest, + bidErrors + )) + .filter(Objects::nonNull) + .map(bidInfo -> toBid( + bidInfo, + targeting, + bidRequest, videoStoredDataResult.getImpIdToStoredVideo(), account, - eventsContext, - bidErrors)) + eventsContext)) .filter(Objects::nonNull) .collect(Collectors.toList()); @@ -815,46 +929,30 @@ private SeatBid toSeatBid(List targetingBidInfos, .build(); } - /** - * Returns an OpenRTB {@link Bid} with "prebid" and "bidder" extension fields populated. - */ - private Bid toBid(TargetingBidInfo targetingBidInfo, - ExtRequestTargeting targeting, - BidRequest bidRequest, - BidRequestCacheInfo requestCacheInfo, - Map bidsWithCacheIds, - Map impIdToStoredVideo, - Account account, - EventsContext eventsContext, - Map> bidErrors) { - final BidInfo bidInfo = targetingBidInfo.getBidInfo(); + private BidInfo injectAdmWithCacheInfo(BidInfo bidInfo, + BidRequestCacheInfo requestCacheInfo, + Map bidsWithCacheIds, + BidRequest bidRequest, + Map> bidErrors) { final Bid bid = bidInfo.getBid(); final BidType bidType = bidInfo.getBidType(); final String bidder = bidInfo.getBidder(); + final Imp correspondingImp = bidInfo.getCorrespondingImp(); final CacheInfo cacheInfo = bidsWithCacheIds.get(bid); final String cacheId = cacheInfo != null ? cacheInfo.getCacheId() : null; final String videoCacheId = cacheInfo != null ? cacheInfo.getVideoCacheId() : null; + String modifiedBidAdm = bid.getAdm(); if ((videoCacheId != null && !requestCacheInfo.isReturnCreativeVideoBids()) || (cacheId != null && !requestCacheInfo.isReturnCreativeBids())) { - bid.setAdm(null); - } else if (bidType.equals(BidType.video)) { - final String adm = vastModifier.createBidVastXml( - bidder, - bid.getAdm(), - bid.getNurl(), - bidInfo.getBidId(), - account.getId(), - eventsContext); - - bid.setAdm(adm); + modifiedBidAdm = null; } final boolean isApp = bidRequest.getApp() != null; - if (isApp && bidType.equals(BidType.xNative) && bid.getAdm() != null) { + if (isApp && bidType.equals(BidType.xNative) && modifiedBidAdm != null) { try { - addNativeMarkup(bid, bidRequest.getImp()); + modifiedBidAdm = crateNativeMarkup(modifiedBidAdm, correspondingImp); } catch (PreBidException e) { bidErrors.computeIfAbsent(bidder, ignored -> new ArrayList<>()) .add(ExtBidderError.of(BidderError.Type.bad_server_response.getCode(), e.getMessage())); @@ -862,15 +960,42 @@ private Bid toBid(TargetingBidInfo targetingBidInfo, } } + final Bid modifiedBid = bid.toBuilder().adm(modifiedBidAdm).build(); + return bidInfo.toBuilder() + .bid(modifiedBid) + .cacheInfo(cacheInfo) + .build(); + } + + /** + * Returns an OpenRTB {@link Bid} with "prebid" and "bidder" extension fields populated. + */ + private Bid toBid(BidInfo bidInfo, + ExtRequestTargeting targeting, + BidRequest bidRequest, + Map impIdToStoredVideo, + Account account, + EventsContext eventsContext) { + final TargetingInfo targetingInfo = bidInfo.getTargetingInfo(); + final BidType bidType = bidInfo.getBidType(); + final String bidder = bidInfo.getBidder(); + final Bid bid = bidInfo.getBid(); + + final CacheInfo cacheInfo = bidInfo.getCacheInfo(); + final String cacheId = cacheInfo != null ? cacheInfo.getCacheId() : null; + final String videoCacheId = cacheInfo != null ? cacheInfo.getVideoCacheId() : null; + + final boolean isApp = bidRequest.getApp() != null; + final Map targetingKeywords; - final String bidderCode = targetingBidInfo.getBidderCode(); - if (targeting != null && targetingBidInfo.isTargetingEnabled() && targetingBidInfo.isBidderWinningBid()) { + final String bidderCode = targetingInfo.getBidderCode(); + if (targeting != null && targetingInfo.isTargetingEnabled() && targetingInfo.isBidderWinningBid()) { final TargetingKeywordsCreator keywordsCreator = resolveKeywordsCreator(bidType, targeting, isApp, bidRequest, account); - final boolean isWinningBid = targetingBidInfo.isWinningBid(); - targetingKeywords = keywordsCreator.makeFor(bid, bidderCode, isWinningBid, cacheId, bidType.getName(), - videoCacheId); + final boolean isWinningBid = targetingInfo.isWinningBid(); + targetingKeywords = keywordsCreator.makeFor(bid, bidderCode, isWinningBid, cacheId, + bidType.getName(), videoCacheId); } else { targetingKeywords = null; } @@ -883,40 +1008,45 @@ private Bid toBid(TargetingBidInfo targetingBidInfo, final Events events = createEvents(bidder, account, bidInfo.getBidId(), eventsContext); final ExtBidPrebidVideo extBidPrebidVideo = getExtBidPrebidVideo(bid.getExt()); - final ExtBidPrebid extBidPrebid = ExtBidPrebid.builder() - .bidid(bidInfo.getGeneratedBidId()) + final ExtPrebid extPrebid = getExtPrebid(bid.getExt()); + final ExtBidPrebid extBidPrebid = extPrebid != null ? extPrebid.getPrebid() : null; + final ExtBidPrebid.ExtBidPrebidBuilder extBidPrebidBuilder = extBidPrebid != null + ? extBidPrebid.toBuilder() + : ExtBidPrebid.builder(); + + final ExtBidPrebid updatedExtBidPrebid = extBidPrebidBuilder .type(bidType) .targeting(targetingKeywords) - .targetBidderCode(targetingBidInfo.isAddTargetBidderCode() ? bidderCode : null) + .targetBidderCode(targetingInfo.isAddTargetBidderCode() ? bidderCode : null) .cache(cache) .storedRequestAttributes(storedVideo) .events(events) .video(extBidPrebidVideo) .build(); - bid.setExt(createBidExt(bid.getExt(), extBidPrebid)); - + final ObjectNode bidExt = createBidExt(bid.getExt(), updatedExtBidPrebid); final Integer ttl = cacheInfo != null ? ObjectUtils.max(cacheInfo.getTtl(), cacheInfo.getVideoTtl()) : null; - bid.setExp(ttl); - return bid; + return bid.toBuilder() + .ext(bidExt) + .exp(ttl) + .build(); } - private void addNativeMarkup(Bid bid, List imps) { + private String crateNativeMarkup(String bidAdm, Imp correspondingImp) { final Response nativeMarkup; try { - nativeMarkup = mapper.decodeValue(bid.getAdm(), Response.class); + nativeMarkup = mapper.decodeValue(bidAdm, Response.class); } catch (DecodeException e) { throw new PreBidException(e.getMessage()); } final List responseAssets = nativeMarkup.getAssets(); if (CollectionUtils.isNotEmpty(responseAssets)) { - final Native nativeImp = imps.stream() - .filter(imp -> imp.getId().equals(bid.getImpid()) && imp.getXNative() != null) - .findFirst() - .map(Imp::getXNative) - .orElseThrow(() -> new PreBidException("Could not find native imp")); + final Native nativeImp = correspondingImp != null ? correspondingImp.getXNative() : null; + if (nativeImp == null) { + throw new PreBidException("Could not find native imp"); + } final Request nativeRequest; try { @@ -926,8 +1056,10 @@ private void addNativeMarkup(Bid bid, List imps) { } responseAssets.forEach(asset -> setAssetTypes(asset, nativeRequest.getAssets())); - bid.setAdm(mapper.encode(nativeMarkup)); + return mapper.encode(nativeMarkup); } + + return bidAdm; } private static void setAssetTypes(Asset responseAsset, List requestAssets) { @@ -1140,25 +1272,45 @@ private String integrationFrom(AuctionContext auctionContext) { * Creates {@link ExtBidPrebidVideo} from bid extension. */ private ExtBidPrebidVideo getExtBidPrebidVideo(ObjectNode bidExt) { - final ExtPrebid extPrebid = mapper.mapper() - .convertValue(bidExt, EXT_PREBID_TYPE_REFERENCE); + final ExtPrebid extPrebid = getExtPrebid(bidExt); final ExtBidPrebid extBidPrebid = extPrebid != null ? extPrebid.getPrebid() : null; return extBidPrebid != null ? extBidPrebid.getVideo() : null; } + private ExtPrebid getExtPrebid(ObjectNode bidExt) { + return bidExt != null ? mapper.mapper().convertValue(bidExt, EXT_PREBID_TYPE_REFERENCE) : null; + } + // will be updated in https://github.com/prebid/prebid-server-java/pull/1126 private ObjectNode createBidExt(ObjectNode existingBidExt, ExtBidPrebid extBidPrebid) { JsonNode skadnObject = mapper.mapper().createObjectNode(); + JsonNode origBidPrice = null; + JsonNode origBidCur = null; if (existingBidExt != null && !existingBidExt.isEmpty()) { - skadnObject = existingBidExt.get(SKADN_PROPERTY); - existingBidExt.remove(SKADN_PROPERTY); + skadnObject = getAndRemoveProperty(SKADN_PROPERTY, existingBidExt); + origBidPrice = getAndRemoveProperty(ORIGINAL_BID_CPM, existingBidExt); + origBidCur = getAndRemoveProperty(ORIGINAL_BID_CURRENCY, existingBidExt); } - final ExtPrebid bidExt = ExtPrebid.of(extBidPrebid, existingBidExt); + final ObjectNode extPrebidBidder = existingBidExt != null && !existingBidExt.isEmpty() ? existingBidExt : null; + final ExtPrebid bidExt = ExtPrebid.of(extBidPrebid, extPrebidBidder); final ObjectNode updatedBidExt = mapper.mapper().valueToTree(bidExt); if (skadnObject != null && !skadnObject.isEmpty()) { updatedBidExt.set(SKADN_PROPERTY, skadnObject); } + if (origBidPrice != null) { + updatedBidExt.set(ORIGINAL_BID_CPM, origBidPrice); + } + if (origBidCur != null) { + updatedBidExt.set(ORIGINAL_BID_CURRENCY, origBidCur); + } return updatedBidExt; } + + private JsonNode getAndRemoveProperty(String propertyName, ObjectNode node) { + final JsonNode property = node.get(propertyName); + node.remove(propertyName); + + return property; + } } diff --git a/src/main/java/org/prebid/server/auction/BidderAliases.java b/src/main/java/org/prebid/server/auction/BidderAliases.java index 0d00adcc392..7b005b59066 100644 --- a/src/main/java/org/prebid/server/auction/BidderAliases.java +++ b/src/main/java/org/prebid/server/auction/BidderAliases.java @@ -18,26 +18,22 @@ public class BidderAliases { private final BidderCatalog bidderCatalog; - private BidderAliases( - Map aliasToBidder, Map aliasToVendorId, BidderCatalog bidderCatalog) { + private BidderAliases(Map aliasToBidder, Map aliasToVendorId, + BidderCatalog bidderCatalog) { this.aliasToBidder = MapUtils.emptyIfNull(aliasToBidder); this.aliasToVendorId = MapUtils.emptyIfNull(aliasToVendorId); this.bidderCatalog = Objects.requireNonNull(bidderCatalog); } - public static BidderAliases of( - Map aliasToBidder, Map aliasToVendorId, BidderCatalog bidderCatalog) { + public static BidderAliases of(Map aliasToBidder, Map aliasToVendorId, + BidderCatalog bidderCatalog) { return new BidderAliases(aliasToBidder, aliasToVendorId, bidderCatalog); } - public static BidderAliases of(BidderCatalog bidderCatalog) { - return new BidderAliases(null, null, bidderCatalog); - } - public boolean isAliasDefined(String alias) { - return aliasToBidder.containsKey(alias) || bidderCatalog.isAlias(alias); + return aliasToBidder.containsKey(alias); } public String resolveBidder(String aliasOrBidder) { @@ -53,8 +49,7 @@ public Integer resolveAliasVendorId(String alias) { } private String resolveBidderViaCatalog(String aliasOrBidder) { - final String resolvedBidder = bidderCatalog.nameByAlias(aliasOrBidder); - return bidderCatalog.isActive(resolvedBidder) ? resolvedBidder : null; + return bidderCatalog.isActive(aliasOrBidder) ? aliasOrBidder : null; } private Integer resolveAliasVendorIdViaCatalog(String alias) { diff --git a/src/main/java/org/prebid/server/auction/ExchangeService.java b/src/main/java/org/prebid/server/auction/ExchangeService.java index 74120681eca..78241edc59f 100644 --- a/src/main/java/org/prebid/server/auction/ExchangeService.java +++ b/src/main/java/org/prebid/server/auction/ExchangeService.java @@ -2,7 +2,9 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.DecimalNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.TextNode; import com.iab.openrtb.request.App; import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Content; @@ -10,6 +12,7 @@ import com.iab.openrtb.request.Site; import com.iab.openrtb.request.Source; import com.iab.openrtb.request.User; +import com.iab.openrtb.request.Video; import com.iab.openrtb.response.Bid; import com.iab.openrtb.response.BidResponse; import com.iab.openrtb.response.SeatBid; @@ -17,6 +20,7 @@ import io.vertx.core.Future; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; +import io.vertx.ext.web.RoutingContext; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; @@ -42,10 +46,12 @@ import org.prebid.server.metric.MetricName; import org.prebid.server.metric.Metrics; import org.prebid.server.proto.openrtb.ext.ExtPrebidBidders; +import org.prebid.server.proto.openrtb.ext.request.BidAdjustmentMediaType; import org.prebid.server.proto.openrtb.ext.request.ExtApp; import org.prebid.server.proto.openrtb.ext.request.ExtBidderConfigOrtb; import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebid; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestBidadjustmentfactors; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidBidderConfig; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidCache; @@ -59,6 +65,7 @@ import org.prebid.server.proto.openrtb.ext.request.ExtSource; import org.prebid.server.proto.openrtb.ext.request.ExtUser; import org.prebid.server.proto.openrtb.ext.request.ExtUserEid; +import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.settings.model.Account; import org.prebid.server.util.StreamUtil; import org.prebid.server.validation.ResponseBidValidator; @@ -85,6 +92,8 @@ public class ExchangeService { private static final String PREBID_EXT = "prebid"; private static final String BIDDER_EXT = "bidder"; + private static final String ORIGINAL_BID_CPM = "origbidcpm"; + private static final String ORIGINAL_BID_CURRENCY = "origbidcur"; private static final String ALL_BIDDERS_CONFIG = "*"; private static final Integer DEFAULT_MULTIBID_LIMIT_MIN = 1; private static final Integer DEFAULT_MULTIBID_LIMIT_MAX = 9; @@ -149,6 +158,7 @@ public Future holdAuction(AuctionContext context) { final UidsCookie uidsCookie = context.getUidsCookie(); final BidRequest bidRequest = context.getBidRequest(); final Timeout timeout = context.getTimeout(); + final RoutingContext routingContext = context.getRoutingContext(); final Account account = context.getAccount(); final List debugWarnings = context.getDebugWarnings(); @@ -170,6 +180,7 @@ public Future holdAuction(AuctionContext context) { .map(bidderRequest -> requestBids( bidderRequest, auctionTimeout(timeout, cacheInfo.isDoCaching()), + routingContext, debugEnabled, aliases)) .collect(Collectors.toList()))) @@ -187,7 +198,7 @@ public Future holdAuction(AuctionContext context) { bidderToMultiBid, debugEnabled)) .compose(bidResponse -> bidResponsePostProcessor.postProcess( - context.getRoutingContext(), uidsCookie, bidRequest, bidResponse, account)); + routingContext, uidsCookie, bidRequest, bidResponse, account)); } private BidderAliases aliases(BidRequest bidRequest) { @@ -960,18 +971,13 @@ private List updateRequestMetric(List bidderReques return bidderRequests; } - private static BigDecimal bidAdjustmentForBidder(BidRequest bidRequest, String bidder) { - final ExtRequestPrebid prebid = extRequestPrebid(bidRequest); - final Map bidAdjustmentFactors = prebid != null ? prebid.getBidadjustmentfactors() : null; - return bidAdjustmentFactors != null ? bidAdjustmentFactors.get(bidder) : null; - } - /** * Passes the request to a corresponding bidder and wraps response in {@link BidderResponse} which also holds * recorded response time. */ private Future requestBids(BidderRequest bidderRequest, Timeout timeout, + RoutingContext routingContext, boolean debugEnabled, BidderAliases aliases) { @@ -979,7 +985,7 @@ private Future requestBids(BidderRequest bidderRequest, final Bidder bidder = bidderCatalog.bidderByName(aliases.resolveBidder(bidderName)); final long startTime = clock.millis(); - return httpBidderRequester.requestBids(bidder, bidderRequest, timeout, debugEnabled) + return httpBidderRequester.requestBids(bidder, bidderRequest, timeout, routingContext, debugEnabled) .map(seatBid -> BidderResponse.of(bidderName, seatBid, responseTime(startTime))); } @@ -1060,22 +1066,12 @@ private BidderResponse applyBidPriceChanges(BidderResponse bidderResponse, BidRe final List errors = new ArrayList<>(seatBid.getErrors()); final String adServerCurrency = bidRequest.getCur().get(0); - final BigDecimal priceAdjustmentFactor = bidAdjustmentForBidder(bidRequest, bidderResponse.getBidder()); for (final BidderBid bidderBid : bidderBids) { - final Bid bid = bidderBid.getBid(); - final String bidCurrency = bidderBid.getBidCurrency(); - final BigDecimal price = bid.getPrice(); try { - final BigDecimal priceInAdServerCurrency = currencyService.convertCurrency( - price, bidRequest, adServerCurrency, StringUtils.stripToNull(bidCurrency)); - - final BigDecimal adjustedPrice = adjustPrice(priceAdjustmentFactor, priceInAdServerCurrency); - - if (adjustedPrice.compareTo(price) != 0) { - bid.setPrice(adjustedPrice); - } - updatedBidderBids.add(bidderBid); + final BidderBid updatedBidderBid = + updateBidderBidWithBidPriceChanges(bidderBid, bidderResponse, bidRequest, adServerCurrency); + updatedBidderBids.add(updatedBidderBid); } catch (PreBidException e) { errors.add(BidderError.generic(e.getMessage())); } @@ -1084,12 +1080,121 @@ private BidderResponse applyBidPriceChanges(BidderResponse bidderResponse, BidRe return bidderResponse.with(BidderSeatBid.of(updatedBidderBids, seatBid.getHttpCalls(), errors)); } + private BidderBid updateBidderBidWithBidPriceChanges(BidderBid bidderBid, + BidderResponse bidderResponse, + BidRequest bidRequest, + String adServerCurrency) { + final Bid bid = bidderBid.getBid(); + final String bidCurrency = bidderBid.getBidCurrency(); + final BigDecimal price = bid.getPrice(); + + final BigDecimal priceInAdServerCurrency = currencyService.convertCurrency( + price, bidRequest, adServerCurrency, StringUtils.stripToNull(bidCurrency)); + + final BigDecimal priceAdjustmentFactor = + bidAdjustmentForBidder(bidderResponse.getBidder(), bidRequest, bidderBid); + final BigDecimal adjustedPrice = adjustPrice(priceAdjustmentFactor, priceInAdServerCurrency); + + final ObjectNode bidExt = bid.getExt(); + final ObjectNode updatedBidExt = bidExt != null ? bidExt : mapper.mapper().createObjectNode(); + + updateExtWithOrigPriceValues(updatedBidExt, price, bidCurrency); + + final Bid.BidBuilder bidBuilder = bid.toBuilder(); + if (adjustedPrice.compareTo(price) != 0) { + bidBuilder.price(adjustedPrice); + } + + if (!updatedBidExt.isEmpty()) { + bidBuilder.ext(updatedBidExt); + } + + return bidderBid.with(bidBuilder.build()); + } + + private static BidAdjustmentMediaType resolveBidAdjustmentMediaType(String bidImpId, + List imps, + BidType bidType) { + + switch (bidType) { + case banner: + return BidAdjustmentMediaType.banner; + case xNative: + return BidAdjustmentMediaType.xNative; + case audio: + return BidAdjustmentMediaType.audio; + case video: + return resolveBidAdjustmentVideoMediaType(bidImpId, imps); + default: + throw new PreBidException("BidType not present for bidderBid"); + } + } + + private static BidAdjustmentMediaType resolveBidAdjustmentVideoMediaType(String bidImpId, List imps) { + final Video bidImpVideo = imps.stream() + .filter(imp -> imp.getId().equals(bidImpId)) + .map(Imp::getVideo) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); + + if (bidImpVideo == null) { + return null; + } + + final Integer placement = bidImpVideo.getPlacement(); + return placement == null || Objects.equals(placement, 1) + ? BidAdjustmentMediaType.video + : BidAdjustmentMediaType.video_outstream; + } + + private static BigDecimal bidAdjustmentForBidder(String bidder, + BidRequest bidRequest, + BidderBid bidderBid) { + final ExtRequestPrebid prebid = extRequestPrebid(bidRequest); + final ExtRequestBidadjustmentfactors extBidadjustmentfactors = prebid != null + ? prebid.getBidadjustmentfactors() + : null; + if (extBidadjustmentfactors == null) { + return null; + } + final BidAdjustmentMediaType mediaType = + resolveBidAdjustmentMediaType(bidderBid.getBid().getImpid(), bidRequest.getImp(), bidderBid.getType()); + + return resolveBidAdjustmentFactor(extBidadjustmentfactors, mediaType, bidder); + } + + private static BigDecimal resolveBidAdjustmentFactor(ExtRequestBidadjustmentfactors extBidadjustmentfactors, + BidAdjustmentMediaType mediaType, + String bidder) { + final Map> mediatypes = + extBidadjustmentfactors.getMediatypes(); + final Map adjustmentsByMediatypes = mediatypes != null ? mediatypes.get(mediaType) : null; + final BigDecimal adjustmentFactorByMediaType = + adjustmentsByMediatypes != null ? adjustmentsByMediatypes.get(bidder) : null; + if (adjustmentFactorByMediaType != null) { + return adjustmentFactorByMediaType; + } + return extBidadjustmentfactors.getAdjustments().get(bidder); + } + private static BigDecimal adjustPrice(BigDecimal priceAdjustmentFactor, BigDecimal price) { return priceAdjustmentFactor != null && priceAdjustmentFactor.compareTo(BigDecimal.ONE) != 0 ? price.multiply(priceAdjustmentFactor) : price; } + private static void updateExtWithOrigPriceValues(ObjectNode updatedBidExt, BigDecimal price, String bidCurrency) { + addPropertyToNode(updatedBidExt, ORIGINAL_BID_CPM, new DecimalNode(price)); + if (StringUtils.isNotBlank(bidCurrency)) { + addPropertyToNode(updatedBidExt, ORIGINAL_BID_CURRENCY, new TextNode(bidCurrency)); + } + } + + private static void addPropertyToNode(ObjectNode node, String propertyName, JsonNode propertyValue) { + node.set(propertyName, propertyValue); + } + private int responseTime(long startTime) { return Math.toIntExact(clock.millis() - startTime); } diff --git a/src/main/java/org/prebid/server/auction/ImplicitParametersExtractor.java b/src/main/java/org/prebid/server/auction/ImplicitParametersExtractor.java index a69526d2349..950bccd144e 100644 --- a/src/main/java/org/prebid/server/auction/ImplicitParametersExtractor.java +++ b/src/main/java/org/prebid/server/auction/ImplicitParametersExtractor.java @@ -7,8 +7,6 @@ import org.prebid.server.exception.PreBidException; import org.prebid.server.util.HttpUtil; -import java.net.MalformedURLException; -import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -41,30 +39,20 @@ public String refererFrom(HttpServerRequest request) { } /** - * Determines domain the address refers to. + * Determines top-level domain of the passed host name. * - * @throws PreBidException if address does not represent valid URL, host could not be found in URL or top level - * domain could not be derived from the host + * @throws PreBidException if top level domain could not be derived from the host name */ - public String domainFrom(String urlString) throws PreBidException { - final URL url; - try { - url = new URL(urlString); - } catch (MalformedURLException e) { - throw new PreBidException(String.format("Invalid URL '%s': %s", urlString, e.getMessage()), e); - } - - final String host = url.getHost(); + public String domainFrom(String host) throws PreBidException { if (StringUtils.isBlank(host)) { - throw new PreBidException(String.format("Host not found from URL '%s'", url.toString())); + throw new PreBidException("Host is not defined or can not be derived from request"); } final String domain = psl.getRegistrableDomain(host); if (domain == null) { // null means effective top level domain plus one couldn't be derived - throw new PreBidException( - String.format("Invalid URL '%s': cannot derive eTLD+1 for domain %s", host, host)); + throw new PreBidException(String.format("Cannot derive eTLD+1 for host %s", host)); } return domain; diff --git a/src/main/java/org/prebid/server/auction/OrtbTypesResolver.java b/src/main/java/org/prebid/server/auction/OrtbTypesResolver.java index df591d5de4c..c85e286c2ea 100644 --- a/src/main/java/org/prebid/server/auction/OrtbTypesResolver.java +++ b/src/main/java/org/prebid/server/auction/OrtbTypesResolver.java @@ -13,6 +13,7 @@ import org.prebid.server.exception.InvalidRequestException; import org.prebid.server.json.JacksonMapper; import org.prebid.server.json.JsonMerger; +import org.prebid.server.log.ConditionalLogger; import java.util.ArrayList; import java.util.Arrays; @@ -33,6 +34,8 @@ public class OrtbTypesResolver { private static final Logger logger = LoggerFactory.getLogger(OrtbTypesResolver.class); + private static final ConditionalLogger ORTB_TYPES_RESOLVING_LOGGER = + new ConditionalLogger("ortb_resolving_warnings", logger); private static final String USER = "user"; private static final String APP = "app"; @@ -82,7 +85,7 @@ public OrtbTypesResolver(JacksonMapper jacksonMapper, JsonMerger jsonMerger) { * and bidderconfig. * Mutates both parameters, {@param fpdContainerNode} and {@param warnings}. */ - void normalizeBidRequest(JsonNode bidRequest, List warnings, String referer) { + public void normalizeBidRequest(JsonNode bidRequest, List warnings, String referer) { final List resolverWarnings = new ArrayList<>(); final String rowOriginBidRequest = getOriginalRowContainerNode(bidRequest); normalizeRequestFpdFields(bidRequest, resolverWarnings); @@ -160,7 +163,7 @@ private void mergeFpdFieldsToOrtb2(JsonNode bidderConfig) { * Resolves fields types inconsistency to ortb2 protocol for {@param targeting}. * Mutates both parameters, {@param targeting} and {@param warnings}. */ - void normalizeTargeting(JsonNode targeting, List warnings, String referer) { + public void normalizeTargeting(JsonNode targeting, List warnings, String referer) { final List resolverWarnings = new ArrayList<>(); final String rowOriginTargeting = getOriginalRowContainerNode(targeting); normalizeStandardFpdFields(targeting, resolverWarnings, TARGETING); @@ -343,12 +346,10 @@ private void processWarnings(List resolverWarning, List warnings if (CollectionUtils.isNotEmpty(resolverWarning)) { warnings.addAll(updateWithWarningPrefix(resolverWarning)); // log only 1% of cases - if (System.currentTimeMillis() % 100 == 0) { - logger.info(String.format("WARNINGS: %s. \n Referer = %s and %s = %s", - String.join("\n", resolverWarning), - StringUtils.isNotBlank(referer) ? referer : UNKNOWN_REFERER, - containerName, containerValue)); - } + ORTB_TYPES_RESOLVING_LOGGER.warn(String.format("WARNINGS: %s. \n Referer = %s and %s = %s", + String.join("\n", resolverWarning), + StringUtils.isNotBlank(referer) ? referer : UNKNOWN_REFERER, + containerName, containerValue), 0.01); } } diff --git a/src/main/java/org/prebid/server/auction/PriceGranularity.java b/src/main/java/org/prebid/server/auction/PriceGranularity.java index 2dc4c22e06a..defae146d43 100644 --- a/src/main/java/org/prebid/server/auction/PriceGranularity.java +++ b/src/main/java/org/prebid/server/auction/PriceGranularity.java @@ -39,7 +39,7 @@ enum PriceGranularityType { range(20, 0.5)); } - static final PriceGranularity DEFAULT = STRING_TO_CUSTOM_PRICE_GRANULARITY.get(PriceGranularityType.med); + public static final PriceGranularity DEFAULT = STRING_TO_CUSTOM_PRICE_GRANULARITY.get(PriceGranularityType.med); private List ranges; private BigDecimal rangesMax; @@ -61,7 +61,7 @@ static PriceGranularity createFromExtPriceGranularity(ExtPriceGranularity extPri /** * Returns {@link PriceGranularity} by string representation if it is present in map, otherwise returns null. */ - static PriceGranularity createFromString(String stringPriceGranularity) { + public static PriceGranularity createFromString(String stringPriceGranularity) { if (isValidStringPriceGranularityType(stringPriceGranularity)) { return STRING_TO_CUSTOM_PRICE_GRANULARITY.get(PriceGranularityType.valueOf(stringPriceGranularity)); } else { diff --git a/src/main/java/org/prebid/server/auction/PrivacyEnforcementService.java b/src/main/java/org/prebid/server/auction/PrivacyEnforcementService.java index 69f6fcdae73..4b486d3837c 100644 --- a/src/main/java/org/prebid/server/auction/PrivacyEnforcementService.java +++ b/src/main/java/org/prebid/server/auction/PrivacyEnforcementService.java @@ -10,8 +10,10 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.BidderPrivacyResult; +import org.prebid.server.auction.model.IpAddress; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.execution.Timeout; import org.prebid.server.metric.MetricName; @@ -32,7 +34,6 @@ import org.prebid.server.proto.request.CookieSyncRequest; import org.prebid.server.settings.model.Account; import org.prebid.server.settings.model.AccountGdprConfig; -import org.prebid.server.util.HttpUtil; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; @@ -62,6 +63,7 @@ public class PrivacyEnforcementService { private final BidderCatalog bidderCatalog; private final PrivacyExtractor privacyExtractor; private final TcfDefinerService tcfDefinerService; + private final ImplicitParametersExtractor implicitParametersExtractor; private final IpAddressHelper ipAddressHelper; private final Metrics metrics; private final boolean ccpaEnforce; @@ -70,6 +72,7 @@ public class PrivacyEnforcementService { public PrivacyEnforcementService(BidderCatalog bidderCatalog, PrivacyExtractor privacyExtractor, TcfDefinerService tcfDefinerService, + ImplicitParametersExtractor implicitParametersExtractor, IpAddressHelper ipAddressHelper, Metrics metrics, boolean ccpaEnforce, @@ -78,26 +81,28 @@ public PrivacyEnforcementService(BidderCatalog bidderCatalog, this.bidderCatalog = Objects.requireNonNull(bidderCatalog); this.privacyExtractor = Objects.requireNonNull(privacyExtractor); this.tcfDefinerService = Objects.requireNonNull(tcfDefinerService); + this.implicitParametersExtractor = Objects.requireNonNull(implicitParametersExtractor); this.ipAddressHelper = Objects.requireNonNull(ipAddressHelper); this.metrics = Objects.requireNonNull(metrics); this.ccpaEnforce = ccpaEnforce; this.lmtEnforce = lmtEnforce; } - Future contextFromBidRequest( - BidRequest bidRequest, Account account, MetricName requestType, Timeout timeout, List errors) { + public Future contextFromBidRequest(AuctionContext auctionContext) { + final BidRequest bidRequest = auctionContext.getBidRequest(); + final List errors = auctionContext.getPrebidErrors(); + final Account account = auctionContext.getAccount(); + final MetricName requestType = auctionContext.getRequestTypeMetric(); + final Timeout timeout = auctionContext.getTimeout(); final Privacy privacy = privacyExtractor.validPrivacyFrom(bidRequest, errors); final Device device = bidRequest.getDevice(); - final String ipAddress = device != null ? device.getIp() : null; final Geo geo = device != null ? device.getGeo() : null; final String country = geo != null ? geo.getCountry() : null; - final String effectiveIpAddress = isCoppaMaskingRequired(privacy) || isLmtEnabled(device) - ? ipAddressHelper.maskIpv4(ipAddress) - : ipAddress; + final String effectiveIpAddress = resolveIpAddress(device, privacy); final AccountGdprConfig accountGdpr = account.getGdpr(); final String accountId = account.getId(); @@ -108,11 +113,27 @@ Future contextFromBidRequest( .map(tcfContext -> PrivacyContext.of(privacy, tcfContext, tcfContext.getIpAddress())); } + private String resolveIpAddress(Device device, Privacy privacy) { + final boolean shouldBeMasked = isCoppaMaskingRequired(privacy) || isLmtEnabled(device); + + final String ipV4Address = device != null ? device.getIp() : null; + if (StringUtils.isNotBlank(ipV4Address)) { + return shouldBeMasked ? ipAddressHelper.maskIpv4(ipV4Address) : ipV4Address; + } + + final String ipV6Address = device != null ? device.getIpv6() : null; + if (StringUtils.isNotBlank(ipV6Address)) { + return shouldBeMasked ? ipAddressHelper.anonymizeIpv6(ipV6Address) : ipV6Address; + } + + return null; + } + public Future contextFromSetuidRequest( HttpServerRequest httpRequest, Account account, Timeout timeout) { final Privacy privacy = privacyExtractor.validPrivacyFromSetuidRequest(httpRequest); - final String ipAddress = HttpUtil.ipFrom(httpRequest); + final String ipAddress = resolveIpFromRequest(httpRequest); final AccountGdprConfig accountGdpr = account.getGdpr(); final String accountId = account.getId(); final RequestLogInfo requestLogInfo = requestLogInfo(MetricName.setuid, null, accountId); @@ -126,7 +147,7 @@ public Future contextFromCookieSyncRequest( CookieSyncRequest cookieSyncRequest, HttpServerRequest httpRequest, Account account, Timeout timeout) { final Privacy privacy = privacyExtractor.validPrivacyFrom(cookieSyncRequest); - final String ipAddress = HttpUtil.ipFrom(httpRequest); + final String ipAddress = resolveIpFromRequest(httpRequest); final AccountGdprConfig accountGdpr = account.getGdpr(); final String accountId = account.getId(); final RequestLogInfo requestLogInfo = requestLogInfo(MetricName.cookiesync, null, accountId); @@ -136,9 +157,19 @@ public Future contextFromCookieSyncRequest( .map(tcfContext -> PrivacyContext.of(privacy, tcfContext)); } + private String resolveIpFromRequest(HttpServerRequest request) { + final List requestIps = implicitParametersExtractor.ipFrom(request); + return requestIps.stream() + .map(ipAddressHelper::toIpAddress) + .filter(Objects::nonNull) + .map(IpAddress::getIp) + .findFirst() + .orElse(null); + } + private static RequestLogInfo requestLogInfo(MetricName requestType, BidRequest bidRequest, String accountId) { if (Objects.equals(requestType, MetricName.openrtb2web)) { - final Site site = bidRequest.getSite(); + final Site site = bidRequest != null ? bidRequest.getSite() : null; final String refUrl = site != null ? site.getRef() : null; return RequestLogInfo.of(requestType, refUrl, accountId); } @@ -307,7 +338,8 @@ private Future> getBidderToEnforcementActi TcfContext tcfContext, Set bidders, BidderAliases aliases, Account account) { return tcfDefinerService.resultForBidderNames( - Collections.unmodifiableSet(bidders), VendorIdResolver.of(aliases), tcfContext, account.getGdpr()) + Collections.unmodifiableSet(bidders), VendorIdResolver.of(aliases, bidderCatalog), tcfContext, + account.getGdpr()) .map(tcfResponse -> mapTcfResponseToEachBidder(tcfResponse, bidders)); } diff --git a/src/main/java/org/prebid/server/auction/StoredRequestProcessor.java b/src/main/java/org/prebid/server/auction/StoredRequestProcessor.java index 7ff50355f9c..63e33848e5d 100644 --- a/src/main/java/org/prebid/server/auction/StoredRequestProcessor.java +++ b/src/main/java/org/prebid/server/auction/StoredRequestProcessor.java @@ -103,7 +103,7 @@ public static StoredRequestProcessor create(long defaultTimeout, * fetched jsons from source. In case any error happen during the process, returns failedFuture with * InvalidRequestException {@link InvalidRequestException} as cause. */ - Future processStoredRequests(String accountId, BidRequest bidRequest) { + public Future processStoredRequests(String accountId, BidRequest bidRequest) { final Map bidRequestToStoredRequestId; final Map impToStoredRequestId; try { @@ -134,7 +134,7 @@ Future processStoredRequests(String accountId, BidRequest bidRequest /** * Fetches AMP request from the source. */ - Future processAmpRequest(String accountId, String ampRequestId) { + public Future processAmpRequest(String accountId, String ampRequestId) { final BidRequest bidRequest = defaultBidRequest != null ? defaultBidRequest : BidRequest.builder().build(); final Future ampStoredDataFuture = applicationSettings.getAmpStoredData( diff --git a/src/main/java/org/prebid/server/auction/TimeoutResolver.java b/src/main/java/org/prebid/server/auction/TimeoutResolver.java index 29b7042dee7..575a6809b78 100644 --- a/src/main/java/org/prebid/server/auction/TimeoutResolver.java +++ b/src/main/java/org/prebid/server/auction/TimeoutResolver.java @@ -24,7 +24,7 @@ public TimeoutResolver(long defaultTimeout, long maxTimeout, long timeoutAdjustm /** * Resolves timeout according to given in request and pre-configured default and max values. */ - long resolve(Long requestTimeout) { + public long resolve(Long requestTimeout) { final long result; if (requestTimeout == null) { diff --git a/src/main/java/org/prebid/server/auction/VideoStoredRequestProcessor.java b/src/main/java/org/prebid/server/auction/VideoStoredRequestProcessor.java index 5c9f35e4265..577fe48fc74 100644 --- a/src/main/java/org/prebid/server/auction/VideoStoredRequestProcessor.java +++ b/src/main/java/org/prebid/server/auction/VideoStoredRequestProcessor.java @@ -132,9 +132,10 @@ public static VideoStoredRequestProcessor create(boolean enforceStoredRequest, /** * Fetches ParsedStoredDataResult<BidRequestVideo, Imp> from stored request. */ - Future> processVideoRequest(String accountId, String storedBidRequestId, - Set podIds, - BidRequestVideo receivedRequest) { + public Future> processVideoRequest(String accountId, + String storedBidRequestId, + Set podIds, + BidRequestVideo receivedRequest) { final Set storedRequestIds = StringUtils.isNotBlank(storedBidRequestId) ? Collections.singleton(storedBidRequestId) : Collections.emptySet(); diff --git a/src/main/java/org/prebid/server/auction/model/AuctionContext.java b/src/main/java/org/prebid/server/auction/model/AuctionContext.java index f752377e0db..5f72f4adf06 100644 --- a/src/main/java/org/prebid/server/auction/model/AuctionContext.java +++ b/src/main/java/org/prebid/server/auction/model/AuctionContext.java @@ -40,4 +40,15 @@ public class AuctionContext { PrivacyContext privacyContext; GeoInfo geoInfo; + + public AuctionContext with(BidRequest bidRequest) { + return this.toBuilder().bidRequest(bidRequest).build(); + } + + public AuctionContext with(PrivacyContext privacyContext) { + return this.toBuilder() + .privacyContext(privacyContext) + .geoInfo(privacyContext.getTcfContext().getGeoInfo()) + .build(); + } } diff --git a/src/main/java/org/prebid/server/auction/model/BidInfo.java b/src/main/java/org/prebid/server/auction/model/BidInfo.java index 27a7dfd73ea..5d8d43b4761 100644 --- a/src/main/java/org/prebid/server/auction/model/BidInfo.java +++ b/src/main/java/org/prebid/server/auction/model/BidInfo.java @@ -1,26 +1,38 @@ package org.prebid.server.auction.model; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.iab.openrtb.request.Imp; import com.iab.openrtb.response.Bid; import lombok.Builder; import lombok.Value; +import org.prebid.server.cache.model.CacheInfo; import org.prebid.server.proto.openrtb.ext.response.BidType; @Builder(toBuilder = true) @Value public class BidInfo { - String generatedBidId; - Bid bid; Imp correspondingImp; + String bidCurrency; + String bidder; BidType bidType; + CacheInfo cacheInfo; + + TargetingInfo targetingInfo; + public String getBidId() { - return generatedBidId != null ? generatedBidId : bid.getId(); + final ObjectNode extNode = bid != null ? bid.getExt() : null; + final JsonNode bidIdNode = extNode != null ? extNode.path("prebid").path("bidid") : null; + final String generatedBidId = bidIdNode != null && bidIdNode.isTextual() ? bidIdNode.textValue() : null; + final String bidId = bid != null ? bid.getId() : null; + + return generatedBidId != null ? generatedBidId : bidId; } } diff --git a/src/main/java/org/prebid/server/auction/model/BidderResponseInfo.java b/src/main/java/org/prebid/server/auction/model/BidderResponseInfo.java new file mode 100644 index 00000000000..f02a9af5b72 --- /dev/null +++ b/src/main/java/org/prebid/server/auction/model/BidderResponseInfo.java @@ -0,0 +1,20 @@ +package org.prebid.server.auction.model; + +import lombok.AllArgsConstructor; +import lombok.Value; +import org.prebid.server.bidder.model.BidderSeatBidInfo; + +@AllArgsConstructor(staticName = "of") +@Value +public class BidderResponseInfo { + + String bidder; + + BidderSeatBidInfo seatBid; + + int responseTime; + + public BidderResponseInfo with(BidderSeatBidInfo seatBid) { + return of(this.bidder, seatBid, this.responseTime); + } +} diff --git a/src/main/java/org/prebid/server/auction/model/CookieSyncContext.java b/src/main/java/org/prebid/server/auction/model/CookieSyncContext.java index 9528a472664..96760cdf529 100644 --- a/src/main/java/org/prebid/server/auction/model/CookieSyncContext.java +++ b/src/main/java/org/prebid/server/auction/model/CookieSyncContext.java @@ -4,6 +4,7 @@ import io.vertx.ext.web.RoutingContext; import lombok.Builder; import lombok.Value; +import org.prebid.server.bidder.UsersyncMethodChooser; import org.prebid.server.cookie.UidsCookie; import org.prebid.server.execution.Timeout; import org.prebid.server.privacy.model.PrivacyContext; @@ -22,6 +23,9 @@ public class CookieSyncContext { CookieSyncRequest cookieSyncRequest; + @JsonIgnore + UsersyncMethodChooser usersyncMethodChooser; + @JsonIgnore Timeout timeout; diff --git a/src/main/java/org/prebid/server/auction/model/SetuidContext.java b/src/main/java/org/prebid/server/auction/model/SetuidContext.java index d3541068b18..6fa4bb6e8de 100644 --- a/src/main/java/org/prebid/server/auction/model/SetuidContext.java +++ b/src/main/java/org/prebid/server/auction/model/SetuidContext.java @@ -26,5 +26,8 @@ public class SetuidContext { String cookieName; + @JsonIgnore + String syncType; + PrivacyContext privacyContext; } diff --git a/src/main/java/org/prebid/server/auction/model/TargetingInfo.java b/src/main/java/org/prebid/server/auction/model/TargetingInfo.java new file mode 100644 index 00000000000..a85b1041971 --- /dev/null +++ b/src/main/java/org/prebid/server/auction/model/TargetingInfo.java @@ -0,0 +1,19 @@ +package org.prebid.server.auction.model; + +import lombok.Builder; +import lombok.Value; + +@Builder(toBuilder = true) +@Value +public class TargetingInfo { + + String bidderCode; + + boolean isTargetingEnabled; + + boolean isWinningBid; + + boolean isBidderWinningBid; + + boolean isAddTargetBidderCode; +} diff --git a/src/main/java/org/prebid/server/auction/AmpRequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java similarity index 92% rename from src/main/java/org/prebid/server/auction/AmpRequestFactory.java rename to src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java index 04ec9d673ce..3ef5093ba58 100644 --- a/src/main/java/org/prebid/server/auction/AmpRequestFactory.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java @@ -1,4 +1,4 @@ -package org.prebid.server.auction; +package org.prebid.server.auction.requestfactory; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; @@ -20,6 +20,13 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import org.prebid.server.auction.FpdResolver; +import org.prebid.server.auction.ImplicitParametersExtractor; +import org.prebid.server.auction.OrtbTypesResolver; +import org.prebid.server.auction.PriceGranularity; +import org.prebid.server.auction.PrivacyEnforcementService; +import org.prebid.server.auction.StoredRequestProcessor; +import org.prebid.server.auction.TimeoutResolver; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.Tuple2; import org.prebid.server.exception.InvalidRequestException; @@ -73,27 +80,34 @@ public class AmpRequestFactory { private static final int NO_LIMIT_SPLIT_MODE = -1; private static final String AMP_CHANNEL = "amp"; + private final Ortb2RequestFactory ortb2RequestFactory; private final StoredRequestProcessor storedRequestProcessor; - private final AuctionRequestFactory auctionRequestFactory; private final OrtbTypesResolver ortbTypesResolver; private final ImplicitParametersExtractor implicitParametersExtractor; + private final Ortb2ImplicitParametersResolver paramsResolver; private final FpdResolver fpdResolver; + private final PrivacyEnforcementService privacyEnforcementService; private final TimeoutResolver timeoutResolver; private final JacksonMapper mapper; public AmpRequestFactory(StoredRequestProcessor storedRequestProcessor, - AuctionRequestFactory auctionRequestFactory, + Ortb2RequestFactory ortb2RequestFactory, OrtbTypesResolver ortbTypesResolver, ImplicitParametersExtractor implicitParametersExtractor, + Ortb2ImplicitParametersResolver paramsResolver, FpdResolver fpdResolver, + PrivacyEnforcementService privacyEnforcementService, TimeoutResolver timeoutResolver, JacksonMapper mapper) { + this.storedRequestProcessor = Objects.requireNonNull(storedRequestProcessor); - this.auctionRequestFactory = Objects.requireNonNull(auctionRequestFactory); + this.ortb2RequestFactory = Objects.requireNonNull(ortb2RequestFactory); this.ortbTypesResolver = Objects.requireNonNull(ortbTypesResolver); this.implicitParametersExtractor = Objects.requireNonNull(implicitParametersExtractor); + this.paramsResolver = Objects.requireNonNull(paramsResolver); this.fpdResolver = Objects.requireNonNull(fpdResolver); this.timeoutResolver = Objects.requireNonNull(timeoutResolver); + this.privacyEnforcementService = Objects.requireNonNull(privacyEnforcementService); this.mapper = Objects.requireNonNull(mapper); } @@ -101,32 +115,42 @@ public AmpRequestFactory(StoredRequestProcessor storedRequestProcessor, * Creates {@link AuctionContext} based on {@link RoutingContext}. */ public Future fromRequest(RoutingContext routingContext, long startTime) { - final String tagId = routingContext.request().getParam(TAG_ID_REQUEST_PARAM); - if (StringUtils.isBlank(tagId)) { - return Future.failedFuture(new InvalidRequestException("AMP requests require an AMP tag_id")); - } - return createBidRequest(routingContext, tagId) - .compose(bidRequestWithErrors -> auctionRequestFactory.toAuctionContext( + return createBidRequest(routingContext) + .compose(bidRequestWithErrors -> ortb2RequestFactory.fetchAccountAndCreateAuctionContext( routingContext, bidRequestWithErrors.getLeft(), MetricName.amp, - bidRequestWithErrors.getRight(), + false, startTime, - timeoutResolver)); + bidRequestWithErrors.getRight())) + + .compose(auctionContext -> privacyEnforcementService.contextFromBidRequest(auctionContext) + .map(auctionContext::with)) + + .map(auctionContext -> auctionContext.with( + ortb2RequestFactory.enrichBidRequestWithAccountAndPrivacyData( + auctionContext.getBidRequest(), + auctionContext.getAccount(), + auctionContext.getPrivacyContext()))); } /** * Creates {@link BidRequest} and sets properties which were not set explicitly by the client, but can be * updated by values derived from headers and other request attributes. */ - private Future>> createBidRequest(RoutingContext context, String tagId) { + private Future>> createBidRequest(RoutingContext context) { + final String tagId = context.request().getParam(TAG_ID_REQUEST_PARAM); + if (StringUtils.isBlank(tagId)) { + return Future.failedFuture(new InvalidRequestException("AMP requests require an AMP tag_id")); + } + final List errors = new ArrayList<>(); return storedRequestProcessor.processAmpRequest(context.request().getParam(ACCOUNT_REQUEST_PARAM), tagId) .map(bidRequest -> validateStoredBidRequest(tagId, bidRequest)) .map(bidRequest -> fillExplicitParameters(bidRequest, context)) .map(bidRequest -> overrideParameters(bidRequest, context.request(), errors)) - .map(bidRequest -> auctionRequestFactory.fillImplicitParameters(bidRequest, context, timeoutResolver)) - .map(auctionRequestFactory::validateRequest) + .map(bidRequest -> paramsResolver.resolve(bidRequest, context, timeoutResolver)) + .map(ortb2RequestFactory::validateRequest) .map(bidRequest -> Tuple2.of(bidRequest, errors)); } @@ -341,7 +365,7 @@ private Site overrideSite(Site site, HttpServerRequest request) { if (StringUtils.isNotBlank(canonicalUrl)) { siteBuilder.page(canonicalUrl); - final String domain = HttpUtil.getDomainFromUrl(canonicalUrl); + final String domain = HttpUtil.getHostFromUrl(canonicalUrl); if (StringUtils.isNotBlank(domain)) { siteBuilder.domain(domain); } diff --git a/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java new file mode 100644 index 00000000000..f0059f06f5e --- /dev/null +++ b/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java @@ -0,0 +1,159 @@ +package org.prebid.server.auction.requestfactory; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.iab.openrtb.request.BidRequest; +import io.vertx.core.Future; +import io.vertx.ext.web.RoutingContext; +import org.prebid.server.auction.ImplicitParametersExtractor; +import org.prebid.server.auction.InterstitialProcessor; +import org.prebid.server.auction.OrtbTypesResolver; +import org.prebid.server.auction.PrivacyEnforcementService; +import org.prebid.server.auction.StoredRequestProcessor; +import org.prebid.server.auction.TimeoutResolver; +import org.prebid.server.auction.model.AuctionContext; +import org.prebid.server.exception.InvalidRequestException; +import org.prebid.server.json.JacksonMapper; +import org.prebid.server.metric.MetricName; +import org.prebid.server.settings.model.Account; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * Used in OpenRTB request processing. + */ +public class AuctionRequestFactory { + + private final long maxRequestSize; + private final Ortb2RequestFactory ortb2RequestFactory; + private final StoredRequestProcessor storedRequestProcessor; + private final ImplicitParametersExtractor paramsExtractor; + private final Ortb2ImplicitParametersResolver paramsResolver; + private final InterstitialProcessor interstitialProcessor; + private final PrivacyEnforcementService privacyEnforcementService; + private final TimeoutResolver timeoutResolver; + private final JacksonMapper mapper; + private final OrtbTypesResolver ortbTypesResolver; + + public AuctionRequestFactory(long maxRequestSize, + Ortb2RequestFactory ortb2RequestFactory, + StoredRequestProcessor storedRequestProcessor, + ImplicitParametersExtractor paramsExtractor, + Ortb2ImplicitParametersResolver paramsResolver, + InterstitialProcessor interstitialProcessor, + OrtbTypesResolver ortbTypesResolver, + PrivacyEnforcementService privacyEnforcementService, + TimeoutResolver timeoutResolver, + JacksonMapper mapper) { + + this.maxRequestSize = maxRequestSize; + this.ortb2RequestFactory = Objects.requireNonNull(ortb2RequestFactory); + this.storedRequestProcessor = Objects.requireNonNull(storedRequestProcessor); + this.paramsExtractor = Objects.requireNonNull(paramsExtractor); + this.paramsResolver = Objects.requireNonNull(paramsResolver); + this.interstitialProcessor = Objects.requireNonNull(interstitialProcessor); + this.ortbTypesResolver = Objects.requireNonNull(ortbTypesResolver); + this.privacyEnforcementService = Objects.requireNonNull(privacyEnforcementService); + this.timeoutResolver = Objects.requireNonNull(timeoutResolver); + this.mapper = Objects.requireNonNull(mapper); + } + + /** + * Creates {@link AuctionContext} based on {@link RoutingContext}. + */ + public Future fromRequest(RoutingContext routingContext, long startTime) { + final List errors = new ArrayList<>(); + final String body; + try { + body = extractAndValidateBody(routingContext); + } catch (InvalidRequestException e) { + return Future.failedFuture(e); + } + + return parseBidRequest(body, routingContext, errors) + .compose(bidRequest -> ortb2RequestFactory.fetchAccountAndCreateAuctionContext( + routingContext, + bidRequest, + requestTypeMetric(bidRequest), + true, + startTime, + errors)) + + .compose(auctionContext -> updateBidRequest(auctionContext) + .map(auctionContext::with)) + + .compose(auctionContext -> privacyEnforcementService.contextFromBidRequest(auctionContext) + .map(auctionContext::with)) + + .map(auctionContext -> auctionContext.with( + ortb2RequestFactory.enrichBidRequestWithAccountAndPrivacyData( + auctionContext.getBidRequest(), + auctionContext.getAccount(), + auctionContext.getPrivacyContext()))); + } + + private String extractAndValidateBody(RoutingContext context) { + final String body = context.getBodyAsString(); + if (body == null) { + throw new InvalidRequestException("Incoming request has no body"); + } + + if (body.length() > maxRequestSize) { + throw new InvalidRequestException( + String.format("Request size exceeded max size of %d bytes.", maxRequestSize)); + } + + return body; + } + + private Future parseBidRequest(String body, RoutingContext context, List errors) { + try { + final JsonNode bidRequestNode = bodyAsJsonNode(body); + + final String referer = paramsExtractor.refererFrom(context.request()); + ortbTypesResolver.normalizeBidRequest(bidRequestNode, errors, referer); + + return Future.succeededFuture(jsonNodeAsBidRequest(bidRequestNode)); + } catch (Exception e) { + return Future.failedFuture(e); + } + } + + private JsonNode bodyAsJsonNode(String body) { + try { + return mapper.mapper().readTree(body); + } catch (IOException e) { + throw new InvalidRequestException(String.format("Error decoding bidRequest: %s", e.getMessage())); + } + } + + private BidRequest jsonNodeAsBidRequest(JsonNode bidRequestNode) { + try { + return mapper.mapper().treeToValue(bidRequestNode, BidRequest.class); + } catch (JsonProcessingException e) { + throw new InvalidRequestException(String.format("Error decoding bidRequest: %s", e.getMessage())); + } + } + + /** + * Sets {@link BidRequest} properties which were not set explicitly by the client, but can be + * updated by values derived from headers and other request attributes. + */ + private Future updateBidRequest(AuctionContext auctionContext) { + final Account account = auctionContext.getAccount(); + final BidRequest bidRequest = auctionContext.getBidRequest(); + final RoutingContext routingContext = auctionContext.getRoutingContext(); + + return storedRequestProcessor.processStoredRequests(account.getId(), bidRequest) + .map(resolvedBidRequest -> paramsResolver.resolve(resolvedBidRequest, routingContext, timeoutResolver)) + .map(ortb2RequestFactory::validateRequest) + .map(interstitialProcessor::process); + } + + private static MetricName requestTypeMetric(BidRequest bidRequest) { + return bidRequest.getApp() != null ? MetricName.openrtb2app : MetricName.openrtb2web; + } +} diff --git a/src/main/java/org/prebid/server/auction/AuctionRequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolver.java similarity index 57% rename from src/main/java/org/prebid/server/auction/AuctionRequestFactory.java rename to src/main/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolver.java index b117663cf94..b7fc82d7ad5 100644 --- a/src/main/java/org/prebid/server/auction/AuctionRequestFactory.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolver.java @@ -1,19 +1,14 @@ -package org.prebid.server.auction; +package org.prebid.server.auction.requestfactory; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.iab.openrtb.request.App; import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Device; -import com.iab.openrtb.request.Geo; import com.iab.openrtb.request.Imp; import com.iab.openrtb.request.Publisher; import com.iab.openrtb.request.Site; import com.iab.openrtb.request.Source; -import io.netty.buffer.ByteBufInputStream; -import io.vertx.core.Future; -import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpServerRequest; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; @@ -21,28 +16,19 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; -import org.prebid.server.auction.model.AuctionContext; +import org.prebid.server.auction.ImplicitParametersExtractor; +import org.prebid.server.auction.IpAddressHelper; +import org.prebid.server.auction.PriceGranularity; +import org.prebid.server.auction.TimeoutResolver; import org.prebid.server.auction.model.IpAddress; -import org.prebid.server.bidder.BidderCatalog; -import org.prebid.server.cookie.UidsCookieService; -import org.prebid.server.exception.BlacklistedAccountException; import org.prebid.server.exception.BlacklistedAppException; import org.prebid.server.exception.InvalidRequestException; import org.prebid.server.exception.PreBidException; -import org.prebid.server.exception.UnauthorizedAccountException; -import org.prebid.server.execution.Timeout; -import org.prebid.server.execution.TimeoutFactory; -import org.prebid.server.geolocation.model.GeoInfo; import org.prebid.server.identity.IdGenerator; import org.prebid.server.json.JacksonMapper; -import org.prebid.server.log.ConditionalLogger; -import org.prebid.server.metric.MetricName; -import org.prebid.server.privacy.model.PrivacyContext; import org.prebid.server.proto.openrtb.ext.request.ExtDevice; import org.prebid.server.proto.openrtb.ext.request.ExtMediaTypePriceGranularity; import org.prebid.server.proto.openrtb.ext.request.ExtPriceGranularity; -import org.prebid.server.proto.openrtb.ext.request.ExtPublisher; -import org.prebid.server.proto.openrtb.ext.request.ExtPublisherPrebid; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidCache; @@ -50,37 +36,22 @@ import org.prebid.server.proto.openrtb.ext.request.ExtRequestTargeting; import org.prebid.server.proto.openrtb.ext.request.ExtSite; import org.prebid.server.proto.openrtb.ext.response.BidType; -import org.prebid.server.settings.ApplicationSettings; -import org.prebid.server.settings.model.Account; -import org.prebid.server.settings.model.AccountStatus; import org.prebid.server.util.HttpUtil; import org.prebid.server.util.StreamUtil; -import org.prebid.server.validation.RequestValidator; -import org.prebid.server.validation.model.ValidationResult; -import java.io.IOException; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Currency; -import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; -/** - * Used in OpenRTB request processing. - */ -public class AuctionRequestFactory { +public class Ortb2ImplicitParametersResolver { - private static final Logger logger = LoggerFactory.getLogger(AuctionRequestFactory.class); - private static final ConditionalLogger EMPTY_ACCOUNT_LOGGER = new ConditionalLogger("empty_account", logger); - private static final ConditionalLogger UNKNOWN_ACCOUNT_LOGGER = new ConditionalLogger("unknown_account", logger); + private static final Logger logger = LoggerFactory.getLogger(Ortb2ImplicitParametersResolver.class); private static final String WEB_CHANNEL = "web"; private static final String APP_CHANNEL = "app"; @@ -91,67 +62,28 @@ public class AuctionRequestFactory { private static final Set IMP_EXT_NON_BIDDER_FIELDS = Collections.unmodifiableSet(new HashSet<>( Arrays.asList(PREBID_EXT, "context", "all", "general", "skadn", "data"))); - private final long maxRequestSize; - private final boolean enforceValidAccount; private final boolean shouldCacheOnlyWinningBids; private final String adServerCurrency; private final List blacklistedApps; - private final List blacklistedAccounts; - private final StoredRequestProcessor storedRequestProcessor; private final ImplicitParametersExtractor paramsExtractor; private final IpAddressHelper ipAddressHelper; - private final UidsCookieService uidsCookieService; - private final BidderCatalog bidderCatalog; - private final RequestValidator requestValidator; - private final InterstitialProcessor interstitialProcessor; - private final TimeoutResolver timeoutResolver; - private final TimeoutFactory timeoutFactory; - private final ApplicationSettings applicationSettings; private final IdGenerator sourceIdGenerator; - private final PrivacyEnforcementService privacyEnforcementService; private final JacksonMapper mapper; - private final OrtbTypesResolver ortbTypesResolver; - - public AuctionRequestFactory(long maxRequestSize, - boolean enforceValidAccount, - boolean shouldCacheOnlyWinningBids, - String adServerCurrency, - List blacklistedApps, - List blacklistedAccounts, - StoredRequestProcessor storedRequestProcessor, - ImplicitParametersExtractor paramsExtractor, - IpAddressHelper ipAddressHelper, - UidsCookieService uidsCookieService, - BidderCatalog bidderCatalog, - RequestValidator requestValidator, - InterstitialProcessor interstitialProcessor, - OrtbTypesResolver ortbTypesResolver, - TimeoutResolver timeoutResolver, - TimeoutFactory timeoutFactory, - ApplicationSettings applicationSettings, - IdGenerator sourceIdGenerator, - PrivacyEnforcementService privacyEnforcementService, - JacksonMapper mapper) { - - this.maxRequestSize = maxRequestSize; - this.enforceValidAccount = enforceValidAccount; + + public Ortb2ImplicitParametersResolver(boolean shouldCacheOnlyWinningBids, + String adServerCurrency, + List blacklistedApps, + ImplicitParametersExtractor paramsExtractor, + IpAddressHelper ipAddressHelper, + IdGenerator sourceIdGenerator, + JacksonMapper mapper) { + this.shouldCacheOnlyWinningBids = shouldCacheOnlyWinningBids; this.adServerCurrency = validateCurrency(Objects.requireNonNull(adServerCurrency)); this.blacklistedApps = Objects.requireNonNull(blacklistedApps); - this.blacklistedAccounts = Objects.requireNonNull(blacklistedAccounts); - this.storedRequestProcessor = Objects.requireNonNull(storedRequestProcessor); this.paramsExtractor = Objects.requireNonNull(paramsExtractor); this.ipAddressHelper = Objects.requireNonNull(ipAddressHelper); - this.uidsCookieService = Objects.requireNonNull(uidsCookieService); - this.bidderCatalog = Objects.requireNonNull(bidderCatalog); - this.requestValidator = Objects.requireNonNull(requestValidator); - this.interstitialProcessor = Objects.requireNonNull(interstitialProcessor); - this.ortbTypesResolver = Objects.requireNonNull(ortbTypesResolver); - this.timeoutResolver = Objects.requireNonNull(timeoutResolver); - this.timeoutFactory = Objects.requireNonNull(timeoutFactory); - this.applicationSettings = Objects.requireNonNull(applicationSettings); this.sourceIdGenerator = Objects.requireNonNull(sourceIdGenerator); - this.privacyEnforcementService = Objects.requireNonNull(privacyEnforcementService); this.mapper = Objects.requireNonNull(mapper); } @@ -167,111 +99,15 @@ private static String validateCurrency(String code) { return code; } - /** - * Creates {@link AuctionContext} based on {@link RoutingContext}. - */ - public Future fromRequest(RoutingContext routingContext, long startTime) { - final List errors = new ArrayList<>(); - final BidRequest incomingBidRequest; - try { - incomingBidRequest = parseRequest(routingContext, errors); - } catch (InvalidRequestException e) { - return Future.failedFuture(e); - } - - return updateBidRequest(routingContext, incomingBidRequest) - .compose(bidRequest -> toAuctionContext( - routingContext, - bidRequest, - requestTypeMetric(bidRequest), - errors, - startTime, - timeoutResolver)); - } - - /** - * Returns filled out {@link AuctionContext} based on given arguments. - *

- * Note: {@link TimeoutResolver} used here as argument because this method is utilized in AMP processing. - */ - Future toAuctionContext(RoutingContext routingContext, - BidRequest bidRequest, - MetricName requestTypeMetric, - List errors, - long startTime, - TimeoutResolver timeoutResolver) { - - final Timeout timeout = timeout(bidRequest, startTime, timeoutResolver); - - return accountFrom(bidRequest, timeout, routingContext) - .compose(account -> privacyEnforcementService.contextFromBidRequest( - bidRequest, account, requestTypeMetric, timeout, errors) - .map(privacyContext -> AuctionContext.builder() - .routingContext(routingContext) - .uidsCookie(uidsCookieService.parseFromRequest(routingContext)) - .bidRequest(enrichBidRequestWithAccountAndPrivacyData( - bidRequest, account, privacyContext)) - .requestTypeMetric(requestTypeMetric) - .timeout(timeout) - .account(account) - .prebidErrors(errors) - .debugWarnings(new ArrayList<>()) - .privacyContext(privacyContext) - .geoInfo(privacyContext.getTcfContext().getGeoInfo()) - .build())); - } - - /** - * Parses request body to {@link BidRequest}. - *

- * Throws {@link InvalidRequestException} if body is empty, exceeds max request size or couldn't be deserialized. - */ - private BidRequest parseRequest(RoutingContext context, List errors) { - final Buffer body = context.getBody(); - if (body == null) { - throw new InvalidRequestException("Incoming request has no body"); - } - - if (body.length() > maxRequestSize) { - throw new InvalidRequestException( - String.format("Request size exceeded max size of %d bytes.", maxRequestSize)); - } - - final JsonNode bidRequestNode; - try (ByteBufInputStream inputStream = new ByteBufInputStream(body.getByteBuf())) { - bidRequestNode = mapper.mapper().readTree(inputStream); - } catch (IOException e) { - throw new InvalidRequestException(String.format("Error decoding bidRequest: %s", e.getMessage())); - } - - final String referer = paramsExtractor.refererFrom(context.request()); - ortbTypesResolver.normalizeBidRequest(bidRequestNode, errors, referer); - - try { - return mapper.mapper().treeToValue(bidRequestNode, BidRequest.class); - } catch (JsonProcessingException e) { - throw new InvalidRequestException(String.format("Error decoding bidRequest: %s", e.getMessage())); - } - } - - /** - * Sets {@link BidRequest} properties which were not set explicitly by the client, but can be - * updated by values derived from headers and other request attributes. - */ - private Future updateBidRequest(RoutingContext context, BidRequest bidRequest) { - return storedRequestProcessor.processStoredRequests(accountIdFrom(bidRequest), bidRequest) - .map(resolvedBidRequest -> fillImplicitParameters(resolvedBidRequest, context, timeoutResolver)) - .map(this::validateRequest) - .map(interstitialProcessor::process); - } - /** * If needed creates a new {@link BidRequest} which is a copy of original but with some fields set with values * derived from request parameters (headers, cookie etc.). *

* Note: {@link TimeoutResolver} used here as argument because this method is utilized in AMP processing. */ - BidRequest fillImplicitParameters(BidRequest bidRequest, RoutingContext context, TimeoutResolver timeoutResolver) { + BidRequest resolve(BidRequest bidRequest, + RoutingContext context, + TimeoutResolver timeoutResolver) { checkBlacklistedApp(bidRequest); final BidRequest result; @@ -506,25 +342,48 @@ private Site populateSite(Site site, HttpServerRequest request) { final String domain = site != null ? StringUtils.trimToNull(site.getDomain()) : null; final String updatedDomain = domain == null - ? getDomainOrNull(ObjectUtils.defaultIfNull(updatedPage, page)) + ? HttpUtil.getHostFromUrl(ObjectUtils.defaultIfNull(updatedPage, page)) : null; + final Publisher publisher = site != null ? site.getPublisher() : null; + final Publisher updatedPublisher = populateSitePublisher( + publisher, ObjectUtils.defaultIfNull(updatedDomain, domain)); + final ExtSite siteExt = site != null ? site.getExt() : null; final ExtSite updatedSiteExt = siteExt == null || siteExt.getAmp() == null ? ExtSite.of(0, getIfNotNull(siteExt, ExtSite::getData)) : null; - if (updatedPage != null || updatedDomain != null || updatedSiteExt != null) { + if (ObjectUtils.anyNotNull(updatedPage, updatedDomain, updatedPublisher, updatedSiteExt)) { + final boolean domainPresent = (publisher != null && publisher.getDomain() != null) + || (updatedPublisher != null && updatedPublisher.getDomain() != null); + return (site == null ? Site.builder() : site.toBuilder()) // do not set page if domain was not parsed successfully - .page(domain == null && updatedDomain == null ? page : ObjectUtils.defaultIfNull(updatedPage, page)) + .page(domainPresent ? ObjectUtils.defaultIfNull(updatedPage, page) : page) .domain(ObjectUtils.defaultIfNull(updatedDomain, domain)) + .publisher(ObjectUtils.defaultIfNull(updatedPublisher, publisher)) .ext(ObjectUtils.defaultIfNull(updatedSiteExt, siteExt)) .build(); } return null; } + private Publisher populateSitePublisher(Publisher publisher, String domain) { + final String publisherDomain = publisher != null ? publisher.getDomain() : null; + final String updatedPublisherDomain = publisherDomain == null + ? getDomainOrNull(domain) + : null; + + if (updatedPublisherDomain != null) { + return (publisher == null ? Publisher.builder() : publisher.toBuilder()) + .domain(updatedPublisherDomain) + .build(); + } + + return null; + } + private String getDomainOrNull(String url) { try { return paramsExtractor.domainFrom(url); @@ -652,18 +511,15 @@ private ExtRequest populateRequestExt(ExtRequest ext, BidRequest bidRequest, Lis final ExtRequestPrebid prebid = ext.getPrebid(); final ExtRequestTargeting updatedTargeting = targetingOrNull(prebid, getImpMediaTypes(imps)); - final Map updatedAliases = aliasesOrNull(prebid, imps); final ExtRequestPrebidCache updatedCache = cacheOrNull(prebid); final ExtRequestPrebidChannel updatedChannel = channelOrNull(prebid, bidRequest); - if (updatedTargeting != null || updatedAliases != null || updatedCache != null || updatedChannel != null) { + if (updatedTargeting != null || updatedCache != null || updatedChannel != null) { final ExtRequestPrebid.ExtRequestPrebidBuilder prebidBuilder = prebid != null ? prebid.toBuilder() : ExtRequestPrebid.builder(); return ExtRequest.of(prebidBuilder - .aliases(ObjectUtils.defaultIfNull(updatedAliases, - getIfNotNull(prebid, ExtRequestPrebid::getAliases))) .targeting(ObjectUtils.defaultIfNull(updatedTargeting, getIfNotNull(prebid, ExtRequestPrebid::getTargeting))) .cache(ObjectUtils.defaultIfNull(updatedCache, @@ -799,41 +655,6 @@ private static Set checkExistingMediaTypes(ExtMediaTypePriceGranularity return priceGranularityTypes; } - /** - * Returns aliases according to request.imp[i].ext.{bidder} - * or null (if no aliases at all or they are already presented in request). - */ - private Map aliasesOrNull(ExtRequestPrebid prebid, List imps) { - final Map aliases = getIfNotNullOrDefault(prebid, ExtRequestPrebid::getAliases, - Collections.emptyMap()); - - // go through imps' bidders and figure out preconfigured aliases - final Map resolvedAliases = imps.stream() - .filter(Objects::nonNull) - .filter(imp -> imp.getExt() != null) // request validator is not called yet - .flatMap(imp -> StreamUtil.asStream(biddersFromImp(imp)) - .filter(bidder -> !aliases.containsKey(bidder)) - .filter(bidderCatalog::isAlias)) - .distinct() - .collect(Collectors.toMap(Function.identity(), bidderCatalog::nameByAlias)); - - final Map result; - if (resolvedAliases.isEmpty()) { - result = null; - } else { - result = new HashMap<>(aliases); - result.putAll(resolvedAliases); - } - return result; - } - - private Iterator biddersFromImp(Imp imp) { - final JsonNode extPrebid = imp.getExt().get(PREBID_EXT); - final JsonNode extPrebidBidder = isObjectNode(extPrebid) ? extPrebid.get(BIDDER_EXT) : null; - - return isObjectNode(extPrebidBidder) ? extPrebidBidder.fieldNames() : Collections.emptyIterator(); - } - /** * Returns populated {@link ExtRequestPrebidCache} or null if no changes were applied. */ @@ -900,190 +721,4 @@ private static Long resolveTmax(Long requestTimeout, TimeoutResolver timeoutReso private static R getIfNotNull(T target, Function getter) { return target != null ? getter.apply(target) : null; } - - private static R getIfNotNullOrDefault(T target, Function getter, R defaultValue) { - return ObjectUtils.defaultIfNull(getIfNotNull(target, getter), defaultValue); - } - - /** - * Performs thorough validation of fully constructed {@link BidRequest} that is going to be used to hold an auction. - */ - BidRequest validateRequest(BidRequest bidRequest) { - final ValidationResult validationResult = requestValidator.validate(bidRequest); - if (validationResult.hasErrors()) { - throw new InvalidRequestException(validationResult.getErrors()); - } - return bidRequest; - } - - /** - * Returns {@link Timeout} based on request.tmax and adjustment value of {@link TimeoutResolver}. - */ - private Timeout timeout(BidRequest bidRequest, long startTime, TimeoutResolver timeoutResolver) { - final long timeout = timeoutResolver.adjustTimeout(bidRequest.getTmax()); - return timeoutFactory.create(startTime, timeout); - } - - /** - * Returns {@link Account} fetched by {@link ApplicationSettings}. - */ - private Future accountFrom(BidRequest bidRequest, Timeout timeout, RoutingContext routingContext) { - final String accountId = accountIdFrom(bidRequest); - final boolean blankAccountId = StringUtils.isBlank(accountId); - - if (CollectionUtils.isNotEmpty(blacklistedAccounts) && !blankAccountId - && blacklistedAccounts.contains(accountId)) { - throw new BlacklistedAccountException(String.format("Prebid-server has blacklisted Account ID: %s, please " - + "reach out to the prebid server host.", accountId)); - } - - return blankAccountId - ? responseForEmptyAccount(routingContext) - : applicationSettings.getAccountById(accountId, timeout) - .compose(this::ensureAccountActive, - exception -> accountFallback(exception, accountId, routingContext)); - } - - /** - * Extracts publisher id either from {@link BidRequest}.app.publisher or {@link BidRequest}.site.publisher. - * If neither is present returns empty string. - */ - private String accountIdFrom(BidRequest bidRequest) { - final App app = bidRequest.getApp(); - final Publisher appPublisher = app != null ? app.getPublisher() : null; - final Site site = bidRequest.getSite(); - final Publisher sitePublisher = site != null ? site.getPublisher() : null; - - final Publisher publisher = ObjectUtils.defaultIfNull(appPublisher, sitePublisher); - final String publisherId = publisher != null ? resolvePublisherId(publisher) : null; - return ObjectUtils.defaultIfNull(publisherId, StringUtils.EMPTY); - } - - /** - * Resolves what value should be used as a publisher id - either taken from publisher.ext.parentAccount - * or publisher.id in this respective priority. - */ - private String resolvePublisherId(Publisher publisher) { - final String parentAccountId = parentAccountIdFromExtPublisher(publisher.getExt()); - return ObjectUtils.defaultIfNull(parentAccountId, publisher.getId()); - } - - /** - * Parses publisher.ext and returns parentAccount value from it. Returns null if any parsing error occurs. - */ - private String parentAccountIdFromExtPublisher(ExtPublisher extPublisher) { - final ExtPublisherPrebid extPublisherPrebid = extPublisher != null ? extPublisher.getPrebid() : null; - return extPublisherPrebid != null ? StringUtils.stripToNull(extPublisherPrebid.getParentAccount()) : null; - } - - private Future responseForEmptyAccount(RoutingContext routingContext) { - EMPTY_ACCOUNT_LOGGER.warn(accountErrorMessage("Account not specified", routingContext), 100); - return responseForUnknownAccount(StringUtils.EMPTY); - } - - private static String accountErrorMessage(String message, RoutingContext routingContext) { - final HttpServerRequest request = routingContext.request(); - return String.format("%s, Url: %s and Referer: %s", message, request.absoluteURI(), - request.headers().get(HttpUtil.REFERER_HEADER)); - } - - private Future accountFallback(Throwable exception, String accountId, - RoutingContext routingContext) { - if (exception instanceof PreBidException) { - UNKNOWN_ACCOUNT_LOGGER.warn(accountErrorMessage(exception.getMessage(), routingContext), 100); - } else { - logger.warn("Error occurred while fetching account: {0}", exception.getMessage()); - logger.debug("Error occurred while fetching account", exception); - } - - // hide all errors occurred while fetching account - return responseForUnknownAccount(accountId); - } - - private Future responseForUnknownAccount(String accountId) { - return enforceValidAccount - ? Future.failedFuture(new UnauthorizedAccountException( - String.format("Unauthorized account id: %s", accountId), accountId)) - : Future.succeededFuture(Account.empty(accountId)); - } - - private Future ensureAccountActive(Account account) { - final String accountId = account.getId(); - - return account.getStatus() == AccountStatus.inactive - ? Future.failedFuture(new UnauthorizedAccountException( - String.format("Account %s is inactive", accountId), accountId)) - : Future.succeededFuture(account); - } - - private BidRequest enrichBidRequestWithAccountAndPrivacyData( - BidRequest bidRequest, Account account, PrivacyContext privacyContext) { - - final ExtRequest requestExt = bidRequest.getExt(); - final ExtRequest enrichedRequestExt = enrichExtRequest(requestExt, account); - - final Device device = bidRequest.getDevice(); - final Device enrichedDevice = enrichDevice(device, privacyContext); - - if (enrichedRequestExt != null || enrichedDevice != null) { - return bidRequest.toBuilder() - .ext(ObjectUtils.defaultIfNull(enrichedRequestExt, requestExt)) - .device(ObjectUtils.defaultIfNull(enrichedDevice, device)) - .build(); - } - - return bidRequest; - } - - private ExtRequest enrichExtRequest(ExtRequest ext, Account account) { - final ExtRequestPrebid prebidExt = getIfNotNull(ext, ExtRequest::getPrebid); - final String integration = getIfNotNull(prebidExt, ExtRequestPrebid::getIntegration); - final String accountDefaultIntegration = account.getDefaultIntegration(); - - if (StringUtils.isBlank(integration) && StringUtils.isNotBlank(accountDefaultIntegration)) { - final ExtRequestPrebid.ExtRequestPrebidBuilder prebidExtBuilder = - prebidExt != null ? prebidExt.toBuilder() : ExtRequestPrebid.builder(); - - prebidExtBuilder.integration(accountDefaultIntegration); - - return ExtRequest.of(prebidExtBuilder.build()); - } - - return null; - } - - private Device enrichDevice(Device device, PrivacyContext privacyContext) { - final String ipAddress = privacyContext.getIpAddress(); - final String country = getIfNotNull(privacyContext.getTcfContext().getGeoInfo(), GeoInfo::getCountry); - - final String ipAddressInRequest = getIfNotNull(device, Device::getIp); - - final Geo geo = getIfNotNull(device, Device::getGeo); - final String countryFromRequest = getIfNotNull(geo, Geo::getCountry); - - final boolean shouldUpdateIp = ipAddress != null && !Objects.equals(ipAddressInRequest, ipAddress); - final boolean shouldUpdateCountry = country != null && !Objects.equals(countryFromRequest, country); - - if (shouldUpdateIp || shouldUpdateCountry) { - final Device.DeviceBuilder deviceBuilder = device != null ? device.toBuilder() : Device.builder(); - - if (shouldUpdateIp) { - deviceBuilder.ip(ipAddress); - } - - if (shouldUpdateCountry) { - final Geo.GeoBuilder geoBuilder = geo != null ? geo.toBuilder() : Geo.builder(); - geoBuilder.country(country); - deviceBuilder.geo(geoBuilder.build()); - } - - return deviceBuilder.build(); - } - - return null; - } - - private static MetricName requestTypeMetric(BidRequest bidRequest) { - return bidRequest.getApp() != null ? MetricName.openrtb2app : MetricName.openrtb2web; - } } diff --git a/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java new file mode 100644 index 00000000000..6a82ab44a10 --- /dev/null +++ b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java @@ -0,0 +1,329 @@ +package org.prebid.server.auction.requestfactory; + +import com.iab.openrtb.request.App; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Device; +import com.iab.openrtb.request.Geo; +import com.iab.openrtb.request.Publisher; +import com.iab.openrtb.request.Site; +import io.vertx.core.Future; +import io.vertx.core.http.HttpServerRequest; +import io.vertx.core.logging.Logger; +import io.vertx.core.logging.LoggerFactory; +import io.vertx.ext.web.RoutingContext; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.prebid.server.auction.IpAddressHelper; +import org.prebid.server.auction.StoredRequestProcessor; +import org.prebid.server.auction.TimeoutResolver; +import org.prebid.server.auction.model.AuctionContext; +import org.prebid.server.auction.model.IpAddress; +import org.prebid.server.cookie.UidsCookieService; +import org.prebid.server.exception.BlacklistedAccountException; +import org.prebid.server.exception.InvalidRequestException; +import org.prebid.server.exception.PreBidException; +import org.prebid.server.exception.UnauthorizedAccountException; +import org.prebid.server.execution.Timeout; +import org.prebid.server.execution.TimeoutFactory; +import org.prebid.server.geolocation.model.GeoInfo; +import org.prebid.server.log.ConditionalLogger; +import org.prebid.server.metric.MetricName; +import org.prebid.server.privacy.model.PrivacyContext; +import org.prebid.server.proto.openrtb.ext.request.ExtPublisher; +import org.prebid.server.proto.openrtb.ext.request.ExtPublisherPrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; +import org.prebid.server.settings.ApplicationSettings; +import org.prebid.server.settings.model.Account; +import org.prebid.server.settings.model.AccountStatus; +import org.prebid.server.util.HttpUtil; +import org.prebid.server.validation.RequestValidator; +import org.prebid.server.validation.model.ValidationResult; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; + +public class Ortb2RequestFactory { + + private static final Logger logger = LoggerFactory.getLogger(Ortb2RequestFactory.class); + + private static final ConditionalLogger EMPTY_ACCOUNT_LOGGER = new ConditionalLogger("empty_account", logger); + private static final ConditionalLogger UNKNOWN_ACCOUNT_LOGGER = new ConditionalLogger("unknown_account", logger); + + private final boolean enforceValidAccount; + private final List blacklistedAccounts; + private final UidsCookieService uidsCookieService; + private final RequestValidator requestValidator; + private final TimeoutResolver timeoutResolver; + private final TimeoutFactory timeoutFactory; + private final StoredRequestProcessor storedRequestProcessor; + private final ApplicationSettings applicationSettings; + private final IpAddressHelper ipAddressHelper; + + public Ortb2RequestFactory(boolean enforceValidAccount, + List blacklistedAccounts, + UidsCookieService uidsCookieService, + RequestValidator requestValidator, + TimeoutResolver timeoutResolver, + TimeoutFactory timeoutFactory, + StoredRequestProcessor storedRequestProcessor, + ApplicationSettings applicationSettings, + IpAddressHelper ipAddressHelper) { + + this.enforceValidAccount = enforceValidAccount; + this.blacklistedAccounts = Objects.requireNonNull(blacklistedAccounts); + this.uidsCookieService = Objects.requireNonNull(uidsCookieService); + this.requestValidator = Objects.requireNonNull(requestValidator); + this.timeoutResolver = Objects.requireNonNull(timeoutResolver); + this.timeoutFactory = Objects.requireNonNull(timeoutFactory); + this.storedRequestProcessor = Objects.requireNonNull(storedRequestProcessor); + this.applicationSettings = Objects.requireNonNull(applicationSettings); + this.ipAddressHelper = Objects.requireNonNull(ipAddressHelper); + } + + public Future fetchAccountAndCreateAuctionContext(RoutingContext routingContext, + BidRequest bidRequest, + MetricName requestTypeMetric, + boolean isLookupStoredRequest, + long startTime, + List errors) { + final Timeout timeout = timeout(bidRequest, startTime, timeoutResolver); + return accountFrom(bidRequest, timeout, routingContext, isLookupStoredRequest) + .map(account -> AuctionContext.builder() + .routingContext(routingContext) + .uidsCookie(uidsCookieService.parseFromRequest(routingContext)) + .bidRequest(bidRequest) + .requestTypeMetric(requestTypeMetric) + .timeout(timeout) + .account(account) + .prebidErrors(errors) + .debugWarnings(new ArrayList<>()) + .build()); + } + + /** + * Performs thorough validation of fully constructed {@link BidRequest} that is going to be used to hold an auction. + */ + public BidRequest validateRequest(BidRequest bidRequest) { + final ValidationResult validationResult = requestValidator.validate(bidRequest); + if (validationResult.hasErrors()) { + throw new InvalidRequestException(validationResult.getErrors()); + } + return bidRequest; + } + + public BidRequest enrichBidRequestWithAccountAndPrivacyData(BidRequest bidRequest, + Account account, + PrivacyContext privacyContext) { + + final ExtRequest requestExt = bidRequest.getExt(); + final ExtRequest enrichedRequestExt = enrichExtRequest(requestExt, account); + + final Device device = bidRequest.getDevice(); + final Device enrichedDevice = enrichDevice(device, privacyContext); + + if (enrichedRequestExt != null || enrichedDevice != null) { + return bidRequest.toBuilder() + .ext(ObjectUtils.defaultIfNull(enrichedRequestExt, requestExt)) + .device(ObjectUtils.defaultIfNull(enrichedDevice, device)) + .build(); + } + + return bidRequest; + } + + /** + * Returns {@link Timeout} based on request.tmax and adjustment value of {@link TimeoutResolver}. + */ + private Timeout timeout(BidRequest bidRequest, long startTime, TimeoutResolver timeoutResolver) { + final long resolvedRequestTimeout = timeoutResolver.resolve(bidRequest.getTmax()); + final long timeout = timeoutResolver.adjustTimeout(resolvedRequestTimeout); + return timeoutFactory.create(startTime, timeout); + } + + /** + * Make lookup for storedRequest if isLookupStoredRequest is true + * and account id is not found in original {@link BidRequest}. + *

+ * Returns {@link Account} fetched by {@link ApplicationSettings}. + */ + private Future accountFrom(BidRequest bidRequest, + Timeout timeout, + RoutingContext routingContext, + boolean isLookupStoredRequest) { + return findAccountIdFrom(bidRequest, isLookupStoredRequest) + .map(this::validateIfAccountBlacklisted) + .compose(accountId -> fetchAccount(timeout, routingContext, accountId)); + } + + private Future findAccountIdFrom(BidRequest bidRequest, boolean isLookupStoredRequest) { + final String accountId = accountIdFrom(bidRequest); + return StringUtils.isNotBlank(accountId) || !isLookupStoredRequest + ? Future.succeededFuture(accountId) + : storedRequestProcessor.processStoredRequests(accountId, bidRequest) + .map(this::accountIdFrom); + } + + private String validateIfAccountBlacklisted(String accountId) { + if (CollectionUtils.isNotEmpty(blacklistedAccounts) + && StringUtils.isNotBlank(accountId) + && blacklistedAccounts.contains(accountId)) { + + throw new BlacklistedAccountException( + String.format("Prebid-server has blacklisted Account ID: %s, please " + + "reach out to the prebid server host.", accountId)); + } + return accountId; + } + + private Future fetchAccount(Timeout timeout, + RoutingContext routingContext, + String accountId) { + return StringUtils.isBlank(accountId) + ? responseForEmptyAccount(routingContext) + : applicationSettings.getAccountById(accountId, timeout) + .compose(this::ensureAccountActive, + exception -> accountFallback(exception, accountId, routingContext)); + } + + /** + * Extracts publisher id either from {@link BidRequest}.app.publisher or {@link BidRequest}.site.publisher. + * If neither is present returns empty string. + */ + private String accountIdFrom(BidRequest bidRequest) { + final App app = bidRequest.getApp(); + final Publisher appPublisher = app != null ? app.getPublisher() : null; + final Site site = bidRequest.getSite(); + final Publisher sitePublisher = site != null ? site.getPublisher() : null; + + final Publisher publisher = ObjectUtils.defaultIfNull(appPublisher, sitePublisher); + final String publisherId = publisher != null ? resolvePublisherId(publisher) : null; + return ObjectUtils.defaultIfNull(publisherId, StringUtils.EMPTY); + } + + /** + * Resolves what value should be used as a publisher id - either taken from publisher.ext.parentAccount + * or publisher.id in this respective priority. + */ + private String resolvePublisherId(Publisher publisher) { + final String parentAccountId = parentAccountIdFromExtPublisher(publisher.getExt()); + return ObjectUtils.defaultIfNull(parentAccountId, publisher.getId()); + } + + /** + * Parses publisher.ext and returns parentAccount value from it. Returns null if any parsing error occurs. + */ + private String parentAccountIdFromExtPublisher(ExtPublisher extPublisher) { + final ExtPublisherPrebid extPublisherPrebid = extPublisher != null ? extPublisher.getPrebid() : null; + return extPublisherPrebid != null ? StringUtils.stripToNull(extPublisherPrebid.getParentAccount()) : null; + } + + private Future responseForEmptyAccount(RoutingContext routingContext) { + EMPTY_ACCOUNT_LOGGER.warn(accountErrorMessage("Account not specified", routingContext), 100); + return responseForUnknownAccount(StringUtils.EMPTY); + } + + private static String accountErrorMessage(String message, RoutingContext routingContext) { + final HttpServerRequest request = routingContext.request(); + return String.format( + "%s, Url: %s and Referer: %s", + message, + request.absoluteURI(), + request.headers().get(HttpUtil.REFERER_HEADER)); + } + + private Future accountFallback(Throwable exception, + String accountId, + RoutingContext routingContext) { + + if (exception instanceof PreBidException) { + UNKNOWN_ACCOUNT_LOGGER.warn(accountErrorMessage(exception.getMessage(), routingContext), 100); + } else { + logger.warn("Error occurred while fetching account: {0}", exception.getMessage()); + logger.debug("Error occurred while fetching account", exception); + } + + // hide all errors occurred while fetching account + return responseForUnknownAccount(accountId); + } + + private Future responseForUnknownAccount(String accountId) { + return enforceValidAccount + ? Future.failedFuture(new UnauthorizedAccountException( + String.format("Unauthorized account id: %s", accountId), accountId)) + : Future.succeededFuture(Account.empty(accountId)); + } + + private Future ensureAccountActive(Account account) { + final String accountId = account.getId(); + + return account.getStatus() == AccountStatus.inactive + ? Future.failedFuture(new UnauthorizedAccountException( + String.format("Account %s is inactive", accountId), accountId)) + : Future.succeededFuture(account); + } + + private ExtRequest enrichExtRequest(ExtRequest ext, Account account) { + final ExtRequestPrebid prebidExt = getIfNotNull(ext, ExtRequest::getPrebid); + final String integration = getIfNotNull(prebidExt, ExtRequestPrebid::getIntegration); + final String accountDefaultIntegration = account.getDefaultIntegration(); + + if (StringUtils.isBlank(integration) && StringUtils.isNotBlank(accountDefaultIntegration)) { + final ExtRequestPrebid.ExtRequestPrebidBuilder prebidExtBuilder = + prebidExt != null ? prebidExt.toBuilder() : ExtRequestPrebid.builder(); + + prebidExtBuilder.integration(accountDefaultIntegration); + + return ExtRequest.of(prebidExtBuilder.build()); + } + + return null; + } + + private Device enrichDevice(Device device, PrivacyContext privacyContext) { + final String ipAddress = privacyContext.getIpAddress(); + final IpAddress ip = ipAddressHelper.toIpAddress(ipAddress); + + final String ipV4InRequest = getIfNotNull(device, Device::getIp); + final String ipV4 = ip != null && ip.getVersion() == IpAddress.IP.v4 ? ipAddress : null; + final boolean shouldUpdateIpV4 = ipV4 != null && !Objects.equals(ipV4InRequest, ipV4); + + final String ipV6InRequest = getIfNotNull(device, Device::getIpv6); + final String ipV6 = ip != null && ip.getVersion() == IpAddress.IP.v6 ? ipAddress : null; + final boolean shouldUpdateIpV6 = ipV6 != null && !Objects.equals(ipV6InRequest, ipV6); + + final Geo geo = getIfNotNull(device, Device::getGeo); + final String countryInRequest = getIfNotNull(geo, Geo::getCountry); + final String country = getIfNotNull(privacyContext.getTcfContext().getGeoInfo(), GeoInfo::getCountry); + final boolean shouldUpdateCountry = country != null && !Objects.equals(countryInRequest, country); + + if (shouldUpdateIpV4 || shouldUpdateIpV6 || shouldUpdateCountry) { + final Device.DeviceBuilder deviceBuilder = device != null ? device.toBuilder() : Device.builder(); + + if (shouldUpdateIpV4) { + deviceBuilder.ip(ipV4); + } + + if (shouldUpdateIpV6) { + deviceBuilder.ipv6(ipV6); + } + + if (shouldUpdateCountry) { + final Geo.GeoBuilder geoBuilder = geo != null ? geo.toBuilder() : Geo.builder(); + geoBuilder.country(country); + deviceBuilder.geo(geoBuilder.build()); + } + + return deviceBuilder.build(); + } + + return null; + } + + private static R getIfNotNull(T target, Function getter) { + return target != null ? getter.apply(target) : null; + } +} diff --git a/src/main/java/org/prebid/server/auction/VideoRequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/VideoRequestFactory.java similarity index 65% rename from src/main/java/org/prebid/server/auction/VideoRequestFactory.java rename to src/main/java/org/prebid/server/auction/requestfactory/VideoRequestFactory.java index 556eedcb9c8..f9da31ee2f0 100644 --- a/src/main/java/org/prebid/server/auction/VideoRequestFactory.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/VideoRequestFactory.java @@ -1,4 +1,4 @@ -package org.prebid.server.auction; +package org.prebid.server.auction.requestfactory; import com.iab.openrtb.request.App; import com.iab.openrtb.request.BidRequest; @@ -10,11 +10,13 @@ import com.iab.openrtb.request.video.PodError; import com.iab.openrtb.request.video.Podconfig; import io.vertx.core.Future; -import io.vertx.core.buffer.Buffer; import io.vertx.ext.web.RoutingContext; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import org.prebid.server.auction.PrivacyEnforcementService; +import org.prebid.server.auction.TimeoutResolver; +import org.prebid.server.auction.VideoStoredRequestProcessor; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.WithPodErrors; import org.prebid.server.exception.InvalidRequestException; @@ -37,22 +39,28 @@ public class VideoRequestFactory { private final int maxRequestSize; private final boolean enforceStoredRequest; + private final Ortb2RequestFactory ortb2RequestFactory; + private final Ortb2ImplicitParametersResolver paramsResolver; private final VideoStoredRequestProcessor storedRequestProcessor; - private final AuctionRequestFactory auctionRequestFactory; + private final PrivacyEnforcementService privacyEnforcementService; private final TimeoutResolver timeoutResolver; private final JacksonMapper mapper; public VideoRequestFactory(int maxRequestSize, boolean enforceStoredRequest, + Ortb2RequestFactory ortb2RequestFactory, + Ortb2ImplicitParametersResolver paramsResolver, VideoStoredRequestProcessor storedRequestProcessor, - AuctionRequestFactory auctionRequestFactory, + PrivacyEnforcementService privacyEnforcementService, TimeoutResolver timeoutResolver, JacksonMapper mapper) { this.enforceStoredRequest = enforceStoredRequest; this.maxRequestSize = maxRequestSize; + this.ortb2RequestFactory = Objects.requireNonNull(ortb2RequestFactory); + this.paramsResolver = Objects.requireNonNull(paramsResolver); this.storedRequestProcessor = Objects.requireNonNull(storedRequestProcessor); - this.auctionRequestFactory = Objects.requireNonNull(auctionRequestFactory); + this.privacyEnforcementService = Objects.requireNonNull(privacyEnforcementService); this.timeoutResolver = Objects.requireNonNull(timeoutResolver); this.mapper = Objects.requireNonNull(mapper); } @@ -61,61 +69,67 @@ public VideoRequestFactory(int maxRequestSize, * Creates {@link AuctionContext} and {@link List} of {@link PodError} based on {@link RoutingContext}. */ public Future> fromRequest(RoutingContext routingContext, long startTime) { - - final BidRequestVideo incomingBidRequest; + final String body; try { - incomingBidRequest = parseRequest(routingContext); + body = extractAndValidateBody(routingContext); } catch (InvalidRequestException e) { return Future.failedFuture(e); } - final String storedRequestId = incomingBidRequest.getStoredrequestid(); - if (StringUtils.isBlank(storedRequestId) && enforceStoredRequest) { - return Future.failedFuture(new InvalidRequestException("Unable to find required stored request id")); - } - - final Set podConfigIds = podConfigIds(incomingBidRequest); - return createBidRequest(routingContext, incomingBidRequest, storedRequestId, podConfigIds) - .compose(bidRequestToPodError -> auctionRequestFactory.toAuctionContext( + return createBidRequest(body, routingContext) + .compose(bidRequestWithErrors -> ortb2RequestFactory.fetchAccountAndCreateAuctionContext( routingContext, - bidRequestToPodError.getData(), + bidRequestWithErrors.getData(), MetricName.video, - new ArrayList<>(), + false, startTime, - timeoutResolver) - .map(auctionContext -> WithPodErrors.of(auctionContext, bidRequestToPodError.getPodErrors()))); - } + new ArrayList<>()) - /** - * Extracts publisher id either from {@link BidRequestVideo}.app.publisher - * or {@link BidRequestVideo}.site.publisher. If neither is present returns empty string. - */ - private String accountIdFrom(BidRequestVideo bidRequestVideo) { - final App app = bidRequestVideo.getApp(); - final Publisher appPublisher = app != null ? app.getPublisher() : null; - final Site site = bidRequestVideo.getSite(); - final Publisher sitePublisher = site != null ? site.getPublisher() : null; + .compose(auctionContext -> privacyEnforcementService.contextFromBidRequest(auctionContext) + .map(auctionContext::with)) - final Publisher publisher = ObjectUtils.defaultIfNull(appPublisher, sitePublisher); - final String publisherId = publisher != null ? resolvePublisherId(publisher) : null; - return ObjectUtils.defaultIfNull(publisherId, StringUtils.EMPTY); + .map(auctionContext -> auctionContext.with( + ortb2RequestFactory.enrichBidRequestWithAccountAndPrivacyData( + auctionContext.getBidRequest(), + auctionContext.getAccount(), + auctionContext.getPrivacyContext()))) + + .map(auctionContext -> WithPodErrors.of(auctionContext, bidRequestWithErrors.getPodErrors()))); } - /** - * Resolves what value should be used as a publisher id - either taken from publisher.ext.parentAccount - * or publisher.id in this respective priority. - */ - private String resolvePublisherId(Publisher publisher) { - final String parentAccountId = parentAccountIdFromExtPublisher(publisher.getExt()); - return ObjectUtils.defaultIfNull(parentAccountId, publisher.getId()); + private String extractAndValidateBody(RoutingContext context) { + final String body = context.getBodyAsString(); + if (body == null) { + throw new InvalidRequestException("Incoming request has no body"); + } + + if (body.length() > maxRequestSize) { + throw new InvalidRequestException(String.format("Request size exceeded max size of %d bytes.", + maxRequestSize)); + } + + return body; } - /** - * Parses publisher.ext and returns parentAccount value from it. Returns null if any parsing error occurs. - */ - private String parentAccountIdFromExtPublisher(ExtPublisher extPublisher) { - final ExtPublisherPrebid extPublisherPrebid = extPublisher != null ? extPublisher.getPrebid() : null; - return extPublisherPrebid != null ? StringUtils.stripToNull(extPublisherPrebid.getParentAccount()) : null; + private Future> createBidRequest(String body, RoutingContext routingContext) { + + final BidRequestVideo bidRequestVideo; + try { + bidRequestVideo = parseRequest(body, routingContext); + } catch (InvalidRequestException e) { + return Future.failedFuture(e); + } + + final String storedRequestId = bidRequestVideo.getStoredrequestid(); + if (StringUtils.isBlank(storedRequestId) && enforceStoredRequest) { + return Future.failedFuture(new InvalidRequestException("Unable to find required stored request id")); + } + + final Set podConfigIds = podConfigIds(bidRequestVideo); + + return storedRequestProcessor.processVideoRequest( + accountIdFrom(bidRequestVideo), storedRequestId, podConfigIds, bidRequestVideo) + .map(bidRequestToErrors -> fillImplicitParametersAndValidate(routingContext, bidRequestToErrors)); } /** @@ -123,20 +137,10 @@ private String parentAccountIdFromExtPublisher(ExtPublisher extPublisher) { *

* Throws {@link InvalidRequestException} if body is empty, exceeds max request size or couldn't be deserialized. */ - private BidRequestVideo parseRequest(RoutingContext context) { - final Buffer body = context.getBody(); - if (body == null) { - throw new InvalidRequestException("Incoming request has no body"); - } - - if (body.length() > maxRequestSize) { - throw new InvalidRequestException( - String.format("Request size exceeded max size of %d bytes.", maxRequestSize)); - } - + private BidRequestVideo parseRequest(String body, RoutingContext routingContext) { try { final BidRequestVideo bidRequestVideo = mapper.decodeValue(body, BidRequestVideo.class); - return insertDeviceUa(context, bidRequestVideo); + return insertDeviceUa(routingContext, bidRequestVideo); } catch (DecodeException e) { throw new InvalidRequestException(e.getMessage()); } @@ -161,6 +165,38 @@ private BidRequestVideo insertDeviceUa(RoutingContext context, BidRequestVideo b return bidRequestVideo; } + /** + * Extracts publisher id either from {@link BidRequestVideo}.app.publisher + * or {@link BidRequestVideo}.site.publisher. If neither is present returns empty string. + */ + private String accountIdFrom(BidRequestVideo bidRequestVideo) { + final App app = bidRequestVideo.getApp(); + final Publisher appPublisher = app != null ? app.getPublisher() : null; + final Site site = bidRequestVideo.getSite(); + final Publisher sitePublisher = site != null ? site.getPublisher() : null; + + final Publisher publisher = ObjectUtils.defaultIfNull(appPublisher, sitePublisher); + final String publisherId = publisher != null ? resolvePublisherId(publisher) : null; + return ObjectUtils.defaultIfNull(publisherId, StringUtils.EMPTY); + } + + /** + * Resolves what value should be used as a publisher id - either taken from publisher.ext.parentAccount + * or publisher.id in this respective priority. + */ + private String resolvePublisherId(Publisher publisher) { + final String parentAccountId = parentAccountIdFromExtPublisher(publisher.getExt()); + return ObjectUtils.defaultIfNull(parentAccountId, publisher.getId()); + } + + /** + * Parses publisher.ext and returns parentAccount value from it. Returns null if any parsing error occurs. + */ + private String parentAccountIdFromExtPublisher(ExtPublisher extPublisher) { + final ExtPublisherPrebid extPublisherPrebid = extPublisher != null ? extPublisher.getPrebid() : null; + return extPublisherPrebid != null ? StringUtils.stripToNull(extPublisherPrebid.getParentAccount()) : null; + } + private static Set podConfigIds(BidRequestVideo incomingBidRequest) { final Podconfig podconfig = incomingBidRequest.getPodconfig(); if (podconfig != null && CollectionUtils.isNotEmpty(podconfig.getPods())) { @@ -169,31 +205,17 @@ private static Set podConfigIds(BidRequestVideo incomingBidRequest) { .filter(Objects::nonNull) .map(String::valueOf) .collect(Collectors.toSet()); - } else { - return Collections.emptySet(); } - } - - private Future> createBidRequest(RoutingContext routingContext, - BidRequestVideo bidRequestVideo, - String storedVideoId, - Set podConfigIds) { - - return storedRequestProcessor.processVideoRequest( - accountIdFrom(bidRequestVideo), storedVideoId, podConfigIds, bidRequestVideo) - .map(bidRequestToErrors -> fillImplicitParameters(routingContext, bidRequestToErrors)) - .map(this::validateRequest); - } - private WithPodErrors validateRequest(WithPodErrors requestToPodErrors) { - final BidRequest bidRequest = auctionRequestFactory.validateRequest(requestToPodErrors.getData()); - return WithPodErrors.of(bidRequest, requestToPodErrors.getPodErrors()); + return Collections.emptySet(); } - private WithPodErrors fillImplicitParameters(RoutingContext routingContext, - WithPodErrors bidRequestToErrors) { - final BidRequest bidRequest = auctionRequestFactory - .fillImplicitParameters(bidRequestToErrors.getData(), routingContext, timeoutResolver); - return WithPodErrors.of(bidRequest, bidRequestToErrors.getPodErrors()); + private WithPodErrors fillImplicitParametersAndValidate(RoutingContext routingContext, + WithPodErrors bidRequestToErrors) { + final BidRequest bidRequest = bidRequestToErrors.getData(); + final BidRequest updatedBidRequest = paramsResolver.resolve(bidRequest, routingContext, + timeoutResolver); + final BidRequest validBidRequest = ortb2RequestFactory.validateRequest(updatedBidRequest); + return WithPodErrors.of(validBidRequest, bidRequestToErrors.getPodErrors()); } } diff --git a/src/main/java/org/prebid/server/bidder/BidderCatalog.java b/src/main/java/org/prebid/server/bidder/BidderCatalog.java index 611cb88d32b..8ce11cc6e48 100644 --- a/src/main/java/org/prebid/server/bidder/BidderCatalog.java +++ b/src/main/java/org/prebid/server/bidder/BidderCatalog.java @@ -2,6 +2,7 @@ import org.prebid.server.proto.response.BidderInfo; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -16,38 +17,52 @@ */ public class BidderCatalog { - private static final String ERROR_MESSAGE_TEMPLATE_FOR_DEPRECATED = "%s has been deprecated and is no " - + "longer available. Use %s instead."; + private static final String ERROR_MESSAGE_TEMPLATE_FOR_DEPRECATED = + "%s has been deprecated and is no longer available. Use %s instead."; - private final Map bidderDepsMap; + private final Map bidderDepsMap = new HashMap<>(); private final Map deprecatedNameToError = new HashMap<>(); - private final Map aliases = new HashMap<>(); private final Map vendorIdToBidderName = new HashMap<>(); public BidderCatalog(List bidderDeps) { - bidderDepsMap = Objects.requireNonNull(bidderDeps).stream() - .collect(Collectors.toMap(BidderDeps::getName, Function.identity())); - - for (BidderDeps deps : bidderDeps) { - deprecatedNameToError.putAll(createErrorsForDeprecatedNames(deps.getDeprecatedNames(), deps.getName())); - aliases.putAll(createAliases(deps.getAliases(), deps.getName())); - - final BidderInfo bidderInfo = deps.getBidderInfo(); - final BidderInfo.GdprInfo gdprInfo = bidderInfo != null ? bidderInfo.getGdpr() : null; - final Integer vendorId = gdprInfo != null ? gdprInfo.getVendorId() : null; - if (vendorId != null && vendorId != 0) { - vendorIdToBidderName.put(vendorId, deps.getName()); - } + Objects.requireNonNull(bidderDeps).stream() + .map(BidderDeps::getInstances) + .flatMap(Collection::stream) + .forEach(this::processDeps); + } + + private void processDeps(BidderInstanceDeps deps) { + final String bidderName = deps.getName(); + + validateBidderName(bidderName); + + bidderDepsMap.put(bidderName, deps); + deprecatedNameToError.putAll(createErrorsForDeprecatedNames(deps)); + processVendorId(deps, bidderName); + } + + private void validateBidderName(String bidderName) { + if (bidderDepsMap.containsKey(bidderName)) { + throw new IllegalArgumentException(String.format( + "Duplicate bidder or alias '%s'. Please check the configuration", bidderName)); } } - private Map createErrorsForDeprecatedNames(List deprecatedNames, String name) { - return deprecatedNames.stream().collect(Collectors.toMap(Function.identity(), - deprecatedName -> String.format(ERROR_MESSAGE_TEMPLATE_FOR_DEPRECATED, deprecatedName, name))); + private Map createErrorsForDeprecatedNames(BidderInstanceDeps deps) { + return deps.getDeprecatedNames().stream().collect(Collectors.toMap( + Function.identity(), + deprecatedName -> String.format( + ERROR_MESSAGE_TEMPLATE_FOR_DEPRECATED, deprecatedName, deps.getName()))); } - private Map createAliases(List aliases, String name) { - return aliases.stream().collect(Collectors.toMap(Function.identity(), ignored -> name)); + private void processVendorId(BidderInstanceDeps coreDeps, String bidderName) { + final BidderInfo bidderInfo = coreDeps.getBidderInfo(); + final BidderInfo.GdprInfo gdprInfo = bidderInfo != null ? bidderInfo.getGdpr() : null; + final Integer vendorId = gdprInfo != null ? gdprInfo.getVendorId() : null; + + if (vendorId != null && vendorId != 0) { + vendorIdToBidderName.put(vendorId, bidderName); + } } /** @@ -85,27 +100,6 @@ public String errorForDeprecatedName(String name) { return deprecatedNameToError.get(name); } - /** - * Returns a list of registered bidders' aliases. - */ - public Set aliases() { - return new HashSet<>(aliases.keySet()); - } - - /** - * Tells if given name corresponds to any of the registered bidder's alias. - */ - public boolean isAlias(String name) { - return aliases.containsKey(name); - } - - /** - * Returns original bidder's name for given alias. - */ - public String nameByAlias(String alias) { - return aliases.get(alias); - } - /** * Tells if given bidder is enabled and ready for auction. */ @@ -120,7 +114,7 @@ public boolean isActive(String name) { * through calling {@link #isValidName(String)}. */ public BidderInfo bidderInfoByName(String name) { - final BidderDeps bidderDeps = bidderDepsMap.get(name); + final BidderInstanceDeps bidderDeps = bidderDepsMap.get(name); return bidderDeps != null ? bidderDeps.getBidderInfo() : null; } @@ -131,7 +125,7 @@ public BidderInfo bidderInfoByName(String name) { * through calling {@link #isValidName(String)}. */ public Integer vendorIdByName(String name) { - final BidderDeps bidderDeps = bidderDepsMap.get(name); + final BidderInstanceDeps bidderDeps = bidderDepsMap.get(name); final BidderInfo bidderInfo = bidderDeps != null ? bidderDeps.getBidderInfo() : null; final BidderInfo.GdprInfo gdprInfo = bidderInfo != null ? bidderInfo.getGdpr() : null; return gdprInfo != null ? gdprInfo.getVendorId() : null; @@ -149,7 +143,7 @@ public String nameByVendorId(Integer vendorId) { */ public Set knownVendorIds() { return bidderDepsMap.values().stream() - .map(BidderDeps::getBidderInfo) + .map(BidderInstanceDeps::getBidderInfo) .map(BidderInfo::getGdpr) .map(BidderInfo.GdprInfo::getVendorId) // TODO change to notNull when migrate from primitives to Object @@ -164,7 +158,7 @@ public Set knownVendorIds() { * through calling {@link #isValidName(String)}. */ public Usersyncer usersyncerByName(String name) { - final BidderDeps bidderDeps = bidderDepsMap.get(name); + final BidderInstanceDeps bidderDeps = bidderDepsMap.get(name); return bidderDeps != null ? bidderDeps.getUsersyncer() : null; } @@ -175,7 +169,7 @@ public Usersyncer usersyncerByName(String name) { * through calling {@link #isValidName(String)}. */ public Bidder bidderByName(String name) { - final BidderDeps bidderDeps = bidderDepsMap.get(name); + final BidderInstanceDeps bidderDeps = bidderDepsMap.get(name); return bidderDeps != null ? bidderDeps.getBidder() : null; } } diff --git a/src/main/java/org/prebid/server/bidder/BidderDeps.java b/src/main/java/org/prebid/server/bidder/BidderDeps.java index 7d6d29783a2..6bc506e78c0 100644 --- a/src/main/java/org/prebid/server/bidder/BidderDeps.java +++ b/src/main/java/org/prebid/server/bidder/BidderDeps.java @@ -1,54 +1,14 @@ package org.prebid.server.bidder; -import lombok.Builder; import lombok.Value; -import org.prebid.server.proto.response.BidderInfo; import java.util.List; /** - * Gathers all dependencies for bidder. + * Gathers all dependencies for different instances of the single bidder. */ -@Builder -@Value +@Value(staticConstructor = "of") public class BidderDeps { - /** - * Bidder's name that will be used to determine if a bidder. - *

- * For example, for OpenRTB 2.5 it should participate in auction by - * inspecting bidrequest.imp[i].ext.{bidder} fields. - */ - String name; - - /** - * Bidder's deprecated names. - *

- * Appropriate error message will be added to response.ext.errors.{bidder} - * in case of bidder determined as deprecated. - */ - List deprecatedNames; - - /** - * Bidder's aliases. - *

- * Indicates predefined synonyms for bidder along with regular name. - */ - List aliases; - - /** - * Bidder's meta information is used in {@link org.prebid.server.handler.info.BidderDetailsHandler} handler - */ - BidderInfo bidderInfo; - - /** - * Bidder's user syncer is used in {@link org.prebid.server.handler.CookieSyncHandler} handler and holds cookie - * family name. - */ - Usersyncer usersyncer; - - /** - * Bidder implementation is used in auction handling. - */ - Bidder bidder; + List instances; } diff --git a/src/main/java/org/prebid/server/bidder/BidderInstanceDeps.java b/src/main/java/org/prebid/server/bidder/BidderInstanceDeps.java new file mode 100644 index 00000000000..840d8485c6f --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/BidderInstanceDeps.java @@ -0,0 +1,47 @@ +package org.prebid.server.bidder; + +import lombok.Builder; +import lombok.Value; +import org.prebid.server.proto.response.BidderInfo; + +import java.util.List; + +/** + * Gathers all dependencies for single bidder instance that may represent core bidder or its alias. + */ +@Builder +@Value +public class BidderInstanceDeps { + + /** + * Bidder's name that will be used to determine if a bidder. + *

+ * For example, for OpenRTB 2.5 it should participate in auction by + * inspecting bidrequest.imp[i].ext.{bidder} fields. + */ + String name; + + /** + * Bidder's deprecated names. + *

+ * Appropriate error message will be added to response.ext.errors.{bidder} + * in case of bidder determined as deprecated. + */ + List deprecatedNames; + + /** + * Bidder's meta information is used in {@link org.prebid.server.handler.info.BidderDetailsHandler} handler + */ + BidderInfo bidderInfo; + + /** + * Bidder's user syncer is used in {@link org.prebid.server.handler.CookieSyncHandler} handler and holds cookie + * family name. + */ + Usersyncer usersyncer; + + /** + * Bidder implementation is used in auction handling. + */ + Bidder bidder; +} diff --git a/src/main/java/org/prebid/server/bidder/HttpBidderRequester.java b/src/main/java/org/prebid/server/bidder/HttpBidderRequester.java index 8446631aa8e..215ecfe7ac2 100644 --- a/src/main/java/org/prebid/server/bidder/HttpBidderRequester.java +++ b/src/main/java/org/prebid/server/bidder/HttpBidderRequester.java @@ -5,8 +5,10 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.CompositeFuture; import io.vertx.core.Future; +import io.vertx.core.MultiMap; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; +import io.vertx.ext.web.RoutingContext; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.prebid.server.auction.ExchangeService; @@ -20,6 +22,7 @@ import org.prebid.server.bidder.model.Result; import org.prebid.server.execution.Timeout; import org.prebid.server.proto.openrtb.ext.response.ExtHttpCall; +import org.prebid.server.util.HttpUtil; import org.prebid.server.vertx.http.HttpClient; import org.prebid.server.vertx.http.model.HttpClientResponse; @@ -29,6 +32,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -46,6 +50,8 @@ public class HttpBidderRequester { private static final Logger logger = LoggerFactory.getLogger(HttpBidderRequester.class); + private static final Set HEADERS_TO_COPY = Collections.singleton(HttpUtil.SEC_GPC.toString()); + private final HttpClient httpClient; private final BidderRequestCompletionTrackerFactory completionTrackerFactory; private final BidderErrorNotifier bidderErrorNotifier; @@ -62,13 +68,16 @@ public HttpBidderRequester(HttpClient httpClient, /** * Executes given request to a given bidder. */ - public Future requestBids( - Bidder bidder, BidderRequest bidderRequest, Timeout timeout, boolean debugEnabled) { + public Future requestBids(Bidder bidder, + BidderRequest bidderRequest, + Timeout timeout, + RoutingContext routingContext, + boolean debugEnabled) { final BidRequest bidRequest = bidderRequest.getBidRequest(); final Result>> httpRequestsWithErrors = bidder.makeHttpRequests(bidRequest); final List bidderErrors = httpRequestsWithErrors.getErrors(); - final List> httpRequests = httpRequestsWithErrors.getValue(); + final List> httpRequests = enrichRequests(httpRequestsWithErrors.getValue(), routingContext); if (CollectionUtils.isEmpty(httpRequests)) { return emptyBidderSeatBidWithErrors(bidderErrors); @@ -99,9 +108,35 @@ public Future requestBids( .map(ignored -> resultBuilder.toBidderSeatBid(debugEnabled)); } - private boolean isStoredResponse(List> httpRequests, - String storedResponse, - String bidder) { + private static List> enrichRequests(List> httpRequests, + RoutingContext routingContext) { + + return httpRequests.stream().map(httpRequest -> httpRequest.toBuilder() + .headers(enrichHeaders(httpRequest.getHeaders(), routingContext.request().headers())) + .build()) + .collect(Collectors.toList()); + } + + private static MultiMap enrichHeaders(MultiMap bidderRequestHeaders, MultiMap originalRequestHeaders) { + // some bidders has headers on class level, so we create copy to not affect them + final MultiMap bidderRequestHeadersCopy = copyMultiMap(bidderRequestHeaders); + + originalRequestHeaders.entries().stream() + .filter(entry -> HEADERS_TO_COPY.contains(entry.getKey()) + && !bidderRequestHeadersCopy.contains(entry.getKey())) + .forEach(entry -> bidderRequestHeadersCopy.add(entry.getKey(), entry.getValue())); + return bidderRequestHeadersCopy; + } + + private static MultiMap copyMultiMap(MultiMap source) { + final MultiMap copiedMultiMap = MultiMap.caseInsensitiveMultiMap(); + if (source != null && !source.isEmpty()) { + source.forEach(entry -> copiedMultiMap.add(entry.getKey(), entry.getValue())); + } + return copiedMultiMap; + } + + private boolean isStoredResponse(List> httpRequests, String storedResponse, String bidder) { if (StringUtils.isBlank(storedResponse)) { return false; } @@ -116,10 +151,11 @@ private boolean isStoredResponse(List> httpRequests, return true; } - final Future> makeStoredHttpCall(HttpRequest httpRequest, - String storedResponse) { - return Future.succeededFuture(HttpCall.success(httpRequest, HttpResponse.of(HttpResponseStatus.OK.code(), null, - storedResponse), null)); + private Future> makeStoredHttpCall(HttpRequest httpRequest, String storedResponse) { + return Future.succeededFuture( + HttpCall.success(httpRequest, + HttpResponse.of(HttpResponseStatus.OK.code(), null, storedResponse), + null)); } /** @@ -201,7 +237,6 @@ private Void processHttpCall(Bidder bidder, } private static Result> makeBids(Bidder bidder, HttpCall httpCall, BidRequest bidRequest) { - return httpCall.getError() != null ? null : makeResult(bidder, httpCall, bidRequest); diff --git a/src/main/java/org/prebid/server/bidder/UsersyncInfoAssembler.java b/src/main/java/org/prebid/server/bidder/UsersyncInfoAssembler.java index 5108e3a2328..8d14a7ba773 100644 --- a/src/main/java/org/prebid/server/bidder/UsersyncInfoAssembler.java +++ b/src/main/java/org/prebid/server/bidder/UsersyncInfoAssembler.java @@ -13,12 +13,13 @@ public class UsersyncInfoAssembler { private String type; private Boolean supportCORS; - public static UsersyncInfoAssembler from(Usersyncer usersyncer) { + public static UsersyncInfoAssembler from(Usersyncer.UsersyncMethod usersyncMethod) { final UsersyncInfoAssembler usersyncInfoAssembler = new UsersyncInfoAssembler(); - usersyncInfoAssembler.usersyncUrl = usersyncer.getUsersyncUrl(); - usersyncInfoAssembler.redirectUrl = ObjectUtils.defaultIfNull(usersyncer.getRedirectUrl(), ""); - usersyncInfoAssembler.type = usersyncer.getType(); - usersyncInfoAssembler.supportCORS = usersyncer.isSupportCORS(); + usersyncInfoAssembler.usersyncUrl = usersyncMethod.getUsersyncUrl(); + usersyncInfoAssembler.redirectUrl = UsersyncUtil.enrichUsersyncUrlWithFormat( + StringUtils.stripToEmpty(usersyncMethod.getRedirectUrl()), usersyncMethod.getType()); + usersyncInfoAssembler.type = usersyncMethod.getType(); + usersyncInfoAssembler.supportCORS = usersyncMethod.isSupportCORS(); return usersyncInfoAssembler; } diff --git a/src/main/java/org/prebid/server/bidder/UsersyncMethodChooser.java b/src/main/java/org/prebid/server/bidder/UsersyncMethodChooser.java new file mode 100644 index 00000000000..cbece8b6186 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/UsersyncMethodChooser.java @@ -0,0 +1,94 @@ +package org.prebid.server.bidder; + +import com.fasterxml.jackson.databind.JsonNode; +import org.apache.commons.lang3.StringUtils; +import org.prebid.server.proto.request.CookieSyncRequest; +import org.prebid.server.util.StreamUtil; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Stream; + +public class UsersyncMethodChooser { + + private static final String CATCH_ALL_BIDDERS = "*"; + + private final Map filters; + + public UsersyncMethodChooser(CookieSyncRequest.FilterSettings filterSettings) { + filters = initializeFilters(filterSettings); + } + + public static UsersyncMethodChooser from(CookieSyncRequest.FilterSettings filterSettings) { + return new UsersyncMethodChooser(filterSettings); + } + + public Usersyncer.UsersyncMethod choose(Usersyncer usersyncer, String bidder) { + return Stream.of(usersyncer.getPrimaryMethod(), usersyncer.getSecondaryMethod()) + .filter(method -> methodValidAndAllowed(method, bidder)) + .findFirst() + .orElse(null); + } + + private static Map initializeFilters( + CookieSyncRequest.FilterSettings filterSettings) { + + if (filterSettings == null) { + return Collections.emptyMap(); + } + + final Map filterMap = new HashMap<>(); + + filterMap.computeIfAbsent(Usersyncer.UsersyncMethod.IFRAME_TYPE, key -> filterSettings.getIframe()); + filterMap.computeIfAbsent(Usersyncer.UsersyncMethod.REDIRECT_TYPE, key -> filterSettings.getImage()); + + return filterMap; + } + + private boolean methodValidAndAllowed(Usersyncer.UsersyncMethod usersyncMethod, String bidder) { + return methodValid(usersyncMethod) && methodAllowed(usersyncMethod, bidder); + } + + private boolean methodValid(Usersyncer.UsersyncMethod usersyncMethod) { + return usersyncMethod != null && StringUtils.isNotBlank(usersyncMethod.getUsersyncUrl()); + } + + private boolean methodAllowed(Usersyncer.UsersyncMethod usersyncMethod, String bidder) { + final CookieSyncRequest.MethodFilter filter = filters.get(usersyncMethod.getType()); + + return filter == null || filter.getFilter() == null + || bidderNotExcluded(bidder, filter) || bidderIncluded(bidder, filter); + } + + private boolean bidderNotExcluded(String bidder, CookieSyncRequest.MethodFilter filter) { + return filter.getFilter() == CookieSyncRequest.FilterType.exclude && !bidderInList(bidder, filter.getBidders()); + } + + private boolean bidderIncluded(String bidder, CookieSyncRequest.MethodFilter filter) { + return filter.getFilter() == CookieSyncRequest.FilterType.include && bidderInList(bidder, filter.getBidders()); + } + + private boolean bidderInList(String bidder, JsonNode bidders) { + return listMatchesAllBidders(bidders) || listContainsBidder(bidders, bidder); + } + + private boolean listMatchesAllBidders(JsonNode bidders) { + return bidders == null + || bidders.isNull() + || (bidders.isTextual() && Objects.equals(bidders.textValue(), CATCH_ALL_BIDDERS)); + } + + private boolean listContainsBidder(JsonNode bidders, String bidder) { + return bidders.isArray() && arrayContainsString(bidders, bidder); + } + + private static boolean arrayContainsString(JsonNode bidders, String value) { + return StreamUtil.asStream(bidders.spliterator()).anyMatch(element -> elementEqualsString(element, value)); + } + + private static boolean elementEqualsString(JsonNode element, String value) { + return element != null && element.isTextual() && Objects.equals(element.textValue(), value); + } +} diff --git a/src/main/java/org/prebid/server/bidder/UsersyncUtil.java b/src/main/java/org/prebid/server/bidder/UsersyncUtil.java new file mode 100644 index 00000000000..a769471df5b --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/UsersyncUtil.java @@ -0,0 +1,61 @@ +package org.prebid.server.bidder; + +import org.apache.commons.lang3.StringUtils; + +public class UsersyncUtil { + + public static final String FORMAT_PARAMETER = "f"; + public static final String BLANK_FORMAT = "b"; + public static final String IMG_FORMAT = "i"; + + private UsersyncUtil() { + } + + /** + * Places format query string param into the given url. + *

+ * Caution: it doesn't care if it already exists in url, just adds new one. + *

+ * Note: format is inserted before the last param for safety reason because of + * usersync url can be appended with UID on the exchange side without parsing query string. + */ + public static String enrichUsersyncUrlWithFormat(String url, String type) { + if (StringUtils.isAnyEmpty(url, type)) { + return url; + } + + final String formatValue = resolveFormatValueByType(type); + + return hasTwoOrMoreParameters(url) + ? insertFormatParameter(url, formatValue) + : appendFormatParameter(url, formatValue); + } + + private static String resolveFormatValueByType(String type) { + switch (type) { + case Usersyncer.UsersyncMethod.REDIRECT_TYPE: + return IMG_FORMAT; + case Usersyncer.UsersyncMethod.IFRAME_TYPE: + return BLANK_FORMAT; + default: + return StringUtils.EMPTY; // never should happen + } + } + + private static boolean hasTwoOrMoreParameters(String url) { + return url.indexOf('&') != -1; + } + + private static String insertFormatParameter(String url, String formatValue) { + final int lastParamIndex = url.lastIndexOf('&'); + + return url.substring(0, lastParamIndex) + + "&" + FORMAT_PARAMETER + "=" + formatValue + + url.substring(lastParamIndex); + } + + private static String appendFormatParameter(String url, String formatValue) { + final String separator = url.indexOf('?') != -1 ? "&" : "?"; + return url + separator + FORMAT_PARAMETER + "=" + formatValue; + } +} diff --git a/src/main/java/org/prebid/server/bidder/Usersyncer.java b/src/main/java/org/prebid/server/bidder/Usersyncer.java index 9cd81b421e5..2aaf8121f86 100644 --- a/src/main/java/org/prebid/server/bidder/Usersyncer.java +++ b/src/main/java/org/prebid/server/bidder/Usersyncer.java @@ -1,39 +1,28 @@ package org.prebid.server.bidder; -import lombok.AllArgsConstructor; -import lombok.Data; -import org.apache.commons.lang3.StringUtils; -import org.prebid.server.util.HttpUtil; +import lombok.Value; -import java.util.Objects; - -@Data -@AllArgsConstructor +@Value(staticConstructor = "of") public class Usersyncer { - private String cookieFamilyName; + String cookieFamilyName; + + UsersyncMethod primaryMethod; + + UsersyncMethod secondaryMethod; - private String usersyncUrl; + @Value(staticConstructor = "of") + public static class UsersyncMethod { - private String redirectUrl; + public static final String IFRAME_TYPE = "iframe"; + public static final String REDIRECT_TYPE = "redirect"; - private String type; + String type; - private boolean supportCORS; + String usersyncUrl; - public Usersyncer(String cookieFamilyName, - String usersyncUrl, - String redirectUrl, - String externalUri, - String type, - boolean supportCORS) { + String redirectUrl; - this.cookieFamilyName = cookieFamilyName; - this.usersyncUrl = Objects.requireNonNull(usersyncUrl); - this.redirectUrl = StringUtils.isNotBlank(redirectUrl) - ? HttpUtil.validateUrl(externalUri) + redirectUrl - : StringUtils.EMPTY; - this.type = type; - this.supportCORS = supportCORS; + boolean supportCORS; } } diff --git a/src/main/java/org/prebid/server/bidder/adform/AdformBidder.java b/src/main/java/org/prebid/server/bidder/adform/AdformBidder.java index 548234336af..576bb3754fc 100644 --- a/src/main/java/org/prebid/server/bidder/adform/AdformBidder.java +++ b/src/main/java/org/prebid/server/bidder/adform/AdformBidder.java @@ -63,11 +63,6 @@ public AdformBidder(String endpointUrl, JacksonMapper mapper) { this.httpUtil = new AdformHttpUtil(); } - /** - * Makes the HTTP requests which should be made to fetch bids. - *

- * Creates GET http request with all parameters in url and headers with empty body. - */ @Override public Result>> makeHttpRequests(BidRequest request) { final List imps = request.getImp(); @@ -286,8 +281,6 @@ private String getUrl(List extImpAdforms) { private List toBidderBid(List adformBids, List imps) { final List bidderBids = new ArrayList<>(); - final String currency = CollectionUtils.isNotEmpty(adformBids) ? adformBids.get(0).getWinCur() : null; - for (int i = 0; i < adformBids.size(); i++) { final AdformBid adformBid = adformBids.get(i); final String adm = resolveAdm(adformBid); @@ -307,7 +300,7 @@ private List toBidderBid(List adformBids, List imps) .crid(adformBid.getWinCrid()) .build(), bidType, - currency)); + adformBid.getWinCur())); } return bidderBids; diff --git a/src/main/java/org/prebid/server/bidder/adgeneration/AdgenerationBidder.java b/src/main/java/org/prebid/server/bidder/adgeneration/AdgenerationBidder.java index 51c862e820d..3ccb8caa6d1 100644 --- a/src/main/java/org/prebid/server/bidder/adgeneration/AdgenerationBidder.java +++ b/src/main/java/org/prebid/server/bidder/adgeneration/AdgenerationBidder.java @@ -1,6 +1,7 @@ package org.prebid.server.bidder.adgeneration; import com.fasterxml.jackson.core.type.TypeReference; +import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Device; import com.iab.openrtb.request.Format; @@ -128,10 +129,9 @@ private String getUri(String endpointUrl, String adSize, String id, String curre } private String getAdSize(Imp imp) { - final List formats = imp.getBanner() == null ? null : imp.getBanner().getFormat(); - return CollectionUtils.isEmpty(formats) - ? null - : formats.stream() + final Banner banner = imp.getBanner(); + final List formats = banner != null ? banner.getFormat() : null; + return CollectionUtils.emptyIfNull(formats).stream() .map(format -> String.format("%sx%s", format.getW(), format.getH())) .collect(Collectors.joining(",")); } diff --git a/src/main/java/org/prebid/server/bidder/adhese/AdheseBidder.java b/src/main/java/org/prebid/server/bidder/adhese/AdheseBidder.java index 6e4c55f666c..df9545801f4 100644 --- a/src/main/java/org/prebid/server/bidder/adhese/AdheseBidder.java +++ b/src/main/java/org/prebid/server/bidder/adhese/AdheseBidder.java @@ -19,6 +19,7 @@ import org.prebid.server.bidder.Bidder; import org.prebid.server.bidder.adhese.model.AdheseBid; import org.prebid.server.bidder.adhese.model.AdheseOriginData; +import org.prebid.server.bidder.adhese.model.AdheseRequestBody; import org.prebid.server.bidder.adhese.model.AdheseResponseExt; import org.prebid.server.bidder.adhese.model.Cpm; import org.prebid.server.bidder.adhese.model.CpmValues; @@ -44,7 +45,6 @@ import java.util.Map; import java.util.Objects; import java.util.TreeMap; -import java.util.stream.Collectors; /** * Adhese {@link Bidder} implementation. @@ -56,9 +56,9 @@ public class AdheseBidder implements Bidder { }; private static final String ORIGIN_BID = "JERLICIA"; - private static final String GDPR_QUERY_PARAMETER = "/xt"; - private static final String REFERER_QUERY_PARAMETER = "/xf"; - private static final String IFA_QUERY_PARAMETER = "/xz"; + private static final String GDPR_QUERY_PARAMETER = "xt"; + private static final String REFERER_QUERY_PARAMETER = "xf"; + private static final String IFA_QUERY_PARAMETER = "xz"; private final String endpointUrl; private final JacksonMapper mapper; @@ -81,12 +81,13 @@ public Result>> makeHttpRequests(BidRequest request) { return Result.withError(BidderError.badInput(e.getMessage())); } - final String uri = buildUrl(request, extImpAdhese); + final String uri = getUrl(extImpAdhese); return Result.of(Collections.singletonList( HttpRequest.builder() .method(HttpMethod.POST) .uri(uri) + .body(mapper.encode(buildBody(request, extImpAdhese))) .headers(replaceHeaders(request.getDevice())) .build()), Collections.emptyList()); @@ -109,14 +110,20 @@ private ExtImpAdhese parseImpExt(Imp imp) { } } - private String buildUrl(BidRequest request, ExtImpAdhese extImpAdhese) { - return String.format("%s%s%s%s%s%s", - getUrl(extImpAdhese), - getSlotParameter(extImpAdhese), - getTargetParameters(extImpAdhese), - getGdprParameter(request.getUser()), - getRefererParameter(request.getSite()), - getIfaParameter(request.getDevice())); + private AdheseRequestBody buildBody(BidRequest request, ExtImpAdhese extImpAdhese) { + final Map> parameterMap = new TreeMap<>(); + parameterMap.putAll(getTargetParameters(extImpAdhese)); + parameterMap.putAll(getGdprParameter(request.getUser())); + parameterMap.putAll(getRefererParameter(request.getSite())); + parameterMap.putAll(getIfaParameter(request.getDevice())); + + return AdheseRequestBody.builder() + .slots(Collections.singletonList( + AdheseRequestBody.Slot.builder() + .slotname(getSlotParameter(extImpAdhese)) + .build())) + .parameters(parameterMap) + .build(); } private String getUrl(ExtImpAdhese extImpAdhese) { @@ -124,21 +131,14 @@ private String getUrl(ExtImpAdhese extImpAdhese) { } private static String getSlotParameter(ExtImpAdhese extImpAdhese) { - return String.format("/sl%s-%s", + return String.format("%s-%s", HttpUtil.encodeUrl(extImpAdhese.getLocation()), HttpUtil.encodeUrl(extImpAdhese.getFormat())); } - private String getTargetParameters(ExtImpAdhese extImpAdhese) { + private Map> getTargetParameters(ExtImpAdhese extImpAdhese) { final JsonNode targets = extImpAdhese.getTargets(); - if (targets == null || targets.isNull()) { - return ""; - } - - final Map> targetParameters = parseTargetParametersAndSort(targets); - return targetParameters.entrySet().stream() - .map(entry -> createPartOrUrl(entry.getKey(), entry.getValue())) - .collect(Collectors.joining()); + return targets == null || targets.isEmpty() ? Collections.emptyMap() : parseTargetParametersAndSort(targets); } private Map> parseTargetParametersAndSort(JsonNode targets) { @@ -147,31 +147,26 @@ private Map> parseTargetParametersAndSort(JsonNode targets) })); } - private static String createPartOrUrl(String key, List values) { - final String formattedValues = String.join(";", values); - return String.format("/%s%s", HttpUtil.encodeUrl(key), formattedValues); - } - - private static String getGdprParameter(User user) { + private static Map> getGdprParameter(User user) { final ExtUser extUser = user != null ? user.getExt() : null; final String consent = extUser != null ? extUser.getConsent() : null; return StringUtils.isNotBlank(consent) - ? String.format("%s%s", GDPR_QUERY_PARAMETER, consent) - : ""; + ? Collections.singletonMap(GDPR_QUERY_PARAMETER, Collections.singletonList(consent)) + : Collections.emptyMap(); } - private static String getRefererParameter(Site site) { + private static Map> getRefererParameter(Site site) { final String page = site != null ? site.getPage() : null; return StringUtils.isNotBlank(page) - ? String.format("%s%s", REFERER_QUERY_PARAMETER, HttpUtil.encodeUrl(page)) - : ""; + ? Collections.singletonMap(REFERER_QUERY_PARAMETER, Collections.singletonList(page)) + : Collections.emptyMap(); } - private static String getIfaParameter(Device device) { + private static Map> getIfaParameter(Device device) { final String ifa = device != null ? device.getIfa() : null; return StringUtils.isNotBlank(ifa) - ? String.format("%s%s", IFA_QUERY_PARAMETER, HttpUtil.encodeUrl(ifa)) - : ""; + ? Collections.singletonMap(IFA_QUERY_PARAMETER, Collections.singletonList(ifa)) + : Collections.emptyMap(); } @Override diff --git a/src/main/java/org/prebid/server/bidder/adhese/model/AdheseRequestBody.java b/src/main/java/org/prebid/server/bidder/adhese/model/AdheseRequestBody.java new file mode 100644 index 00000000000..608f79d905b --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/adhese/model/AdheseRequestBody.java @@ -0,0 +1,22 @@ +package org.prebid.server.bidder.adhese.model; + +import lombok.Builder; +import lombok.Value; + +import java.util.List; +import java.util.Map; + +@Builder +@Value +public class AdheseRequestBody { + + List slots; + Map> parameters; + + @Builder + @Value + public static class Slot { + + String slotname; + } +} diff --git a/src/main/java/org/prebid/server/bidder/adman/AdmanBidder.java b/src/main/java/org/prebid/server/bidder/adman/AdmanBidder.java index f3c6d5fa9de..1760b406b61 100644 --- a/src/main/java/org/prebid/server/bidder/adman/AdmanBidder.java +++ b/src/main/java/org/prebid/server/bidder/adman/AdmanBidder.java @@ -32,10 +32,7 @@ protected BidType getBidType(Bid bid, List imps) { final String impId = bid.getImpid(); for (Imp imp : imps) { if (imp.getId().equals(impId)) { - if (imp.getBanner() == null && imp.getVideo() != null) { - return BidType.video; - } - return BidType.banner; + return imp.getBanner() == null && imp.getVideo() != null ? BidType.video : BidType.banner; } } throw new PreBidException(String.format("Failed to find impression %s", impId)); diff --git a/src/main/java/org/prebid/server/bidder/adocean/AdoceanBidder.java b/src/main/java/org/prebid/server/bidder/adocean/AdoceanBidder.java index 35ab178dccd..2a6eb1e4157 100644 --- a/src/main/java/org/prebid/server/bidder/adocean/AdoceanBidder.java +++ b/src/main/java/org/prebid/server/bidder/adocean/AdoceanBidder.java @@ -307,8 +307,8 @@ private List getAdoceanResponseAdUnitList(String response return mapper.mapper().readValue( responseBody, mapper.mapper().getTypeFactory().constructCollectionType(List.class, AdoceanResponseAdUnit.class)); - } catch (IOException ex) { - throw new PreBidException(ex.getMessage()); + } catch (IOException e) { + throw new PreBidException(e.getMessage()); } } } diff --git a/src/main/java/org/prebid/server/bidder/adoppler/AdopplerBidder.java b/src/main/java/org/prebid/server/bidder/adoppler/AdopplerBidder.java index b8842478526..7ffe30b7420 100644 --- a/src/main/java/org/prebid/server/bidder/adoppler/AdopplerBidder.java +++ b/src/main/java/org/prebid/server/bidder/adoppler/AdopplerBidder.java @@ -12,8 +12,9 @@ import io.vertx.core.http.HttpMethod; import org.apache.commons.lang3.StringUtils; import org.prebid.server.bidder.Bidder; +import org.prebid.server.bidder.adoppler.model.AdopplerResponseAdsExt; import org.prebid.server.bidder.adoppler.model.AdopplerResponseExt; -import org.prebid.server.bidder.adoppler.model.AdopplerResponseVideoExt; +import org.prebid.server.bidder.adoppler.model.AdopplerResponseVideoAdsExt; import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderError; import org.prebid.server.bidder.model.HttpCall; @@ -146,9 +147,7 @@ private Map getImpTypes(BidRequest bidRequest) { final Map impTypes = new HashMap<>(); for (Imp imp : bidRequest.getImp()) { final String impId = imp.getId(); - if (impTypes.get(impId) != null) { - throw new PreBidException(String.format("duplicate $.imp.id %s", impId)); - } + if (imp.getBanner() != null) { impTypes.put(impId, BidType.banner); } else if (imp.getVideo() != null) { @@ -157,30 +156,31 @@ private Map getImpTypes(BidRequest bidRequest) { impTypes.put(impId, BidType.audio); } else if (imp.getXNative() != null) { impTypes.put(impId, BidType.xNative); - } else { - throw new PreBidException("one of $.imp.banner, $.imp.video, $.imp.audio " - + "and $.imp.native field required"); } } return impTypes; } private BidderBid createBid(Bid bid, Map impTypes, String currency) { - if (impTypes.get(bid.getImpid()) == null) { - throw new PreBidException(String.format("unknown impId: %s", bid.getImpid())); + final String bidImpId = bid.getImpid(); + + if (impTypes.get(bidImpId) == null) { + throw new PreBidException(String.format("unknown impId: %s", bidImpId)); } - validateResponseVideoExt(bid, impTypes); - return BidderBid.of(bid, impTypes.get(bid.getImpid()), currency); + if (impTypes.get(bidImpId) == BidType.video) { + validateVideoBidExt(bid); + } + + return BidderBid.of(bid, impTypes.get(bidImpId), currency); } - private void validateResponseVideoExt(Bid bid, Map impTypes) { - if (impTypes.get(bid.getImpid()) == BidType.video) { - final ObjectNode ext = bid.getExt(); - final AdopplerResponseExt adopplerResponseExt = parseResponseExt(ext); - final AdopplerResponseVideoExt adopplerResponseVideoExt = adopplerResponseExt.getAds(); - if (adopplerResponseVideoExt == null) { - throw new PreBidException("$.seatbid.bid.ext.ads.video required"); - } + private void validateVideoBidExt(Bid bid) { + final ObjectNode extNode = bid.getExt(); + final AdopplerResponseExt ext = extNode != null ? parseResponseExt(extNode) : null; + final AdopplerResponseAdsExt adsExt = ext != null ? ext.getAds() : null; + final AdopplerResponseVideoAdsExt videoAdsExt = adsExt != null ? adsExt.getVideo() : null; + if (videoAdsExt == null) { + throw new PreBidException("$.seatbid.bid.ext.ads.video required"); } } diff --git a/src/main/java/org/prebid/server/bidder/adoppler/model/AdopplerResponseVideoExt.java b/src/main/java/org/prebid/server/bidder/adoppler/model/AdopplerResponseAdsExt.java similarity index 82% rename from src/main/java/org/prebid/server/bidder/adoppler/model/AdopplerResponseVideoExt.java rename to src/main/java/org/prebid/server/bidder/adoppler/model/AdopplerResponseAdsExt.java index 75f7b33f9e4..ba9df1a3034 100644 --- a/src/main/java/org/prebid/server/bidder/adoppler/model/AdopplerResponseVideoExt.java +++ b/src/main/java/org/prebid/server/bidder/adoppler/model/AdopplerResponseAdsExt.java @@ -5,7 +5,7 @@ @AllArgsConstructor(staticName = "of") @Value -public class AdopplerResponseVideoExt { +public class AdopplerResponseAdsExt { AdopplerResponseVideoAdsExt video; } diff --git a/src/main/java/org/prebid/server/bidder/adoppler/model/AdopplerResponseExt.java b/src/main/java/org/prebid/server/bidder/adoppler/model/AdopplerResponseExt.java index 847c0a82e57..7165870d695 100644 --- a/src/main/java/org/prebid/server/bidder/adoppler/model/AdopplerResponseExt.java +++ b/src/main/java/org/prebid/server/bidder/adoppler/model/AdopplerResponseExt.java @@ -7,5 +7,5 @@ @Value public class AdopplerResponseExt { - AdopplerResponseVideoExt ads; + AdopplerResponseAdsExt ads; } diff --git a/src/main/java/org/prebid/server/bidder/adtarget/AdtargetBidder.java b/src/main/java/org/prebid/server/bidder/adtarget/AdtargetBidder.java index 3033153b756..b0a7e089a59 100644 --- a/src/main/java/org/prebid/server/bidder/adtarget/AdtargetBidder.java +++ b/src/main/java/org/prebid/server/bidder/adtarget/AdtargetBidder.java @@ -33,7 +33,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.stream.Collectors; /** @@ -81,8 +80,8 @@ private Result>> mapSourceIdToImp(List imps) { try { validateImpression(imp); extImpAdtarget = parseImpAdtarget(imp); - } catch (PreBidException ex) { - errors.add(BidderError.badInput(ex.getMessage())); + } catch (PreBidException e) { + errors.add(BidderError.badInput(e.getMessage())); continue; } final Imp updatedImp = updateImp(imp, extImpAdtarget); @@ -164,9 +163,10 @@ private static BidderBid createBidderBid(Bid bid, List imps, String currenc } private static BidType getBidType(String bidImpId, String bidId, List imps) { - final Optional impWithBidId = imps.stream().filter(imp -> imp.getId().equals(bidImpId)).findFirst(); - if (impWithBidId.isPresent()) { - return impWithBidId.get().getVideo() != null ? BidType.video : BidType.banner; + for (Imp imp : imps) { + if (imp.getId().equals(bidImpId)) { + return imp.getVideo() != null ? BidType.video : BidType.banner; + } } throw new PreBidException(String.format( "ignoring bid id=%s, request doesn't contain any impression with id=%s", bidId, bidImpId)); diff --git a/src/main/java/org/prebid/server/bidder/adtelligent/AdtelligentBidder.java b/src/main/java/org/prebid/server/bidder/adtelligent/AdtelligentBidder.java index fd06147d1e3..fdcf46c79d3 100644 --- a/src/main/java/org/prebid/server/bidder/adtelligent/AdtelligentBidder.java +++ b/src/main/java/org/prebid/server/bidder/adtelligent/AdtelligentBidder.java @@ -91,8 +91,8 @@ private Result>> mapSourceIdToImp(List imps) { try { validateImpression(imp); extImpAdtelligent = getExtImpAdtelligent(imp); - } catch (PreBidException ex) { - errors.add(BidderError.badInput(ex.getMessage())); + } catch (PreBidException e) { + errors.add(BidderError.badInput(e.getMessage())); continue; } final Imp updatedImp = updateImp(imp, extImpAdtelligent); diff --git a/src/main/java/org/prebid/server/bidder/advangelists/AdvangelistsBidder.java b/src/main/java/org/prebid/server/bidder/advangelists/AdvangelistsBidder.java index 4132501fe03..54b5020709d 100644 --- a/src/main/java/org/prebid/server/bidder/advangelists/AdvangelistsBidder.java +++ b/src/main/java/org/prebid/server/bidder/advangelists/AdvangelistsBidder.java @@ -231,10 +231,7 @@ private static List bidsFromResponse(BidRequest bidRequest, BidRespon private static BidType getBidType(String impId, List imps) { for (Imp imp : imps) { if (imp.getId().equals(impId)) { - if (imp.getVideo() != null) { - return BidType.video; - } - return BidType.banner; + return imp.getVideo() != null ? BidType.video : BidType.banner; } } return BidType.banner; diff --git a/src/main/java/org/prebid/server/bidder/adyoulike/AdyoulikeBidder.java b/src/main/java/org/prebid/server/bidder/adyoulike/AdyoulikeBidder.java new file mode 100644 index 00000000000..159b3c1a727 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/adyoulike/AdyoulikeBidder.java @@ -0,0 +1,133 @@ +package org.prebid.server.bidder.adyoulike; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Imp; +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; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.HttpCall; +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.ExtPrebid; +import org.prebid.server.proto.openrtb.ext.request.adyoulike.ExtImpAdyoulike; +import org.prebid.server.proto.openrtb.ext.response.BidType; +import org.prebid.server.util.HttpUtil; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * Adyoulike {@link Bidder} implementation. + */ +public class AdyoulikeBidder implements Bidder { + + private static final TypeReference> ADYOULIKE_EXT_TYPE_REFERENCE = + new TypeReference>() { + }; + private static final String URL_PUBLISHER_ID_MACRO = "{{publisherId}}"; + + private final String endpointUrl; + private final JacksonMapper mapper; + + public AdyoulikeBidder(String endpointUrl, JacksonMapper mapper) { + this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.mapper = Objects.requireNonNull(mapper); + } + + @Override + public Result>> makeHttpRequests(BidRequest request) { + + final List modifiedImps = new ArrayList<>(); + final List errors = new ArrayList<>(); + + for (Imp imp : request.getImp()) { + try { + final ExtImpAdyoulike impExt = parseImpExt(imp); + + modifiedImps.add(imp.toBuilder().tagid(impExt.getPlacement()).build()); + } catch (PreBidException e) { + errors.add(BidderError.badInput(e.getMessage())); + } + } + + if (errors.size() > 0) { + return Result.withErrors(errors); + } + + final BidRequest outgoingRequest = request.toBuilder().imp(modifiedImps).build(); + + return Result.withValue(HttpRequest.builder() + .method(HttpMethod.POST) + .uri(endpointUrl) + .headers(resolveHeaders()) + .payload(outgoingRequest) + .body(mapper.encode(outgoingRequest)) + .build()); + } + + private ExtImpAdyoulike parseImpExt(Imp imp) { + try { + return mapper.mapper().convertValue(imp.getExt(), ADYOULIKE_EXT_TYPE_REFERENCE).getBidder(); + } catch (IllegalArgumentException e) { + throw new PreBidException(e.getMessage()); + } + } + + private static MultiMap resolveHeaders() { + return HttpUtil.headers() + .add(HttpUtil.X_OPENRTB_VERSION_HEADER, "2.5"); + } + + @Override + public final Result> makeBids(HttpCall httpCall, BidRequest bidRequest) { + try { + final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class); + return Result.of(extractBids(httpCall.getRequest().getPayload(), bidResponse), Collections.emptyList()); + } catch (DecodeException | PreBidException e) { + return Result.withError(BidderError.badServerResponse(e.getMessage())); + } + } + + private static List extractBids(BidRequest bidRequest, BidResponse bidResponse) { + if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) { + return Collections.emptyList(); + } + return bidsFromResponse(bidRequest, bidResponse); + } + + private static List bidsFromResponse(BidRequest bidRequest, BidResponse bidResponse) { + 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())) + .collect(Collectors.toList()); + } + + private static BidType getBidType(String impId, List imps) { + for (Imp imp : imps) { + if (imp.getId().equals(impId)) { + if (imp.getBanner() == null && imp.getVideo() != null) { + return BidType.video; + } else if (imp.getBanner() == null && imp.getXNative() != null) { + return BidType.xNative; + } + } + } + return BidType.banner; + } +} diff --git a/src/main/java/org/prebid/server/bidder/appnexus/AppnexusBidder.java b/src/main/java/org/prebid/server/bidder/appnexus/AppnexusBidder.java index 52568155086..799fc9a83cb 100644 --- a/src/main/java/org/prebid/server/bidder/appnexus/AppnexusBidder.java +++ b/src/main/java/org/prebid/server/bidder/appnexus/AppnexusBidder.java @@ -312,7 +312,7 @@ private ImpWithMemberId makeImpWithMemberId(Imp imp, String defaultDisplayManage } final BigDecimal reserve = appnexusExt.getReserve(); - if (reserve != null && reserve.compareTo(BigDecimal.ZERO) > 0) { + if (!bidFloorIsValid(imp.getBidfloor()) && bidFloorIsValid(reserve)) { impBuilder.bidfloor(reserve); // This will be broken for non-USD currency. } @@ -324,6 +324,10 @@ private ImpWithMemberId makeImpWithMemberId(Imp imp, String defaultDisplayManage return ImpWithMemberId.of(impBuilder.build(), appnexusExt.getMember()); } + private static boolean bidFloorIsValid(BigDecimal bidFloor) { + return bidFloor != null && bidFloor.compareTo(BigDecimal.ZERO) > 0; + } + private static AppnexusImpExt makeAppnexusImpExt(ExtImpAppnexus appnexusExt) { return AppnexusImpExt.of( AppnexusImpExtAppnexus.of(appnexusExt.getPlacementId(), makeKeywords(appnexusExt.getKeywords()), @@ -444,14 +448,17 @@ private BidderBid bidderBid(Bid bid, String currency) { } final String iabCategory = iabCategory(appnexus.getBrandCategoryId()); + + List cat = bid.getCat(); if (iabCategory != null) { - bid.setCat(Collections.singletonList(iabCategory)); + cat = Collections.singletonList(iabCategory); } else if (CollectionUtils.isNotEmpty(bid.getCat())) { //create empty categories array to force bid to be rejected - bid.setCat(Collections.emptyList()); + cat = Collections.emptyList(); } - return BidderBid.of(bid, bidType(appnexus.getBidAdType()), currency); + final Bid modifiedBid = bid.toBuilder().cat(cat).build(); + return BidderBid.of(modifiedBid, bidType(appnexus.getBidAdType()), currency); } private static String iabCategory(Integer brandId) { diff --git a/src/main/java/org/prebid/server/bidder/beachfront/BeachfrontBidder.java b/src/main/java/org/prebid/server/bidder/beachfront/BeachfrontBidder.java index 138e7072095..62d9080a99a 100644 --- a/src/main/java/org/prebid/server/bidder/beachfront/BeachfrontBidder.java +++ b/src/main/java/org/prebid/server/bidder/beachfront/BeachfrontBidder.java @@ -54,9 +54,9 @@ public class BeachfrontBidder implements Bidder { private static final String NURL_VIDEO_TYPE = "nurl"; private static final String ADM_VIDEO_TYPE = "adm"; private static final String BEACHFRONT_NAME = "BF_PREBID_S2S"; - private static final String BEACHFRONT_VERSION = "0.9.1"; + private static final String BEACHFRONT_VERSION = "0.9.2"; private static final String NURL_VIDEO_ENDPOINT_SUFFIX = "&prebidserver"; - private static final String TEST_IP = "192.168.255.255"; + private static final String FAKE_IP = "255.255.255.255"; private static final BigDecimal MIN_BID_FLOOR = BigDecimal.valueOf(0.01); private static final int DEFAULT_VIDEO_WIDTH = 300; @@ -171,6 +171,7 @@ private BeachfrontBannerRequest getBannerRequest(BidRequest bidRequest, List 0 ? bidFloor : BigDecimal.ZERO; + return bidFloor != null && bidFloor.compareTo(MIN_BID_FLOOR) > 0 ? bidFloor : BigDecimal.ZERO; } /** @@ -272,7 +273,7 @@ private static User makeUser(User user) { */ private static void populateDeviceFields(BeachfrontBannerRequest.BeachfrontBannerRequestBuilder builder, Device device) { - builder.ip(getIP(device.getIp())); + builder.ip(device.getIp()); builder.deviceModel(device.getModel()); builder.deviceOs(device.getOs()); if (device.getDnt() != null) { @@ -283,10 +284,6 @@ private static void populateDeviceFields(BeachfrontBannerRequest.BeachfrontBanne } } - private static String getIP(String ip) { - return StringUtils.isBlank(ip) || ip.equals("::1") || ip.equals("127.0.0.1") ? TEST_IP : ip; - } - private static int getSecure(String page) { return StringUtils.contains(page, "https") ? 1 : 0; } @@ -307,34 +304,28 @@ private List getVideoRequests(BidRequest bidRequest, Lis } final String videoResponseType = extImpBeachfront.getVideoResponseType(); - final String responseType = StringUtils.isBlank(videoResponseType) ? ADM_VIDEO_TYPE : videoResponseType; final BeachfrontVideoRequest.BeachfrontVideoRequestBuilder requestBuilder = BeachfrontVideoRequest.builder() - .appId(appId) - .videoResponseType(responseType); + .appId(appId); + final String responseType; - if (responseType.equals(NURL_VIDEO_TYPE)) { + if (videoResponseType != null && videoResponseType.equals(NURL_VIDEO_TYPE)) { requestBuilder.isPrebid(true); + responseType = NURL_VIDEO_TYPE; + } else { + responseType = ADM_VIDEO_TYPE; } + requestBuilder.videoResponseType(responseType); + final BidRequest.BidRequestBuilder bidRequestBuilder = bidRequest.toBuilder(); int secure = 0; final Site site = bidRequest.getSite(); if (site != null && StringUtils.isBlank(site.getDomain()) && StringUtils.isNotBlank(site.getPage())) { - bidRequestBuilder.site(site.toBuilder().domain(HttpUtil.getDomainFromUrl(site.getPage())).build()); + bidRequestBuilder.site(site.toBuilder().domain(HttpUtil.getHostFromUrl(site.getPage())).build()); secure = getSecure(site.getPage()); } - final App app = bidRequest.getApp(); - if (app != null && StringUtils.isBlank(app.getDomain()) && StringUtils.isNotBlank(app.getBundle())) { - final String trimmedBundle = StringUtils.removeStart(app.getBundle(), "_"); - final String[] split = StringUtils.removeEnd(trimmedBundle, "_").split("\\."); - - if (split.length > 1) { - bidRequestBuilder.app(app.toBuilder().domain(String.format("%s.%s", split[1], split[0])).build()); - } - } - final Device device = bidRequest.getDevice(); if (device != null) { final Device.DeviceBuilder deviceBuilder = device.toBuilder(); @@ -342,12 +333,23 @@ private List getVideoRequests(BidRequest bidRequest, Lis if (devicetype == null || devicetype == 0) { deviceBuilder.devicetype(bidRequest.getSite() != null ? 2 : 1); } - if (StringUtils.isNotBlank(device.getIp())) { - deviceBuilder.ip(getIP(device.getIp())); + if (StringUtils.isBlank(device.getIp()) && responseType.equals(ADM_VIDEO_TYPE)) { + deviceBuilder.ip(FAKE_IP); } + bidRequestBuilder.device(deviceBuilder.build()); } + final App app = bidRequest.getApp(); + if (app != null && StringUtils.isBlank(app.getDomain()) && StringUtils.isNotBlank(app.getBundle())) { + final String trimmedBundle = StringUtils.removeStart(app.getBundle(), "_"); + final String[] split = StringUtils.removeEnd(trimmedBundle, "_").split("\\."); + + if (split.length > 1) { + bidRequestBuilder.app(app.toBuilder().domain(String.format("%s.%s", split[1], split[0])).build()); + } + } + final Imp.ImpBuilder impBuilder = imp.toBuilder() .banner(null) .ext(null) @@ -387,11 +389,11 @@ public Result> makeBids(HttpCall httpCall, BidRequest bidR final String bodyString = httpCall.getResponse().getBody(); try { return processVideoResponse(bodyString, httpCall.getRequest()); - } catch (DecodeException e) { + } catch (DecodeException ignored) { try { return processBannerResponse(bodyString); - } catch (PreBidException ex) { - return Result.withError(BidderError.badServerResponse(ex.getMessage())); + } catch (PreBidException e) { + return Result.withError(BidderError.badServerResponse(e.getMessage())); } } } @@ -420,7 +422,8 @@ private List makeBeachfrontResponseSlots(String response responseBody, mapper.mapper().getTypeFactory().constructCollectionType(List.class, BeachfrontResponseSlot.class)); } catch (IOException ex) { - throw new PreBidException(ex.getMessage()); + throw new PreBidException("server response failed to unmarshal " + + "as valid rtb. Run with request.debug = 1 for more info"); } } @@ -452,38 +455,44 @@ private Result> processVideoResponse(String responseBody, HttpRe final List bids = bidResponse.getSeatbid().get(0).getBid(); final List imps = videoRequest.getRequest().getImp(); if (httpRequest.getUri().contains(NURL_VIDEO_ENDPOINT_SUFFIX)) { - return Result.withValues(updateVideoBids(bids, imps).stream() + return Result.withValues(updateNurlVideoBids(bids, imps).stream() .map(bid -> BidderBid.of(bid, BidType.video, bidResponse.getCur())) .collect(Collectors.toList())); } else { - return Result.withValues(bids.stream() - .peek(bid -> bid.setId(bid.getImpid() + "AdmVideo")) + return Result.withValues(updateVideoBids(bids).stream() .map(bid -> BidderBid.of(bid, BidType.video, bidResponse.getCur())) .collect(Collectors.toList())); } } - private static List updateVideoBids(List bids, List imps) { + private static List updateNurlVideoBids(List bids, List imps) { + final List result = new ArrayList<>(); for (int i = 0; i < bids.size(); i++) { - final Bid bid = bids.get(i); + Bid bid = bids.get(i); final Imp imp = imps.get(i); final String impId = imp.getId(); - bid.setCrid(getCrId(bid.getNurl())); - bid.setImpid(impId); - bid.setH(imp.getVideo().getH()); - bid.setW(imp.getVideo().getW()); - bid.setId(impId + "NurlVideo"); + + bid = bid.toBuilder() + .crid(getCrId(bid.getNurl())) + .impid(impId) + .h(imp.getVideo().getH()) + .w(imp.getVideo().getW()) + .id(impId + "NurlVideo") + .build(); + result.add(bid); } - return bids; + return result; + } + + private static List updateVideoBids(List bids) { + return bids.stream() + .map(bid -> bid.toBuilder().id(bid.getImpid() + "AdmVideo").build()) + .collect(Collectors.toList()); } private static String getCrId(String nurl) { final String[] split = nurl.split(":"); - - if (split.length > 1) { - return split[2]; //Index out of bound???... - } - return null; + return split.length > 2 ? split[2] : null; } } diff --git a/src/main/java/org/prebid/server/bidder/beachfront/model/BeachfrontBannerRequest.java b/src/main/java/org/prebid/server/bidder/beachfront/model/BeachfrontBannerRequest.java index dfc290c50e9..7ef91ded78c 100644 --- a/src/main/java/org/prebid/server/bidder/beachfront/model/BeachfrontBannerRequest.java +++ b/src/main/java/org/prebid/server/bidder/beachfront/model/BeachfrontBannerRequest.java @@ -48,4 +48,6 @@ public class BeachfrontBannerRequest { @JsonProperty("requestId") String requestId; + + Boolean real204; } diff --git a/src/main/java/org/prebid/server/bidder/brightroll/BrightrollBidder.java b/src/main/java/org/prebid/server/bidder/brightroll/BrightrollBidder.java index cf73e74cc1b..cd38acb3c88 100644 --- a/src/main/java/org/prebid/server/bidder/brightroll/BrightrollBidder.java +++ b/src/main/java/org/prebid/server/bidder/brightroll/BrightrollBidder.java @@ -10,6 +10,7 @@ import com.iab.openrtb.request.Video; 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; @@ -69,8 +70,8 @@ public Result>> makeHttpRequests(BidRequest request final String firstImpExtPublisher; try { firstImpExtPublisher = getAndValidateImpExt(request.getImp().get(0)); - } catch (PreBidException ex) { - return Result.withError(BidderError.badInput(ex.getMessage())); + } catch (PreBidException e) { + return Result.withError(BidderError.badInput(e.getMessage())); } final BidRequest updateBidRequest = updateBidRequest(request, firstImpExtPublisher, errors); @@ -260,26 +261,27 @@ public Result> makeBids(HttpCall httpCall, BidReques * Extracts {@link Bid}s from response. */ private Result> extractBids(BidResponse bidResponse, List imps) { - return bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid()) - ? Result.empty() - : Result.withValues(createBiddersBid(bidResponse, imps)); + if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) { + return Result.empty(); + } + return Result.withValues(createBiddersBids(bidResponse.getSeatbid(), imps, bidResponse.getCur())); } /** * Extracts {@link Bid}s from response and finds its type against matching {@link Imp}. In case matching {@link Imp} - * was not found, {@link BidType} is considered as banner . + * was not found, {@link BidType} is considered as banner. */ - private static List createBiddersBid(BidResponse bidResponse, List imps) { - - return bidResponse.getSeatbid().get(0).getBid().stream().filter(Objects::nonNull) - .map(bid -> BidderBid.of(bid, getBidderType(imps, bid.getImpid()), bidResponse.getCur())) + private static List createBiddersBids(List seatBids, List imps, String currency) { + return seatBids.get(0).getBid().stream() + .filter(Objects::nonNull) + .map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), imps), currency)) .collect(Collectors.toList()); } /** * Finds matching {@link Imp} by impId and checks for {@link BidType}. */ - private static BidType getBidderType(List imps, String impId) { + private static BidType getBidType(String impId, List imps) { return imps.stream() .filter(imp -> Objects.equals(imp.getId(), impId)) .findAny() diff --git a/src/main/java/org/prebid/server/bidder/cpmstar/CpmStarBidder.java b/src/main/java/org/prebid/server/bidder/cpmstar/CpmStarBidder.java index db17595f491..a82137c18b2 100644 --- a/src/main/java/org/prebid/server/bidder/cpmstar/CpmStarBidder.java +++ b/src/main/java/org/prebid/server/bidder/cpmstar/CpmStarBidder.java @@ -119,18 +119,15 @@ private static List bidsFromResponse(List imps, List respon final List bidderBids = new ArrayList<>(); for (Bid bid : responseBids) { try { - final BidType bidType = resolveBidType(bid.getImpid(), imps); - bidderBids.add(BidderBid.of(bid, bidType, currency)); + bidderBids.add(BidderBid.of(bid, bidType(bid.getImpid(), imps), currency)); } catch (PreBidException e) { - errors.add(BidderError.badInput( - String.format("bid id=%s %s", bid.getId(), e.getMessage())) - ); + errors.add(BidderError.badInput(String.format("bid id=%s %s", bid.getId(), e.getMessage()))); } } return bidderBids; } - private static BidType resolveBidType(String impId, List imps) { + private static BidType bidType(String impId, List imps) { for (Imp imp : imps) { if (imp.getId().equals(impId)) { if (imp.getBanner() != null) { diff --git a/src/main/java/org/prebid/server/bidder/datablocks/DatablocksBidder.java b/src/main/java/org/prebid/server/bidder/datablocks/DatablocksBidder.java index ef96e1167a4..7d16c383bbe 100644 --- a/src/main/java/org/prebid/server/bidder/datablocks/DatablocksBidder.java +++ b/src/main/java/org/prebid/server/bidder/datablocks/DatablocksBidder.java @@ -120,22 +120,21 @@ private static List extractBids(BidResponse bidResponse, BidRequest b : bidsFromResponse(bidResponse, bidRequest.getImp()); } - private static List bidsFromResponse(BidResponse bidResponse, List requestImps) { + private static List bidsFromResponse(BidResponse bidResponse, List imps) { return bidResponse.getSeatbid().stream() .map(SeatBid::getBid) .filter(Objects::nonNull) .flatMap(Collection::stream) - .map(bid -> BidderBid.of(bid, getMediaType(bid.getImpid(), requestImps), bidResponse.getCur())) + .map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), imps), bidResponse.getCur())) .collect(Collectors.toList()); } - private static BidType getMediaType(String impId, List requestImps) { - for (Imp imp : requestImps) { + private static BidType getBidType(String impId, List imps) { + for (Imp imp : imps) { if (imp.getId().equals(impId)) { if (imp.getVideo() != null) { return BidType.video; - } - if (imp.getXNative() != null) { + } else if (imp.getXNative() != null) { return BidType.xNative; } return BidType.banner; diff --git a/src/main/java/org/prebid/server/bidder/decenterads/DecenteradsBidder.java b/src/main/java/org/prebid/server/bidder/decenterads/DecenteradsBidder.java new file mode 100644 index 00000000000..d1448734871 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/decenterads/DecenteradsBidder.java @@ -0,0 +1,129 @@ +package org.prebid.server.bidder.decenterads; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.response.BidResponse; +import com.iab.openrtb.response.SeatBid; +import io.vertx.core.http.HttpMethod; +import org.apache.commons.collections4.CollectionUtils; +import org.prebid.server.bidder.Bidder; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.HttpCall; +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.HttpUtil; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * Decenterads {@link Bidder} implementation. + */ +public class DecenteradsBidder implements Bidder { + + private final String endpointUrl; + private final JacksonMapper mapper; + + public DecenteradsBidder(String endpointUrl, JacksonMapper mapper) { + this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.mapper = Objects.requireNonNull(mapper); + } + + @Override + public Result>> makeHttpRequests(BidRequest request) { + final List errors = new ArrayList<>(); + final List> validRequests = new ArrayList<>(); + + for (Imp imp : request.getImp()) { + try { + final ObjectNode decenteradsImpExt = parseAndValidateImpExt(imp.getExt()); + final Imp updatedImp = updateImp(imp, decenteradsImpExt); + + validRequests.add(createRequest(request, updatedImp)); + } catch (PreBidException e) { + errors.add(BidderError.badInput(e.getMessage())); + } + } + + return Result.of(validRequests, errors); + } + + private static ObjectNode parseAndValidateImpExt(ObjectNode impExt) { + final JsonNode ext = impExt.get("bidder"); + if (ext.isEmpty() || !ext.isObject()) { + throw new PreBidException("bidder parameters required"); + } + return (ObjectNode) ext; + } + + private static Imp updateImp(Imp imp, ObjectNode impExt) { + return imp.toBuilder().ext(impExt).build(); + } + + private HttpRequest createRequest(BidRequest request, Imp requestImp) { + final BidRequest outgoingRequest = request.toBuilder().imp(Collections.singletonList(requestImp)).build(); + + return HttpRequest.builder() + .method(HttpMethod.POST) + .uri(endpointUrl) + .headers(HttpUtil.headers()) + .payload(outgoingRequest) + .body(mapper.encode(outgoingRequest)) + .build(); + } + + @Override + public final Result> makeBids(HttpCall httpCall, BidRequest bidRequest) { + try { + final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class); + return Result.of(extractBids(httpCall.getRequest().getPayload(), bidResponse), Collections.emptyList()); + } catch (DecodeException | PreBidException e) { + return Result.withError(BidderError.badServerResponse(e.getMessage())); + } + } + + private static List extractBids(BidRequest bidRequest, BidResponse bidResponse) { + if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) { + return Collections.emptyList(); + } + return bidsFromResponse(bidRequest, bidResponse); + } + + private static List bidsFromResponse(BidRequest bidRequest, BidResponse bidResponse) { + 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())) + .collect(Collectors.toList()); + } + + private static BidType getBidType(String impId, List imps) { + for (Imp imp : imps) { + if (imp.getId().equals(impId)) { + if (imp.getBanner() != null) { + return BidType.banner; + } else if (imp.getVideo() != null) { + return BidType.video; + } else if (imp.getXNative() != null) { + return BidType.xNative; + } else if (imp.getAudio() != null) { + return BidType.audio; + } + } + } + return BidType.banner; + } +} diff --git a/src/main/java/org/prebid/server/bidder/dmx/DmxBidder.java b/src/main/java/org/prebid/server/bidder/dmx/DmxBidder.java index 2ef1beaf85d..923536f1d25 100644 --- a/src/main/java/org/prebid/server/bidder/dmx/DmxBidder.java +++ b/src/main/java/org/prebid/server/bidder/dmx/DmxBidder.java @@ -5,10 +5,13 @@ import com.iab.openrtb.request.App; import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Device; +import com.iab.openrtb.request.Format; import com.iab.openrtb.request.Imp; import com.iab.openrtb.request.Publisher; import com.iab.openrtb.request.Site; import com.iab.openrtb.request.User; +import com.iab.openrtb.request.Video; import com.iab.openrtb.response.Bid; import com.iab.openrtb.response.BidResponse; import com.iab.openrtb.response.SeatBid; @@ -35,6 +38,7 @@ import java.math.BigDecimal; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -51,6 +55,7 @@ public class DmxBidder implements Bidder { private static final int SECURE = 1; private static final String IMP = ""; private static final String SEARCH = ""; + private static final List VIDEO_PROTOCOLS = Arrays.asList(2, 3, 5, 6, 7, 8); private final String endpointUrl; private final JacksonMapper mapper; @@ -63,7 +68,7 @@ public DmxBidder(String endpointUrl, JacksonMapper mapper) { @Override public Result>> makeHttpRequests(BidRequest request) { try { - validateUserAndApp(request.getApp(), request.getUser()); + validateRequest(request); } catch (PreBidException e) { return Result.withError(BidderError.badInput(e.getMessage())); } @@ -102,7 +107,7 @@ public Result>> makeHttpRequests(BidRequest request final BidRequest outgoingRequest = request.toBuilder() .imp(validImps) .site(modifySite(request.getSite(), updatedPublisherId)) - .app(modifyApp(request.getApp(), updatedPublisherId)) + .app(modifyApp(request.getApp(), request.getDevice(), updatedPublisherId)) .build(); final String urlParameter = StringUtils.isNotBlank(updatedSellerId) @@ -121,6 +126,37 @@ public Result>> makeHttpRequests(BidRequest request errors); } + private static void validateRequest(BidRequest bidRequest) { + final User user = bidRequest.getUser(); + final App app = bidRequest.getApp(); + + if (user == null && app == null) { + throw new PreBidException("No user id or app id found. Could not send request to DMX."); + } + + if (app != null) { + if (StringUtils.isNotBlank(app.getId())) { + return; + } else if (StringUtils.isNotBlank(bidRequest.getDevice().getIfa())) { + return; + } + } + + if (user != null) { + if (StringUtils.isNotBlank(user.getId())) { + return; + } + + final ExtUser userExt = user.getExt(); + // Notice that digitrust is absent to keep prebid convention + if (userExt != null && CollectionUtils.isNotEmpty(userExt.getEids())) { + return; + } + } + + throw new PreBidException("This request contained no identifier"); + } + private ExtImpDmx parseImpExt(Imp imp) { try { return mapper.mapper().convertValue(imp.getExt(), DMX_EXT_TYPE_REFERENCE).getBidder(); @@ -157,60 +193,72 @@ private static Imp fetchParams(Imp imp, ExtImpDmx extImp) { return null; } - BigDecimal bidFloor = imp.getBidfloor(); - final BigDecimal extBidFloor = extImp.getBidFloor(); - if (extBidFloor != null && extBidFloor.compareTo(BigDecimal.ZERO) > 0) { - bidFloor = extBidFloor; - } - return imp.toBuilder() .tagid(tagId) .secure(StringUtils.isAllBlank(extTagId, dmxId) ? imp.getSecure() : SECURE) - .bidfloor(bidFloor) + .bidfloor(resolveBidFloor(extImp, imp.getBidfloor())) + .banner(resolveBanner(imp.getBanner())) + .video(resolveVideo(imp.getVideo())) .build(); } - private static void validateUserAndApp(App app, User user) { - if (user == null && app == null) { - throw new PreBidException("No user id or app id found. Could not send request to DMX."); - } + private static BigDecimal resolveBidFloor(ExtImpDmx extImp, BigDecimal bidFloor) { + final BigDecimal extBidFloor = extImp.getBidFloor(); + return extBidFloor != null && extBidFloor.compareTo(BigDecimal.ZERO) > 0 + ? extBidFloor + : bidFloor; + } - if (app != null && StringUtils.isNotBlank(app.getId())) { - return; + private static Banner resolveBanner(Banner banner) { + final Integer width = banner == null ? null : banner.getW(); + final Integer height = banner == null ? null : banner.getH(); + final List format = banner != null ? banner.getFormat() : null; + + if ((height == null || width == null) && CollectionUtils.isNotEmpty(format)) { + final Format firstFormat = format.get(0); + if (firstFormat != null) { + return banner.toBuilder() + .w(firstFormat.getW()) + .h(firstFormat.getH()) + .build(); + } } + return banner; + } - if (user != null) { - if (StringUtils.isNotBlank(user.getId())) { - return; - } + private static Video resolveVideo(Video video) { + return video == null + ? null + : video.toBuilder() + .protocols(resolveVideoProtocols(video.getProtocols())) + .build(); - final ExtUser userExt = user.getExt(); - // Notice that digitrust is absent to keep prebid convention - if (userExt != null && CollectionUtils.isNotEmpty(userExt.getEids())) { - return; - } - } + } - throw new PreBidException("This request contained no identifier"); + private static List resolveVideoProtocols(List videoProtocols) { + return CollectionUtils.isNotEmpty(videoProtocols) + ? videoProtocols + : VIDEO_PROTOCOLS; } private Site modifySite(Site site, String updatedPublisherId) { return site == null ? null : site.toBuilder() - .publisher(modifyPublisher(site.getPublisher(), updatedPublisherId, false)) - .build(); + .publisher(modifyPublisher(site.getPublisher(), updatedPublisherId, false)) + .build(); } - private App modifyApp(App app, String updatedPublisherId) { + private App modifyApp(App app, Device device, String updatedPublisherId) { return app == null ? null : app.toBuilder() - .publisher(modifyPublisher(app.getPublisher(), updatedPublisherId, true)) - .build(); + .id(StringUtils.isNotBlank(app.getId()) ? app.getId() : device.getIfa()) + .publisher(modifyPublisher(app.getPublisher(), updatedPublisherId, true)) + .build(); } - private Publisher modifyPublisher(Publisher publisher, String updatedPublisherId, boolean extOnEmptyPublisher) { + private Publisher modifyPublisher(Publisher publisher, String updatedPublisherId, boolean setExtOnEmptyPublisher) { final DmxPublisherExtId dmxPublisherExtId = DmxPublisherExtId.of(updatedPublisherId); final ObjectNode encodedPublisherExt = mapper.mapper().valueToTree(dmxPublisherExtId); @@ -220,11 +268,11 @@ private Publisher modifyPublisher(Publisher publisher, String updatedPublisherId if (publisher == null) { return Publisher.builder() .id(updatedPublisherId) - .ext(extOnEmptyPublisher ? extPublisher : null) + .ext(setExtOnEmptyPublisher ? extPublisher : null) .build(); } else { return publisher.toBuilder() - .id(ObjectUtils.firstNonNull(publisher.getId(), updatedPublisherId)) + .id(ObjectUtils.defaultIfNull(publisher.getId(), updatedPublisherId)) .ext(extPublisher) .build(); } diff --git a/src/main/java/org/prebid/server/bidder/engagebdr/EngagebdrBidder.java b/src/main/java/org/prebid/server/bidder/engagebdr/EngagebdrBidder.java index 7e9d851938f..e6fc64e68f0 100644 --- a/src/main/java/org/prebid/server/bidder/engagebdr/EngagebdrBidder.java +++ b/src/main/java/org/prebid/server/bidder/engagebdr/EngagebdrBidder.java @@ -126,12 +126,11 @@ private static List bidsFromResponse(BidResponse bidResponse, BidRequ .map(SeatBid::getBid) .filter(Objects::nonNull) .flatMap(Collection::stream) - .map(bid -> BidderBid.of(bid, getMediaTypes(bid.getImpid(), bidRequest.getImp()), - bidResponse.getCur())) + .map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), bidRequest.getImp()), bidResponse.getCur())) .collect(Collectors.toList()); } - private static BidType getMediaTypes(String impId, List imps) { + private static BidType getBidType(String impId, List imps) { for (Imp imp : imps) { if (imp.getId().equals(impId)) { if (imp.getVideo() != null) { diff --git a/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java b/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java index 02f745b50ce..8b5d6b57c43 100644 --- a/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java +++ b/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java @@ -126,9 +126,9 @@ private ExtImpEplanning validateAndModifyImpExt(Imp imp) throws PreBidException final ExtImpEplanning extImpEplanning; try { extImpEplanning = mapper.mapper().convertValue(imp.getExt(), EPLANNING_EXT_TYPE_REFERENCE).getBidder(); - } catch (IllegalArgumentException ex) { + } catch (IllegalArgumentException e) { throw new PreBidException(String.format( - "Ignoring imp id=%s, error while decoding extImpBidder, err: %s", imp.getId(), ex.getMessage())); + "Ignoring imp id=%s, error while decoding extImpBidder, err: %s", imp.getId(), e.getMessage())); } if (extImpEplanning == null) { diff --git a/src/main/java/org/prebid/server/bidder/epom/EpomBidder.java b/src/main/java/org/prebid/server/bidder/epom/EpomBidder.java new file mode 100644 index 00000000000..ec00e2ff0c8 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/epom/EpomBidder.java @@ -0,0 +1,100 @@ +package org.prebid.server.bidder.epom; + +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Device; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.response.BidResponse; +import com.iab.openrtb.response.SeatBid; +import io.vertx.core.http.HttpMethod; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.prebid.server.bidder.Bidder; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.HttpCall; +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.HttpUtil; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * Epom {@link Bidder} implementation. + */ +public class EpomBidder implements Bidder { + + private final String endpointUrl; + private final JacksonMapper mapper; + + public EpomBidder(String endpointUrl, JacksonMapper mapper) { + this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.mapper = Objects.requireNonNull(mapper); + } + + @Override + public Result>> makeHttpRequests(BidRequest request) { + final Device device = request.getDevice(); + final String ip = device != null ? device.getIp() : null; + if (StringUtils.isBlank(ip)) { + return Result.withError(BidderError.badInput("ipv4 address is required field")); + } + + return Result.withValue(HttpRequest.builder() + .method(HttpMethod.POST) + .uri(endpointUrl) + .headers(HttpUtil.headers()) + .payload(request) + .body(mapper.encode(request)) + .build()); + } + + @Override + public final Result> makeBids(HttpCall httpCall, BidRequest bidRequest) { + try { + final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class); + return Result.of(extractBids(httpCall.getRequest().getPayload(), bidResponse), Collections.emptyList()); + } catch (DecodeException | PreBidException e) { + return Result.withError(BidderError.badServerResponse(e.getMessage())); + } + } + + private static List extractBids(BidRequest bidRequest, BidResponse bidResponse) { + if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) { + return Collections.emptyList(); + } + return bidsFromResponse(bidRequest, bidResponse); + } + + private static List bidsFromResponse(BidRequest bidRequest, BidResponse bidResponse) { + 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())) + .collect(Collectors.toList()); + } + + private static BidType getBidType(String impId, List imps) { + for (Imp imp : imps) { + if (imp.getId().equals(impId)) { + if (imp.getBanner() != null) { + return BidType.banner; + } else if (imp.getVideo() != null) { + return BidType.video; + } else if (imp.getXNative() != null) { + return BidType.xNative; + } + } + } + return BidType.banner; + } +} diff --git a/src/main/java/org/prebid/server/bidder/facebook/FacebookBidder.java b/src/main/java/org/prebid/server/bidder/facebook/FacebookBidder.java index 7c0ba8b4776..a366c032dca 100644 --- a/src/main/java/org/prebid/server/bidder/facebook/FacebookBidder.java +++ b/src/main/java/org/prebid/server/bidder/facebook/FacebookBidder.java @@ -317,10 +317,12 @@ private BidderBid toBidderBid(Bid bid, List imps, String currency, List imps, String currency, List imps) { + private static BidType getBidType(String impId, List imps) { for (Imp imp : imps) { if (impId.equals(imp.getId())) { final BidType bidType = resolveImpType(imp); @@ -353,16 +355,13 @@ public HttpRequest makeTimeoutNotification(HttpRequest httpReq final App app = bidRequest.getApp(); final Publisher publisher = app != null ? app.getPublisher() : null; final String publisherId = publisher != null ? publisher.getId() : null; - if (StringUtils.isEmpty(publisherId)) { return null; } - final String url = String.format(timeoutNotificationUrlTemplate, this.platformId, publisherId, requestId); - return HttpRequest.builder() .method(HttpMethod.GET) - .uri(url) + .uri(String.format(timeoutNotificationUrlTemplate, platformId, publisherId, requestId)) .build(); } } diff --git a/src/main/java/org/prebid/server/bidder/gamma/GammaBidder.java b/src/main/java/org/prebid/server/bidder/gamma/GammaBidder.java index 87c6b6bdb53..c55a360e4be 100644 --- a/src/main/java/org/prebid/server/bidder/gamma/GammaBidder.java +++ b/src/main/java/org/prebid/server/bidder/gamma/GammaBidder.java @@ -204,14 +204,14 @@ public Result> makeBids(HttpCall httpCall, BidRequest bidR try { final GammaBidResponse bidResponse = mapper.decodeValue(body, GammaBidResponse.class); final List errors = new ArrayList<>(); - return Result.of(extractBidsAndFillErorrs(bidResponse, bidRequest, errors), errors); + return Result.of(extractBidsAndFillErrors(bidResponse, bidRequest, errors), errors); } catch (DecodeException e) { return Result.withError(BidderError.badServerResponse( String.format("bad server response: %s", e.getMessage()))); } } - private static List extractBidsAndFillErorrs(GammaBidResponse bidResponse, + private static List extractBidsAndFillErrors(GammaBidResponse bidResponse, BidRequest bidRequest, List errors) { return bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid()) @@ -248,28 +248,29 @@ private static BidType getMediaTypes(String impId, List imps) { private static Bid convertBid(GammaBid gammaBid, BidType bidType) { final boolean isVideo = BidType.video.equals(bidType); - if (!isVideo && StringUtils.isBlank(gammaBid.getAdm())) { + if (!isVideo && StringUtils.isBlank(gammaBid.getBid().getAdm())) { throw new PreBidException("Missing Ad Markup. Run with request.debug = 1 for more info"); } + Bid bid = gammaBid.getBid(); if (isVideo) { //Return inline VAST XML Document (Section 6.4.2) final String vastXml = gammaBid.getVastXml(); if (StringUtils.isNotBlank(vastXml)) { - final Bid.BidBuilder bidBuilder = gammaBid.toBuilder().adm(vastXml); + final Bid.BidBuilder bidBuilder = gammaBid.getBid().toBuilder().adm(vastXml); final String vastUrl = gammaBid.getVastUrl(); if (StringUtils.isNotBlank(vastUrl)) { bidBuilder.nurl(vastUrl); } - return bidBuilder.build(); + bid = bidBuilder.build(); } else { throw new PreBidException("Missing Ad Markup. Run with request.debug = 1 for more info"); } } - return gammaBid; + return bid; } } diff --git a/src/main/java/org/prebid/server/bidder/gamma/model/GammaBid.java b/src/main/java/org/prebid/server/bidder/gamma/model/GammaBid.java index 26f24d9c498..991c1982b96 100644 --- a/src/main/java/org/prebid/server/bidder/gamma/model/GammaBid.java +++ b/src/main/java/org/prebid/server/bidder/gamma/model/GammaBid.java @@ -1,21 +1,27 @@ package org.prebid.server.bidder.gamma.model; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.iab.openrtb.response.Bid; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; -import lombok.experimental.SuperBuilder; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.RequiredArgsConstructor; -@EqualsAndHashCode(callSuper = true) -@SuperBuilder -@NoArgsConstructor -@Data -public class GammaBid extends Bid { +@Getter +@Builder +@AllArgsConstructor(onConstructor = @__(@JsonIgnore)) +@RequiredArgsConstructor +public class GammaBid { + + @JsonUnwrapped + Bid bid; @JsonProperty("vastXml") String vastXml; @JsonProperty("vastUrl") String vastUrl; + } diff --git a/src/main/java/org/prebid/server/bidder/gamoshi/GamoshiBidder.java b/src/main/java/org/prebid/server/bidder/gamoshi/GamoshiBidder.java index 48e8418f902..31465604f2a 100644 --- a/src/main/java/org/prebid/server/bidder/gamoshi/GamoshiBidder.java +++ b/src/main/java/org/prebid/server/bidder/gamoshi/GamoshiBidder.java @@ -149,7 +149,7 @@ private static List extractBids(BidRequest bidRequest, BidResponse bi } private static List bidsFromResponse(BidRequest bidRequest, BidResponse bidResponse) { - final Map requestImpIdToBidType = bidRequest.getImp().stream() + final Map impIdToBidType = bidRequest.getImp().stream() .collect(Collectors.toMap(Imp::getId, GamoshiBidder::getBidType)); return bidResponse.getSeatbid().stream() @@ -157,8 +157,8 @@ private static List bidsFromResponse(BidRequest bidRequest, BidRespon .map(SeatBid::getBid) .filter(Objects::nonNull) .flatMap(Collection::stream) - .map(bid -> BidderBid.of(bid, - requestImpIdToBidType.getOrDefault(bid.getImpid(), BidType.banner), bidResponse.getCur())) + .map(bid -> BidderBid.of(bid, impIdToBidType.getOrDefault(bid.getImpid(), BidType.banner), + bidResponse.getCur())) .collect(Collectors.toList()); } diff --git a/src/main/java/org/prebid/server/bidder/gumgum/GumgumBidder.java b/src/main/java/org/prebid/server/bidder/gumgum/GumgumBidder.java index e5cfe5dcacc..17852e7eb1e 100644 --- a/src/main/java/org/prebid/server/bidder/gumgum/GumgumBidder.java +++ b/src/main/java/org/prebid/server/bidder/gumgum/GumgumBidder.java @@ -1,10 +1,12 @@ package org.prebid.server.bidder.gumgum; import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Format; import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Publisher; import com.iab.openrtb.request.Site; import com.iab.openrtb.request.Video; import com.iab.openrtb.response.Bid; @@ -13,7 +15,6 @@ import io.vertx.core.http.HttpMethod; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ArrayUtils; -import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.prebid.server.bidder.Bidder; import org.prebid.server.bidder.model.BidderBid; @@ -26,10 +27,12 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.proto.openrtb.ext.ExtPrebid; import org.prebid.server.proto.openrtb.ext.request.gumgum.ExtImpGumgum; +import org.prebid.server.proto.openrtb.ext.request.gumgum.ExtImpGumgumVideo; import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.util.HttpUtil; import java.math.BigDecimal; +import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -80,20 +83,21 @@ public Result>> makeHttpRequests(BidRequest bidRequ private BidRequest createBidRequest(BidRequest bidRequest, List errors) { final List modifiedImps = new ArrayList<>(); - String trackingId = null; + String zone = null; + BigInteger pubId = null; + for (Imp imp : bidRequest.getImp()) { try { - final ExtImpGumgum impExt = parseImpExt(imp); - if (imp.getBanner() != null) { - modifiedImps.add(modifyImp(imp)); - trackingId = impExt.getZone(); - } else { - final Video video = imp.getVideo(); - if (video != null) { - validateVideoParams(video); - modifiedImps.add(imp); - trackingId = impExt.getZone(); - } + final ExtImpGumgum extImp = parseImpExt(imp); + modifiedImps.add(modifyImp(imp, extImp)); + + final String extZone = extImp.getZone(); + if (StringUtils.isNotEmpty(extZone)) { + zone = extZone; + } + final BigInteger extPubId = extImp.getPubId(); + if (extPubId != null && !extPubId.equals(BigInteger.ZERO)) { + pubId = extPubId; } } catch (PreBidException e) { errors.add(BidderError.badInput(e.getMessage())); @@ -104,11 +108,9 @@ private BidRequest createBidRequest(BidRequest bidRequest, List err throw new PreBidException("No valid impressions"); } - final Site modifiedSite = modifySite(bidRequest.getSite(), trackingId); - return bidRequest.toBuilder() .imp(modifiedImps) - .site(modifiedSite) + .site(modifySite(bidRequest.getSite(), zone, pubId)) .build(); } @@ -120,14 +122,26 @@ private ExtImpGumgum parseImpExt(Imp imp) { } } - private static Imp modifyImp(Imp imp) { - final Banner resolvedBanner = resolveBanner(imp.getBanner()); - if (resolvedBanner != null) { - return imp.toBuilder() - .banner(resolvedBanner) - .build(); + private Imp modifyImp(Imp imp, ExtImpGumgum extImp) { + final Imp.ImpBuilder impBuilder = imp.toBuilder(); + if (imp.getBanner() != null) { + final Banner resolvedBanner = resolveBanner(imp.getBanner()); + if (resolvedBanner != null) { + impBuilder.banner(resolvedBanner); + } + } + + final Video video = imp.getVideo(); + if (video != null) { + validateVideoParams(video); + final String irisId = extImp.getIrisId(); + if (StringUtils.isNotEmpty(irisId)) { + final Video resolvedVideo = resolveVideo(video, irisId); + impBuilder.video(resolvedVideo); + } } - return imp; + + return impBuilder.build(); } private static Banner resolveBanner(Banner banner) { @@ -151,6 +165,11 @@ private void validateVideoParams(Video video) { } } + private Video resolveVideo(Video video, String irisId) { + final ObjectNode videoExt = mapper.mapper().valueToTree(ExtImpGumgumVideo.of(irisId)); + return video.toBuilder().ext(videoExt).build(); + } + private static boolean anyOfNull(Integer... numbers) { return Arrays.stream(ArrayUtils.nullToEmpty(numbers)).anyMatch(GumgumBidder::isNullOrZero); } @@ -159,8 +178,22 @@ private static boolean isNullOrZero(Integer number) { return number == null || number == 0; } - private static Site modifySite(Site site, String trackingId) { - return site != null ? site.toBuilder().id(ObjectUtils.defaultIfNull(trackingId, "")).build() : null; + private static Site modifySite(Site requestSite, String zone, BigInteger pubId) { + if (requestSite == null) { + return null; + } + + final Site.SiteBuilder modifiedSite = requestSite.toBuilder(); + if (StringUtils.isNotEmpty(zone)) { + modifiedSite.id(zone); + } + if (pubId != null && !pubId.equals(BigInteger.ZERO)) { + final Publisher publisher = requestSite.getPublisher(); + final Publisher.PublisherBuilder publisherBuilder = publisher != null + ? publisher.toBuilder() : Publisher.builder(); + modifiedSite.publisher(publisherBuilder.id(pubId.toString()).build()); + } + return modifiedSite.build(); } @Override @@ -190,15 +223,15 @@ private static List bidsFromResponse(BidResponse bidResponse, BidRequ } private static BidderBid toBidderBid(Bid bid, BidRequest bidRequest, String currency) { - final BidType bidType = getMediaType(bid.getImpid(), bidRequest.getImp()); + final BidType bidType = getBidType(bid.getImpid(), bidRequest.getImp()); final Bid updatedBid = bidType == BidType.video ? bid.toBuilder().adm(resolveAdm(bid.getAdm(), bid.getPrice())).build() : bid; return BidderBid.of(updatedBid, bidType, currency); } - private static BidType getMediaType(String impId, List requestImps) { - for (Imp imp : requestImps) { + private static BidType getBidType(String impId, List imps) { + for (Imp imp : imps) { if (imp.getId().equals(impId)) { return imp.getBanner() != null ? BidType.banner : BidType.video; } diff --git a/src/main/java/org/prebid/server/bidder/improvedigital/ImprovedigitalBidder.java b/src/main/java/org/prebid/server/bidder/improvedigital/ImprovedigitalBidder.java index ec51f890f44..f4dfdaef1cf 100644 --- a/src/main/java/org/prebid/server/bidder/improvedigital/ImprovedigitalBidder.java +++ b/src/main/java/org/prebid/server/bidder/improvedigital/ImprovedigitalBidder.java @@ -1,15 +1,101 @@ package org.prebid.server.bidder.improvedigital; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.response.BidResponse; +import com.iab.openrtb.response.SeatBid; +import io.vertx.core.http.HttpMethod; +import org.apache.commons.collections4.CollectionUtils; import org.prebid.server.bidder.Bidder; -import org.prebid.server.bidder.OpenrtbBidder; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.HttpCall; +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.HttpUtil; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; /** * ImproveDigital {@link Bidder} implementation. */ -public class ImprovedigitalBidder extends OpenrtbBidder { +public class ImprovedigitalBidder implements Bidder { + + private final String endpointUrl; + private final JacksonMapper mapper; public ImprovedigitalBidder(String endpointUrl, JacksonMapper mapper) { - super(endpointUrl, RequestCreationStrategy.SINGLE_REQUEST, Void.class, mapper); + this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.mapper = Objects.requireNonNull(mapper); + } + + @Override + public Result>> makeHttpRequests(BidRequest request) { + + return Result.withValues(Collections.singletonList( + HttpRequest.builder() + .method(HttpMethod.POST) + .uri(endpointUrl) + .headers(HttpUtil.headers()) + .payload(request) + .body(mapper.encode(request)) + .build())); + } + + @Override + public Result> makeBids(HttpCall httpCall, BidRequest bidRequest) { + try { + final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class); + return Result.withValues(extractBids(httpCall.getRequest().getPayload(), bidResponse)); + } catch (DecodeException | PreBidException e) { + return Result.withError(BidderError.badServerResponse(e.getMessage())); + } + } + + private static List extractBids(BidRequest bidRequest, BidResponse bidResponse) { + if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) { + return Collections.emptyList(); + } + if (bidResponse.getSeatbid().size() > 1) { + throw new PreBidException(String.format("Unexpected SeatBid! Must be only one but have: %d", + bidResponse.getSeatbid().size())); + } + return bidsFromResponse(bidRequest, bidResponse); + } + + private static List bidsFromResponse(BidRequest bidRequest, BidResponse bidResponse) { + 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())) + .collect(Collectors.toList()); + } + + private static BidType getBidType(String impId, List imps) { + for (Imp imp : imps) { + if (imp.getId().equals(impId)) { + if (imp.getBanner() != null) { + return BidType.banner; + } + if (imp.getVideo() != null) { + return BidType.video; + } + if (imp.getXNative() != null) { + return BidType.xNative; + } + throw new PreBidException(String.format("Unknown impression type for ID: \"%s\"", impId)); + } + } + throw new PreBidException(String.format("Failed to find impression for ID: \"%s\"", impId)); } } diff --git a/src/main/java/org/prebid/server/bidder/inmobi/InmobiBidder.java b/src/main/java/org/prebid/server/bidder/inmobi/InmobiBidder.java index 52f53f3e695..7cd76b417d2 100644 --- a/src/main/java/org/prebid/server/bidder/inmobi/InmobiBidder.java +++ b/src/main/java/org/prebid/server/bidder/inmobi/InmobiBidder.java @@ -129,7 +129,7 @@ private List bidsFromResponse(BidRequest bidRequest, BidResponse bidR .collect(Collectors.toList()); } - private BidType getBidType(String impId, List imps) { + private static BidType getBidType(String impId, List imps) { for (Imp imp : imps) { if (imp.getId().equals(impId) && imp.getVideo() != null) { return BidType.video; diff --git a/src/main/java/org/prebid/server/bidder/ix/IxBidder.java b/src/main/java/org/prebid/server/bidder/ix/IxBidder.java index aa222cc82d9..e12efde3deb 100644 --- a/src/main/java/org/prebid/server/bidder/ix/IxBidder.java +++ b/src/main/java/org/prebid/server/bidder/ix/IxBidder.java @@ -132,8 +132,8 @@ private static Site modifySite(Site site, ExtImpIx extImpIx) { return site == null ? null : site.toBuilder() - .publisher(modifyPublisher(site.getPublisher(), extImpIx.getSiteId())) - .build(); + .publisher(modifyPublisher(site.getPublisher(), extImpIx.getSiteId())) + .build(); } private static Publisher modifyPublisher(Publisher publisher, String siteId) { @@ -227,9 +227,10 @@ private static BidType getBidType(String impId, List imps) { } private static Bid prepareBid(Bid bid, BidRequest bidRequest) { - // Current implementation ensure that we have one imp + // Current implementation ensure that we have at least one imp in request + final boolean bidHasNoSizes = bid.getH() == null || bid.getW() == null; final Banner banner = bidRequest.getImp().get(0).getBanner(); - if (bid.getH() == null || bid.getW() == null && banner != null) { + if (bidHasNoSizes && banner != null) { return bid.toBuilder() .w(banner.getW()) .h(banner.getH()) diff --git a/src/main/java/org/prebid/server/bidder/jixie/JixieBidder.java b/src/main/java/org/prebid/server/bidder/jixie/JixieBidder.java new file mode 100644 index 00000000000..c23b82c2682 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/jixie/JixieBidder.java @@ -0,0 +1,101 @@ +package org.prebid.server.bidder.jixie; + +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Device; +import com.iab.openrtb.request.Site; +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.apache.commons.lang3.StringUtils; +import org.prebid.server.bidder.Bidder; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.HttpCall; +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.HttpUtil; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * Jixie {@link Bidder} implementation. + */ +public class JixieBidder implements Bidder { + + private final String endpointUrl; + private final JacksonMapper mapper; + + public JixieBidder(String endpointUrl, JacksonMapper mapper) { + this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.mapper = Objects.requireNonNull(mapper); + } + + @Override + public Result>> makeHttpRequests(BidRequest request) { + + return Result.withValue(HttpRequest.builder() + .method(HttpMethod.POST) + .uri(endpointUrl) + .headers(resolveHeaders(request.getDevice(), request.getSite())) + .payload(request) + .body(mapper.encode(request)) + .build()); + } + + private static MultiMap resolveHeaders(Device device, Site site) { + final MultiMap headers = HttpUtil.headers(); + + if (device != null) { + HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.USER_AGENT_HEADER, device.getUa()); + HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.X_FORWARDED_FOR_HEADER, device.getIp()); + } + if (site != null) { + HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.REFERER_HEADER, site.getPage()); + } + + return headers; + } + + @Override + public final Result> makeBids(HttpCall httpCall, BidRequest bidRequest) { + try { + final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class); + return Result.of(extractBids(bidResponse), Collections.emptyList()); + } catch (DecodeException | PreBidException e) { + return Result.withError(BidderError.badServerResponse(e.getMessage())); + } + } + + private static List extractBids(BidResponse bidResponse) { + if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) { + return Collections.emptyList(); + } + return bidsFromResponse(bidResponse); + } + + private static List bidsFromResponse(BidResponse bidResponse) { + return bidResponse.getSeatbid().stream() + .filter(Objects::nonNull) + .map(SeatBid::getBid) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .map(bid -> BidderBid.of(bid, getBidType(bid.getAdm()), bidResponse.getCur())) + .collect(Collectors.toList()); + } + + private static BidType getBidType(String adm) { + return StringUtils.containsAny(adm, "> extractBids(BidRequest bidRequest, BidResponse b private BidderBid toBidderBid(BidRequest bidRequest, String currency, Bid bid, List errors) { try { - final BidType bidType = getBidType(bid.getImpid(), bidRequest.getImp()); - return BidderBid.of(bid, bidType, currency); + return BidderBid.of(bid, getBidType(bid.getImpid(), bidRequest.getImp()), currency); } catch (PreBidException e) { errors.add(BidderError.badInput(e.getMessage())); return null; diff --git a/src/main/java/org/prebid/server/bidder/lifestreet/LifestreetBidder.java b/src/main/java/org/prebid/server/bidder/lifestreet/LifestreetBidder.java index 366a4bd99cc..d0379215751 100644 --- a/src/main/java/org/prebid/server/bidder/lifestreet/LifestreetBidder.java +++ b/src/main/java/org/prebid/server/bidder/lifestreet/LifestreetBidder.java @@ -144,14 +144,13 @@ private static List bidsFromResponse(BidRequest bidRequest, BidRespon .map(SeatBid::getBid) .filter(Objects::nonNull) .flatMap(Collection::stream) - .map(bid -> BidderBid.of(bid, getMediaTypes(bid.getImpid(), bidRequest.getImp()), - bidResponse.getCur())) + .map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), bidRequest.getImp()), bidResponse.getCur())) // one bid per request/response .limit(1) .collect(Collectors.toList()); } - private static BidType getMediaTypes(String impId, List imps) { + private static BidType getBidType(String impId, List imps) { for (Imp imp : imps) { if (imp.getId().equals(impId) && imp.getVideo() != null) { return BidType.video; diff --git a/src/main/java/org/prebid/server/bidder/lunamedia/LunamediaBidder.java b/src/main/java/org/prebid/server/bidder/lunamedia/LunamediaBidder.java index 341c5a419f3..d65ecf482ce 100644 --- a/src/main/java/org/prebid/server/bidder/lunamedia/LunamediaBidder.java +++ b/src/main/java/org/prebid/server/bidder/lunamedia/LunamediaBidder.java @@ -222,11 +222,11 @@ private static List bidsFromResponse(BidRequest bidRequest, BidRespon .map(SeatBid::getBid) .filter(Objects::nonNull) .flatMap(Collection::stream) - .map(bid -> BidderBid.of(bid, getType(bid.getImpid(), bidRequest.getImp()), bidResponse.getCur())) + .map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), bidRequest.getImp()), bidResponse.getCur())) .collect(Collectors.toList()); } - private static BidType getType(String impId, List imps) { + private static BidType getBidType(String impId, List imps) { for (Imp imp : imps) { if (imp.getId().equals(impId)) { return imp.getVideo() != null ? BidType.video : BidType.banner; diff --git a/src/main/java/org/prebid/server/bidder/mobfoxpb/MobfoxpbBidder.java b/src/main/java/org/prebid/server/bidder/mobfoxpb/MobfoxpbBidder.java index fa4f22f3658..f6ef6d052af 100644 --- a/src/main/java/org/prebid/server/bidder/mobfoxpb/MobfoxpbBidder.java +++ b/src/main/java/org/prebid/server/bidder/mobfoxpb/MobfoxpbBidder.java @@ -8,6 +8,7 @@ import com.iab.openrtb.response.SeatBid; import io.vertx.core.http.HttpMethod; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.prebid.server.bidder.Bidder; import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderError; @@ -34,6 +35,13 @@ */ public class MobfoxpbBidder implements Bidder { + private static final String ROUTE_RTB = "rtb"; + private static final String METHOD_RTB = "req"; + private static final String ROUTE_NATIVE = "o"; + private static final String METHOD_NATIVE = "ortb"; + private static final String URL_KEY_MACROS = "__key__"; + private static final String URL_ROUTE_MACROS = "__route__"; + private static final String URL_METHOD_MACROS = "__method__"; private final String endpointUrl; private final JacksonMapper mapper; @@ -48,16 +56,15 @@ public MobfoxpbBidder(String endpoint, JacksonMapper mapper) { @Override public final Result>> makeHttpRequests(BidRequest bidRequest) { - BidRequest outgoingRequest; + final BidRequest outgoingRequest; + final String uri; try { final Imp firstImp = bidRequest.getImp().get(0); final ExtImpMobfoxpb impExt = parseImpExt(firstImp); - final Imp modifiedImp = firstImp.toBuilder() - .tagid(impExt.getTagId()) - .build(); + uri = buildUri(impExt.getKey()); outgoingRequest = bidRequest.toBuilder() - .imp(Collections.singletonList(modifiedImp)) + .imp(Collections.singletonList(firstImp)) .build(); } catch (PreBidException e) { return Result.withError(BidderError.badInput(e.getMessage())); @@ -65,7 +72,7 @@ public final Result>> makeHttpRequests(BidRequest b return Result.withValue(HttpRequest.builder() .method(HttpMethod.POST) - .uri(endpointUrl) + .uri(uri) .body(mapper.encode(outgoingRequest)) .headers(HttpUtil.headers()) .payload(outgoingRequest) @@ -73,11 +80,32 @@ public final Result>> makeHttpRequests(BidRequest b } private ExtImpMobfoxpb parseImpExt(Imp imp) { + final ExtImpMobfoxpb extImpMobfoxpb; try { - return mapper.mapper().convertValue(imp.getExt(), MOBFOXPB_EXT_TYPE_REFERENCE).getBidder(); + extImpMobfoxpb = mapper.mapper().convertValue(imp.getExt(), MOBFOXPB_EXT_TYPE_REFERENCE).getBidder(); } catch (IllegalArgumentException e) { - throw new PreBidException(e.getMessage(), e); + throw new PreBidException(e.getMessage()); + } + if (StringUtils.isEmpty(extImpMobfoxpb.getKey()) && StringUtils.isEmpty(extImpMobfoxpb.getTagId())) { + throw new PreBidException("Invalid or non existing key and tagId, atleast one should be present"); + } + return extImpMobfoxpb; + } + + private String buildUri(String key) { + final String route; + final String method; + String uri = endpointUrl; + if (StringUtils.isNotEmpty(key)) { + route = ROUTE_RTB; + method = METHOD_RTB; + uri = uri.replace(URL_KEY_MACROS, key); + } else { + route = ROUTE_NATIVE; + method = METHOD_NATIVE; } + + return uri.replace(URL_ROUTE_MACROS, route).replace(URL_METHOD_MACROS, method); } @Override @@ -112,8 +140,7 @@ private static Result> extractBids(BidResponse bidResponse, List private static BidderBid bidFromResponse(List imps, Bid bid, String currency, List errors) { try { - final BidType bidType = getBidType(bid.getImpid(), imps); - return BidderBid.of(bid, bidType, currency); + return BidderBid.of(bid, getBidType(bid.getImpid(), imps), currency); } catch (PreBidException e) { errors.add(BidderError.badInput(e.getMessage())); return null; @@ -132,6 +159,6 @@ private static BidType getBidType(String impId, List imps) { } } } - throw new PreBidException(String.format("Failed to find impression %s", impId)); + throw new PreBidException(String.format("Failed to find impression \"%s\"", impId)); } } diff --git a/src/main/java/org/prebid/server/bidder/model/BidderBid.java b/src/main/java/org/prebid/server/bidder/model/BidderBid.java index 11aba88396e..52bd90db136 100644 --- a/src/main/java/org/prebid/server/bidder/model/BidderBid.java +++ b/src/main/java/org/prebid/server/bidder/model/BidderBid.java @@ -27,4 +27,8 @@ public class BidderBid { * Will be used for converting to ad server currency */ String bidCurrency; + + public BidderBid with(Bid bid) { + return BidderBid.of(bid, this.type, this.bidCurrency); + } } diff --git a/src/main/java/org/prebid/server/bidder/model/BidderSeatBid.java b/src/main/java/org/prebid/server/bidder/model/BidderSeatBid.java index 93e9afb809a..2f87e64608c 100644 --- a/src/main/java/org/prebid/server/bidder/model/BidderSeatBid.java +++ b/src/main/java/org/prebid/server/bidder/model/BidderSeatBid.java @@ -8,7 +8,7 @@ import java.util.List; /** - * Seatid returned by a {@link Bidder}. + * Seatbid returned by a {@link Bidder}. *

* This is distinct from the {@link com.iab.openrtb.response.SeatBid} so that the prebid-server ext can be passed * back with type safety. @@ -41,4 +41,8 @@ public class BidderSeatBid { * Error messages should help publishers understand what might account for "bad" bids. */ List errors; + + public BidderSeatBid with(List bids) { + return BidderSeatBid.of(bids, this.httpCalls, this.errors); + } } diff --git a/src/main/java/org/prebid/server/bidder/model/BidderSeatBidInfo.java b/src/main/java/org/prebid/server/bidder/model/BidderSeatBidInfo.java new file mode 100644 index 00000000000..4d8f7bf575c --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/model/BidderSeatBidInfo.java @@ -0,0 +1,23 @@ +package org.prebid.server.bidder.model; + +import lombok.AllArgsConstructor; +import lombok.Value; +import org.prebid.server.auction.model.BidInfo; +import org.prebid.server.proto.openrtb.ext.response.ExtHttpCall; + +import java.util.List; + +@AllArgsConstructor(staticName = "of") +@Value +public class BidderSeatBidInfo { + + List bidsInfos; + + List httpCalls; + + List errors; + + public BidderSeatBidInfo with(List bids) { + return BidderSeatBidInfo.of(bids, this.httpCalls, this.errors); + } +} diff --git a/src/main/java/org/prebid/server/bidder/model/HttpRequest.java b/src/main/java/org/prebid/server/bidder/model/HttpRequest.java index 9b295fb3e97..069f187467f 100644 --- a/src/main/java/org/prebid/server/bidder/model/HttpRequest.java +++ b/src/main/java/org/prebid/server/bidder/model/HttpRequest.java @@ -8,7 +8,7 @@ /** * Packages together the fields needed to make an http request. */ -@Builder +@Builder(toBuilder = true) @Value public class HttpRequest { diff --git a/src/main/java/org/prebid/server/bidder/ninthdecimal/NinthdecimalBidder.java b/src/main/java/org/prebid/server/bidder/ninthdecimal/NinthdecimalBidder.java index 01853fc2552..067867b9dc0 100644 --- a/src/main/java/org/prebid/server/bidder/ninthdecimal/NinthdecimalBidder.java +++ b/src/main/java/org/prebid/server/bidder/ninthdecimal/NinthdecimalBidder.java @@ -216,14 +216,11 @@ private static List bidsFromResponse(BidRequest bidRequest, BidRespon return bidResponse.getSeatbid().stream() .map(SeatBid::getBid) .flatMap(Collection::stream) - .map(bid -> BidderBid.of(bid, getType(bid.getImpid(), bidRequest.getImp()), bidResponse.getCur())) + .map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), bidRequest.getImp()), bidResponse.getCur())) .collect(Collectors.toList()); } - /** - * Resolves the media type for the bid. - */ - private static BidType getType(String impId, List imps) { + private static BidType getBidType(String impId, List imps) { for (Imp imp : imps) { if (imp.getId().equals(impId) && imp.getVideo() != null) { return BidType.video; diff --git a/src/main/java/org/prebid/server/bidder/nobid/NobidBidder.java b/src/main/java/org/prebid/server/bidder/nobid/NobidBidder.java index e373d77c5e1..87952f4584d 100644 --- a/src/main/java/org/prebid/server/bidder/nobid/NobidBidder.java +++ b/src/main/java/org/prebid/server/bidder/nobid/NobidBidder.java @@ -76,29 +76,25 @@ private List bidsFromResponse(BidRequest bidRequest, BidResponse bidR return bidResponse.getSeatbid().stream() .map(SeatBid::getBid) .flatMap(Collection::stream) - .map(bid -> mapToBidderBid(bid, bidRequest.getImp(), bidResponse.getCur(), errors)) + .map(bid -> toBidderBid(bid, bidRequest.getImp(), bidResponse.getCur(), errors)) .filter(Objects::nonNull) .collect(Collectors.toList()); } - private static BidderBid mapToBidderBid(Bid bid, List imps, String currency, List errors) { - final BidType bidType; + private static BidderBid toBidderBid(Bid bid, List imps, String currency, List errors) { try { - bidType = getBidType(bid.getImpid(), imps); + return BidderBid.of(bid, getBidType(bid.getImpid(), imps), currency); } catch (PreBidException e) { errors.add(BidderError.badInput(e.getMessage())); return null; } - return BidderBid.of(bid, bidType, currency); + } private static BidType getBidType(String impId, List imps) { for (Imp imp : imps) { if (imp.getId().equals(impId)) { - if (imp.getBanner() == null && imp.getVideo() != null) { - return BidType.video; - } - return BidType.banner; + return imp.getBanner() == null && imp.getVideo() != null ? BidType.video : BidType.banner; } } throw new PreBidException(String.format("Failed to find impression %s", impId)); diff --git a/src/main/java/org/prebid/server/bidder/onetag/OnetagBidder.java b/src/main/java/org/prebid/server/bidder/onetag/OnetagBidder.java new file mode 100644 index 00000000000..2eb0692e31c --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/onetag/OnetagBidder.java @@ -0,0 +1,140 @@ +package org.prebid.server.bidder.onetag; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.response.BidResponse; +import com.iab.openrtb.response.SeatBid; +import io.vertx.core.http.HttpMethod; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.prebid.server.bidder.Bidder; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.HttpCall; +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.ExtPrebid; +import org.prebid.server.proto.openrtb.ext.request.onetag.ExtImpOnetag; +import org.prebid.server.proto.openrtb.ext.response.BidType; +import org.prebid.server.util.HttpUtil; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * Onetag {@link Bidder} implementation. + */ +public class OnetagBidder implements Bidder { + + private static final TypeReference> ONETAG_EXT_TYPE_REFERENCE = + new TypeReference>() { + }; + private static final String URL_PUBLISHER_ID_MACRO = "{{publisherId}}"; + + private final String endpointUrl; + private final JacksonMapper mapper; + + public OnetagBidder(String endpointUrl, JacksonMapper mapper) { + this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.mapper = Objects.requireNonNull(mapper); + } + + @Override + public Result>> makeHttpRequests(BidRequest request) { + final List modifiedImps = new ArrayList<>(); + String requestPubId = null; + for (Imp imp : request.getImp()) { + try { + final ExtImpOnetag impExt = parseImpExt(imp); + requestPubId = resolveAndValidatePubId(impExt.getPubId(), requestPubId); + + modifiedImps.add(imp.toBuilder().ext(impExt.getExt()).build()); + } catch (PreBidException e) { + return Result.withError(BidderError.badInput(e.getMessage())); + } + } + + return Result.withValue(createRequest(request, modifiedImps, requestPubId)); + } + + private ExtImpOnetag parseImpExt(Imp imp) { + try { + return mapper.mapper().convertValue(imp.getExt(), ONETAG_EXT_TYPE_REFERENCE).getBidder(); + } catch (IllegalArgumentException e) { + throw new PreBidException(e.getMessage()); + } + } + + private String resolveAndValidatePubId(String impExtPubId, String requestPubId) { + if (StringUtils.isEmpty(impExtPubId)) { + throw new PreBidException("The publisher ID must not be empty"); + } + if (requestPubId != null && !impExtPubId.equals(requestPubId)) { + throw new PreBidException("There must be only one publisher ID"); + } + return impExtPubId; + } + + private HttpRequest createRequest(BidRequest request, List imps, String pubId) { + final String url = endpointUrl.replace(URL_PUBLISHER_ID_MACRO, pubId); + final BidRequest outgoingRequest = request.toBuilder().imp(imps).build(); + + return HttpRequest.builder() + .method(HttpMethod.POST) + .uri(url) + .headers(HttpUtil.headers()) + .payload(outgoingRequest) + .body(mapper.encode(outgoingRequest)) + .build(); + } + + @Override + public final Result> makeBids(HttpCall httpCall, BidRequest bidRequest) { + try { + final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class); + return Result.of(extractBids(httpCall.getRequest().getPayload(), bidResponse), Collections.emptyList()); + } catch (DecodeException | PreBidException e) { + return Result.withError(BidderError.badServerResponse(e.getMessage())); + } + } + + private static List extractBids(BidRequest bidRequest, BidResponse bidResponse) { + if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) { + return Collections.emptyList(); + } + return bidsFromResponse(bidRequest, bidResponse); + } + + private static List bidsFromResponse(BidRequest bidRequest, BidResponse bidResponse) { + 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())) + .collect(Collectors.toList()); + } + + private static BidType getBidType(String impId, List imps) { + for (Imp imp : imps) { + if (imp.getId().equals(impId)) { + if (imp.getBanner() != null) { + return BidType.banner; + } else if (imp.getVideo() != null) { + return BidType.video; + } else if (imp.getXNative() != null) { + return BidType.xNative; + } + } + } + throw new PreBidException(String.format("The impression with ID %s is not present into the request", impId)); + } +} diff --git a/src/main/java/org/prebid/server/bidder/openx/OpenxBidder.java b/src/main/java/org/prebid/server/bidder/openx/OpenxBidder.java index fcba756266b..a96adab96a0 100644 --- a/src/main/java/org/prebid/server/bidder/openx/OpenxBidder.java +++ b/src/main/java/org/prebid/server/bidder/openx/OpenxBidder.java @@ -31,6 +31,7 @@ import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.util.HttpUtil; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -159,7 +160,7 @@ private Imp makeImp(Imp imp) { final ExtImpPrebid prebidImpExt = impExt.getPrebid(); final Imp.ImpBuilder impBuilder = imp.toBuilder() .tagid(openxImpExt.getUnit()) - .bidfloor(openxImpExt.getCustomFloor()) + .bidfloor(resolveBidFloor(imp.getBidfloor(), openxImpExt.getCustomFloor())) .ext(makeImpExt(openxImpExt.getCustomParams())); if (resolveImpType(imp) == OpenxImpType.video @@ -172,6 +173,16 @@ private Imp makeImp(Imp imp) { return impBuilder.build(); } + private static BigDecimal resolveBidFloor(BigDecimal impBidFloor, BigDecimal customFloor) { + return !bidFloorIsValid(impBidFloor) && bidFloorIsValid(customFloor) + ? customFloor + : impBidFloor; + } + + private static boolean bidFloorIsValid(BigDecimal bidFloor) { + return bidFloor != null && bidFloor.compareTo(BigDecimal.ZERO) > 0; + } + private ExtRequest makeReqExt(Imp imp) { final ExtImpOpenx openxImpExt = parseOpenxExt(imp).getBidder(); return mapper.fillExtension( @@ -223,7 +234,7 @@ private static List bidsFromResponse(BidRequest bidRequest, BidRespon .map(SeatBid::getBid) .filter(Objects::nonNull) .flatMap(Collection::stream) - .map(bid -> BidderBid.of(bid, bidType(bid, impIdToBidType), bidCurrency)) + .map(bid -> BidderBid.of(bid, getBidType(bid, impIdToBidType), bidCurrency)) .collect(Collectors.toList()); } @@ -232,7 +243,7 @@ private static Map impIdToBidType(BidRequest bidRequest) { .collect(Collectors.toMap(Imp::getId, imp -> imp.getBanner() != null ? BidType.banner : BidType.video)); } - private static BidType bidType(Bid bid, Map impIdToBidType) { + private static BidType getBidType(Bid bid, Map impIdToBidType) { return impIdToBidType.getOrDefault(bid.getImpid(), BidType.banner); } } diff --git a/src/main/java/org/prebid/server/bidder/outbrain/OutbrainBidder.java b/src/main/java/org/prebid/server/bidder/outbrain/OutbrainBidder.java new file mode 100644 index 00000000000..9d219e9ebf0 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/outbrain/OutbrainBidder.java @@ -0,0 +1,177 @@ +package org.prebid.server.bidder.outbrain; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.iab.openrtb.request.App; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Publisher; +import com.iab.openrtb.request.Site; +import com.iab.openrtb.response.BidResponse; +import com.iab.openrtb.response.SeatBid; +import io.vertx.core.http.HttpMethod; +import org.apache.commons.collections4.CollectionUtils; +import org.prebid.server.bidder.Bidder; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.HttpCall; +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.ExtPrebid; +import org.prebid.server.proto.openrtb.ext.request.outbrains.ExtImpOutbrain; +import org.prebid.server.proto.openrtb.ext.request.outbrains.ExtImpOutbrainPublisher; +import org.prebid.server.proto.openrtb.ext.response.BidType; +import org.prebid.server.util.HttpUtil; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * Outbrain {@link Bidder} implementation. + */ +public class OutbrainBidder implements Bidder { + + private static final TypeReference> OUTBRAIN_EXT_TYPE_REFERENCE = + new TypeReference>() { + }; + + private final String endpointUrl; + private final JacksonMapper mapper; + + public OutbrainBidder(String endpointUrl, JacksonMapper mapper) { + this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.mapper = Objects.requireNonNull(mapper); + } + + @Override + public Result>> makeHttpRequests(BidRequest request) { + final List errors = new ArrayList<>(); + final List modifiedImps = new ArrayList<>(); + + ExtImpOutbrain extImpOutbrain = null; + for (Imp imp : request.getImp()) { + try { + extImpOutbrain = parseImpExt(imp); + modifiedImps.add(modifyImp(imp, extImpOutbrain.getTagid())); + } catch (PreBidException e) { + errors.add(BidderError.badInput(e.getMessage())); + } + } + + if (!errors.isEmpty()) { + return Result.withErrors(errors); + } + + final BidRequest updatedRequest = updateBidRequest(request, modifiedImps, extImpOutbrain); + + return Result.of(Collections.singletonList( + HttpRequest.builder() + .method(HttpMethod.POST) + .uri(endpointUrl) + .body(mapper.encode(updatedRequest)) + .headers(HttpUtil.headers()) + .payload(updatedRequest) + .build()), errors); + } + + private ExtImpOutbrain parseImpExt(Imp imp) { + try { + return mapper.mapper().convertValue(imp.getExt(), OUTBRAIN_EXT_TYPE_REFERENCE).getBidder(); + } catch (IllegalArgumentException e) { + throw new PreBidException(String.format("Impression id=%s, has invalid Ext", imp.getId())); + } + } + + private static Imp modifyImp(Imp imp, String tagId) { + return imp.toBuilder() + .tagid(tagId) + .build(); + } + + private static BidRequest updateBidRequest(BidRequest bidRequest, List imps, ExtImpOutbrain extImpOutbrain) { + final BidRequest.BidRequestBuilder bidRequestBuilder = bidRequest.toBuilder(); + final Publisher publisher = createPublisher(extImpOutbrain.getPublisher()); + + final Site site = bidRequest.getSite(); + final App app = bidRequest.getApp(); + if (site != null) { + bidRequestBuilder.site(updateSite(site, publisher)); + } else if (app != null) { + bidRequestBuilder.app(updateApp(app, publisher)); + } + + final List bcat = extImpOutbrain.getBcat(); + if (CollectionUtils.isNotEmpty(bcat)) { + bidRequestBuilder.bcat(bcat); + } + + final List badv = extImpOutbrain.getBadv(); + if (CollectionUtils.isNotEmpty(badv)) { + bidRequestBuilder.badv(badv); + } + + return bidRequestBuilder.imp(imps).build(); + } + + private static Publisher createPublisher(ExtImpOutbrainPublisher extImpPublisher) { + return Publisher.builder() + .id(extImpPublisher.getId()) + .name(extImpPublisher.getName()) + .domain(extImpPublisher.getDomain()) + .build(); + } + + private static Site updateSite(Site site, Publisher publisher) { + return site.toBuilder().publisher(publisher).build(); + } + + private static App updateApp(App app, Publisher publisher) { + return app.toBuilder().publisher(publisher).build(); + } + + @Override + public final Result> makeBids(HttpCall httpCall, BidRequest bidRequest) { + try { + final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class); + return Result.of(extractBids(httpCall.getRequest().getPayload(), bidResponse), Collections.emptyList()); + } catch (DecodeException | PreBidException e) { + return Result.withError(BidderError.badServerResponse(e.getMessage())); + } + } + + private static List extractBids(BidRequest bidRequest, BidResponse bidResponse) { + if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) { + return Collections.emptyList(); + } + return bidsFromResponse(bidRequest, bidResponse); + } + + private static List bidsFromResponse(BidRequest bidRequest, BidResponse bidResponse) { + 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())) + .collect(Collectors.toList()); + } + + private static BidType getBidType(String impId, List imps) { + for (Imp imp : imps) { + if (imp.getId().equals(impId)) { + if (imp.getXNative() != null) { + return BidType.xNative; + } else if (imp.getBanner() != null) { + return BidType.banner; + } + } + } + throw new PreBidException(String.format("Failed to find native/banner impression \"%s\"", impId)); + } +} diff --git a/src/main/java/org/prebid/server/bidder/pangle/PangleBidder.java b/src/main/java/org/prebid/server/bidder/pangle/PangleBidder.java new file mode 100644 index 00000000000..1c30a714ba6 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/pangle/PangleBidder.java @@ -0,0 +1,207 @@ +package org.prebid.server.bidder.pangle; + +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.apache.commons.lang3.StringUtils; +import org.prebid.server.bidder.Bidder; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.HttpCall; +import org.prebid.server.bidder.model.HttpRequest; +import org.prebid.server.bidder.model.Result; +import org.prebid.server.bidder.pangle.model.BidExt; +import org.prebid.server.bidder.pangle.model.PangleBidExt; +import org.prebid.server.bidder.pangle.model.WrappedImpExtBidder; +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.request.ExtImpPrebid; +import org.prebid.server.proto.openrtb.ext.response.BidType; +import org.prebid.server.util.HttpUtil; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * Pangle {@link Bidder} implementation. + */ +public class PangleBidder implements Bidder { + + private final String endpointUrl; + private final JacksonMapper mapper; + + public PangleBidder(String endpointUrl, JacksonMapper mapper) { + this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.mapper = Objects.requireNonNull(mapper); + } + + @Override + public Result>> makeHttpRequests(BidRequest request) { + final List> requests = new ArrayList<>(); + final List errors = new ArrayList<>(); + + for (Imp imp : request.getImp()) { + try { + final WrappedImpExtBidder extBidder = parseImpExt(imp); + final Integer adType = resolveAdType(imp, extBidder); + final Imp modifiedImp = modifyImp(imp, adType, extBidder); + + requests.add(createRequest(request, modifiedImp, extBidder.getBidder().getToken())); + } catch (PreBidException e) { + errors.add(BidderError.badInput(e.getMessage())); + } + } + + return Result.of(requests, errors); + } + + private WrappedImpExtBidder parseImpExt(Imp imp) { + try { + return mapper.mapper().convertValue(imp.getExt(), WrappedImpExtBidder.class); + } catch (IllegalArgumentException e) { + throw new PreBidException(String.format("failed unmarshalling imp ext (err)%s", e.getMessage())); + } + } + + private static int resolveAdType(Imp imp, WrappedImpExtBidder extBidder) { + if (imp.getVideo() != null) { + final ExtImpPrebid extPrebid = extBidder != null ? extBidder.getPrebid() : null; + final Integer isRewardedInventory = extPrebid != null ? extPrebid.getIsRewardedInventory() : null; + if (Objects.equals(isRewardedInventory, 1)) { + return 7; + } + + if (Objects.equals(imp.getInstl(), 1)) { + return 8; + } + } + + if (imp.getBanner() != null) { + if (Objects.equals(imp.getInstl(), 1)) { + return 2; + } else { + return 1; + } + } + if (imp.getXNative() != null && StringUtils.isNotBlank(imp.getXNative().getRequest())) { + return 5; + } + + throw new PreBidException("not a supported adtype"); + } + + private Imp modifyImp(Imp imp, Integer adType, WrappedImpExtBidder extBidder) { + final WrappedImpExtBidder updatedImpExt = extBidder.toBuilder().adType(adType).build(); + return imp.toBuilder() + .ext(mapper.mapper().convertValue(updatedImpExt, ObjectNode.class)) + .build(); + } + + private HttpRequest createRequest(BidRequest request, Imp imp, String token) { + final BidRequest outgoingRequest = request.toBuilder().imp(Collections.singletonList(imp)).build(); + + return HttpRequest.builder() + .method(HttpMethod.POST) + .uri(endpointUrl) + .headers(makeHeaders(token)) + .payload(outgoingRequest) + .body(mapper.encode(outgoingRequest)) + .build(); + } + + private static MultiMap makeHeaders(String token) { + return HttpUtil.headers() + .add("TOKEN", token); + } + + @Override + public final Result> makeBids(HttpCall httpCall, BidRequest bidRequest) { + try { + final List errors = new ArrayList<>(); + final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class); + return Result.of(extractBids(bidResponse, errors), errors); + } catch (DecodeException e) { + return Result.withError(BidderError.badServerResponse(e.getMessage())); + } + } + + private List extractBids(BidResponse bidResponse, List errors) { + if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) { + return Collections.emptyList(); + } + return bidsFromResponse(bidResponse, errors); + } + + private List bidsFromResponse(BidResponse bidResponse, List errors) { + return bidResponse.getSeatbid().stream() + .filter(Objects::nonNull) + .map(SeatBid::getBid) + .flatMap(Collection::stream) + .map(bid -> createBid(bid, bidResponse.getCur(), errors)) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + + private BidderBid createBid(Bid bid, String currency, List errors) { + final Integer adType; + try { + adType = getAdTypeFromBidExt(bid); + } catch (PreBidException e) { + errors.add(BidderError.badServerResponse(e.getMessage())); + return null; + } + final BidType bidType; + switch (adType) { + case 1: + bidType = BidType.banner; + break; + case 2: + bidType = BidType.banner; + break; + case 5: + bidType = BidType.xNative; + break; + case 7: + bidType = BidType.video; + break; + case 8: + bidType = BidType.video; + break; + default: + errors.add(BidderError.badServerResponse("unrecognized adtype in response")); + return null; + } + + return BidderBid.of(bid, bidType, currency); + } + + private Integer getAdTypeFromBidExt(Bid bid) { + if (bid == null) { + throw new PreBidException("the bid request object is not present"); + } + final PangleBidExt bidExt; + try { + bidExt = mapper.mapper().convertValue(bid.getExt(), PangleBidExt.class); + } catch (IllegalArgumentException e) { + throw new PreBidException("invalid bid ext"); + } + + final BidExt pangleBidExt = bidExt != null ? bidExt.getPangle() : null; + final Integer adType = pangleBidExt != null ? pangleBidExt.getAdType() : null; + if (adType == null) { + throw new PreBidException("missing pangleExt/adtype in bid ext"); + } + return adType; + } +} diff --git a/src/main/java/org/prebid/server/bidder/pangle/model/BidExt.java b/src/main/java/org/prebid/server/bidder/pangle/model/BidExt.java new file mode 100644 index 00000000000..ded899b2091 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/pangle/model/BidExt.java @@ -0,0 +1,15 @@ +package org.prebid.server.bidder.pangle.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Value; + +@AllArgsConstructor(staticName = "of") +@Builder(toBuilder = true) +@Value +public class BidExt { + + @JsonProperty("adtype") + Integer adType; +} diff --git a/src/main/java/org/prebid/server/bidder/pangle/model/PangleBidExt.java b/src/main/java/org/prebid/server/bidder/pangle/model/PangleBidExt.java new file mode 100644 index 00000000000..c85dd19b087 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/pangle/model/PangleBidExt.java @@ -0,0 +1,13 @@ +package org.prebid.server.bidder.pangle.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Value; + +@AllArgsConstructor(staticName = "of") +@Builder(toBuilder = true) +@Value +public class PangleBidExt { + + BidExt pangle; +} diff --git a/src/main/java/org/prebid/server/bidder/pangle/model/WrappedImpExtBidder.java b/src/main/java/org/prebid/server/bidder/pangle/model/WrappedImpExtBidder.java new file mode 100644 index 00000000000..833b88c9bb6 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/pangle/model/WrappedImpExtBidder.java @@ -0,0 +1,21 @@ +package org.prebid.server.bidder.pangle.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Value; +import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebid; +import org.prebid.server.proto.openrtb.ext.request.pangle.ExtImpPangle; + +@AllArgsConstructor(staticName = "of") +@Builder(toBuilder = true) +@Value +public class WrappedImpExtBidder { + + ExtImpPrebid prebid; + + ExtImpPangle bidder; + + @JsonProperty("adtype") + Integer adType; +} diff --git a/src/main/java/org/prebid/server/bidder/rhythmone/RhythmoneBidder.java b/src/main/java/org/prebid/server/bidder/rhythmone/RhythmoneBidder.java index 26e9c5a1447..5f0d204396a 100644 --- a/src/main/java/org/prebid/server/bidder/rhythmone/RhythmoneBidder.java +++ b/src/main/java/org/prebid/server/bidder/rhythmone/RhythmoneBidder.java @@ -129,14 +129,15 @@ private static List extractBids(BidRequest bidRequest, BidResponse bi private static List bidsFromResponse(BidRequest bidRequest, BidResponse bidResponse) { return bidResponse.getSeatbid().stream() + .filter(Objects::nonNull) .map(SeatBid::getBid) + .filter(Objects::nonNull) .flatMap(Collection::stream) - .map(bid -> BidderBid.of(bid, getMediaTypes(bid.getImpid(), bidRequest.getImp()), - bidResponse.getCur())) + .map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), bidRequest.getImp()), bidResponse.getCur())) .collect(Collectors.toList()); } - private static BidType getMediaTypes(String impId, List imps) { + private static BidType getBidType(String impId, List imps) { for (Imp imp : imps) { if (imp.getId().equals(impId)) { if (imp.getBanner() != null) { diff --git a/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java b/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java index 1f978943d22..a6ad980a7a9 100644 --- a/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java +++ b/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.collect.ImmutableSet; import com.iab.openrtb.request.App; import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; @@ -22,7 +23,6 @@ import com.iab.openrtb.response.Bid; import com.iab.openrtb.response.BidResponse; import com.iab.openrtb.response.SeatBid; -import io.netty.handler.codec.http.HttpHeaderValues; import io.vertx.core.MultiMap; import io.vertx.core.http.HttpMethod; import io.vertx.core.logging.Logger; @@ -61,6 +61,7 @@ import org.prebid.server.bidder.rubicon.proto.RubiconUserExtRp; import org.prebid.server.bidder.rubicon.proto.RubiconVideoExt; import org.prebid.server.bidder.rubicon.proto.RubiconVideoExtRp; +import org.prebid.server.currency.CurrencyConversionService; import org.prebid.server.exception.PreBidException; import org.prebid.server.json.DecodeException; import org.prebid.server.json.JacksonMapper; @@ -139,6 +140,10 @@ public class RubiconBidder implements Bidder { private static final String PPUID_STYPE = "ppuid"; private static final String SHA256EMAIL_STYPE = "sha256email"; private static final String DMP_STYPE = "dmp"; + private static final String XAPI_CURRENCY = "USD"; + private static final Set USER_SEGTAXES = ImmutableSet.of(3); + private static final Set SITE_SEGTAXES = ImmutableSet.of(1, 2); + private static final Set STYPE_TO_REMOVE = new HashSet<>(Arrays.asList(PPUID_STYPE, SHA256EMAIL_STYPE, DMP_STYPE)); private static final TypeReference> RUBICON_EXT_TYPE_REFERENCE = @@ -150,6 +155,7 @@ public class RubiconBidder implements Bidder { private final String endpointUrl; private final Set supportedVendors; private final boolean generateBidId; + private final CurrencyConversionService currencyConversionService; private final JacksonMapper mapper; private final MultiMap headers; @@ -159,11 +165,13 @@ public RubiconBidder(String endpoint, String xapiPassword, List supportedVendors, boolean generateBidId, + CurrencyConversionService currencyConversionService, JacksonMapper mapper) { this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpoint)); this.supportedVendors = new HashSet<>(supportedVendors); this.generateBidId = generateBidId; + this.currencyConversionService = Objects.requireNonNull(currencyConversionService); this.mapper = Objects.requireNonNull(mapper); this.headers = headers(Objects.requireNonNull(xapiUsername), Objects.requireNonNull(xapiPassword)); @@ -189,7 +197,7 @@ public Result>> makeHttpRequests(BidRequest bidRequ final Imp imp = impToExt.getKey(); final ExtPrebid ext = impToExt.getValue(); final BidRequest singleRequest = createSingleRequest( - imp, ext.getPrebid(), ext.getBidder(), bidRequest, impLanguage); + imp, ext.getPrebid(), ext.getBidder(), bidRequest, impLanguage, errors); final String body = mapper.encode(singleRequest); httpRequests.add(HttpRequest.builder() .method(HttpMethod.POST) @@ -228,11 +236,11 @@ public Map extractTargeting(ObjectNode extBidBidder) { } final RubiconTargetingExtRp rp = rubiconTargetingExt.getRp(); - final List targeting = rp != null ? rp.getTargeting() : null; - return targeting != null - ? targeting.stream() - .filter(rubiconTargeting -> !CollectionUtils.isEmpty(rubiconTargeting.getValues())) - .collect(Collectors.toMap(RubiconTargeting::getKey, t -> t.getValues().get(0))) + final List targetings = rp != null ? rp.getTargeting() : null; + return targetings != null + ? targetings.stream() + .filter(targeting -> !CollectionUtils.isEmpty(targeting.getValues())) + .collect(Collectors.toMap(RubiconTargeting::getKey, targeting -> targeting.getValues().get(0))) : Collections.emptyMap(); } @@ -275,10 +283,8 @@ private static BidType resolveExpectedBidType(Imp imp) { } private static MultiMap headers(String xapiUsername, String xapiPassword) { - return MultiMap.caseInsensitiveMultiMap() + return HttpUtil.headers() .add(HttpUtil.AUTHORIZATION_HEADER, authHeader(xapiUsername, xapiPassword)) - .add(HttpUtil.CONTENT_TYPE_HEADER, HttpUtil.APPLICATION_JSON_CONTENT_TYPE) - .add(HttpUtil.ACCEPT_HEADER, HttpHeaderValues.APPLICATION_JSON) .add(HttpUtil.USER_AGENT_HEADER, PREBID_SERVER_USER_AGENT); } @@ -322,21 +328,19 @@ private static String firstImpExtLanguage(Collection errors) { return bidRequest.toBuilder() - .imp(Collections.singletonList(makeImp(imp, extPrebid, extRubicon, site, app, bidRequest.getExt()))) - .user(makeUser(bidRequest.getUser(), extRubicon)) + .imp(Collections.singletonList(makeImp(imp, extImpPrebid, extImpRubicon, bidRequest, errors))) + .user(makeUser(bidRequest.getUser(), extImpRubicon)) .device(makeDevice(bidRequest.getDevice())) - .site(makeSite(site, impLanguage, extRubicon)) - .app(makeApp(app, extRubicon)) - .source(makeSource(bidRequest.getSource(), extRubicon.getPchain())) + .site(makeSite(bidRequest.getSite(), impLanguage, extImpRubicon)) + .app(makeApp(bidRequest.getApp(), extImpRubicon)) + .source(makeSource(bidRequest.getSource(), extImpRubicon.getPchain())) .cur(null) // suppress currencies .ext(null) // suppress ext .build(); @@ -380,21 +384,33 @@ private RubiconExtPrebidBiddersBidder extPrebidBiddersRubicon(ExtRequest extRequ } private Imp makeImp(Imp imp, - ExtImpPrebid extPrebid, - ExtImpRubicon extRubicon, - Site site, App app, - ExtRequest extRequest) { + ExtImpPrebid extImpPrebid, + ExtImpRubicon extImpRubicon, + BidRequest bidRequest, + List errors) { + + final App app = bidRequest.getApp(); + final Site site = bidRequest.getSite(); + final ExtRequest extRequest = bidRequest.getExt(); + final Imp.ImpBuilder builder = imp.toBuilder() .metric(makeMetrics(imp)) - .ext(mapper.mapper().valueToTree(makeImpExt(imp, extRubicon, site, app, extRequest))); + .ext(mapper.mapper().valueToTree(makeImpExt(imp, extImpRubicon, site, app, extRequest))); + + final BigDecimal resolvedBidFloor = resolveBidFloor(imp, bidRequest, errors); + if (resolvedBidFloor != null) { + builder + .bidfloorcur(XAPI_CURRENCY) + .bidfloor(resolvedBidFloor); + } if (isVideo(imp)) { builder .banner(null) - .video(makeVideo(imp, extRubicon.getVideo(), extPrebid, referer(site))); + .video(makeVideo(imp, extImpRubicon.getVideo(), extImpPrebid, referer(site))); } else { builder - .banner(makeBanner(imp, overriddenSizes(extRubicon))) + .banner(makeBanner(imp, overriddenSizes(extImpRubicon))) .video(null); } @@ -424,6 +440,60 @@ private boolean isMetricSupported(Metric metric) { return supportedVendors.contains(metric.getVendor()) && Objects.equals(metric.getType(), "viewability"); } + private BigDecimal resolveBidFloor(Imp imp, BidRequest bidRequest, List errors) { + final BigDecimal resolvedBidFloorPrice = resolveBidFloorPrice(imp); + if (resolvedBidFloorPrice == null) { + return null; + } + + final String resolvedBidFloorCurrency = resolveBidFloorCurrency(imp, bidRequest, errors); + return ObjectUtils.notEqual(resolvedBidFloorCurrency, XAPI_CURRENCY) + ? convertBidFloorCurrency(resolvedBidFloorPrice, resolvedBidFloorCurrency, imp, bidRequest) + : null; + } + + private static BigDecimal resolveBidFloorPrice(Imp imp) { + final BigDecimal bidFloor = imp.getBidfloor(); + return bidFloor != null && bidFloor.compareTo(BigDecimal.ZERO) > 0 ? bidFloor : null; + } + + private static String resolveBidFloorCurrency(Imp imp, BidRequest bidRequest, List errors) { + final String bidFloorCurrency = imp.getBidfloorcur(); + if (StringUtils.isBlank(bidFloorCurrency)) { + if (isDebugEnabled(bidRequest)) { + errors.add(BidderError.badInput(String.format("Imp `%s` floor provided with no currency, assuming %s", + imp.getId(), XAPI_CURRENCY))); + } + return XAPI_CURRENCY; + } + return bidFloorCurrency; + } + + /** + * Determines debug flag from {@link BidRequest} or {@link ExtRequest}. + */ + private static boolean isDebugEnabled(BidRequest bidRequest) { + if (Objects.equals(bidRequest.getTest(), 1)) { + return true; + } + final ExtRequest extRequest = bidRequest.getExt(); + final ExtRequestPrebid extRequestPrebid = extRequest != null ? extRequest.getPrebid() : null; + return extRequestPrebid != null && Objects.equals(extRequestPrebid.getDebug(), 1); + } + + private BigDecimal convertBidFloorCurrency(BigDecimal bidFloor, + String bidFloorCurrency, + Imp imp, + BidRequest bidRequest) { + try { + return currencyConversionService.convertCurrency(bidFloor, bidRequest, bidFloorCurrency, XAPI_CURRENCY); + } catch (PreBidException e) { + throw new PreBidException(String.format( + "Unable to convert provided bid floor currency from %s to %s for imp `%s` with a reason: %s", + bidFloorCurrency, XAPI_CURRENCY, imp.getId(), e.getMessage())); + } + } + private RubiconImpExt makeImpExt(Imp imp, ExtImpRubicon rubiconImpExt, Site site, @@ -1004,7 +1074,7 @@ private JsonNode rubiconUserExtRpTarget(Map> sourceToUs if (user != null) { mergeFirstPartyDataFromUser(user.getExt(), result); - enrichWithIabAttribute(result, user.getData()); + enrichWithIabAttribute(result, user.getData(), USER_SEGTAXES); } return result.size() > 0 ? result : null; @@ -1039,10 +1109,10 @@ private void mergeFirstPartyDataFromUser(ExtUser userExt, ObjectNode result) { } } - private void enrichWithIabAttribute(ObjectNode target, List data) { + private static void enrichWithIabAttribute(ObjectNode target, List data, Set segtaxValues) { final List iabValue = CollectionUtils.emptyIfNull(data).stream() .filter(Objects::nonNull) - .filter(dataRecord -> containsIabTaxonomyName(dataRecord.getExt())) + .filter(dataRecord -> containsSegtaxValue(dataRecord.getExt(), segtaxValues)) .map(Data::getSegment) .filter(Objects::nonNull) .flatMap(segments -> segments.stream() @@ -1056,10 +1126,10 @@ private void enrichWithIabAttribute(ObjectNode target, List data) { } } - private boolean containsIabTaxonomyName(ObjectNode ext) { - final JsonNode taxonomyName = ext != null ? ext.get("taxonomyname") : null; - return taxonomyName != null && taxonomyName.isTextual() - && StringUtils.containsIgnoreCase(taxonomyName.textValue(), "iab"); + private static boolean containsSegtaxValue(ObjectNode ext, Set segtaxValues) { + final JsonNode taxonomyName = ext != null ? ext.get("segtax") : null; + + return taxonomyName != null && taxonomyName.isInt() && segtaxValues.contains(taxonomyName.intValue()); } private static String extractLiverampId(Map> sourceToUserEidExt) { @@ -1126,10 +1196,29 @@ private ExtPublisher makePublisherExt(ExtImpRubicon rubiconImpExt) { private ExtSite makeSiteExt(Site site, ExtImpRubicon rubiconImpExt) { final ExtSite extSite = site != null ? site.getExt() : null; final Integer siteExtAmp = extSite != null ? extSite.getAmp() : null; + final Content siteContent = site != null ? site.getContent() : null; + final List siteContentData = siteContent != null ? siteContent.getData() : null; + ObjectNode target = null; + + if (CollectionUtils.isNotEmpty(siteContentData)) { + target = existingRubiconSiteExtRpTargetOrEmptyNode(extSite); + enrichWithIabAttribute(target, siteContentData, SITE_SEGTAXES); + } return mapper.fillExtension( ExtSite.of(siteExtAmp, null), - RubiconSiteExt.of(RubiconSiteExtRp.of(rubiconImpExt.getSiteId()))); + RubiconSiteExt.of(RubiconSiteExtRp.of(rubiconImpExt.getSiteId(), + target != null && !target.isEmpty() ? target : null))); + } + + private ObjectNode existingRubiconSiteExtRpTargetOrEmptyNode(ExtSite siteExt) { + final RubiconSiteExt rubiconSiteExt = siteExt != null + ? mapper.mapper().convertValue(siteExt, RubiconSiteExt.class) + : null; + final RubiconSiteExtRp rubiconSiteExtRp = rubiconSiteExt != null ? rubiconSiteExt.getRp() : null; + final JsonNode target = rubiconSiteExtRp != null ? rubiconSiteExtRp.getTarget() : null; + + return target != null && target.isObject() ? (ObjectNode) target : mapper.mapper().createObjectNode(); } private App makeApp(App app, ExtImpRubicon rubiconImpExt) { @@ -1141,7 +1230,7 @@ private App makeApp(App app, ExtImpRubicon rubiconImpExt) { private ExtApp makeAppExt(ExtImpRubicon rubiconImpExt) { return mapper.fillExtension(ExtApp.of(null, null), - RubiconAppExt.of(RubiconSiteExtRp.of(rubiconImpExt.getSiteId()))); + RubiconAppExt.of(RubiconSiteExtRp.of(rubiconImpExt.getSiteId(), null))); } private static Source makeSource(Source source, String pchain) { @@ -1161,7 +1250,7 @@ private List extractBids(BidRequest prebidRequest, BidRequest bidRequ private List bidsFromResponse(BidRequest prebidRequest, BidRequest bidRequest, BidResponse bidResponse) { final Map idToImp = prebidRequest.getImp().stream() .collect(Collectors.toMap(Imp::getId, Function.identity())); - final Float cmpOverrideFromRequest = cmpOverrideFromRequest(prebidRequest); + final Float cpmOverrideFromRequest = cpmOverrideFromRequest(prebidRequest); final BidType bidType = bidType(bidRequest); return bidResponse.getSeatbid().stream() @@ -1169,7 +1258,7 @@ private List bidsFromResponse(BidRequest prebidRequest, BidRequest bi .map(SeatBid::getBid) .filter(Objects::nonNull) .flatMap(Collection::stream) - .map(bid -> updateBid(bid, idToImp.get(bid.getImpid()), cmpOverrideFromRequest, bidResponse)) + .map(bid -> updateBid(bid, idToImp.get(bid.getImpid()), cpmOverrideFromRequest, bidResponse)) .filter(RubiconBidder::validatePrice) .map(bid -> BidderBid.of(bid, bidType, bidResponse.getCur())) .collect(Collectors.toList()); @@ -1180,35 +1269,40 @@ private static boolean validatePrice(Bid bid) { return bid.getDealid() != null ? price.compareTo(BigDecimal.ZERO) >= 0 : price.compareTo(BigDecimal.ZERO) > 0; } - private Bid updateBid(Bid bid, Imp imp, Float cmpOverrideFromRequest, BidResponse bidResponse) { + private Bid updateBid(Bid bid, Imp imp, Float cpmOverrideFromRequest, BidResponse bidResponse) { + String bidId = bid.getId(); if (generateBidId) { // Since Rubicon XAPI returns openrtb_response.seatbid.bid.id not unique enough // generate new value for it - bid.setId(UUID.randomUUID().toString()); + bidId = UUID.randomUUID().toString(); } else if (Objects.equals(bid.getId(), "0")) { // Since Rubicon XAPI returns only one bid per response // copy bidResponse.bidid to openrtb_response.seatbid.bid.id - bid.setId(bidResponse.getBidid()); + bidId = bidResponse.getBidid(); } // Unconditionally set price if coming from CPM override - final Float cpmOverride = ObjectUtils.defaultIfNull(cpmOverrideFromImp(imp), cmpOverrideFromRequest); - if (cpmOverride != null) { - bid.setPrice(new BigDecimal(String.valueOf(cpmOverride))); - } - - return bid; + final Float cpmOverride = ObjectUtils.defaultIfNull(cpmOverrideFromImp(imp), cpmOverrideFromRequest); + final BigDecimal bidPrice = cpmOverride != null + ? new BigDecimal(String.valueOf(cpmOverride)) + : bid.getPrice(); + + return bid.toBuilder() + .id(bidId) + .price(bidPrice) + .build(); } - private Float cmpOverrideFromRequest(BidRequest bidRequest) { + private Float cpmOverrideFromRequest(BidRequest bidRequest) { final RubiconExtPrebidBiddersBidder bidder = extPrebidBiddersRubicon(bidRequest.getExt()); final RubiconExtPrebidBiddersBidderDebug debug = bidder != null ? bidder.getDebug() : null; return debug != null ? debug.getCpmoverride() : null; } private Float cpmOverrideFromImp(Imp imp) { - final ExtImpRubiconDebug debug = parseRubiconExt(imp).getBidder().getDebug(); - + final ExtPrebid extPrebid = imp != null ? parseRubiconExt(imp) : null; + final ExtImpRubicon bidder = extPrebid != null ? extPrebid.getBidder() : null; + final ExtImpRubiconDebug debug = bidder != null ? bidder.getDebug() : null; return debug != null ? debug.getCpmoverride() : null; } diff --git a/src/main/java/org/prebid/server/bidder/rubicon/proto/RubiconSiteExtRp.java b/src/main/java/org/prebid/server/bidder/rubicon/proto/RubiconSiteExtRp.java index d96a1680103..1eca04ea728 100644 --- a/src/main/java/org/prebid/server/bidder/rubicon/proto/RubiconSiteExtRp.java +++ b/src/main/java/org/prebid/server/bidder/rubicon/proto/RubiconSiteExtRp.java @@ -1,5 +1,6 @@ package org.prebid.server.bidder.rubicon.proto; +import com.fasterxml.jackson.databind.JsonNode; import lombok.AllArgsConstructor; import lombok.Value; @@ -8,4 +9,6 @@ public class RubiconSiteExtRp { Integer siteId; + + JsonNode target; } diff --git a/src/main/java/org/prebid/server/bidder/sharethrough/SharethroughBidder.java b/src/main/java/org/prebid/server/bidder/sharethrough/SharethroughBidder.java index 181a6c6e4ce..bac73e26fac 100644 --- a/src/main/java/org/prebid/server/bidder/sharethrough/SharethroughBidder.java +++ b/src/main/java/org/prebid/server/bidder/sharethrough/SharethroughBidder.java @@ -62,11 +62,6 @@ public SharethroughBidder(String endpointUrl, JacksonMapper mapper) { this.requestUtil = new SharethroughRequestUtil(); } - /** - * Makes the HTTP requests which should be made to fetch bids. - *

- * Creates POST http request with all parameters in url and headers with empty body. - */ @Override public Result>> makeHttpRequests(BidRequest request) { final String page = requestUtil.getPage(request.getSite()); diff --git a/src/main/java/org/prebid/server/bidder/silvermob/SilvermobBidder.java b/src/main/java/org/prebid/server/bidder/silvermob/SilvermobBidder.java index bf7d1021f4e..b0a668e8eec 100644 --- a/src/main/java/org/prebid/server/bidder/silvermob/SilvermobBidder.java +++ b/src/main/java/org/prebid/server/bidder/silvermob/SilvermobBidder.java @@ -145,7 +145,9 @@ private List extractBids(HttpCall httpCall) { private static List bidsFromResponse(BidResponse bidResponse, BidRequest bidRequest) { 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())) .collect(Collectors.toList()); diff --git a/src/main/java/org/prebid/server/bidder/smaato/SmaatoBidder.java b/src/main/java/org/prebid/server/bidder/smaato/SmaatoBidder.java index 4b4b3569fe1..a917460490e 100644 --- a/src/main/java/org/prebid/server/bidder/smaato/SmaatoBidder.java +++ b/src/main/java/org/prebid/server/bidder/smaato/SmaatoBidder.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.iab.openrtb.request.App; import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Format; @@ -60,7 +61,7 @@ public class SmaatoBidder implements Bidder { new TypeReference>() { }; - private static final String CLIENT_VERSION = "prebid_server_0.1"; + private static final String CLIENT_VERSION = "prebid_server_0.2"; private static final String SMT_ADTYPE_HEADER = "X-SMT-ADTYPE"; private static final String SMT_AD_TYPE_IMG = "Img"; private static final String SMT_ADTYPE_RICHMEDIA = "Richmedia"; @@ -96,6 +97,7 @@ public Result>> makeHttpRequests(BidRequest request outgoingRequest = request.toBuilder() .imp(imps) .site(modifySite(request.getSite(), firstPublisherId)) + .app(modifyApp(request.getApp(), firstPublisherId)) .user(modifyUser(request.getUser())) .ext(mapper.fillExtension(ExtRequest.empty(), SmaatoBidRequestExt.of(CLIENT_VERSION))) .build(); @@ -166,6 +168,12 @@ private Site modifySite(Site site, String firstPublisherId) { return siteBuilder.build(); } + private App modifyApp(App app, String publishedId) { + return app != null + ? app.toBuilder().publisher(Publisher.builder().id(publishedId).build()).build() + : null; + } + private User modifyUser(User user) { if (user == null) { return null; diff --git a/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java b/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java index c5764ca7fc3..1bf06829c6b 100644 --- a/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java +++ b/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java @@ -61,11 +61,7 @@ public Result>> makeHttpRequests(BidRequest request final ExtImpSmartadserver extImpSmartadserver = parseImpExt(imp); final BidRequest updatedRequest = request.toBuilder() .imp(Collections.singletonList(imp)) - .site(Site.builder() - .publisher(Publisher.builder() - .id(String.valueOf(extImpSmartadserver.getNetworkId())) - .build()) - .build()) + .site(modifySite(request.getSite(), extImpSmartadserver.getNetworkId())) .build(); result.add(createSingleRequest(updatedRequest)); } catch (PreBidException e) { @@ -107,6 +103,21 @@ private String getUri() { .toString(); } + private static Site modifySite(Site site, Integer networkId) { + final Site.SiteBuilder siteBuilder = site != null ? site.toBuilder() : Site.builder(); + final Publisher sitePublisher = site != null ? site.getPublisher() : null; + + return siteBuilder.publisher(modifyPublisher(sitePublisher, networkId)).build(); + } + + private static Publisher modifyPublisher(Publisher publisher, Integer networkId) { + final Publisher.PublisherBuilder publisherBuilder = publisher != null + ? publisher.toBuilder() + : Publisher.builder(); + + return publisherBuilder.id(String.valueOf(networkId)).build(); + } + @Override public Result> makeBids(HttpCall httpCall, BidRequest bidRequest) { try { diff --git a/src/main/java/org/prebid/server/bidder/smartyads/SmartyAdsBidder.java b/src/main/java/org/prebid/server/bidder/smartyads/SmartyAdsBidder.java index 25a4637cd08..f1c5eb0e555 100644 --- a/src/main/java/org/prebid/server/bidder/smartyads/SmartyAdsBidder.java +++ b/src/main/java/org/prebid/server/bidder/smartyads/SmartyAdsBidder.java @@ -4,7 +4,6 @@ import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Device; 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; @@ -152,12 +151,7 @@ private List extractBids(HttpCall httpCall) { private static List bidsFromResponse(BidRequest bidRequest, BidResponse bidResponse) { final SeatBid firstSeatBid = bidResponse.getSeatbid().get(FIRST_SEAT_BID_INDEX); - final List bidsFromSeat = firstSeatBid.getBid(); - if (CollectionUtils.isEmpty(bidsFromSeat)) { - return Collections.emptyList(); - } - - return bidsFromSeat.stream() + return CollectionUtils.emptyIfNull(firstSeatBid.getBid()).stream() .filter(Objects::nonNull) .map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), bidRequest.getImp()), bidResponse.getCur())) .collect(Collectors.toList()); diff --git a/src/main/java/org/prebid/server/bidder/somoaudience/SomoaudienceBidder.java b/src/main/java/org/prebid/server/bidder/somoaudience/SomoaudienceBidder.java index 81bdb6e30d6..29c1e4d2b64 100644 --- a/src/main/java/org/prebid/server/bidder/somoaudience/SomoaudienceBidder.java +++ b/src/main/java/org/prebid/server/bidder/somoaudience/SomoaudienceBidder.java @@ -179,11 +179,11 @@ private static List createBiddersBid(BidResponse bidResponse, List BidderBid.of(bid, getType(imps, bid.getImpid()), bidResponse.getCur())) + .map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), imps), bidResponse.getCur())) .collect(Collectors.toList()); } - private static BidType getType(List imps, String impId) { + private static BidType getBidType(String impId, List imps) { return imps.stream() .filter(imp -> Objects.equals(imp.getId(), impId)) .findAny() diff --git a/src/main/java/org/prebid/server/bidder/sovrn/SovrnBidder.java b/src/main/java/org/prebid/server/bidder/sovrn/SovrnBidder.java index 3ee974870c1..646d7f6dac6 100644 --- a/src/main/java/org/prebid/server/bidder/sovrn/SovrnBidder.java +++ b/src/main/java/org/prebid/server/bidder/sovrn/SovrnBidder.java @@ -157,7 +157,8 @@ private static List bidsFromResponse(BidResponse bidResponse) { } private static Bid updateBid(Bid bid) { - bid.setAdm(HttpUtil.decodeUrl(bid.getAdm())); - return bid; + return bid.toBuilder() + .adm(HttpUtil.decodeUrl(bid.getAdm())) + .build(); } } diff --git a/src/main/java/org/prebid/server/bidder/synacormedia/SynacormediaBidder.java b/src/main/java/org/prebid/server/bidder/synacormedia/SynacormediaBidder.java index e555e32d211..0cd8b905132 100644 --- a/src/main/java/org/prebid/server/bidder/synacormedia/SynacormediaBidder.java +++ b/src/main/java/org/prebid/server/bidder/synacormedia/SynacormediaBidder.java @@ -138,10 +138,10 @@ private static List bidsFromResponse(BidResponse bidResponse, BidRequ } private static BidderBid mapBidToBidderBid(Bid bid, List imps, String currency) { - final BidType mediaType = getBidType(bid.getImpid(), imps); + final BidType bidType = getBidType(bid.getImpid(), imps); - if (mediaType == BidType.banner || mediaType == BidType.video) { - return BidderBid.of(bid, mediaType, currency); + if (bidType == BidType.banner || bidType == BidType.video) { + return BidderBid.of(bid, bidType, currency); } return null; } @@ -150,7 +150,7 @@ private static BidType getBidType(String impId, List imps) { for (Imp imp : imps) { if (imp.getId().equals(impId)) { if (imp.getBanner() != null) { - break; + return BidType.banner; } if (imp.getVideo() != null) { return BidType.video; diff --git a/src/main/java/org/prebid/server/bidder/tappx/TappxBidder.java b/src/main/java/org/prebid/server/bidder/tappx/TappxBidder.java index 5166930985e..f28f89b2ac4 100644 --- a/src/main/java/org/prebid/server/bidder/tappx/TappxBidder.java +++ b/src/main/java/org/prebid/server/bidder/tappx/TappxBidder.java @@ -8,6 +8,7 @@ import io.vertx.core.http.HttpMethod; import org.apache.commons.collections4.CollectionUtils; 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.BidderError; @@ -23,6 +24,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; @@ -32,7 +34,7 @@ public class TappxBidder implements Bidder { - private static final String VERSION = "1.1"; + private static final String VERSION = "1.2"; private static final String TYPE_CNN = "prebid"; private static final TypeReference> TAPX_EXT_TYPE_REFERENCE = @@ -47,18 +49,13 @@ public TappxBidder(String endpointUrl, JacksonMapper mapper) { this.mapper = Objects.requireNonNull(mapper); } - /** - * Makes the HTTP requests which should be made to fetch bids. - *

- * Creates POST http request with all parameters in url and headers with encoded request in body. - */ @Override public Result>> makeHttpRequests(BidRequest request) { final ExtImpTappx extImpTappx; final String url; try { extImpTappx = parseBidRequestToExtImpTappx(request); - url = buildEndpointUrl(extImpTappx, request.getTest()); + url = resolveUrl(extImpTappx, request.getTest()); } catch (PreBidException e) { return Result.withError(BidderError.badInput(e.getMessage())); } @@ -91,7 +88,7 @@ private ExtImpTappx parseBidRequestToExtImpTappx(BidRequest request) { /** * Builds endpoint url based on adapter-specific pub settings from imp.ext. */ - private String buildEndpointUrl(ExtImpTappx extImpTappx, Integer test) { + private String resolveUrl(ExtImpTappx extImpTappx, Integer test) { final String host = extImpTappx.getHost(); if (StringUtils.isBlank(host)) { throw new PreBidException("Tappx host undefined"); @@ -107,22 +104,42 @@ private String buildEndpointUrl(ExtImpTappx extImpTappx, Integer test) { throw new PreBidException("Tappx tappxkey undefined"); } - String url = String.format("%s%s/%s?tappxkey=%s", endpointUrl, host, endpoint, tappxkey); - if (test != null && test == 0) { - int t = (int) System.nanoTime(); - url += "&ts=" + t; - } - - url += "&v=" + VERSION; - url += "&type_cnn=" + TYPE_CNN; + return buildUrl(host, endpoint, tappxkey, test); + } + private String buildUrl(String host, String endpoint, String tappxkey, Integer test) { try { - HttpUtil.validateUrl(url); - } catch (IllegalArgumentException e) { - throw new PreBidException("Not valid url: " + url, e); + final URIBuilder uriBuilder = new URIBuilder(resolveHost(host)); + + if (!StringUtils.containsIgnoreCase(host, endpoint)) { + final String path = buildUrlPath(uriBuilder.getPath(), endpoint); + uriBuilder.setPath(path); + } + + uriBuilder.addParameter("tappxkey", tappxkey); + uriBuilder.addParameter("v", VERSION); + uriBuilder.addParameter("type_cnn", TYPE_CNN); + + if (test != null && test == 0) { + final String ts = String.valueOf(System.nanoTime()); + uriBuilder.addParameter("ts", ts); + } + return uriBuilder.build().toString(); + } catch (URISyntaxException e) { + throw new PreBidException(String.format("Failed to build endpoint URL: %s", e.getMessage())); } + } + + private String resolveHost(String host) { + return StringUtils.startsWithAny(host.toLowerCase(), "http://", "https://") + ? host + : endpointUrl + host; + } - return url; + private static String buildUrlPath(String path, String endpoint) { + final String strippedPath = StringUtils.stripEnd(path, "/"); + final String strippedEndpoint = StringUtils.stripStart(endpoint, "/"); + return strippedPath + "/" + strippedEndpoint; } /** diff --git a/src/main/java/org/prebid/server/bidder/unicorn/UnicornBidder.java b/src/main/java/org/prebid/server/bidder/unicorn/UnicornBidder.java new file mode 100644 index 00000000000..7f4f2b8f76b --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/unicorn/UnicornBidder.java @@ -0,0 +1,239 @@ +package org.prebid.server.bidder.unicorn; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.IntNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.TextNode; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Device; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Regs; +import com.iab.openrtb.request.Source; +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.apache.commons.lang3.StringUtils; +import org.prebid.server.bidder.Bidder; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.HttpCall; +import org.prebid.server.bidder.model.HttpRequest; +import org.prebid.server.bidder.model.Result; +import org.prebid.server.bidder.unicorn.model.UnicornImpExt; +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.ExtPrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtRegs; +import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtSource; +import org.prebid.server.proto.openrtb.ext.request.unicorn.ExtImpUnicorn; +import org.prebid.server.proto.openrtb.ext.response.BidType; +import org.prebid.server.util.HttpUtil; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * Unicorn {@link Bidder} implementation. + */ +public class UnicornBidder implements Bidder { + + private static final TypeReference> UNICORN_EXT_TYPE_REFERENCE = + new TypeReference>() { + }; + + private final String endpointUrl; + private final JacksonMapper mapper; + + public UnicornBidder(String endpointUrl, JacksonMapper mapper) { + this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.mapper = Objects.requireNonNull(mapper); + } + + @Override + public Result>> makeHttpRequests(BidRequest request) { + final List requestImps = request.getImp(); + final List modifiedImps; + final Source source; + final Integer firstImpAccountId; + try { + validateRegs(request.getRegs()); + modifiedImps = modifyImps(requestImps); + source = updateSource(request.getSource()); + firstImpAccountId = parseImpExtBidder(requestImps.get(0)).getAccountId(); + } catch (PreBidException e) { + return Result.withError(BidderError.badInput(e.getMessage())); + } + final ExtRequest modifiedExtRequest = modifyExtRequest(request.getExt(), firstImpAccountId); + return Result.withValue(createRequest(request, modifiedImps, source, modifiedExtRequest)); + } + + private static void validateRegs(Regs regs) { + if (regs != null) { + if (Objects.equals(regs.getCoppa(), 1)) { + throw new PreBidException("COPPA is not supported"); + } + final ExtRegs extRegs = regs.getExt(); + if (extRegs != null) { + if (Objects.equals(extRegs.getGdpr(), 1)) { + throw new PreBidException("GDPR is not supported"); + } + if (StringUtils.isNotEmpty(extRegs.getUsPrivacy())) { + throw new PreBidException("CCPA is not supported"); + } + } + } + } + + private List modifyImps(List imps) { + final List modifiedImps = new ArrayList<>(); + for (Imp imp : imps) { + final UnicornImpExt unicornImpExt = parseImpExt(imp); + final ExtImpUnicorn extImpBidder = unicornImpExt.getBidder(); + final Imp.ImpBuilder impBuilder = imp.toBuilder().secure(1); + final String placementId = extImpBidder.getPlacementId(); + + if (StringUtils.isEmpty(placementId)) { + final String resolvedPlacementId = getStoredRequestImpId(imp); + final UnicornImpExt updatedExt = unicornImpExt.toBuilder() + .bidder(extImpBidder.toBuilder().placementId(resolvedPlacementId).build()) + .build(); + impBuilder + .tagid(resolvedPlacementId) + .ext(mapper.mapper().convertValue(updatedExt, ObjectNode.class)); + } else { + impBuilder + .tagid(placementId) + .ext(mapper.mapper().convertValue(unicornImpExt, ObjectNode.class)); + } + + modifiedImps.add(impBuilder.build()); + + } + return modifiedImps; + } + + private UnicornImpExt parseImpExt(Imp imp) { + try { + return mapper.mapper().convertValue(imp.getExt(), UnicornImpExt.class); + } catch (IllegalArgumentException e) { + throw new PreBidException(String.format( + "Error while decoding ext of imp with id: %s, error: %s ", imp.getId(), e.getMessage())); + } + } + + private static String getStoredRequestImpId(Imp imp) { + final JsonNode extPrebid = imp.getExt().get("prebid"); + final JsonNode storedRequestNode = isNotEmptyNode(extPrebid) ? extPrebid.get("storedrequest") : null; + final JsonNode storedRequestIdNode = isNotEmptyNode(storedRequestNode) ? storedRequestNode.get("id") : null; + final String storedRequestId = storedRequestIdNode != null && storedRequestIdNode.isTextual() + ? storedRequestIdNode.textValue() + : null; + if (StringUtils.isNotEmpty(storedRequestId)) { + return storedRequestId; + } else { + throw new PreBidException(String.format("stored request id not found in imp: %s", imp.getId())); + } + } + + private static boolean isNotEmptyNode(JsonNode node) { + return node != null && !node.isEmpty(); + } + + private static Source updateSource(Source source) { + return source != null + ? source.toBuilder().ext(createExtSource()).build() + : Source.builder().ext(createExtSource()).build(); + } + + private static ExtSource createExtSource() { + final ExtSource extSource = ExtSource.of(null); + extSource.addProperty("stype", new TextNode("prebid_server_uncn")); + extSource.addProperty("bidder", new TextNode("unicorn")); + return extSource; + } + + private ExtImpUnicorn parseImpExtBidder(Imp imp) { + try { + return mapper.mapper().convertValue(imp.getExt(), UNICORN_EXT_TYPE_REFERENCE).getBidder(); + } catch (IllegalArgumentException e) { + throw new PreBidException(e.getMessage()); + } + } + + private static ExtRequest modifyExtRequest(ExtRequest extRequest, Integer accountId) { + final ExtRequest modifiedRequest = extRequest != null + ? ExtRequest.of(extRequest.getPrebid()) + : ExtRequest.of(null); + final int resolvedAccountId = accountId == null ? 0 : accountId; + modifiedRequest.addProperty("accountId", new IntNode(resolvedAccountId)); + + return modifiedRequest; + } + + private HttpRequest createRequest(BidRequest request, + List imps, Source source, + ExtRequest extRequest) { + final BidRequest outgoingRequest = request.toBuilder() + .imp(imps) + .source(source) + .ext(extRequest) + .build(); + + return HttpRequest.builder() + .method(HttpMethod.POST) + .uri(endpointUrl) + .headers(resolveHeaders(request.getDevice())) + .payload(outgoingRequest) + .body(mapper.encode(outgoingRequest)) + .build(); + } + + private static MultiMap resolveHeaders(Device device) { + final MultiMap headers = HttpUtil.headers(); + HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.X_OPENRTB_VERSION_HEADER, "2.5"); + + if (device != null) { + HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.USER_AGENT_HEADER, device.getUa()); + HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.X_FORWARDED_FOR_HEADER, device.getIpv6()); + HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.X_FORWARDED_FOR_HEADER, device.getIp()); + } + + return headers; + } + + @Override + public final Result> makeBids(HttpCall httpCall, BidRequest bidRequest) { + try { + final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class); + return Result.of(extractBids(bidResponse), Collections.emptyList()); + } catch (DecodeException | PreBidException e) { + return Result.withError(BidderError.badServerResponse(e.getMessage())); + } + } + + private static List extractBids(BidResponse bidResponse) { + if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) { + return Collections.emptyList(); + } + return bidsFromResponse(bidResponse); + } + + private static List bidsFromResponse(BidResponse bidResponse) { + return bidResponse.getSeatbid().stream() + .filter(Objects::nonNull) + .map(SeatBid::getBid) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .map(bid -> BidderBid.of(bid, BidType.banner, bidResponse.getCur())) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/org/prebid/server/bidder/unicorn/model/UnicornImpExt.java b/src/main/java/org/prebid/server/bidder/unicorn/model/UnicornImpExt.java new file mode 100644 index 00000000000..b4f534d1aad --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/unicorn/model/UnicornImpExt.java @@ -0,0 +1,16 @@ +package org.prebid.server.bidder.unicorn.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Value; +import org.prebid.server.proto.openrtb.ext.request.unicorn.ExtImpUnicorn; + +@AllArgsConstructor(staticName = "of") +@Value +@Builder(toBuilder = true) +public class UnicornImpExt { + + UnicornImpExtContext context; + + ExtImpUnicorn bidder; +} diff --git a/src/main/java/org/prebid/server/bidder/unicorn/model/UnicornImpExtContext.java b/src/main/java/org/prebid/server/bidder/unicorn/model/UnicornImpExtContext.java new file mode 100644 index 00000000000..05e6f9c36a6 --- /dev/null +++ b/src/main/java/org/prebid/server/bidder/unicorn/model/UnicornImpExtContext.java @@ -0,0 +1,12 @@ +package org.prebid.server.bidder.unicorn.model; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.AllArgsConstructor; +import lombok.Value; + +@AllArgsConstructor(staticName = "of") +@Value +public class UnicornImpExtContext { + + ObjectNode data; +} diff --git a/src/main/java/org/prebid/server/bidder/valueimpression/ValueImpressionBidder.java b/src/main/java/org/prebid/server/bidder/valueimpression/ValueImpressionBidder.java index 86dc5f9bf08..3982c5c7d82 100644 --- a/src/main/java/org/prebid/server/bidder/valueimpression/ValueImpressionBidder.java +++ b/src/main/java/org/prebid/server/bidder/valueimpression/ValueImpressionBidder.java @@ -114,18 +114,15 @@ private static List bidsFromResponse(List imps, List respon final List bidderBids = new ArrayList<>(); for (Bid bid : responseBids) { try { - final BidType bidType = resolveBidType(bid.getImpid(), imps); - bidderBids.add(BidderBid.of(bid, bidType, currency)); + bidderBids.add(BidderBid.of(bid, getBidType(bid.getImpid(), imps), currency)); } catch (PreBidException e) { - errors.add(BidderError.badInput( - String.format("bid id=%s %s", bid.getId(), e.getMessage())) - ); + errors.add(BidderError.badInput(String.format("bid id=%s %s", bid.getId(), e.getMessage()))); } } return bidderBids; } - private static BidType resolveBidType(String impId, List imps) { + private static BidType getBidType(String impId, List imps) { for (Imp imp : imps) { if (imp.getId().equals(impId)) { if (imp.getBanner() != null) { diff --git a/src/main/java/org/prebid/server/bidder/verizonmedia/VerizonmediaBidder.java b/src/main/java/org/prebid/server/bidder/verizonmedia/VerizonmediaBidder.java index 54257780b4e..cf8c6a19e51 100644 --- a/src/main/java/org/prebid/server/bidder/verizonmedia/VerizonmediaBidder.java +++ b/src/main/java/org/prebid/server/bidder/verizonmedia/VerizonmediaBidder.java @@ -170,13 +170,13 @@ public Result> makeBids(HttpCall httpCall, BidReques } private static List extractBids(BidResponse bidResponse, BidRequest bidRequest) { - final List seatbid = bidResponse != null ? bidResponse.getSeatbid() : null; - if (seatbid == null) { + final List seatBids = bidResponse != null ? bidResponse.getSeatbid() : null; + if (seatBids == null) { return Collections.emptyList(); } - if (seatbid.isEmpty()) { - throw new PreBidException(String.format("Invalid SeatBids count: %d", seatbid.size())); + if (seatBids.isEmpty()) { + throw new PreBidException(String.format("Invalid SeatBids count: %d", seatBids.size())); } return bidsFromResponse(bidResponse, bidRequest.getImp()); } diff --git a/src/main/java/org/prebid/server/bidder/yieldone/YieldoneBidder.java b/src/main/java/org/prebid/server/bidder/yieldone/YieldoneBidder.java index 168def886e1..1384988f7fa 100644 --- a/src/main/java/org/prebid/server/bidder/yieldone/YieldoneBidder.java +++ b/src/main/java/org/prebid/server/bidder/yieldone/YieldoneBidder.java @@ -102,14 +102,18 @@ private void validateImpExt(Imp imp) { @Override public Result> makeBids(HttpCall httpCall, BidRequest bidRequest) { try { - final List requestImps = bidRequest.getImp(); final BidResponse bidResponse = decodeBodyToBidResponse(httpCall); + if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) { + return Result.empty(); + } + final List bidderBids = bidResponse.getSeatbid().stream() .filter(Objects::nonNull) .map(SeatBid::getBid) .filter(Objects::nonNull) .flatMap(Collection::stream) - .map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), requestImps), bidResponse.getCur())) + .map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), bidRequest.getImp()), + bidResponse.getCur())) .collect(Collectors.toList()); return Result.withValues(bidderBids); diff --git a/src/main/java/org/prebid/server/bidder/zeroclickfraud/ZeroclickfraudBidder.java b/src/main/java/org/prebid/server/bidder/zeroclickfraud/ZeroclickfraudBidder.java index 30e5f33ecf3..22aa638a381 100644 --- a/src/main/java/org/prebid/server/bidder/zeroclickfraud/ZeroclickfraudBidder.java +++ b/src/main/java/org/prebid/server/bidder/zeroclickfraud/ZeroclickfraudBidder.java @@ -125,17 +125,18 @@ private static List extractBids(BidResponse bidResponse, BidRequest b : bidsFromResponse(bidResponse, bidRequest.getImp()); } - private static List bidsFromResponse(BidResponse bidResponse, List requestImps) { + private static List bidsFromResponse(BidResponse bidResponse, List imps) { return bidResponse.getSeatbid().stream() + .filter(Objects::nonNull) .map(SeatBid::getBid) .filter(Objects::nonNull) .flatMap(Collection::stream) - .map(bid -> BidderBid.of(bid, getMediaType(bid.getImpid(), requestImps), bidResponse.getCur())) + .map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), imps), bidResponse.getCur())) .collect(Collectors.toList()); } - private static BidType getMediaType(String impId, List requestImps) { - for (Imp imp : requestImps) { + private static BidType getBidType(String impId, List imps) { + for (Imp imp : imps) { if (imp.getId().equals(impId)) { if (imp.getVideo() != null) { return BidType.video; diff --git a/src/main/java/org/prebid/server/cache/CacheService.java b/src/main/java/org/prebid/server/cache/CacheService.java index a7ab3788f69..77cbcff60c4 100644 --- a/src/main/java/org/prebid/server/cache/CacheService.java +++ b/src/main/java/org/prebid/server/cache/CacheService.java @@ -252,7 +252,7 @@ private CacheBid toCacheBid(BidInfo bidInfo, final com.iab.openrtb.response.Bid bid = bidInfo.getBid(); final Integer bidTtl = bid.getExp(); final Imp correspondingImp = bidInfo.getCorrespondingImp(); - final Integer impTtl = correspondingImp.getExp(); + final Integer impTtl = correspondingImp != null ? correspondingImp.getExp() : null; final Integer accountMediaTypeTtl = isVideoBid ? accountCacheTtl.getVideoCacheTtl() : accountCacheTtl.getBannerCacheTtl(); @@ -282,7 +282,7 @@ private Future doCacheOpenrtb(List bids, final String accountId = account.getId(); final List cachedCreatives = Stream.concat( bids.stream().map(cacheBid -> createJsonPutObjectOpenrtb(cacheBid, accountId, eventsContext)), - videoBids.stream().map(cacheBid -> createXmlPutObjectOpenrtb(cacheBid, accountId, eventsContext))) + videoBids.stream().map(this::createXmlPutObjectOpenrtb)) .collect(Collectors.toList()); if (cachedCreatives.isEmpty()) { @@ -403,18 +403,10 @@ private CachedCreative createJsonPutObjectOpenrtb(CacheBid cacheBid, /** * Makes XML type {@link PutObject} from {@link com.iab.openrtb.response.Bid}. Used for OpenRTB auction request. */ - private CachedCreative createXmlPutObjectOpenrtb(CacheBid cacheBid, - String accountId, - EventsContext eventsContext) { + private CachedCreative createXmlPutObjectOpenrtb(CacheBid cacheBid) { final BidInfo bidInfo = cacheBid.getBidInfo(); final com.iab.openrtb.response.Bid bid = bidInfo.getBid(); - final String vastXml = vastModifier.createBidVastXml( - bidInfo.getBidder(), - bid.getAdm(), - bid.getNurl(), - bidInfo.getBidId(), - accountId, - eventsContext); + final String vastXml = bid.getAdm(); final PutObject payload = PutObject.builder() .type("xml") diff --git a/src/main/java/org/prebid/server/currency/CurrencyConversionService.java b/src/main/java/org/prebid/server/currency/CurrencyConversionService.java index 21ebcb07a9a..9102810867a 100644 --- a/src/main/java/org/prebid/server/currency/CurrencyConversionService.java +++ b/src/main/java/org/prebid/server/currency/CurrencyConversionService.java @@ -205,7 +205,7 @@ private BigDecimal convertCurrency(BigDecimal price, Map { private static final Logger logger = LoggerFactory.getLogger(CookieSyncHandler.class); + private static final ConditionalLogger BAD_REQUEST_LOGGER = new ConditionalLogger(logger); + private static final Map JSON_HEADERS_MAP = Collections.singletonMap( HttpUtil.CONTENT_TYPE_HEADER, HttpHeaderValues.APPLICATION_JSON); private static final String REJECTED_BY_TCF = "Rejected by TCF"; private static final String REJECTED_BY_CCPA = "Rejected by CCPA"; + private static final String METRICS_UNKNOWN_BIDDER = "UNKNOWN"; + + // Probably this should be moved to config since hardcoding of "uid" param is not ideal + private static final String HOST_BIDDER_USERSYNC_URL_TEMPLATE = + "%s/setuid?bidder=%s&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&uid=%s"; private final String externalUrl; private final long defaultTimeout; @@ -165,6 +176,8 @@ private Future toCookieSyncContext(RoutingContext routingCont .routingContext(routingContext) .uidsCookie(uidsCookie) .cookieSyncRequest(cookieSyncRequest) + .usersyncMethodChooser( + UsersyncMethodChooser.from(cookieSyncRequest.getFilterSettings())) .timeout(timeout) .account(account) .privacyContext(privacyContext) @@ -200,9 +213,10 @@ private void handleCookieSyncContextResult(AsyncResult cookie final CookieSyncContext cookieSyncContext = cookieSyncContextResult.result(); final TcfContext tcfContext = cookieSyncContext.getPrivacyContext().getTcfContext(); - final Exception validationException = validateCookieSyncContext(cookieSyncContext); - if (validationException != null) { - handleErrors(validationException, routingContext, tcfContext); + try { + validateCookieSyncContext(cookieSyncContext); + } catch (InvalidRequestException | UnauthorizedUidsException ex) { + handleErrors(ex, routingContext, tcfContext); return; } @@ -212,23 +226,26 @@ private void handleCookieSyncContextResult(AsyncResult cookie biddersToSync(cookieSyncContext), cookieSyncContext)); } else { - final Throwable error = cookieSyncContextResult.cause(); - handleErrors(error, routingContext, null); + handleErrors(cookieSyncContextResult.cause(), routingContext, null); } } - private static Exception validateCookieSyncContext(CookieSyncContext cookieSyncContext) { + private void validateCookieSyncContext(CookieSyncContext cookieSyncContext) { final UidsCookie uidsCookie = cookieSyncContext.getUidsCookie(); if (!uidsCookie.allowsSync()) { - return new UnauthorizedUidsException("Sync is not allowed for this uids"); + throw new UnauthorizedUidsException("Sync is not allowed for this uids"); } final CookieSyncRequest cookieSyncRequest = cookieSyncContext.getCookieSyncRequest(); if (isGdprParamsNotConsistent(cookieSyncRequest)) { - return new InvalidRequestException("gdpr_consent is required if gdpr is 1"); + throw new InvalidRequestException("gdpr_consent is required if gdpr is 1"); } - return null; + final TcfContext tcfContext = cookieSyncContext.getPrivacyContext().getTcfContext(); + if (StringUtils.equals(tcfContext.getGdpr(), "1") && BooleanUtils.isFalse(tcfContext.getIsConsentValid())) { + metrics.updateUserSyncTcfInvalidMetric(); + throw new InvalidRequestException("Consent string is invalid"); + } } private static boolean isGdprParamsNotConsistent(CookieSyncRequest request) { @@ -335,13 +352,6 @@ private Set addCoopSyncBidders(List bidders, int limit) { return allBidders; } - /** - * Determines original bidder's name. - */ - private String bidderNameFor(String bidder) { - return bidderCatalog.isAlias(bidder) ? bidderCatalog.nameByAlias(bidder) : bidder; - } - private void respondByTcfResponse(AsyncResult hostTcfResponseResult, Set biddersToSync, CookieSyncContext cookieSyncContext) { @@ -413,7 +423,7 @@ private RejectedBidders rejectedRequestBiddersToSync(TcfResponse tcfResp private Set extractCcpaEnforcedBidders(Account account, Collection biddersToSync, Privacy privacy) { if (privacyEnforcementService.isCcpaEnforced(privacy.getCcpa(), account)) { return biddersToSync.stream() - .filter(bidder -> bidderCatalog.bidderInfoByName(bidderNameFor(bidder)).isCcpaEnforced()) + .filter(bidder -> bidderCatalog.bidderInfoByName(bidder).isCcpaEnforced()) .collect(Collectors.toSet()); } return Collections.emptySet(); @@ -430,9 +440,8 @@ private void respondWithRejectedBidders(CookieSyncContext cookieSyncContext, final RoutingContext routingContext = cookieSyncContext.getRoutingContext(); final UidsCookie uidsCookie = cookieSyncContext.getUidsCookie(); - final Privacy privacy = cookieSyncContext.getPrivacyContext().getPrivacy(); final List bidderStatuses = bidders.stream() - .map(bidder -> bidderStatusFor(bidder, routingContext, uidsCookie, rejectedBidders, privacy)) + .map(bidder -> bidderStatusFor(bidder, cookieSyncContext, rejectedBidders)) .filter(Objects::nonNull) // skip bidder with live UID .collect(Collectors.toList()); @@ -457,7 +466,8 @@ private void respondWithRejectedBidders(CookieSyncContext cookieSyncContext, private void updateCookieSyncTcfMetrics(Collection syncBidders, Collection rejectedBidders) { for (String bidder : syncBidders) { if (rejectedBidders.contains(bidder)) { - metrics.updateCookieSyncTcfBlockedMetric(bidder); + metrics.updateCookieSyncTcfBlockedMetric( + bidderCatalog.isValidName(bidder) ? bidder : METRICS_UNKNOWN_BIDDER); } else { metrics.updateCookieSyncGenMetric(bidder); } @@ -468,54 +478,55 @@ private void updateCookieSyncTcfMetrics(Collection syncBidders, Collecti * Creates {@link BidderUsersyncStatus} for given bidder. */ private BidderUsersyncStatus bidderStatusFor(String bidder, - RoutingContext context, - UidsCookie uidsCookie, - RejectedBidders rejectedBidders, - Privacy privacy) { + CookieSyncContext cookieSyncContext, + RejectedBidders rejectedBidders) { - final boolean isNotAlias = !bidderCatalog.isAlias(bidder); final Set biddersRejectedByTcf = rejectedBidders.getRejectedByTcf(); final Set biddersRejectedByCcpa = rejectedBidders.getRejectedByCcpa(); - if (isNotAlias && !bidderCatalog.isValidName(bidder)) { + if (!bidderCatalog.isValidName(bidder)) { return bidderStatusBuilder(bidder) .error("Unsupported bidder") .build(); - } else if (isNotAlias && !bidderCatalog.isActive(bidder)) { + } else if (!bidderCatalog.isActive(bidder)) { return bidderStatusBuilder(bidder) .error(String.format("%s is not configured properly on this Prebid Server deploy. " + "If you believe this should work, contact the company hosting the service " + "and tell them to check their configuration.", bidder)) .build(); - } else if (isNotAlias && biddersRejectedByTcf.contains(bidder)) { + } else if (biddersRejectedByTcf.contains(bidder)) { return bidderStatusBuilder(bidder) .error(REJECTED_BY_TCF) .build(); - } else if (isNotAlias && biddersRejectedByCcpa.contains(bidder)) { + } else if (biddersRejectedByCcpa.contains(bidder)) { return bidderStatusBuilder(bidder) .error(REJECTED_BY_CCPA) .build(); - } else { - final Usersyncer usersyncer = bidderCatalog.usersyncerByName(bidderNameFor(bidder)); + } - if (StringUtils.isEmpty(usersyncer.getUsersyncUrl())) { - // there is nothing to sync - return null; - } + final Usersyncer usersyncer = bidderCatalog.usersyncerByName(bidder); - final UsersyncInfo hostBidderUsersyncInfo = hostBidderUsersyncInfo(context, privacy, usersyncer); + final Usersyncer.UsersyncMethod usersyncMethod = + cookieSyncContext.getUsersyncMethodChooser().choose(usersyncer, bidder); + if (usersyncMethod == null) { + // there is nothing to sync + return null; + } - if (hostBidderUsersyncInfo != null || !uidsCookie.hasLiveUidFrom(usersyncer.getCookieFamilyName())) { - return bidderStatusBuilder(bidder) - .noCookie(true) - .usersync(ObjectUtils.defaultIfNull( - hostBidderUsersyncInfo, - UsersyncInfoAssembler.from(usersyncer).withPrivacy(privacy).assemble())) - .build(); - } + final RoutingContext routingContext = cookieSyncContext.getRoutingContext(); + final UidsCookie uidsCookie = cookieSyncContext.getUidsCookie(); + final String cookieFamilyName = usersyncer.getCookieFamilyName(); + final String uidFromHostCookieToSet = resolveUidFromHostCookie(routingContext, cookieFamilyName); + if (uidFromHostCookieToSet == null && uidsCookie.hasLiveUidFrom(cookieFamilyName)) { + return null; } - return null; + final Privacy privacy = cookieSyncContext.getPrivacyContext().getPrivacy(); + + return bidderStatusBuilder(bidder) + .noCookie(true) + .usersync(toUsersyncInfo(usersyncMethod, cookieFamilyName, uidFromHostCookieToSet, privacy)) + .build(); } private static BidderUsersyncStatus.BidderUsersyncStatusBuilder bidderStatusBuilder(String bidder) { @@ -523,8 +534,7 @@ private static BidderUsersyncStatus.BidderUsersyncStatusBuilder bidderStatusBuil } /** - * Returns {@link UsersyncInfo} with updated usersync-url (pointed directly to Prebid Server /setuid endpoint) - * or null if normal usersync flow should be applied. + * Returns UID from host cookie to sync with uids cookie or null if normal usersync flow should be applied. *

* Uids cookie should be in sync with host-cookie value, so the next conditions must be satisfied: *

@@ -534,31 +544,59 @@ private static BidderUsersyncStatus.BidderUsersyncStatusBuilder bidderStatusBuil *

* 3. Host-bidder uid value in uids cookie should not exist or be different from host-cookie uid value. */ - private UsersyncInfo hostBidderUsersyncInfo(RoutingContext context, Privacy privacy, Usersyncer usersyncer) { - final String cookieFamilyName = usersyncer.getCookieFamilyName(); - if (Objects.equals(cookieFamilyName, uidsCookieService.getHostCookieFamily())) { - - final Map cookies = HttpUtil.cookiesAsMap(context); - final String hostCookieUid = uidsCookieService.parseHostCookie(cookies); - - if (hostCookieUid != null) { - final Uids parsedUids = uidsCookieService.parseUids(cookies); - final Map uidsMap = parsedUids != null ? parsedUids.getUids() : null; - final UidWithExpiry uidWithExpiry = uidsMap != null ? uidsMap.get(cookieFamilyName) : null; - final String uid = uidWithExpiry != null ? uidWithExpiry.getUid() : null; - - if (!Objects.equals(hostCookieUid, uid)) { - final String url = String.format("%s/setuid?bidder=%s&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}" - + "&us_privacy={{us_privacy}}&uid=%s", externalUrl, cookieFamilyName, - HttpUtil.encodeUrl(hostCookieUid)); - return UsersyncInfoAssembler.from(usersyncer) - .withUrl(url) - .withPrivacy(privacy) - .assemble(); - } - } + private String resolveUidFromHostCookie(RoutingContext context, String cookieFamilyName) { + if (!Objects.equals(cookieFamilyName, uidsCookieService.getHostCookieFamily())) { + return null; + } + + final Map cookies = HttpUtil.cookiesAsMap(context); + final String hostCookieUid = uidsCookieService.parseHostCookie(cookies); + + if (hostCookieUid == null) { + return null; } - return null; + + final Uids parsedUids = uidsCookieService.parseUids(cookies); + final Map uidsMap = parsedUids != null ? parsedUids.getUids() : null; + final UidWithExpiry uidWithExpiry = uidsMap != null ? uidsMap.get(cookieFamilyName) : null; + final String uid = uidWithExpiry != null ? uidWithExpiry.getUid() : null; + + if (Objects.equals(hostCookieUid, uid)) { + return null; + } + + return hostCookieUid; + } + + private UsersyncInfo toUsersyncInfo(Usersyncer.UsersyncMethod usersyncMethod, + String cookieFamilyName, + String uidFromHostCookieToSet, + Privacy privacy) { + + final UsersyncInfoAssembler usersyncInfoAssembler = UsersyncInfoAssembler.from(usersyncMethod); + + return (uidFromHostCookieToSet == null + ? usersyncInfoAssembler + : usersyncInfoAssembler + .withUrl(toHostBidderUsersyncUrl(cookieFamilyName, usersyncMethod, uidFromHostCookieToSet))) + .withPrivacy(privacy) + .assemble(); + } + + /** + * Returns updated usersync-url pointed directly to Prebid Server /setuid endpoint. + */ + private String toHostBidderUsersyncUrl(String cookieFamilyName, + Usersyncer.UsersyncMethod usersyncMethod, + String hostCookieUid) { + + final String url = String.format( + HOST_BIDDER_USERSYNC_URL_TEMPLATE, + externalUrl, + cookieFamilyName, + HttpUtil.encodeUrl(hostCookieUid)); + + return UsersyncUtil.enrichUsersyncUrlWithFormat(url, usersyncMethod.getType()); } private void updateCookieSyncMatchMetrics(Collection syncBidders, @@ -605,8 +643,7 @@ private void handleErrors(Throwable error, RoutingContext routingContext, TcfCon metrics.updateUserSyncBadRequestMetric(); status = HttpResponseStatus.BAD_REQUEST.code(); body = String.format("Invalid request format: %s", message); - logger.info(message, error); - + BAD_REQUEST_LOGGER.info(message, 0.01); } else if (error instanceof UnauthorizedUidsException) { metrics.updateUserSyncOptoutMetric(); status = HttpResponseStatus.UNAUTHORIZED.code(); diff --git a/src/main/java/org/prebid/server/handler/SetuidHandler.java b/src/main/java/org/prebid/server/handler/SetuidHandler.java index da7beebc3aa..766298551ef 100644 --- a/src/main/java/org/prebid/server/handler/SetuidHandler.java +++ b/src/main/java/org/prebid/server/handler/SetuidHandler.java @@ -5,6 +5,7 @@ import io.vertx.core.Future; import io.vertx.core.Handler; import io.vertx.core.http.Cookie; +import io.vertx.core.http.HttpHeaders; import io.vertx.core.http.HttpServerRequest; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; @@ -16,6 +17,7 @@ import org.prebid.server.auction.PrivacyEnforcementService; import org.prebid.server.auction.model.SetuidContext; import org.prebid.server.bidder.BidderCatalog; +import org.prebid.server.bidder.UsersyncUtil; import org.prebid.server.bidder.Usersyncer; import org.prebid.server.cookie.UidsCookie; import org.prebid.server.cookie.UidsCookieService; @@ -36,7 +38,6 @@ import java.util.Collections; import java.util.Map; import java.util.Objects; -import java.util.Set; import java.util.stream.Collectors; public class SetuidHandler implements Handler { @@ -45,10 +46,9 @@ public class SetuidHandler implements Handler { private static final String BIDDER_PARAM = "bidder"; private static final String UID_PARAM = "uid"; - private static final String FORMAT_PARAM = "format"; - private static final String IMG_FORMAT_PARAM = "img"; private static final String PIXEL_FILE_PATH = "static/tracking-pixel.png"; private static final String ACCOUNT_PARAM = "account"; + private static final int UNAVAILABLE_FOR_LEGAL_REASONS = 451; private final long defaultTimeout; private final UidsCookieService uidsCookieService; @@ -59,7 +59,7 @@ public class SetuidHandler implements Handler { private final AnalyticsReporterDelegator analyticsDelegator; private final Metrics metrics; private final TimeoutFactory timeoutFactory; - private final Set activeCookieFamilyNames; + private final Map cookieNameToSyncType; public SetuidHandler(long defaultTimeout, UidsCookieService uidsCookieService, @@ -82,11 +82,11 @@ public SetuidHandler(long defaultTimeout, this.metrics = Objects.requireNonNull(metrics); this.timeoutFactory = Objects.requireNonNull(timeoutFactory); - activeCookieFamilyNames = bidderCatalog.names().stream() + cookieNameToSyncType = bidderCatalog.names().stream() .filter(bidderCatalog::isActive) .map(bidderCatalog::usersyncerByName) - .map(Usersyncer::getCookieFamilyName) - .collect(Collectors.toSet()); + .distinct() // built-in aliases looks like bidders with the same usersyncers + .collect(Collectors.toMap(Usersyncer::getCookieFamilyName, SetuidHandler::preferredUserSyncType)); } private static Integer validateHostVendorId(Integer gdprHostVendorId) { @@ -96,6 +96,10 @@ private static Integer validateHostVendorId(Integer gdprHostVendorId) { return gdprHostVendorId; } + private static String preferredUserSyncType(Usersyncer usersyncer) { + return usersyncer.getPrimaryMethod().getType(); + } + @Override public void handle(RoutingContext context) { toSetuidContext(context) @@ -117,6 +121,7 @@ private Future toSetuidContext(RoutingContext routingContext) { .timeout(timeout) .account(account) .cookieName(cookieName) + .syncType(cookieNameToSyncType.get(cookieName)) .privacyContext(privacyContext) .build())); } @@ -125,17 +130,20 @@ private Future accountById(String accountId, Timeout timeout) { return StringUtils.isBlank(accountId) ? Future.succeededFuture(Account.empty(accountId)) : applicationSettings.getAccountById(accountId, timeout) - .otherwise(Account.empty(accountId)); + .otherwise(Account.empty(accountId)); } private void handleSetuidContextResult(AsyncResult setuidContextResult, RoutingContext routingContext) { if (setuidContextResult.succeeded()) { final SetuidContext setuidContext = setuidContextResult.result(); + final String bidder = setuidContext.getCookieName(); final TcfContext tcfContext = setuidContext.getPrivacyContext().getTcfContext(); - final Exception exception = validateSetuidContext(setuidContext); - if (exception != null) { - handleErrors(exception, routingContext, tcfContext); + + try { + validateSetuidContext(setuidContext, bidder); + } catch (InvalidRequestException | UnauthorizedUidsException ex) { + handleErrors(ex, routingContext, tcfContext); return; } @@ -147,20 +155,24 @@ private void handleSetuidContextResult(AsyncResult setuidContextR } } - private Exception validateSetuidContext(SetuidContext setuidContext) { + private void validateSetuidContext(SetuidContext setuidContext, String bidder) { final String cookieName = setuidContext.getCookieName(); final boolean isCookieNameBlank = StringUtils.isBlank(cookieName); - if (isCookieNameBlank || !activeCookieFamilyNames.contains(cookieName)) { + if (isCookieNameBlank || !cookieNameToSyncType.containsKey(cookieName)) { final String cookieNameError = isCookieNameBlank ? "required" : "invalid"; - return new InvalidRequestException(String.format("\"bidder\" query param is %s", cookieNameError)); + throw new InvalidRequestException(String.format("\"bidder\" query param is %s", cookieNameError)); + } + + final TcfContext tcfContext = setuidContext.getPrivacyContext().getTcfContext(); + if (StringUtils.equals(tcfContext.getGdpr(), "1") && BooleanUtils.isFalse(tcfContext.getIsConsentValid())) { + metrics.updateUserSyncTcfInvalidMetric(bidder); + throw new InvalidRequestException("Consent string is invalid"); } final UidsCookie uidsCookie = setuidContext.getUidsCookie(); if (!uidsCookie.allowsSync()) { - return new UnauthorizedUidsException("Sync is not allowed for this uids"); + throw new UnauthorizedUidsException("Sync is not allowed for this uids"); } - - return null; } /** @@ -170,7 +182,7 @@ private Future isAllowedForHostVendorId(TcfContext tcfCon return gdprHostVendorId == null ? Future.succeededFuture(HostVendorTcfResponse.allowedVendor()) : tcfDefinerService.resultForVendorIds(Collections.singleton(gdprHostVendorId), tcfContext) - .map(this::toHostVendorTcfResponse); + .map(this::toHostVendorTcfResponse); } private HostVendorTcfResponse toHostVendorTcfResponse(TcfResponse tcfResponse) { @@ -204,7 +216,7 @@ private void respondByTcfResponse(AsyncResult hostTcfResp } else { metrics.updateUserSyncTcfBlockedMetric(bidderCookieName); - final int status = HttpResponseStatus.OK.code(); + final int status = UNAVAILABLE_FOR_LEGAL_REASONS; respondWith(routingContext, status, "The gdpr_consent param prevents cookies from being saved"); analyticsDelegator.processEvent(SetuidEvent.error(status), tcfContext); } @@ -241,9 +253,8 @@ private void respondWithCookie(SetuidContext setuidContext) { final int status = HttpResponseStatus.OK.code(); - // Send pixel file to response if "format=img" - final String format = routingContext.request().getParam(FORMAT_PARAM); - if (StringUtils.equals(format, IMG_FORMAT_PARAM)) { + final String format = routingContext.request().getParam(UsersyncUtil.FORMAT_PARAMETER); + if (shouldRespondWithPixel(format, setuidContext.getSyncType())) { routingContext.response().sendFile(PIXEL_FILE_PATH); } else { respondWith(routingContext, status, null); @@ -258,6 +269,12 @@ private void respondWithCookie(SetuidContext setuidContext) { .build(), tcfContext); } + private boolean shouldRespondWithPixel(String format, String syncType) { + return StringUtils.equals(format, UsersyncUtil.IMG_FORMAT) + || (!StringUtils.equals(format, UsersyncUtil.BLANK_FORMAT) + && StringUtils.equals(syncType, Usersyncer.UsersyncMethod.REDIRECT_TYPE)); + } + private void handleErrors(Throwable error, RoutingContext routingContext, TcfContext tcfContext) { final String message = error.getMessage(); final int status; @@ -300,7 +317,10 @@ private static void respondWith(RoutingContext context, int status, String body) if (body != null) { context.response().end(body); } else { - context.response().end(); + context.response() + .putHeader(HttpHeaders.CONTENT_LENGTH, "0") + .putHeader(HttpHeaders.CONTENT_TYPE, HttpHeaders.TEXT_HTML) + .end(); } } } diff --git a/src/main/java/org/prebid/server/handler/info/BidderDetailsHandler.java b/src/main/java/org/prebid/server/handler/info/BidderDetailsHandler.java index de5e4a5aec7..ee7eed10e1b 100644 --- a/src/main/java/org/prebid/server/handler/info/BidderDetailsHandler.java +++ b/src/main/java/org/prebid/server/handler/info/BidderDetailsHandler.java @@ -1,7 +1,7 @@ package org.prebid.server.handler.info; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.fasterxml.jackson.databind.node.TextNode; import io.netty.handler.codec.http.HttpHeaderValues; import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.Handler; @@ -31,14 +31,13 @@ public class BidderDetailsHandler implements Handler { public BidderDetailsHandler(BidderCatalog bidderCatalog, JacksonMapper mapper) { validateAliases(Objects.requireNonNull(bidderCatalog)); this.mapper = Objects.requireNonNull(mapper); - bidderInfos = createBidderInfos(bidderCatalog); + this.bidderInfos = createBidderInfos(bidderCatalog); } private static void validateAliases(BidderCatalog bidderCatalog) { - if (bidderCatalog.aliases().contains(ALL_PARAM_VALUE)) { - throw new IllegalArgumentException( - String.format("The '%s' bidder has '%s' alias configured which is unacceptable.", - bidderCatalog.nameByAlias(ALL_PARAM_VALUE), ALL_PARAM_VALUE)); + if (bidderCatalog.names().contains(ALL_PARAM_VALUE)) { + throw new IllegalArgumentException(String.format( + "There is '%s' bidder or alias configured which is unacceptable.", ALL_PARAM_VALUE)); } } @@ -51,14 +50,10 @@ private Map createBidderInfos(BidderCatalog bidderCatalog) { .filter(bidderCatalog::isActive) .collect(Collectors.toMap(Function.identity(), name -> bidderNode(bidderCatalog, name))); - final Map aliasToInfo = bidderCatalog.aliases().stream() - .filter(alias -> bidderCatalog.isActive(bidderCatalog.nameByAlias(alias))) - .collect(Collectors.toMap(Function.identity(), alias -> aliasNode(bidderCatalog, alias))); - final Map allToInfos = Collections.singletonMap( - ALL_PARAM_VALUE, allInfos(nameToInfo, aliasToInfo)); + ALL_PARAM_VALUE, allInfos(nameToInfo)); - return Stream.of(nameToInfo, aliasToInfo, allToInfos) + return Stream.of(nameToInfo, allToInfos) .flatMap(map -> map.entrySet().stream()) .collect(Collectors.toMap(Map.Entry::getKey, map -> mapper.encode(map.getValue()))); } @@ -72,24 +67,10 @@ private ObjectNode bidderNode(BidderCatalog bidderCatalog, String name) { } /** - * Returns alias info as {@link ObjectNode}. + * Returns a {@link Map} of all bidder's infos sorted by name as {@link ObjectNode}. */ - private ObjectNode aliasNode(BidderCatalog bidderCatalog, String alias) { - final String name = bidderCatalog.nameByAlias(alias); - - final ObjectNode node = bidderNode(bidderCatalog, name); - node.set("aliasOf", new TextNode(name)); - return node; - } - - /** - * Returns a {@link Map} of all bidder's infos sorted by name (and alias) as {@link ObjectNode}. - */ - private ObjectNode allInfos(Map nameToInfo, Map aliasToInfo) { - final Map result = new TreeMap<>(); - result.putAll(nameToInfo); - result.putAll(aliasToInfo); - return mapper.mapper().valueToTree(result); + private ObjectNode allInfos(Map nameToInfo) { + return mapper.mapper().valueToTree(new TreeMap<>(nameToInfo)); } @Override @@ -107,15 +88,18 @@ public void handle(RoutingContext context) { } } - @Value + @Value(staticConstructor = "of") private static class BidderInfoResponseModel { BidderInfo.MaintainerInfo maintainer; BidderInfo.CapabilitiesInfo capabilities; + @JsonProperty("aliasOf") + String aliasOf; + static BidderInfoResponseModel from(BidderInfo bidderInfo) { - return new BidderInfoResponseModel(bidderInfo.getMaintainer(), bidderInfo.getCapabilities()); + return of(bidderInfo.getMaintainer(), bidderInfo.getCapabilities(), bidderInfo.getAliasOf()); } } } diff --git a/src/main/java/org/prebid/server/handler/info/BiddersHandler.java b/src/main/java/org/prebid/server/handler/info/BiddersHandler.java index 61241d65019..dcbc54886f7 100644 --- a/src/main/java/org/prebid/server/handler/info/BiddersHandler.java +++ b/src/main/java/org/prebid/server/handler/info/BiddersHandler.java @@ -11,7 +11,6 @@ import java.util.Set; import java.util.TreeSet; import java.util.stream.Collectors; -import java.util.stream.Stream; public class BiddersHandler implements Handler { @@ -21,11 +20,8 @@ public BiddersHandler(BidderCatalog bidderCatalog, JacksonMapper mapper) { Objects.requireNonNull(bidderCatalog); Objects.requireNonNull(mapper); - final Set bidderNamesAndAliases = Stream.concat( - bidderCatalog.names().stream() - .filter(bidderCatalog::isActive), - bidderCatalog.aliases().stream() - .filter(alias -> bidderCatalog.isActive(bidderCatalog.nameByAlias(alias)))) + final Set bidderNamesAndAliases = bidderCatalog.names().stream() + .filter(bidderCatalog::isActive) .collect(Collectors.toCollection(TreeSet::new)); body = mapper.encode(bidderNamesAndAliases); diff --git a/src/main/java/org/prebid/server/handler/openrtb2/AmpHandler.java b/src/main/java/org/prebid/server/handler/openrtb2/AmpHandler.java index c19caf6e9de..8b5dc3d7f5e 100644 --- a/src/main/java/org/prebid/server/handler/openrtb2/AmpHandler.java +++ b/src/main/java/org/prebid/server/handler/openrtb2/AmpHandler.java @@ -22,7 +22,7 @@ import org.prebid.server.analytics.AnalyticsReporterDelegator; import org.prebid.server.analytics.model.AmpEvent; import org.prebid.server.analytics.model.HttpContext; -import org.prebid.server.auction.AmpRequestFactory; +import org.prebid.server.auction.requestfactory.AmpRequestFactory; import org.prebid.server.auction.AmpResponsePostProcessor; import org.prebid.server.auction.ExchangeService; import org.prebid.server.auction.model.AuctionContext; diff --git a/src/main/java/org/prebid/server/handler/openrtb2/AuctionHandler.java b/src/main/java/org/prebid/server/handler/openrtb2/AuctionHandler.java index ebcc9fffeb3..4317d7900d0 100644 --- a/src/main/java/org/prebid/server/handler/openrtb2/AuctionHandler.java +++ b/src/main/java/org/prebid/server/handler/openrtb2/AuctionHandler.java @@ -13,7 +13,7 @@ import org.prebid.server.analytics.AnalyticsReporterDelegator; import org.prebid.server.analytics.model.AuctionEvent; import org.prebid.server.analytics.model.HttpContext; -import org.prebid.server.auction.AuctionRequestFactory; +import org.prebid.server.auction.requestfactory.AuctionRequestFactory; import org.prebid.server.auction.ExchangeService; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.Tuple2; diff --git a/src/main/java/org/prebid/server/handler/openrtb2/VideoHandler.java b/src/main/java/org/prebid/server/handler/openrtb2/VideoHandler.java index cd74a24c6b8..04d37a2ff63 100644 --- a/src/main/java/org/prebid/server/handler/openrtb2/VideoHandler.java +++ b/src/main/java/org/prebid/server/handler/openrtb2/VideoHandler.java @@ -11,7 +11,7 @@ import org.prebid.server.analytics.model.HttpContext; import org.prebid.server.analytics.model.VideoEvent; import org.prebid.server.auction.ExchangeService; -import org.prebid.server.auction.VideoRequestFactory; +import org.prebid.server.auction.requestfactory.VideoRequestFactory; import org.prebid.server.auction.VideoResponseFactory; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.Tuple2; diff --git a/src/main/java/org/prebid/server/json/IntegerFlagDeserializer.java b/src/main/java/org/prebid/server/json/IntegerFlagDeserializer.java new file mode 100644 index 00000000000..26cf097f350 --- /dev/null +++ b/src/main/java/org/prebid/server/json/IntegerFlagDeserializer.java @@ -0,0 +1,36 @@ +package org.prebid.server.json; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +import java.io.IOException; + +/** + * Deserialized json boolean FALSE to 0 and TRUE to 1. + */ +public class IntegerFlagDeserializer extends StdDeserializer { + + public IntegerFlagDeserializer() { + super(Integer.class); + } + + @Override + public Integer deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException { + switch (parser.getCurrentToken()) { + case VALUE_NUMBER_INT: + return parser.getValueAsInt(); + case VALUE_FALSE: + return 0; + case VALUE_TRUE: + return 1; + default: + ctxt.reportWrongTokenException(JsonToken.class, JsonToken.VALUE_NUMBER_INT, + String.format("Failed to parse field %s to Integer type with a reason: Expected type boolean" + + " or integer(`0` or `1`).", parser.getCurrentName())); + // the previous method should have thrown + throw new AssertionError(); + } + } +} diff --git a/src/main/java/org/prebid/server/json/ZonedDateTimeModule.java b/src/main/java/org/prebid/server/json/ZonedDateTimeModule.java index bce4d90c26a..6a2b60bd649 100644 --- a/src/main/java/org/prebid/server/json/ZonedDateTimeModule.java +++ b/src/main/java/org/prebid/server/json/ZonedDateTimeModule.java @@ -14,7 +14,6 @@ import java.time.format.DateTimeFormatterBuilder; import java.time.temporal.ChronoField; -@SuppressWarnings("serial") class ZonedDateTimeModule extends SimpleModule { // see https://stackoverflow.com/q/30090710 diff --git a/src/main/java/org/prebid/server/log/ConditionalLogger.java b/src/main/java/org/prebid/server/log/ConditionalLogger.java index 0b1f9d5c4cd..f5c960a4e9d 100644 --- a/src/main/java/org/prebid/server/log/ConditionalLogger.java +++ b/src/main/java/org/prebid/server/log/ConditionalLogger.java @@ -56,6 +56,12 @@ public void info(String message, long duration, TimeUnit unit) { log(message, duration, unit, logger -> logger.info(message)); } + public void info(String message, double samplingRate) { + if (samplingRate >= 1.0d || ThreadLocalRandom.current().nextDouble() < samplingRate) { + logger.warn(message); + } + } + public void errorWithKey(String key, String message, int limit) { log(key, limit, logger -> logger.error(message)); } diff --git a/src/main/java/org/prebid/server/metric/Metrics.java b/src/main/java/org/prebid/server/metric/Metrics.java index 4eefaea1c80..4f667003bc6 100644 --- a/src/main/java/org/prebid/server/metric/Metrics.java +++ b/src/main/java/org/prebid/server/metric/Metrics.java @@ -2,7 +2,6 @@ import com.codahale.metrics.MetricRegistry; import com.iab.openrtb.request.Imp; -import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.metric.model.AccountMetricsVerbosityLevel; import java.util.ArrayList; @@ -22,10 +21,9 @@ */ public class Metrics extends UpdatableMetrics { - private static final String METRICS_UNKNOWN_BIDDER = "UNKNOWN"; + private static final String ALL_REQUEST_BIDDERS = "all"; private final AccountMetricsVerbosity accountMetricsVerbosity; - private final BidderCatalog bidderCatalog; private final Function requestMetricsCreator; private final Function accountMetricsCreator; @@ -49,12 +47,11 @@ public class Metrics extends UpdatableMetrics { private final CurrencyRatesMetrics currencyRatesMetrics; private final Map settingsCacheMetrics; - public Metrics(MetricRegistry metricRegistry, CounterType counterType, AccountMetricsVerbosity - accountMetricsVerbosity, BidderCatalog bidderCatalog) { + public Metrics(MetricRegistry metricRegistry, CounterType counterType, + AccountMetricsVerbosity accountMetricsVerbosity) { super(metricRegistry, counterType, MetricName::toString); this.accountMetricsVerbosity = Objects.requireNonNull(accountMetricsVerbosity); - this.bidderCatalog = Objects.requireNonNull(bidderCatalog); requestMetricsCreator = requestType -> new RequestStatusMetrics(metricRegistry, counterType, requestType); accountMetricsCreator = account -> new AccountMetrics(metricRegistry, counterType, account); @@ -130,7 +127,17 @@ public void updateAppAndNoCookieAndImpsRequestedMetrics(boolean isApp, boolean l incCounter(MetricName.imps_requested, numImps); } - public void updateImpTypesMetrics(Map countPerMediaType) { + public void updateImpTypesMetrics(List imps) { + + final Map mediaTypeToCount = imps.stream() + .map(Metrics::getPresentMediaTypes) + .flatMap(Collection::stream) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + + updateImpTypesMetrics(mediaTypeToCount); + } + + void updateImpTypesMetrics(Map countPerMediaType) { for (Map.Entry mediaTypeCount : countPerMediaType.entrySet()) { switch (mediaTypeCount.getKey()) { case "banner": @@ -152,16 +159,6 @@ public void updateImpTypesMetrics(Map countPerMediaType) { } } - public void updateImpTypesMetrics(List imps) { - - final Map mediaTypeToCount = imps.stream() - .map(Metrics::getPresentMediaTypes) - .flatMap(Collection::stream) - .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - - updateImpTypesMetrics(mediaTypeToCount); - } - private static List getPresentMediaTypes(Imp imp) { final List impMediaTypes = new ArrayList<>(); @@ -211,7 +208,7 @@ public void updateAccountRequestRejectedMetrics(String accountId) { } public void updateAdapterRequestTypeAndNoCookieMetrics(String bidder, MetricName requestType, boolean noCookie) { - final AdapterTypeMetrics adapterTypeMetrics = forAdapter(resolveMetricsBidderName(bidder)); + final AdapterTypeMetrics adapterTypeMetrics = forAdapter(bidder); adapterTypeMetrics.requestType(requestType).incCounter(MetricName.requests); @@ -221,36 +218,32 @@ public void updateAdapterRequestTypeAndNoCookieMetrics(String bidder, MetricName } public void updateAdapterResponseTime(String bidder, String accountId, int responseTime) { - final String metricsBidderName = resolveMetricsBidderName(bidder); - final AdapterTypeMetrics adapterTypeMetrics = forAdapter(metricsBidderName); + final AdapterTypeMetrics adapterTypeMetrics = forAdapter(bidder); adapterTypeMetrics.updateTimer(MetricName.request_time, responseTime); if (accountMetricsVerbosity.forAccount(accountId).isAtLeast(AccountMetricsVerbosityLevel.detailed)) { final AdapterTypeMetrics accountAdapterMetrics = - forAccount(accountId).adapter().forAdapter(metricsBidderName); + forAccount(accountId).adapter().forAdapter(bidder); accountAdapterMetrics.updateTimer(MetricName.request_time, responseTime); } } public void updateAdapterRequestNobidMetrics(String bidder, String accountId) { - final String metricsBidderName = resolveMetricsBidderName(bidder); - forAdapter(metricsBidderName).request().incCounter(MetricName.nobid); + forAdapter(bidder).request().incCounter(MetricName.nobid); if (accountMetricsVerbosity.forAccount(accountId).isAtLeast(AccountMetricsVerbosityLevel.detailed)) { - forAccount(accountId).adapter().forAdapter(metricsBidderName).request().incCounter(MetricName.nobid); + forAccount(accountId).adapter().forAdapter(bidder).request().incCounter(MetricName.nobid); } } public void updateAdapterRequestGotbidsMetrics(String bidder, String accountId) { - final String metricsBidderName = resolveMetricsBidderName(bidder); - forAdapter(metricsBidderName).request().incCounter(MetricName.gotbids); + forAdapter(bidder).request().incCounter(MetricName.gotbids); if (accountMetricsVerbosity.forAccount(accountId).isAtLeast(AccountMetricsVerbosityLevel.detailed)) { - forAccount(accountId).adapter().forAdapter(metricsBidderName).request().incCounter(MetricName.gotbids); + forAccount(accountId).adapter().forAdapter(bidder).request().incCounter(MetricName.gotbids); } } public void updateAdapterBidMetrics(String bidder, String accountId, long cpm, boolean isAdm, String bidType) { - final String metricsBidderName = resolveMetricsBidderName(bidder); - final AdapterTypeMetrics adapterTypeMetrics = forAdapter(metricsBidderName); + final AdapterTypeMetrics adapterTypeMetrics = forAdapter(bidder); adapterTypeMetrics.updateHistogram(MetricName.prices, cpm); adapterTypeMetrics.incCounter(MetricName.bids_received); adapterTypeMetrics.forBidType(bidType) @@ -258,23 +251,23 @@ public void updateAdapterBidMetrics(String bidder, String accountId, long cpm, b if (accountMetricsVerbosity.forAccount(accountId).isAtLeast(AccountMetricsVerbosityLevel.detailed)) { final AdapterTypeMetrics accountAdapterMetrics = - forAccount(accountId).adapter().forAdapter(metricsBidderName); + forAccount(accountId).adapter().forAdapter(bidder); accountAdapterMetrics.updateHistogram(MetricName.prices, cpm); accountAdapterMetrics.incCounter(MetricName.bids_received); } } public void updateAdapterRequestErrorMetric(String bidder, MetricName errorMetric) { - forAdapter(resolveMetricsBidderName(bidder)).request().incCounter(errorMetric); + forAdapter(bidder).request().incCounter(errorMetric); } public void updateSizeValidationMetrics(String bidder, String accountId, MetricName type) { - forAdapter(resolveMetricsBidderName(bidder)).response().validation().size().incCounter(type); + forAdapter(bidder).response().validation().size().incCounter(type); forAccount(accountId).response().validation().size().incCounter(type); } public void updateSecureValidationMetrics(String bidder, String accountId, MetricName type) { - forAdapter(resolveMetricsBidderName(bidder)).response().validation().secure().incCounter(type); + forAdapter(bidder).response().validation().secure().incCounter(type); forAccount(accountId).response().validation().secure().incCounter(type); } @@ -294,6 +287,14 @@ public void updateUserSyncTcfBlockedMetric(String bidder) { userSync().forBidder(bidder).tcf().incCounter(MetricName.blocked); } + public void updateUserSyncTcfInvalidMetric(String bidder) { + userSync().forBidder(bidder).tcf().incCounter(MetricName.invalid); + } + + public void updateUserSyncTcfInvalidMetric() { + updateUserSyncTcfInvalidMetric(ALL_REQUEST_BIDDERS); + } + public void updateCookieSyncRequestMetric() { incCounter(MetricName.cookie_sync_requests); } @@ -307,7 +308,7 @@ public void updateCookieSyncMatchesMetric(String bidder) { } public void updateCookieSyncTcfBlockedMetric(String bidder) { - cookieSync().forBidder(resolveMetricsBidderName(bidder)).tcf().incCounter(MetricName.blocked); + cookieSync().forBidder(bidder).tcf().incCounter(MetricName.blocked); } public void updateAuctionTcfMetrics(String bidder, @@ -317,7 +318,7 @@ public void updateAuctionTcfMetrics(String bidder, boolean analyticsBlocked, boolean requestBlocked) { - final TcfMetrics tcf = forAdapter(resolveMetricsBidderName(bidder)).requestType(requestType).tcf(); + final TcfMetrics tcf = forAdapter(bidder).requestType(requestType).tcf(); if (userIdRemoved) { tcf.incCounter(MetricName.userid_removed); @@ -490,8 +491,4 @@ public void updateSettingsCacheRefreshErrorMetric(MetricName cacheType, MetricNa public void updateSettingsCacheEventMetric(MetricName cacheType, MetricName event) { forSettingsCacheType(cacheType).incCounter(event); } - - private String resolveMetricsBidderName(String bidder) { - return bidderCatalog.isValidName(bidder) ? bidder : METRICS_UNKNOWN_BIDDER; - } } diff --git a/src/main/java/org/prebid/server/privacy/gdpr/GdprService.java b/src/main/java/org/prebid/server/privacy/gdpr/GdprService.java index 247400dcb18..e75e2d6bf6a 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/GdprService.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/GdprService.java @@ -11,7 +11,7 @@ import org.prebid.server.privacy.gdpr.model.PrivacyEnforcementAction; import org.prebid.server.privacy.gdpr.model.VendorPermission; import org.prebid.server.privacy.gdpr.vendorlist.VendorListService; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorListV1; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV1; @@ -120,7 +120,7 @@ private static VendorPermission toVendorPermission(Integer vendorId, final VendorV1 vendorListEntry = vendorListMapping.get(vendorId); // confirm purposes - final EnumSet claimedPurposes = vendorListEntry.combinedPurposes(); + final EnumSet claimedPurposes = vendorListEntry.combinedPurposes(); final boolean claimedPurposesAllowed = isClaimedPurposesAllowed(claimedPurposes, allowedPurposeIds); final boolean purposeOneClaimedAndAllowed = isPurposeOneClaimedAndAllowed(claimedPurposes, allowedPurposeIds); @@ -144,14 +144,15 @@ private static boolean isVendorAllowed(VendorConsent vendorConsent, Integer vend } } - private static boolean isClaimedPurposesAllowed(EnumSet claimedPurposes, Set allowedPurposeIds) { - return claimedPurposes.stream().allMatch(o -> allowedPurposeIds.contains(o.code())); + private static boolean isClaimedPurposesAllowed(EnumSet claimedPurposeCodes, + Set allowedPurposeIds) { + return claimedPurposeCodes.stream().allMatch(o -> allowedPurposeIds.contains(o.code())); } private static boolean isPurposeOneClaimedAndAllowed( - EnumSet claimedPurposes, Set allowedPurposeIds) { + EnumSet claimedPurposeCodes, Set allowedPurposeIds) { - return claimedPurposes.contains(Purpose.ONE) && allowedPurposeIds.contains(Purpose.ONE.code()); + return claimedPurposeCodes.contains(PurposeCode.ONE) && allowedPurposeIds.contains(PurposeCode.ONE.code()); } private static PrivacyEnforcementAction allDenied() { diff --git a/src/main/java/org/prebid/server/privacy/gdpr/Tcf2Service.java b/src/main/java/org/prebid/server/privacy/gdpr/Tcf2Service.java index 40a159f677a..0a883b7d8c5 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/Tcf2Service.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/Tcf2Service.java @@ -2,6 +2,8 @@ import com.iabtcf.decoder.TCString; import io.vertx.core.Future; +import lombok.Value; +import org.apache.commons.collections4.CollectionUtils; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.privacy.gdpr.model.PrivacyEnforcementAction; import org.prebid.server.privacy.gdpr.model.VendorPermission; @@ -9,6 +11,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.PurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.specialfeature.SpecialFeaturesStrategy; import org.prebid.server.privacy.gdpr.vendorlist.VendorListServiceV2; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV2; import org.prebid.server.settings.model.AccountGdprConfig; import org.prebid.server.settings.model.EnforcePurpose; @@ -20,11 +23,13 @@ import org.prebid.server.settings.model.SpecialFeatures; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; public class Tcf2Service { @@ -92,25 +97,59 @@ private Future> permissionsForInternal(Collection vendorPermissionsByType = toVendorPermissionsByType( + vendorPermissions, accountGdprConfig); + return vendorListServiceV2.forVersion(tcfConsent.getVendorListVersion()) - .map(vendorGvlPermissions -> wrapWithGVL(vendorPermissions, vendorGvlPermissions)) + .map(vendorGvlPermissions -> wrapWithGVL(vendorPermissionsByType, vendorGvlPermissions)) .compose(gvlResult -> processSupportedPurposeStrategies(tcfConsent, gvlResult, mergedPurposes, purposeOneTreatmentInterpretation), - ignoredFailed -> processDowngradedSupportedPurposeStrategies(tcfConsent, vendorPermissions, - mergedPurposes, mergedPurposeOneTreatmentInterpretation)) + ignoredFailed -> processDowngradedSupportedPurposeStrategies(tcfConsent, + vendorPermissionsByType, mergedPurposes, mergedPurposeOneTreatmentInterpretation)) .map(changedVendorPermissions -> processSupportedSpecialFeatureStrategies(tcfConsent, changedVendorPermissions, mergedSpecialFeatures)); + } + + private static VendorPermissionsByType toVendorPermissionsByType( + Collection vendorPermissions, + AccountGdprConfig accountGdprConfig) { + + final List basicEnforcedVendors = accountGdprConfig != null + ? accountGdprConfig.getBasicEnforcementVendors() + : null; + if (CollectionUtils.isEmpty(basicEnforcedVendors)) { + return VendorPermissionsByType.of(Collections.emptyList(), vendorPermissions); + } + + final Map> isBasicEnforcedToPermissions = vendorPermissions.stream() + .collect(Collectors.partitioningBy(vendorPermission -> + basicEnforcedVendors.contains(vendorPermission.getBidderName()))); + + final List weakPermissions = isBasicEnforcedToPermissions.getOrDefault(true, + Collections.emptyList()); + final List standardPermissions = isBasicEnforcedToPermissions.getOrDefault(false, + Collections.emptyList()); + + return VendorPermissionsByType.of(weakPermissions, standardPermissions); } - private static Collection wrapWithGVL(Collection vendorPermissions, - Map vendorGvlPermissions) { + private static VendorPermissionsByType wrapWithGVL( + VendorPermissionsByType vendorPermissionsByType, + Map vendorGvlPermissions) { - return vendorPermissions.stream() + final List weakPermissions = vendorPermissionsByType.getWeakPermissions().stream() .map(vendorPermission -> wrapWithGVL(vendorPermission, vendorGvlPermissions)) .collect(Collectors.toList()); + + final List standardPermissions = vendorPermissionsByType.getStandardPermissions() + .stream() + .map(vendorPermission -> wrapWithGVL(vendorPermission, vendorGvlPermissions)) + .collect(Collectors.toList()); + + return VendorPermissionsByType.of(weakPermissions, standardPermissions); } private static VendorPermissionWithGvl wrapWithGVL(VendorPermission vendorPermission, @@ -126,38 +165,57 @@ private static VendorPermissionWithGvl wrapWithGVL(VendorPermission vendorPermis private Future> processSupportedPurposeStrategies( TCString tcfConsent, - Collection vendorPermissionsWithGvl, + VendorPermissionsByType vendorPermissionsByType, Purposes purposes, PurposeOneTreatmentInterpretation purposeOneTreatmentInterpretation) { for (PurposeStrategy purposeStrategy : purposeStrategies) { - final org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose tcfPurpose = purposeStrategy.getPurpose(); + final PurposeCode tcfPurpose = purposeStrategy.getPurpose(); final Purpose purposeById = findPurposeByTcfPurpose(tcfPurpose, purposes); - processPurposeStrategy(tcfConsent, vendorPermissionsWithGvl, purposeById, purposeStrategy, + final Purpose weakPurpose = weakPurpose(purposeById); + + final Collection standardPermissions = vendorPermissionsByType + .getStandardPermissions(); + final Collection weakPermissions = vendorPermissionsByType.getWeakPermissions(); + + processPurposeStrategy(tcfConsent, standardPermissions, purposeById, purposeStrategy, purposeOneTreatmentInterpretation, false); + processPurposeStrategy(tcfConsent, weakPermissions, weakPurpose, purposeStrategy, + purposeOneTreatmentInterpretation, true); } - return Future.succeededFuture(vendorPermissionsWithGvl.stream() + return Future.succeededFuture(vendorPermissionsByType.joinPermissions().stream() .map(VendorPermissionWithGvl::getVendorPermission) .collect(Collectors.toList())); } private Future> processDowngradedSupportedPurposeStrategies( TCString tcfConsent, - Collection vendorPermissions, + VendorPermissionsByType vendorPermissionsByType, Purposes purposes, PurposeOneTreatmentInterpretation purposeOneTreatmentInterpretation) { - final List vendorPermissionsWithGvl = wrapWithEmptyGVL(vendorPermissions); + final VendorPermissionsByType vendorPermissionsWithGvlByType = wrapWithGVL( + vendorPermissionsByType, Collections.emptyMap()); for (PurposeStrategy purposeStrategy : purposeStrategies) { - final org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose tcfPurpose = purposeStrategy.getPurpose(); - final Purpose downgradedPurpose = downgradePurpose(findPurposeByTcfPurpose(tcfPurpose, purposes)); - processPurposeStrategy(tcfConsent, vendorPermissionsWithGvl, downgradedPurpose, purposeStrategy, + final PurposeCode tcfPurpose = purposeStrategy.getPurpose(); + final Purpose downgradedPurposeById = downgradePurpose(findPurposeByTcfPurpose(tcfPurpose, purposes)); + final Purpose weakPurpose = weakPurpose(downgradedPurposeById); + + final Collection standardPermissions = vendorPermissionsWithGvlByType + .getStandardPermissions(); + final Collection weakPermissions = vendorPermissionsWithGvlByType + .getWeakPermissions(); + + processPurposeStrategy(tcfConsent, standardPermissions, downgradedPurposeById, purposeStrategy, + purposeOneTreatmentInterpretation, true); + processPurposeStrategy(tcfConsent, weakPermissions, weakPurpose, purposeStrategy, purposeOneTreatmentInterpretation, true); + } - return Future.succeededFuture(vendorPermissions); + return Future.succeededFuture(vendorPermissionsByType.joinPermissions()); } private void processPurposeStrategy(TCString tcfConsent, @@ -167,7 +225,7 @@ private void processPurposeStrategy(TCString tcfConsent, PurposeOneTreatmentInterpretation purposeOneTreatmentInterpretation, boolean wasDowngraded) { - if (purposeStrategy.getPurpose() == org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.ONE + if (purposeStrategy.getPurpose() == PurposeCode.ONE && tcfConsent.getPurposeOneTreatment()) { processPurposeOneTreatment( @@ -204,13 +262,6 @@ private void processPurposeOneTreatment(PurposeOneTreatmentInterpretation purpos } } - private static List wrapWithEmptyGVL(Collection vendorPermissions) { - return vendorPermissions.stream() - .map(vendorPermission -> VendorPermissionWithGvl.of(vendorPermission, - VendorV2.empty(vendorPermission.getVendorId()))) - .collect(Collectors.toList()); - } - private static Purpose downgradePurpose(Purpose purpose) { final EnforcePurpose enforcePurpose = purpose.getEnforcePurpose(); @@ -219,6 +270,16 @@ private static Purpose downgradePurpose(Purpose purpose) { : purpose; } + private static Purpose weakPurpose(Purpose purpose) { + final EnforcePurpose enforcePurpose = purpose.getEnforcePurpose(); + final EnforcePurpose downgradedEnforce = + enforcePurpose == null || Objects.equals(enforcePurpose, EnforcePurpose.full) + ? EnforcePurpose.basic + : enforcePurpose; + + return Purpose.of(downgradedEnforce, false, purpose.getVendorExceptions()); + } + private Collection processSupportedSpecialFeatureStrategies( TCString tcfConsent, Collection vendorPermissions, @@ -265,10 +326,7 @@ private SpecialFeatures mergeAccountSpecialFeatures(AccountGdprConfig accountGdp .build(); } - private Purpose findPurposeByTcfPurpose( - org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose tcfPurpose, - Purposes purposes) { - + private Purpose findPurposeByTcfPurpose(PurposeCode tcfPurpose, Purposes purposes) { switch (tcfPurpose) { case ONE: return purposes.getP1(); @@ -320,4 +378,17 @@ private PurposeOneTreatmentInterpretation mergePurposeOneTreatmentInterpretation private static T mergeItem(T prioritisedItem, T item) { return prioritisedItem == null ? item : prioritisedItem; } + + @Value(staticConstructor = "of") + private static class VendorPermissionsByType { + + Collection weakPermissions; + + Collection standardPermissions; + + public Collection joinPermissions() { + return Stream.concat(weakPermissions.stream(), standardPermissions.stream()) + .collect(Collectors.toList()); + } + } } diff --git a/src/main/java/org/prebid/server/privacy/gdpr/TcfDefinerService.java b/src/main/java/org/prebid/server/privacy/gdpr/TcfDefinerService.java index 81c2ec3b2f0..56c78ebc2c2 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/TcfDefinerService.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/TcfDefinerService.java @@ -8,6 +8,7 @@ import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.prebid.server.auction.IpAddressHelper; +import org.prebid.server.auction.model.IpAddress; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.execution.Timeout; import org.prebid.server.geolocation.GeoLocationService; @@ -83,6 +84,9 @@ public TcfDefinerService(GdprConfig gdprConfig, this.metrics = Objects.requireNonNull(metrics); } + /** + * Used for auctions. + */ public Future resolveTcfContext(Privacy privacy, String country, String ipAddress, @@ -99,6 +103,9 @@ public Future resolveTcfContext(Privacy privacy, .map(this::updateTcfGeoMetrics); } + /** + * Used for cookie sync and setuid. + */ public Future resolveTcfContext(Privacy privacy, String ipAddress, AccountGdprConfig accountGdprConfig, @@ -183,12 +190,14 @@ private Future toTcfContext(Privacy privacy, final String consentString = privacy.getConsentString(); final TCString consent = parseConsentString(consentString, requestLogInfo); final String effectiveIpAddress = maybeMaskIp(ipAddress, consent); + final boolean consentIsValid = isConsentValid(consent); - if (consentStringMeansInScope && isConsentValid(consent)) { + if (consentStringMeansInScope && consentIsValid) { return Future.succeededFuture(TcfContext.builder() .gdpr(GDPR_ONE) .consentString(consentString) .consent(consent) + .isConsentValid(true) .ipAddress(effectiveIpAddress) .build()); } @@ -199,6 +208,7 @@ private Future toTcfContext(Privacy privacy, .gdpr(gdpr) .consentString(consentString) .consent(consent) + .isConsentValid(consentIsValid) .ipAddress(effectiveIpAddress) .build()); } @@ -211,6 +221,7 @@ private Future toTcfContext(Privacy privacy, .gdpr(gdprFromGeo(inEea)) .consentString(consentString) .consent(consent) + .isConsentValid(consentIsValid) .inEea(inEea) .ipAddress(effectiveIpAddress) .build()); @@ -230,7 +241,18 @@ private Future toTcfContext(Privacy privacy, } private String maybeMaskIp(String ipAddress, TCString consent) { - return shouldMaskIp(consent) ? ipAddressHelper.maskIpv4(ipAddress) : ipAddress; + if (!shouldMaskIp(consent)) { + return ipAddress; + } + + final IpAddress ip = ipAddressHelper.toIpAddress(ipAddress); + if (ip == null) { + return ipAddress; + } + + return ip.getVersion() == IpAddress.IP.v4 + ? ipAddressHelper.maskIpv4(ipAddress) + : ipAddressHelper.anonymizeIpv6(ipAddress); } private static boolean shouldMaskIp(TCString consent) { @@ -246,6 +268,7 @@ private TcfContext tcfContextFromGeo(GeoInfo geoInfo, String consentString, TCSt .gdpr(gdprFromGeo(inEea)) .consentString(consentString) .consent(consent) + .isConsentValid(isConsentValid(consent)) .geoInfo(geoInfo) .inEea(inEea) .ipAddress(ipAddress) @@ -279,6 +302,7 @@ private TcfContext defaultTcfContext(String consentString, TCString consent, Str .gdpr(gdprDefaultValue) .consentString(consentString) .consent(consent) + .isConsentValid(isConsentValid(consent)) .ipAddress(ipAddress) .build(); } diff --git a/src/main/java/org/prebid/server/privacy/gdpr/VendorIdResolver.java b/src/main/java/org/prebid/server/privacy/gdpr/VendorIdResolver.java index e9ebe258752..3076d653030 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/VendorIdResolver.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/VendorIdResolver.java @@ -6,20 +6,30 @@ public class VendorIdResolver { private final BidderAliases aliases; + private final BidderCatalog bidderCatalog; - private VendorIdResolver(BidderAliases aliases) { + private VendorIdResolver(BidderAliases aliases, BidderCatalog bidderCatalog) { this.aliases = aliases; + this.bidderCatalog = bidderCatalog; } - public static VendorIdResolver of(BidderAliases aliases) { - return new VendorIdResolver(aliases); + public static VendorIdResolver of(BidderAliases aliases, BidderCatalog bidderCatalog) { + return new VendorIdResolver(aliases, bidderCatalog); } public static VendorIdResolver of(BidderCatalog bidderCatalog) { - return of(BidderAliases.of(bidderCatalog)); + return of(null, bidderCatalog); } public Integer resolve(String aliasOrBidder) { - return aliases.resolveAliasVendorId(aliasOrBidder); + final Integer requestAliasVendorId = aliases != null ? aliases.resolveAliasVendorId(aliasOrBidder) : null; + + return requestAliasVendorId != null ? requestAliasVendorId : resolveViaCatalog(aliasOrBidder); + } + + private Integer resolveViaCatalog(String aliasOrBidder) { + final String bidderName = aliases != null ? aliases.resolveBidder(aliasOrBidder) : aliasOrBidder; + + return bidderCatalog.isActive(bidderName) ? bidderCatalog.vendorIdByName(bidderName) : null; } } diff --git a/src/main/java/org/prebid/server/privacy/gdpr/model/TcfContext.java b/src/main/java/org/prebid/server/privacy/gdpr/model/TcfContext.java index bd4a8ec6618..8b58ddde302 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/model/TcfContext.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/model/TcfContext.java @@ -18,6 +18,8 @@ public class TcfContext { TCString consent; + Boolean isConsentValid; + GeoInfo geoInfo; Boolean inEea; diff --git a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeEightStrategy.java b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeEightStrategy.java index ba5aa99f1a1..416acfe78c8 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeEightStrategy.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeEightStrategy.java @@ -4,7 +4,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; public class PurposeEightStrategy extends PurposeStrategy { @@ -26,8 +26,8 @@ public void allowNaturally(PrivacyEnforcementAction privacyEnforcementAction) { } @Override - public Purpose getPurpose() { - return Purpose.EIGHT; + public PurposeCode getPurpose() { + return PurposeCode.EIGHT; } } diff --git a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeFiveStrategy.java b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeFiveStrategy.java index a904a423093..89266044c1b 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeFiveStrategy.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeFiveStrategy.java @@ -4,7 +4,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; public class PurposeFiveStrategy extends PurposeStrategy { @@ -26,8 +26,8 @@ public void allowNaturally(PrivacyEnforcementAction privacyEnforcementAction) { } @Override - public Purpose getPurpose() { - return Purpose.FIVE; + public PurposeCode getPurpose() { + return PurposeCode.FIVE; } } diff --git a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeFourStrategy.java b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeFourStrategy.java index 956d8c3bd99..6f5c5036f40 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeFourStrategy.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeFourStrategy.java @@ -4,7 +4,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; public class PurposeFourStrategy extends PurposeStrategy { @@ -26,8 +26,8 @@ public void allowNaturally(PrivacyEnforcementAction privacyEnforcementAction) { } @Override - public Purpose getPurpose() { - return Purpose.FOUR; + public PurposeCode getPurpose() { + return PurposeCode.FOUR; } } diff --git a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeNineStrategy.java b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeNineStrategy.java index 2672795895c..fc8922112b5 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeNineStrategy.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeNineStrategy.java @@ -4,7 +4,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; public class PurposeNineStrategy extends PurposeStrategy { @@ -26,8 +26,8 @@ public void allowNaturally(PrivacyEnforcementAction privacyEnforcementAction) { } @Override - public Purpose getPurpose() { - return Purpose.NINE; + public PurposeCode getPurpose() { + return PurposeCode.NINE; } } diff --git a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeOneStrategy.java b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeOneStrategy.java index 76f370b7ff5..a4eb920e776 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeOneStrategy.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeOneStrategy.java @@ -4,7 +4,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; public class PurposeOneStrategy extends PurposeStrategy { @@ -25,8 +25,8 @@ public void allowNaturally(PrivacyEnforcementAction privacyEnforcementAction) { } @Override - public Purpose getPurpose() { - return Purpose.ONE; + public PurposeCode getPurpose() { + return PurposeCode.ONE; } } diff --git a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeSevenStrategy.java b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeSevenStrategy.java index 04972eec93c..c28c63f6311 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeSevenStrategy.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeSevenStrategy.java @@ -4,7 +4,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; public class PurposeSevenStrategy extends PurposeStrategy { @@ -27,8 +27,8 @@ public void allowNaturally(PrivacyEnforcementAction privacyEnforcementAction) { } @Override - public Purpose getPurpose() { - return Purpose.SEVEN; + public PurposeCode getPurpose() { + return PurposeCode.SEVEN; } } diff --git a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeSixStrategy.java b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeSixStrategy.java index 1bd2e65d01b..de332a75dd3 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeSixStrategy.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeSixStrategy.java @@ -4,7 +4,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; public class PurposeSixStrategy extends PurposeStrategy { @@ -26,8 +26,8 @@ public void allowNaturally(PrivacyEnforcementAction privacyEnforcementAction) { } @Override - public Purpose getPurpose() { - return Purpose.SIX; + public PurposeCode getPurpose() { + return PurposeCode.SIX; } } diff --git a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeStrategy.java b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeStrategy.java index 17d0c890b9f..4b7b111a1bc 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeStrategy.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeStrategy.java @@ -9,6 +9,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.settings.model.EnforcePurpose; import org.prebid.server.settings.model.Purpose; @@ -33,7 +34,7 @@ public PurposeStrategy(FullEnforcePurposeStrategy fullEnforcePurposeStrategy, this.noEnforcePurposeStrategy = noEnforcePurposeStrategy; } - public abstract org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose getPurpose(); + public abstract PurposeCode getPurpose(); /** * This method is allow permission for purpose when account and server config was used. diff --git a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeTenStrategy.java b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeTenStrategy.java index 2f927093982..834f5de800b 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeTenStrategy.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeTenStrategy.java @@ -4,7 +4,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; public class PurposeTenStrategy extends PurposeStrategy { @@ -26,8 +26,8 @@ public void allowNaturally(PrivacyEnforcementAction privacyEnforcementAction) { } @Override - public Purpose getPurpose() { - return Purpose.TEN; + public PurposeCode getPurpose() { + return PurposeCode.TEN; } } diff --git a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeThreeStrategy.java b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeThreeStrategy.java index c86850f248d..324b3e4cf92 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeThreeStrategy.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeThreeStrategy.java @@ -4,7 +4,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; public class PurposeThreeStrategy extends PurposeStrategy { @@ -26,8 +26,8 @@ public void allowNaturally(PrivacyEnforcementAction privacyEnforcementAction) { } @Override - public Purpose getPurpose() { - return Purpose.THREE; + public PurposeCode getPurpose() { + return PurposeCode.THREE; } } diff --git a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeTwoStrategy.java b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeTwoStrategy.java index 8220328c659..0268713310e 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeTwoStrategy.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeTwoStrategy.java @@ -4,7 +4,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; public class PurposeTwoStrategy extends PurposeStrategy { @@ -27,8 +27,8 @@ public void allowNaturally(PrivacyEnforcementAction privacyEnforcementAction) { } @Override - public Purpose getPurpose() { - return Purpose.TWO; + public PurposeCode getPurpose() { + return PurposeCode.TWO; } } diff --git a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/BasicEnforcePurposeStrategy.java b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/BasicEnforcePurposeStrategy.java index fdab207ffa4..4f07e5fe737 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/BasicEnforcePurposeStrategy.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/BasicEnforcePurposeStrategy.java @@ -6,7 +6,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.prebid.server.privacy.gdpr.model.VendorPermission; import org.prebid.server.privacy.gdpr.model.VendorPermissionWithGvl; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import java.util.Collection; import java.util.List; @@ -16,7 +16,7 @@ public class BasicEnforcePurposeStrategy extends EnforcePurposeStrategy { private static final Logger logger = LoggerFactory.getLogger(BasicEnforcePurposeStrategy.class); - public Collection allowedByTypeStrategy(Purpose purpose, + public Collection allowedByTypeStrategy(PurposeCode purpose, TCString vendorConsent, Collection vendorsForPurpose, Collection excludedVendors, diff --git a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/EnforcePurposeStrategy.java b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/EnforcePurposeStrategy.java index 37c9e481a7e..a23088432e6 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/EnforcePurposeStrategy.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/EnforcePurposeStrategy.java @@ -4,7 +4,7 @@ import com.iabtcf.utils.IntIterable; import org.prebid.server.privacy.gdpr.model.VendorPermission; import org.prebid.server.privacy.gdpr.model.VendorPermissionWithGvl; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import java.util.Collection; import java.util.stream.Collectors; @@ -12,13 +12,13 @@ public abstract class EnforcePurposeStrategy { public abstract Collection allowedByTypeStrategy( - Purpose purpose, + PurposeCode purpose, TCString vendorConsent, Collection vendorsForPurpose, Collection excludedVendors, boolean isEnforceVendors); - protected boolean isAllowedBySimpleConsentOrLegitimateInterest(Purpose purpose, + protected boolean isAllowedBySimpleConsentOrLegitimateInterest(PurposeCode purpose, Integer vendorId, boolean isEnforceVendor, TCString tcString) { @@ -28,7 +28,7 @@ protected boolean isAllowedBySimpleConsentOrLegitimateInterest(Purpose purpose, } - protected boolean isAllowedBySimpleConsent(Purpose purpose, + protected boolean isAllowedBySimpleConsent(PurposeCode purpose, Integer vendorId, boolean isEnforceVendor, TCString tcString) { @@ -39,7 +39,7 @@ protected boolean isAllowedBySimpleConsent(Purpose purpose, return isAllowedByConsents(purpose, vendorId, isEnforceVendor, purposesConsent, vendorConsent); } - protected boolean isAllowedByLegitimateInterest(Purpose purpose, + protected boolean isAllowedByLegitimateInterest(PurposeCode purpose, Integer vendorId, boolean isEnforceVendor, TCString tcString) { @@ -50,7 +50,7 @@ protected boolean isAllowedByLegitimateInterest(Purpose purpose, return isAllowedByConsents(purpose, vendorId, isEnforceVendor, purposesConsent, vendorConsent); } - private boolean isAllowedByConsents(Purpose purpose, + private boolean isAllowedByConsents(PurposeCode purpose, Integer vendorId, boolean isEnforceVendors, IntIterable purposesConsent, diff --git a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/FullEnforcePurposeStrategy.java b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/FullEnforcePurposeStrategy.java index 378e3c70895..0e5aae4e0b4 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/FullEnforcePurposeStrategy.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/FullEnforcePurposeStrategy.java @@ -6,7 +6,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.prebid.server.privacy.gdpr.model.VendorPermission; import org.prebid.server.privacy.gdpr.model.VendorPermissionWithGvl; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV2; import java.util.Collection; @@ -19,7 +19,7 @@ public class FullEnforcePurposeStrategy extends EnforcePurposeStrategy { - public Collection allowedByTypeStrategy(Purpose purpose, + public Collection allowedByTypeStrategy(PurposeCode purpose, TCString vendorConsent, Collection vendorsForPurpose, Collection excludedVendors, @@ -106,7 +106,7 @@ private RestrictionType restrictionType(VendorPermissionWithGvl vendorPermission * or purposesLITransparency and vendorLegitimateInterest *

*/ - private boolean isAllowedByPublisherRestrictionAndFlexible(Purpose purpose, + private boolean isAllowedByPublisherRestrictionAndFlexible(PurposeCode purpose, boolean isEnforceVendor, VendorPermissionWithGvl vendorPermissionWithGvl, TCString tcString, @@ -119,18 +119,18 @@ private boolean isAllowedByPublisherRestrictionAndFlexible(Purpose purpose, final Integer vendorId = vendorPermissionWithGvl.getVendorPermission().getVendorId(); final VendorV2 vendorGvl = vendorPermissionWithGvl.getVendorV2(); - final EnumSet flexiblePurposes = vendorGvl.getFlexiblePurposes(); + final EnumSet flexiblePurposes = vendorGvl.getFlexiblePurposes(); final boolean isFlexible = CollectionUtils.isNotEmpty(flexiblePurposes) && flexiblePurposes.contains(purpose); - final EnumSet gvlPurposes = vendorGvl.getPurposes(); - if (gvlPurposes != null && gvlPurposes.contains(purpose)) { + final EnumSet gvlPurposeCodes = vendorGvl.getPurposes(); + if (gvlPurposeCodes != null && gvlPurposeCodes.contains(purpose)) { return isFlexible ? isAllowedByFlexible(purpose, vendorId, isEnforceVendor, tcString, restrictionType) : isAllowedByNotFlexiblePurpose(purpose, vendorId, isEnforceVendor, tcString, restrictionType); } - final EnumSet legIntGvlPurposes = vendorGvl.getLegIntPurposes(); - if (legIntGvlPurposes != null && legIntGvlPurposes.contains(purpose)) { + final EnumSet legIntGvlPurposeCodes = vendorGvl.getLegIntPurposes(); + if (legIntGvlPurposeCodes != null && legIntGvlPurposeCodes.contains(purpose)) { return isFlexible ? isAllowedByFlexible(purpose, vendorId, isEnforceVendor, tcString, restrictionType) : isAllowedByNotFlexibleLegitimateInterest(purpose, vendorId, isEnforceVendor, tcString, @@ -140,7 +140,7 @@ private boolean isAllowedByPublisherRestrictionAndFlexible(Purpose purpose, return false; } - private boolean isAllowedByNotFlexiblePurpose(Purpose purpose, + private boolean isAllowedByNotFlexiblePurpose(PurposeCode purpose, Integer vendorId, boolean isEnforceVendor, TCString tcString, @@ -151,7 +151,7 @@ private boolean isAllowedByNotFlexiblePurpose(Purpose purpose, return isSupportedRestriction && isAllowedBySimpleConsent(purpose, vendorId, isEnforceVendor, tcString); } - private boolean isAllowedByNotFlexibleLegitimateInterest(Purpose purpose, + private boolean isAllowedByNotFlexibleLegitimateInterest(PurposeCode purpose, Integer vendorId, boolean isEnforceVendor, TCString tcString, @@ -162,7 +162,7 @@ private boolean isAllowedByNotFlexibleLegitimateInterest(Purpose purpose, return isSupportedRestriction && isAllowedByLegitimateInterest(purpose, vendorId, isEnforceVendor, tcString); } - private boolean isAllowedByFlexible(Purpose purpose, + private boolean isAllowedByFlexible(PurposeCode purpose, Integer vendorId, boolean isEnforceVendor, TCString tcString, diff --git a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/NoEnforcePurposeStrategy.java b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/NoEnforcePurposeStrategy.java index 4160aaa5038..1e7c247744d 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/NoEnforcePurposeStrategy.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/NoEnforcePurposeStrategy.java @@ -5,7 +5,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.prebid.server.privacy.gdpr.model.VendorPermission; import org.prebid.server.privacy.gdpr.model.VendorPermissionWithGvl; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import java.util.Collection; import java.util.List; @@ -13,7 +13,7 @@ public class NoEnforcePurposeStrategy extends EnforcePurposeStrategy { - public Collection allowedByTypeStrategy(Purpose purpose, + public Collection allowedByTypeStrategy(PurposeCode purpose, TCString tcString, Collection vendorsForPurpose, Collection excludedVendors, diff --git a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/PurposeTwoBasicEnforcePurposeStrategy.java b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/PurposeTwoBasicEnforcePurposeStrategy.java index d61b01b887b..c3870047270 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/PurposeTwoBasicEnforcePurposeStrategy.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/PurposeTwoBasicEnforcePurposeStrategy.java @@ -7,7 +7,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.prebid.server.privacy.gdpr.model.VendorPermission; import org.prebid.server.privacy.gdpr.model.VendorPermissionWithGvl; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import java.util.Collection; import java.util.List; @@ -17,7 +17,7 @@ public class PurposeTwoBasicEnforcePurposeStrategy extends BasicEnforcePurposeSt private static final Logger logger = LoggerFactory.getLogger(PurposeTwoBasicEnforcePurposeStrategy.class); - public Collection allowedByTypeStrategy(Purpose purpose, + public Collection allowedByTypeStrategy(PurposeCode purpose, TCString vendorConsent, Collection vendorsForPurpose, Collection excludedVendors, @@ -35,7 +35,7 @@ public Collection allowedByTypeStrategy(Purpose purpose, return CollectionUtils.union(allowedVendorPermissions, toVendorPermissions(excludedVendors)); } - private boolean isAllowedBySimpleConsentOrPurposeLI(Purpose purpose, + private boolean isAllowedBySimpleConsentOrPurposeLI(PurposeCode purpose, Integer vendorId, boolean isEnforceVendor, TCString tcString) { diff --git a/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/Purpose.java b/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/PurposeCode.java similarity index 86% rename from src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/Purpose.java rename to src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/PurposeCode.java index 90da789cc94..c6d08462045 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/Purpose.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/PurposeCode.java @@ -5,7 +5,7 @@ import java.util.Arrays; -public enum Purpose { +public enum PurposeCode { ONE(1), TWO(2), @@ -22,7 +22,7 @@ public enum Purpose { @JsonValue private final int code; - Purpose(int code) { + PurposeCode(int code) { this.code = code; } @@ -31,7 +31,7 @@ public int code() { } @JsonCreator - public static Purpose valueOf(int code) { + public static PurposeCode valueOf(int code) { return Arrays.stream(values()) .filter(purpose -> purpose.code == code) .findFirst() diff --git a/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/VendorV1.java b/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/VendorV1.java index f33778c8249..f87b262298c 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/VendorV1.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/VendorV1.java @@ -11,13 +11,13 @@ public class VendorV1 { Integer id; @JsonProperty("purposeIds") - EnumSet purposeIds; + EnumSet purposeIds; @JsonProperty("legIntPurposeIds") - EnumSet legIntPurposeIds; + EnumSet legIntPurposeIds; - public EnumSet combinedPurposes() { - final EnumSet combinedPurposes = EnumSet.noneOf(Purpose.class); + public EnumSet combinedPurposes() { + final EnumSet combinedPurposes = EnumSet.noneOf(PurposeCode.class); if (purposeIds != null) { combinedPurposes.addAll(purposeIds); } diff --git a/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/VendorV2.java b/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/VendorV2.java index 42577b53722..364889444d2 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/VendorV2.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/VendorV2.java @@ -16,13 +16,13 @@ public class VendorV2 { Integer id; - EnumSet purposes; + EnumSet purposes; @JsonProperty("legIntPurposes") - EnumSet legIntPurposes; + EnumSet legIntPurposes; @JsonProperty("flexiblePurposes") - EnumSet flexiblePurposes; + EnumSet flexiblePurposes; @JsonProperty("specialPurposes") EnumSet specialPurposes; @@ -36,9 +36,9 @@ public class VendorV2 { public static VendorV2 empty(Integer id) { return VendorV2.builder() .id(id) - .purposes(EnumSet.noneOf(Purpose.class)) - .legIntPurposes(EnumSet.noneOf(Purpose.class)) - .flexiblePurposes(EnumSet.noneOf(Purpose.class)) + .purposes(EnumSet.noneOf(PurposeCode.class)) + .legIntPurposes(EnumSet.noneOf(PurposeCode.class)) + .flexiblePurposes(EnumSet.noneOf(PurposeCode.class)) .specialPurposes(EnumSet.noneOf(SpecialPurpose.class)) .features(EnumSet.noneOf(Feature.class)) .specialFeatures(EnumSet.noneOf(SpecialFeature.class)) diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/BidAdjustmentMediaType.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/BidAdjustmentMediaType.java new file mode 100644 index 00000000000..8c2d0351d82 --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/BidAdjustmentMediaType.java @@ -0,0 +1,21 @@ +package org.prebid.server.proto.openrtb.ext.request; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public enum BidAdjustmentMediaType { + + banner, + audio, + @JsonProperty("native") + xNative, + video, + @JsonProperty("video-outstream") + video_outstream; + + @Override + public String toString() { + return this == xNative ? "native" + : this == video_outstream ? "video-outstream" + : super.toString(); + } +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestBidadjustmentfactors.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestBidadjustmentfactors.java new file mode 100644 index 00000000000..105c141fc21 --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestBidadjustmentfactors.java @@ -0,0 +1,31 @@ +package org.prebid.server.proto.openrtb.ext.request; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import lombok.Builder; +import lombok.Value; + +import java.math.BigDecimal; +import java.util.Collections; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; + +@Value(staticConstructor = "of") +@Builder(toBuilder = true) +public class ExtRequestBidadjustmentfactors { + + Map adjustments = new HashMap<>(); + + EnumMap> mediatypes; + + @JsonAnyGetter + public Map getAdjustments() { + return Collections.unmodifiableMap(adjustments); + } + + @JsonAnySetter + public void addFactor(String key, BigDecimal value) { + adjustments.put(key, value); + } +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java index 7e19569bbec..783c1dccaaf 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java @@ -1,10 +1,11 @@ package org.prebid.server.proto.openrtb.ext.request; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.Builder; import lombok.Value; +import org.prebid.server.json.IntegerFlagDeserializer; -import java.math.BigDecimal; import java.util.List; import java.util.Map; @@ -18,6 +19,7 @@ public class ExtRequestPrebid { /** * Defines the contract for bidrequest.ext.prebid.debug */ + @JsonDeserialize(using = IntegerFlagDeserializer.class) Integer debug; /** @@ -33,7 +35,7 @@ public class ExtRequestPrebid { /** * Defines the contract for bidrequest.ext.prebid.bidadjustmentfactors */ - Map bidadjustmentfactors; + ExtRequestBidadjustmentfactors bidadjustmentfactors; /** * Defines the contract for bidrequest.ext.prebid.currency @@ -114,4 +116,9 @@ public class ExtRequestPrebid { * Defines the contract for bidrequest.ext.prebid.multibid */ List multibid; + + /** + * Defines the contract for bidrequest.ext.prebid.analytics + */ + ObjectNode analytics; } diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/adyoulike/ExtImpAdyoulike.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/adyoulike/ExtImpAdyoulike.java new file mode 100644 index 00000000000..19f4172942a --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/adyoulike/ExtImpAdyoulike.java @@ -0,0 +1,24 @@ +package org.prebid.server.proto.openrtb.ext.request.adyoulike; + +import lombok.AllArgsConstructor; +import lombok.Value; + +/** + * Defines the contract for bidRequest.imp[i].ext.adyoulike + */ +@AllArgsConstructor(staticName = "of") +@Value +public class ExtImpAdyoulike { + + String placement; + + String campaign; + + String track; + + String creative; + + String source; + + String debug; +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/decenterads/ExtImpDecenterads.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/decenterads/ExtImpDecenterads.java new file mode 100644 index 00000000000..d009f9b014e --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/decenterads/ExtImpDecenterads.java @@ -0,0 +1,16 @@ +package org.prebid.server.proto.openrtb.ext.request.decenterads; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Value; + +/** + * Defines the contract for bidRequest.imp[i].ext.decenterads + */ +@AllArgsConstructor(staticName = "of") +@Value +public class ExtImpDecenterads { + + @JsonProperty("placementId") + String placementId; +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/gumgum/ExtImpGumgum.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/gumgum/ExtImpGumgum.java index 3177c5bf57d..f7d137152b7 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/gumgum/ExtImpGumgum.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/gumgum/ExtImpGumgum.java @@ -1,11 +1,20 @@ package org.prebid.server.proto.openrtb.ext.request.gumgum; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; import lombok.Value; +import java.math.BigInteger; + @AllArgsConstructor(staticName = "of") @Value public class ExtImpGumgum { String zone; + + @JsonProperty("pubId") + BigInteger pubId; + + @JsonProperty("irisid") + String irisId; } diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/gumgum/ExtImpGumgumVideo.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/gumgum/ExtImpGumgumVideo.java new file mode 100644 index 00000000000..a0880109568 --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/gumgum/ExtImpGumgumVideo.java @@ -0,0 +1,13 @@ +package org.prebid.server.proto.openrtb.ext.request.gumgum; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Value; + +@AllArgsConstructor(staticName = "of") +@Value +public class ExtImpGumgumVideo { + + @JsonProperty("irisid") + String irisId; +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/jixie/ExtImpJixie.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/jixie/ExtImpJixie.java new file mode 100644 index 00000000000..ee9d29f28e7 --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/jixie/ExtImpJixie.java @@ -0,0 +1,21 @@ +package org.prebid.server.proto.openrtb.ext.request.jixie; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Value; + +@AllArgsConstructor(staticName = "of") +@Value +public class ExtImpJixie { + + String unit; + + @JsonProperty("accountid") + String accountId; + + @JsonProperty("jxprop1") + String jxProp1; + + @JsonProperty("jxprop2") + String jxProp2; +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/mobfoxpb/ExtImpMobfoxpb.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/mobfoxpb/ExtImpMobfoxpb.java index 0b02ee8cb70..b19f6fa5fc8 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/mobfoxpb/ExtImpMobfoxpb.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/mobfoxpb/ExtImpMobfoxpb.java @@ -13,4 +13,6 @@ public class ExtImpMobfoxpb { @JsonProperty("TagID") String tagId; + + String key; } diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/onetag/ExtImpOnetag.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/onetag/ExtImpOnetag.java new file mode 100644 index 00000000000..18cb4dd8ae2 --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/onetag/ExtImpOnetag.java @@ -0,0 +1,16 @@ +package org.prebid.server.proto.openrtb.ext.request.onetag; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.AllArgsConstructor; +import lombok.Value; + +@AllArgsConstructor(staticName = "of") +@Value +public class ExtImpOnetag { + + @JsonProperty("pubId") + String pubId; + + ObjectNode ext; +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/outbrains/ExtImpOutbrain.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/outbrains/ExtImpOutbrain.java new file mode 100644 index 00000000000..a7d771bd1be --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/outbrains/ExtImpOutbrain.java @@ -0,0 +1,19 @@ +package org.prebid.server.proto.openrtb.ext.request.outbrains; + +import lombok.AllArgsConstructor; +import lombok.Value; + +import java.util.List; + +@Value +@AllArgsConstructor(staticName = "of") +public class ExtImpOutbrain { + + ExtImpOutbrainPublisher publisher; + + String tagid; + + List bcat; + + List badv; +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/outbrains/ExtImpOutbrainPublisher.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/outbrains/ExtImpOutbrainPublisher.java new file mode 100644 index 00000000000..ba613cc8ff4 --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/outbrains/ExtImpOutbrainPublisher.java @@ -0,0 +1,15 @@ +package org.prebid.server.proto.openrtb.ext.request.outbrains; + +import lombok.AllArgsConstructor; +import lombok.Value; + +@Value +@AllArgsConstructor(staticName = "of") +public class ExtImpOutbrainPublisher { + + String id; + + String name; + + String domain; +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/pangle/ExtImpPangle.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/pangle/ExtImpPangle.java new file mode 100644 index 00000000000..fcf02381406 --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/pangle/ExtImpPangle.java @@ -0,0 +1,11 @@ +package org.prebid.server.proto.openrtb.ext.request.pangle; + +import lombok.AllArgsConstructor; +import lombok.Value; + +@AllArgsConstructor(staticName = "of") +@Value +public class ExtImpPangle { + + String token; +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/unicorn/ExtImpUnicorn.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/unicorn/ExtImpUnicorn.java new file mode 100644 index 00000000000..83f12303fc4 --- /dev/null +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/unicorn/ExtImpUnicorn.java @@ -0,0 +1,24 @@ +package org.prebid.server.proto.openrtb.ext.request.unicorn; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Value; + +@AllArgsConstructor(staticName = "of") +@Value +@Builder(toBuilder = true) +public class ExtImpUnicorn { + + @JsonProperty("placementId") + String placementId; + + @JsonProperty("publisherId") + Integer publisherId; + + @JsonProperty("mediaId") + String mediaId; + + @JsonProperty("accountId") + Integer accountId; +} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtBidPrebid.java b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtBidPrebid.java index 98c3a21c4bc..6dba7b42189 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtBidPrebid.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtBidPrebid.java @@ -10,7 +10,7 @@ /** * Defines the contract for bidresponse.seatbid.bid[i].ext.prebid */ -@Builder +@Builder(toBuilder = true) @Value public class ExtBidPrebid { diff --git a/src/main/java/org/prebid/server/proto/request/CookieSyncRequest.java b/src/main/java/org/prebid/server/proto/request/CookieSyncRequest.java index abbe4f52344..1de4ace0369 100644 --- a/src/main/java/org/prebid/server/proto/request/CookieSyncRequest.java +++ b/src/main/java/org/prebid/server/proto/request/CookieSyncRequest.java @@ -1,6 +1,7 @@ package org.prebid.server.proto.request; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; import lombok.Builder; import lombok.Value; @@ -24,5 +25,28 @@ public class CookieSyncRequest { Integer limit; String account; + + @JsonProperty("filterSettings") + FilterSettings filterSettings; + + @Value(staticConstructor = "of") + public static class FilterSettings { + + MethodFilter iframe; + + MethodFilter image; + } + + @Value(staticConstructor = "of") + public static class MethodFilter { + + JsonNode bidders; + + FilterType filter; + } + + public enum FilterType { + include, exclude + } } diff --git a/src/main/java/org/prebid/server/proto/response/BidderInfo.java b/src/main/java/org/prebid/server/proto/response/BidderInfo.java index c1dcbc7ba12..540df9c76e7 100644 --- a/src/main/java/org/prebid/server/proto/response/BidderInfo.java +++ b/src/main/java/org/prebid/server/proto/response/BidderInfo.java @@ -5,11 +5,13 @@ import java.util.List; -@Value +@Value(staticConstructor = "of") public class BidderInfo { boolean enabled; + String aliasOf; + MaintainerInfo maintainer; CapabilitiesInfo capabilities; @@ -22,16 +24,26 @@ public class BidderInfo { boolean modifyingVastXmlAllowed; - public static BidderInfo create(boolean enabled, String maintainerEmail, List appMediaTypes, - List siteMediaTypes, List supportedVendors, int vendorId, - boolean enforceGdpr, boolean ccpaEnforced, boolean modifyingVastXmlAllowed) { - final MaintainerInfo maintainer = new MaintainerInfo(maintainerEmail); - final CapabilitiesInfo capabilities = new CapabilitiesInfo(platformInfo(appMediaTypes), - platformInfo(siteMediaTypes)); - final GdprInfo gdpr = new GdprInfo(vendorId, enforceGdpr); - - return new BidderInfo( - enabled, maintainer, capabilities, supportedVendors, gdpr, ccpaEnforced, modifyingVastXmlAllowed); + public static BidderInfo create(boolean enabled, + String aliasOf, + String maintainerEmail, + List appMediaTypes, + List siteMediaTypes, + List supportedVendors, + int vendorId, + boolean enforceGdpr, + boolean ccpaEnforced, + boolean modifyingVastXmlAllowed) { + + return of( + enabled, + aliasOf, + new MaintainerInfo(maintainerEmail), + new CapabilitiesInfo(platformInfo(appMediaTypes), platformInfo(siteMediaTypes)), + supportedVendors, + new GdprInfo(vendorId, enforceGdpr), + ccpaEnforced, + modifyingVastXmlAllowed); } private static PlatformInfo platformInfo(List mediaTypes) { diff --git a/src/main/java/org/prebid/server/settings/model/AccountGdprConfig.java b/src/main/java/org/prebid/server/settings/model/AccountGdprConfig.java index 16eb51b5f1f..65760b8cd49 100644 --- a/src/main/java/org/prebid/server/settings/model/AccountGdprConfig.java +++ b/src/main/java/org/prebid/server/settings/model/AccountGdprConfig.java @@ -4,6 +4,8 @@ import lombok.Builder; import lombok.Value; +import java.util.List; + @Builder @Value public class AccountGdprConfig { @@ -21,4 +23,7 @@ public class AccountGdprConfig { @JsonProperty("purpose-one-treatment-interpretation") PurposeOneTreatmentInterpretation purposeOneTreatmentInterpretation; + + @JsonProperty("basic-enforcement-vendors") + List basicEnforcementVendors; } diff --git a/src/main/java/org/prebid/server/spring/config/MetricsConfiguration.java b/src/main/java/org/prebid/server/spring/config/MetricsConfiguration.java index 9e9f1b1db8d..4027c169cbe 100644 --- a/src/main/java/org/prebid/server/spring/config/MetricsConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/MetricsConfiguration.java @@ -22,7 +22,6 @@ import lombok.Data; import lombok.NoArgsConstructor; import org.apache.commons.lang3.ObjectUtils; -import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.metric.AccountMetricsVerbosity; import org.prebid.server.metric.CounterType; import org.prebid.server.metric.Metrics; @@ -109,8 +108,8 @@ ScheduledReporter consoleReporter(ConsoleProperties consoleProperties, MetricReg @Bean Metrics metrics(@Value("${metrics.metricType}") CounterType counterType, MetricRegistry metricRegistry, - AccountMetricsVerbosity accountMetricsVerbosity, BidderCatalog bidderCatalog) { - return new Metrics(metricRegistry, counterType, accountMetricsVerbosity, bidderCatalog); + AccountMetricsVerbosity accountMetricsVerbosity) { + return new Metrics(metricRegistry, counterType, accountMetricsVerbosity); } @Bean diff --git a/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java b/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java index ce674c47070..2c965862c1b 100644 --- a/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java @@ -6,9 +6,7 @@ import io.vertx.core.file.FileSystem; import io.vertx.core.http.HttpClientOptions; import io.vertx.core.net.JksOptions; -import org.prebid.server.auction.AmpRequestFactory; import org.prebid.server.auction.AmpResponsePostProcessor; -import org.prebid.server.auction.AuctionRequestFactory; import org.prebid.server.auction.BidResponseCreator; import org.prebid.server.auction.BidResponsePostProcessor; import org.prebid.server.auction.ExchangeService; @@ -22,10 +20,14 @@ import org.prebid.server.auction.StoredRequestProcessor; import org.prebid.server.auction.StoredResponseProcessor; import org.prebid.server.auction.TimeoutResolver; -import org.prebid.server.auction.VideoRequestFactory; import org.prebid.server.auction.VideoResponseFactory; import org.prebid.server.auction.VideoStoredRequestProcessor; import org.prebid.server.auction.WinningBidComparator; +import org.prebid.server.auction.requestfactory.AmpRequestFactory; +import org.prebid.server.auction.requestfactory.AuctionRequestFactory; +import org.prebid.server.auction.requestfactory.Ortb2ImplicitParametersResolver; +import org.prebid.server.auction.requestfactory.Ortb2RequestFactory; +import org.prebid.server.auction.requestfactory.VideoRequestFactory; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.bidder.BidderDeps; import org.prebid.server.bidder.BidderErrorNotifier; @@ -178,50 +180,75 @@ TimeoutResolver ampTimeoutResolver( } @Bean - AuctionRequestFactory auctionRequestFactory( - @Value("${auction.max-request-size}") @Min(0) int maxRequestSize, - @Value("${settings.enforce-valid-account}") boolean enforceValidAccount, + Ortb2ImplicitParametersResolver ortb2ImplicitParametersResolver( @Value("${auction.cache.only-winning-bids}") boolean shouldCacheOnlyWinningBids, @Value("${auction.ad-server-currency}") String adServerCurrency, @Value("${auction.blacklisted-apps}") String blacklistedAppsString, - @Value("${auction.blacklisted-accounts}") String blacklistedAccountsString, - StoredRequestProcessor storedRequestProcessor, ImplicitParametersExtractor implicitParametersExtractor, IpAddressHelper ipAddressHelper, - UidsCookieService uidsCookieService, - BidderCatalog bidderCatalog, - RequestValidator requestValidator, - OrtbTypesResolver ortbTypesResolver, - TimeoutResolver timeoutResolver, - TimeoutFactory timeoutFactory, - ApplicationSettings applicationSettings, - PrivacyEnforcementService privacyEnforcementService, IdGenerator sourceIdGenerator, JacksonMapper mapper) { final List blacklistedApps = splitToList(blacklistedAppsString); - final List blacklistedAccounts = splitToList(blacklistedAccountsString); - return new AuctionRequestFactory( - maxRequestSize, - enforceValidAccount, + return new Ortb2ImplicitParametersResolver( shouldCacheOnlyWinningBids, adServerCurrency, blacklistedApps, - blacklistedAccounts, - storedRequestProcessor, implicitParametersExtractor, ipAddressHelper, + sourceIdGenerator, + mapper); + } + + @Bean + Ortb2RequestFactory openRtb2RequestFactory( + @Value("${settings.enforce-valid-account}") boolean enforceValidAccount, + @Value("${auction.blacklisted-accounts}") String blacklistedAccountsString, + UidsCookieService uidsCookieService, + RequestValidator requestValidator, + TimeoutResolver timeoutResolver, + TimeoutFactory timeoutFactory, + StoredRequestProcessor storedRequestProcessor, + ApplicationSettings applicationSettings, + IpAddressHelper ipAddressHelper) { + + final List blacklistedAccounts = splitToList(blacklistedAccountsString); + + return new Ortb2RequestFactory( + enforceValidAccount, + blacklistedAccounts, uidsCookieService, - bidderCatalog, requestValidator, - new InterstitialProcessor(), - ortbTypesResolver, timeoutResolver, timeoutFactory, + storedRequestProcessor, applicationSettings, - sourceIdGenerator, + ipAddressHelper); + } + + @Bean + AuctionRequestFactory auctionRequestFactory( + @Value("${auction.max-request-size}") @Min(0) int maxRequestSize, + Ortb2RequestFactory ortb2RequestFactory, + StoredRequestProcessor storedRequestProcessor, + ImplicitParametersExtractor implicitParametersExtractor, + Ortb2ImplicitParametersResolver ortb2ImplicitParametersResolver, + OrtbTypesResolver ortbTypesResolver, + PrivacyEnforcementService privacyEnforcementService, + TimeoutResolver timeoutResolver, + JacksonMapper mapper) { + + return new AuctionRequestFactory( + maxRequestSize, + ortb2RequestFactory, + storedRequestProcessor, + implicitParametersExtractor, + ortb2ImplicitParametersResolver, + new InterstitialProcessor(), + ortbTypesResolver, privacyEnforcementService, + timeoutResolver, mapper); } @@ -241,19 +268,23 @@ IdGenerator sourceIdGenerator(@Value("${auction.generate-source-tid}") boolean g @Bean AmpRequestFactory ampRequestFactory(StoredRequestProcessor storedRequestProcessor, - AuctionRequestFactory auctionRequestFactory, + Ortb2RequestFactory ortb2RequestFactory, OrtbTypesResolver ortbTypesResolver, ImplicitParametersExtractor implicitParametersExtractor, + Ortb2ImplicitParametersResolver ortb2ImplicitParametersResolver, FpdResolver fpdResolver, + PrivacyEnforcementService privacyEnforcementService, TimeoutResolver timeoutResolver, JacksonMapper mapper) { return new AmpRequestFactory( storedRequestProcessor, - auctionRequestFactory, + ortb2RequestFactory, ortbTypesResolver, implicitParametersExtractor, + ortb2ImplicitParametersResolver, fpdResolver, + privacyEnforcementService, timeoutResolver, mapper); } @@ -263,15 +294,19 @@ VideoRequestFactory videoRequestFactory( @Value("${auction.max-request-size}") int maxRequestSize, @Value("${video.stored-request-required}") boolean enforceStoredRequest, VideoStoredRequestProcessor storedRequestProcessor, - AuctionRequestFactory auctionRequestFactory, + Ortb2RequestFactory ortb2RequestFactory, + Ortb2ImplicitParametersResolver ortb2ImplicitParametersResolver, + PrivacyEnforcementService privacyEnforcementService, TimeoutResolver timeoutResolver, JacksonMapper mapper) { return new VideoRequestFactory( maxRequestSize, enforceStoredRequest, + ortb2RequestFactory, + ortb2ImplicitParametersResolver, storedRequestProcessor, - auctionRequestFactory, + privacyEnforcementService, timeoutResolver, mapper); } @@ -552,13 +587,21 @@ PrivacyEnforcementService privacyEnforcementService( BidderCatalog bidderCatalog, PrivacyExtractor privacyExtractor, TcfDefinerService tcfDefinerService, + ImplicitParametersExtractor implicitParametersExtractor, IpAddressHelper ipAddressHelper, Metrics metrics, @Value("${ccpa.enforce}") boolean ccpaEnforce, @Value("${lmt.enforce}") boolean lmtEnforce) { return new PrivacyEnforcementService( - bidderCatalog, privacyExtractor, tcfDefinerService, ipAddressHelper, metrics, ccpaEnforce, lmtEnforce); + bidderCatalog, + privacyExtractor, + tcfDefinerService, + implicitParametersExtractor, + ipAddressHelper, + metrics, + ccpaEnforce, + lmtEnforce); } @Bean diff --git a/src/main/java/org/prebid/server/spring/config/WebConfiguration.java b/src/main/java/org/prebid/server/spring/config/WebConfiguration.java index 1fcc5eb513a..60f4161fab9 100644 --- a/src/main/java/org/prebid/server/spring/config/WebConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/WebConfiguration.java @@ -14,12 +14,12 @@ import lombok.Data; import lombok.NoArgsConstructor; import org.prebid.server.analytics.AnalyticsReporterDelegator; -import org.prebid.server.auction.AmpRequestFactory; +import org.prebid.server.auction.requestfactory.AmpRequestFactory; import org.prebid.server.auction.AmpResponsePostProcessor; -import org.prebid.server.auction.AuctionRequestFactory; +import org.prebid.server.auction.requestfactory.AuctionRequestFactory; import org.prebid.server.auction.ExchangeService; import org.prebid.server.auction.PrivacyEnforcementService; -import org.prebid.server.auction.VideoRequestFactory; +import org.prebid.server.auction.requestfactory.VideoRequestFactory; import org.prebid.server.auction.VideoResponseFactory; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.cache.CacheService; diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AcuityadsConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AcuityadsConfiguration.java index 94cdc034302..361aa204d08 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AcuityadsConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AcuityadsConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.acuityads.AcuityadsBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps acuityadsBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new AcuityadsBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AcuityadsBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AdformConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AdformConfiguration.java index 119a7e86b2f..9086202958c 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AdformConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AdformConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.adform.AdformBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps adformBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new AdformBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AdformBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AdgenerationConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AdgenerationConfiguration.java index 969e5ff1632..fae95e0926d 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AdgenerationConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AdgenerationConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps adgenerationBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new AdgenerationBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AdgenerationBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AdheseConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AdheseConfiguration.java index 929952e4599..9865075ff3b 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AdheseConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AdheseConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps adheseBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new AdheseBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AdheseBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AdkernelAdnConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AdkernelAdnConfiguration.java index cdf86d35c1c..262c6163b07 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AdkernelAdnConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AdkernelAdnConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps adkernelAdnBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new AdkernelAdnBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AdkernelAdnBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AdkernelConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AdkernelConfiguration.java index 1687767fa78..ca5c089a8a5 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AdkernelConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AdkernelConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps adkernelBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new AdkernelBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AdkernelBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AdmanConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AdmanConfiguration.java index 37f1fed97c2..fadaedb31bd 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AdmanConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AdmanConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.adman.AdmanBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,11 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps admanBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new AdmanBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AdmanBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AdmixerConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AdmixerConfiguration.java index 3d8706b1dda..9404f361c41 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AdmixerConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AdmixerConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.admixer.AdmixerBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps admixerBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new AdmixerBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AdmixerBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AdoceanConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AdoceanConfiguration.java index 1f9ecf51159..736203977f1 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AdoceanConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AdoceanConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps adoceanBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new AdoceanBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AdoceanBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AdopplerConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AdopplerConfiguration.java index 94a49031a04..511c4e37cc4 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AdopplerConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AdopplerConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps adopplerBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new AdopplerBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AdopplerBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AdotConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AdotConfiguration.java index 1e03bb6ef05..2d161533883 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AdotConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AdotConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.adot.AdotBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps adotBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new AdotBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AdotBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AdponeConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AdponeConfiguration.java index 4bf7664983d..134e656ac41 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AdponeConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AdponeConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps adponeBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new AdponeBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AdponeBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AdprimeConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AdprimeConfiguration.java index eea67f295c2..94caa6a2ed9 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AdprimeConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AdprimeConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps adprimeBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new AdprimeBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AdprimeBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AdtargetConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AdtargetConfiguration.java index 21b2af0b168..0303208de9b 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AdtargetConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AdtargetConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps adtargetBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new AdtargetBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AdtargetBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AdtelligentConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AdtelligentConfiguration.java index 9d7a9e8f653..c13c559ae9a 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AdtelligentConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AdtelligentConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps adtelligentBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new AdtelligentBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AdtelligentBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AdvangelistsConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AdvangelistsConfiguration.java index c4e23f53981..49a4ea62db0 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AdvangelistsConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AdvangelistsConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps advangelistsBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new AdvangelistsBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AdvangelistsBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AdyoulikeConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AdyoulikeConfiguration.java new file mode 100644 index 00000000000..e8e9d6e9954 --- /dev/null +++ b/src/main/java/org/prebid/server/spring/config/bidder/AdyoulikeConfiguration.java @@ -0,0 +1,51 @@ +package org.prebid.server.spring.config.bidder; + +import org.prebid.server.bidder.BidderDeps; +import org.prebid.server.bidder.adyoulike.AdyoulikeBidder; +import org.prebid.server.json.JacksonMapper; +import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; +import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; +import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; +import org.prebid.server.spring.env.YamlPropertySourceFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +import javax.validation.constraints.NotBlank; + +@Configuration +@PropertySource(value = "classpath:/bidder-config/adyoulike.yaml", factory = YamlPropertySourceFactory.class) +public class AdyoulikeConfiguration { + + private static final String BIDDER_NAME = "adyoulike"; + + @Value("${external-url}") + @NotBlank + private String externalUrl; + + @Autowired + private JacksonMapper mapper; + + @Autowired + @Qualifier("adyoulikeConfigurationProperties") + private BidderConfigurationProperties configProperties; + + @Bean("adyoulikeConfigurationProperties") + @ConfigurationProperties("adapters.adyoulike") + BidderConfigurationProperties configurationProperties() { + return new BidderConfigurationProperties(); + } + + @Bean + BidderDeps adyoulileBidderDeps() { + return BidderDepsAssembler.forBidder(BIDDER_NAME) + .withConfig(configProperties) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AdyoulikeBidder(config.getEndpoint(), mapper)) + .assemble(); + } +} diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AjaConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AjaConfiguration.java index 675385dfa8a..c0ff4b12730 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AjaConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AjaConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps ajaBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new AjaBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AjaBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AmxConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AmxConfiguration.java index 6cdf5db7287..40242d3c37e 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AmxConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AmxConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.amx.AmxBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,11 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps amxBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new AmxBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AmxBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/ApplogyConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/ApplogyConfiguration.java index 5ea812a80b6..decd29ca15f 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/ApplogyConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/ApplogyConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps applogyBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new ApplogyBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new ApplogyBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AppnexusConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AppnexusConfiguration.java index bb30e0af566..36faefc6970 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AppnexusConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AppnexusConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.appnexus.AppnexusBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps appnexusBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new AppnexusBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AppnexusBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/AvocetConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/AvocetConfiguration.java index f969df09f37..a87164a1112 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/AvocetConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/AvocetConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,10 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps avocetBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new AvocetBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new AvocetBidder(config.getEndpoint(), mapper)) .assemble(); } - } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/BeachfrontConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/BeachfrontConfiguration.java index f9654db662e..9f361445026 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/BeachfrontConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/BeachfrontConfiguration.java @@ -8,7 +8,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -47,12 +46,13 @@ BeachfrontConfigurationProperties configurationProperties() { @Bean BidderDeps beachfrontBidderDeps() { - return BidderDepsAssembler.forBidder(BIDDER_NAME) + return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new BeachfrontBidder(configProperties.getEndpoint(), - configProperties.getVideoEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new BeachfrontBidder( + config.getEndpoint(), + config.getVideoEndpoint(), + mapper)) .assemble(); } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/BeintooConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/BeintooConfiguration.java index c426720bc11..40ef37304be 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/BeintooConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/BeintooConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.beintoo.BeintooBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps beintooBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new BeintooBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new BeintooBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/BetweenConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/BetweenConfiguration.java index 9dc09ed7e35..4295db5b595 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/BetweenConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/BetweenConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.between.BetweenBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps betweenBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new BetweenBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new BetweenBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/BrightrollConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/BrightrollConfiguration.java index bf8084cfff5..00302be6203 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/BrightrollConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/BrightrollConfiguration.java @@ -10,7 +10,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -57,19 +56,20 @@ BidderDeps brightrollBidderDeps() { final Map publisherIdToOverride = configProperties.getAccounts() == null ? Collections.emptyMap() : configProperties.getAccounts().stream() - .collect(Collectors.toMap(BidderAccount::getId, this::toPublisherOverride)); + .collect(Collectors.toMap(BidderAccount::getId, this::toPublisherOverride)); return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new BrightrollBidder(configProperties.getEndpoint(), mapper, + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new BrightrollBidder( + config.getEndpoint(), + mapper, publisherIdToOverride)) .assemble(); } private PublisherOverride toPublisherOverride(BidderAccount bidderAccount) { return PublisherOverride.of(bidderAccount.getBadv(), bidderAccount.getBcat(), bidderAccount.getImpBattr(), - bidderAccount.getBidFloor()); + bidderAccount.getBidFloor()); } @Validated diff --git a/src/main/java/org/prebid/server/spring/config/bidder/ColossusConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/ColossusConfiguration.java index 1465f9a8285..58830106cce 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/ColossusConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/ColossusConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps colossusBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new ColossusBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new ColossusBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/ConfigurationYeahmobi.java b/src/main/java/org/prebid/server/spring/config/bidder/ConfigurationYeahmobi.java index f64616b80a2..06e754ea443 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/ConfigurationYeahmobi.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/ConfigurationYeahmobi.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.yeahmobi.YeahmobiBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,9 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps yeahmobiBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) - .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new YeahmobiBidder(configProperties.getEndpoint(), mapper)) + .withConfig(configProperties).usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new YeahmobiBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/ConnectAdConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/ConnectAdConfiguration.java index e6a2e4622b1..2cbfb25e7ad 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/ConnectAdConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/ConnectAdConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.connectad.ConnectadBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps connectadBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new ConnectadBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new ConnectadBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/ConsumableConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/ConsumableConfiguration.java index 4945703dea7..d79d0c766bf 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/ConsumableConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/ConsumableConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps consumableBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new ConsumableBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new ConsumableBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/ConversantConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/ConversantConfiguration.java index 585b69372d5..86be8426e13 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/ConversantConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/ConversantConfiguration.java @@ -7,9 +7,7 @@ import org.prebid.server.bidder.conversant.ConversantBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -49,14 +47,11 @@ ConversantConfigurationProperties configurationProperties() { @Bean BidderDeps conversantBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new ConversantBidder(configProperties.getEndpoint(), - configProperties.getGenerateBidId(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new ConversantBidder(config.getEndpoint(), configProperties.getGenerateBidId(), + mapper)) .assemble(); } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/CpmStarConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/CpmStarConfiguration.java index 3035cec5f2b..68e93e1d3f9 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/CpmStarConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/CpmStarConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps cpmstarBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new CpmStarBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new CpmStarBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/DatablocksConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/DatablocksConfiguration.java index 4eaa10950f3..c0be7355116 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/DatablocksConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/DatablocksConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps datablocksBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new DatablocksBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new DatablocksBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/DecenteradsConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/DecenteradsConfiguration.java new file mode 100644 index 00000000000..403771912c8 --- /dev/null +++ b/src/main/java/org/prebid/server/spring/config/bidder/DecenteradsConfiguration.java @@ -0,0 +1,51 @@ +package org.prebid.server.spring.config.bidder; + +import org.prebid.server.bidder.BidderDeps; +import org.prebid.server.bidder.decenterads.DecenteradsBidder; +import org.prebid.server.json.JacksonMapper; +import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; +import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; +import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; +import org.prebid.server.spring.env.YamlPropertySourceFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +import javax.validation.constraints.NotBlank; + +@Configuration +@PropertySource(value = "classpath:/bidder-config/decenterads.yaml", factory = YamlPropertySourceFactory.class) +public class DecenteradsConfiguration { + + private static final String BIDDER_NAME = "decenterads"; + + @Value("${external-url}") + @NotBlank + private String externalUrl; + + @Autowired + private JacksonMapper mapper; + + @Autowired + @Qualifier("decenteradsConfigurationProperties") + private BidderConfigurationProperties configProperties; + + @Bean("decenteradsConfigurationProperties") + @ConfigurationProperties("adapters.decenterads") + BidderConfigurationProperties configurationProperties() { + return new BidderConfigurationProperties(); + } + + @Bean + BidderDeps decenteradsBidderDeps() { + return BidderDepsAssembler.forBidder(BIDDER_NAME) + .withConfig(configProperties) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new DecenteradsBidder(config.getEndpoint(), mapper)) + .assemble(); + } +} diff --git a/src/main/java/org/prebid/server/spring/config/bidder/DeepintentConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/DeepintentConfiguration.java index ecb64f95749..5c0f9f360fa 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/DeepintentConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/DeepintentConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.deepintent.DeepintentBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps deepintentBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new DeepintentBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new DeepintentBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/DmxConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/DmxConfiguration.java index cd27128ed33..a3440843a64 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/DmxConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/DmxConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.dmx.DmxBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps dmxBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new DmxBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new DmxBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/EmxDigitalConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/EmxDigitalConfiguration.java index c5b36ff9d85..c4b42e27680 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/EmxDigitalConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/EmxDigitalConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps emxDigitalBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new EmxDigitalBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new EmxDigitalBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/EngagebdrConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/EngagebdrConfiguration.java index 1b0541c953d..98f0ed029c1 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/EngagebdrConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/EngagebdrConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps engagebdrBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new EngagebdrBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new EngagebdrBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/EplanningConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/EplanningConfiguration.java index c60575a7c23..be155807061 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/EplanningConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/EplanningConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps eplanningBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new EplanningBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new EplanningBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/EpomConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/EpomConfiguration.java new file mode 100644 index 00000000000..a9a9c0d9834 --- /dev/null +++ b/src/main/java/org/prebid/server/spring/config/bidder/EpomConfiguration.java @@ -0,0 +1,51 @@ +package org.prebid.server.spring.config.bidder; + +import org.prebid.server.bidder.BidderDeps; +import org.prebid.server.bidder.epom.EpomBidder; +import org.prebid.server.json.JacksonMapper; +import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; +import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; +import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; +import org.prebid.server.spring.env.YamlPropertySourceFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +import javax.validation.constraints.NotBlank; + +@Configuration +@PropertySource(value = "classpath:/bidder-config/epom.yaml", factory = YamlPropertySourceFactory.class) +public class EpomConfiguration { + + private static final String BIDDER_NAME = "epom"; + + @Value("${external-url}") + @NotBlank + private String externalUrl; + + @Autowired + private JacksonMapper mapper; + + @Autowired + @Qualifier("epomConfigurationProperties") + private BidderConfigurationProperties configProperties; + + @Bean("epomConfigurationProperties") + @ConfigurationProperties("adapters.epom") + BidderConfigurationProperties configurationProperties() { + return new BidderConfigurationProperties(); + } + + @Bean + BidderDeps epomBidderDeps() { + return BidderDepsAssembler.forBidder(BIDDER_NAME) + .withConfig(configProperties) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new EpomBidder(config.getEndpoint(), mapper)) + .assemble(); + } +} diff --git a/src/main/java/org/prebid/server/spring/config/bidder/FacebookConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/FacebookConfiguration.java index 340e006e83e..0779fd44715 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/FacebookConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/FacebookConfiguration.java @@ -7,9 +7,7 @@ import org.prebid.server.bidder.facebook.FacebookBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -43,15 +41,15 @@ FacebookConfigurationProperties configurationProperties() { @Bean BidderDeps facebookBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - - return BidderDepsAssembler.forBidder(BIDDER_NAME) + return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, null)) + .usersyncerCreator(UsersyncerCreator.create(null)) .bidderCreator(configProperties.getEnabled() - ? () -> new FacebookBidder(configProperties.getEndpoint(), configProperties.getPlatformId(), - configProperties.getAppSecret(), configProperties.getTimeoutNotificationUrlTemplate(), mapper) + ? config -> new FacebookBidder( + config.getEndpoint(), + config.getPlatformId(), + config.getAppSecret(), + configProperties.getTimeoutNotificationUrlTemplate(), mapper) : null) .assemble(); } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/GammaConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/GammaConfiguration.java index 45ba40e34ff..3435b15e208 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/GammaConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/GammaConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps gammaBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new GammaBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new GammaBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/GamoshiConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/GamoshiConfiguration.java index 42ce780f2d5..44ee27fef48 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/GamoshiConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/GamoshiConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps gamoshiBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new GamoshiBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new GamoshiBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/GridConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/GridConfiguration.java index f3932540321..3810f471c4e 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/GridConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/GridConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps gridBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new GridBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new GridBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/GumgumConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/GumgumConfiguration.java index 0509e7e55ac..c1706eb9953 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/GumgumConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/GumgumConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps gumGumOneBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new GumgumBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new GumgumBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/ImprovedigitalConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/ImprovedigitalConfiguration.java index 24294d22683..4db80aeebbe 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/ImprovedigitalConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/ImprovedigitalConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps improvedigitalBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new ImprovedigitalBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new ImprovedigitalBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/InmobiConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/InmobiConfiguration.java index 3287fbf163d..1dafdd159ee 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/InmobiConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/InmobiConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.inmobi.InmobiBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps inmobiBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new InmobiBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new InmobiBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/InvibesConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/InvibesConfiguration.java index d1694a86dce..ecdc684aa2f 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/InvibesConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/InvibesConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.invibes.InvibesBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps invibesBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new InvibesBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new InvibesBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/IxConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/IxConfiguration.java index 7b7aada3e7e..1f93961d506 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/IxConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/IxConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.ix.IxBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps ixBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new IxBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new IxBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/JixieConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/JixieConfiguration.java new file mode 100644 index 00000000000..6283dd4b7ac --- /dev/null +++ b/src/main/java/org/prebid/server/spring/config/bidder/JixieConfiguration.java @@ -0,0 +1,51 @@ +package org.prebid.server.spring.config.bidder; + +import org.prebid.server.bidder.BidderDeps; +import org.prebid.server.bidder.jixie.JixieBidder; +import org.prebid.server.json.JacksonMapper; +import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; +import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; +import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; +import org.prebid.server.spring.env.YamlPropertySourceFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +import javax.validation.constraints.NotBlank; + +@Configuration +@PropertySource(value = "classpath:/bidder-config/jixie.yaml", factory = YamlPropertySourceFactory.class) +public class JixieConfiguration { + + private static final String BIDDER_NAME = "jixie"; + + @Value("${external-url}") + @NotBlank + private String externalUrl; + + @Autowired + private JacksonMapper mapper; + + @Autowired + @Qualifier("jixieConfigurationProperties") + private BidderConfigurationProperties configProperties; + + @Bean("jixieConfigurationProperties") + @ConfigurationProperties("adapters.jixie") + BidderConfigurationProperties configurationProperties() { + return new BidderConfigurationProperties(); + } + + @Bean + BidderDeps jixieBidderDeps() { + return BidderDepsAssembler.forBidder(BIDDER_NAME) + .withConfig(configProperties) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new JixieBidder(config.getEndpoint(), mapper)) + .assemble(); + } +} diff --git a/src/main/java/org/prebid/server/spring/config/bidder/KidozConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/KidozConfiguration.java index 97b4af511dd..cb3ce6090bf 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/KidozConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/KidozConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps kidozBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new KidozBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new KidozBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/KrushmediaConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/KrushmediaConfiguration.java index 44a8d741447..f5c1f939aa4 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/KrushmediaConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/KrushmediaConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.krushmedia.KrushmediaBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps krushmediaBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new KrushmediaBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new KrushmediaBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/KubientConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/KubientConfiguration.java index bcc49f59d89..2e9c58faa19 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/KubientConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/KubientConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps kubientBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new KubientBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new KubientBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/LifestreetConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/LifestreetConfiguration.java index 6fb5c4188a2..84fe157cc9a 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/LifestreetConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/LifestreetConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.lifestreet.LifestreetBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps lifestreetBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new LifestreetBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new LifestreetBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/LockerdomeConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/LockerdomeConfiguration.java index 4d7acd2aca9..4fdeb3f5b58 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/LockerdomeConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/LockerdomeConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps lockerdomeBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new LockerdomeBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new LockerdomeBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/LogicadConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/LogicadConfiguration.java index adaf6cfe4d4..c6f06965cec 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/LogicadConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/LogicadConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.logicad.LogicadBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps logicadBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new LogicadBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new LogicadBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/LunamediaConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/LunamediaConfiguration.java index 67b5e21af9c..c9ec2b01cfd 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/LunamediaConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/LunamediaConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.lunamedia.LunamediaBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps lunamediaBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new LunamediaBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new LunamediaBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/MarsmediaConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/MarsmediaConfiguration.java index b2684a89f84..2aa6bdefc67 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/MarsmediaConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/MarsmediaConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps marsmediaBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new MarsmediaBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new MarsmediaBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/MgidConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/MgidConfiguration.java index 333782c787a..fc9ab73ea5a 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/MgidConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/MgidConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps mgidBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new MgidBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new MgidBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/MobfoxpbConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/MobfoxpbConfiguration.java index e6ef28730db..1bab192e03f 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/MobfoxpbConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/MobfoxpbConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps mobfoxpbBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new MobfoxpbBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new MobfoxpbBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/MobilefuseConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/MobilefuseConfiguration.java index d4bf6e3badb..f10a3b6f7db 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/MobilefuseConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/MobilefuseConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.mobilefuse.MobilefuseBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps mobilefuseBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new MobilefuseBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new MobilefuseBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/NanointeractiveConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/NanointeractiveConfiguration.java index adcfa4cc54b..4ef236cc5d0 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/NanointeractiveConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/NanointeractiveConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps nanointeractiveBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new NanointeractiveBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new NanointeractiveBidder(config.getEndpoint(), mapper)) .assemble(); } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/NinthdecimalConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/NinthdecimalConfiguration.java index afb349cf5f8..9e46fdce768 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/NinthdecimalConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/NinthdecimalConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps ninthdecimalBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new NinthdecimalBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new NinthdecimalBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/NobidConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/NobidConfiguration.java index 8f5b0067458..d61b953554f 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/NobidConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/NobidConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.nobid.NobidBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps nobidBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new NobidBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new NobidBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/OnetagConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/OnetagConfiguration.java new file mode 100644 index 00000000000..c72fa861929 --- /dev/null +++ b/src/main/java/org/prebid/server/spring/config/bidder/OnetagConfiguration.java @@ -0,0 +1,51 @@ +package org.prebid.server.spring.config.bidder; + +import org.prebid.server.bidder.BidderDeps; +import org.prebid.server.bidder.onetag.OnetagBidder; +import org.prebid.server.json.JacksonMapper; +import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; +import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; +import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; +import org.prebid.server.spring.env.YamlPropertySourceFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +import javax.validation.constraints.NotBlank; + +@Configuration +@PropertySource(value = "classpath:/bidder-config/onetag.yaml", factory = YamlPropertySourceFactory.class) +public class OnetagConfiguration { + + private static final String BIDDER_NAME = "onetag"; + + @Value("${external-url}") + @NotBlank + private String externalUrl; + + @Autowired + private JacksonMapper mapper; + + @Autowired + @Qualifier("onetagConfigurationProperties") + private BidderConfigurationProperties configProperties; + + @Bean("onetagConfigurationProperties") + @ConfigurationProperties("adapters.onetag") + BidderConfigurationProperties configurationProperties() { + return new BidderConfigurationProperties(); + } + + @Bean + BidderDeps onetagBidderDeps() { + return BidderDepsAssembler.forBidder(BIDDER_NAME) + .withConfig(configProperties) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new OnetagBidder(config.getEndpoint(), mapper)) + .assemble(); + } +} diff --git a/src/main/java/org/prebid/server/spring/config/bidder/OpenxConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/OpenxConfiguration.java index 5acd81d5e29..f22b3a4aa97 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/OpenxConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/OpenxConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties openxProperties() { BidderDeps openxBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new OpenxBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new OpenxBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/OrbidderConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/OrbidderConfiguration.java index 9436c25bd8d..ad1889633b9 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/OrbidderConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/OrbidderConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.orbidder.OrbidderBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps orbidderBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new OrbidderBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new OrbidderBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/OutbrainConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/OutbrainConfiguration.java new file mode 100644 index 00000000000..a58f12c5ec6 --- /dev/null +++ b/src/main/java/org/prebid/server/spring/config/bidder/OutbrainConfiguration.java @@ -0,0 +1,51 @@ +package org.prebid.server.spring.config.bidder; + +import org.prebid.server.bidder.BidderDeps; +import org.prebid.server.bidder.outbrain.OutbrainBidder; +import org.prebid.server.json.JacksonMapper; +import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; +import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; +import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; +import org.prebid.server.spring.env.YamlPropertySourceFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +import javax.validation.constraints.NotBlank; + +@Configuration +@PropertySource(value = "classpath:/bidder-config/outbrain.yaml", factory = YamlPropertySourceFactory.class) +public class OutbrainConfiguration { + + private static final String BIDDER_NAME = "outbrain"; + + @Value("${external-url}") + @NotBlank + private String externalUrl; + + @Autowired + private JacksonMapper mapper; + + @Autowired + @Qualifier("outbrainConfigurationProperties") + private BidderConfigurationProperties configProperties; + + @Bean("outbrainConfigurationProperties") + @ConfigurationProperties("adapters.outbrain") + BidderConfigurationProperties configurationProperties() { + return new BidderConfigurationProperties(); + } + + @Bean + BidderDeps outbrainBidderDeps() { + return BidderDepsAssembler.forBidder(BIDDER_NAME) + .withConfig(configProperties) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new OutbrainBidder(config.getEndpoint(), mapper)) + .assemble(); + } +} diff --git a/src/main/java/org/prebid/server/spring/config/bidder/PangleConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/PangleConfiguration.java new file mode 100644 index 00000000000..26c04626faf --- /dev/null +++ b/src/main/java/org/prebid/server/spring/config/bidder/PangleConfiguration.java @@ -0,0 +1,51 @@ +package org.prebid.server.spring.config.bidder; + +import org.prebid.server.bidder.BidderDeps; +import org.prebid.server.bidder.pangle.PangleBidder; +import org.prebid.server.json.JacksonMapper; +import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; +import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; +import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; +import org.prebid.server.spring.env.YamlPropertySourceFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +import javax.validation.constraints.NotBlank; + +@Configuration +@PropertySource(value = "classpath:/bidder-config/pangle.yaml", factory = YamlPropertySourceFactory.class) +public class PangleConfiguration { + + private static final String BIDDER_NAME = "pangle"; + + @Value("${external-url}") + @NotBlank + private String externalUrl; + + @Autowired + private JacksonMapper mapper; + + @Autowired + @Qualifier("pangleConfigurationProperties") + private BidderConfigurationProperties configProperties; + + @Bean("pangleConfigurationProperties") + @ConfigurationProperties("adapters.pangle") + BidderConfigurationProperties configurationProperties() { + return new BidderConfigurationProperties(); + } + + @Bean + BidderDeps pangleBidderDeps() { + return BidderDepsAssembler.forBidder(BIDDER_NAME) + .withConfig(configProperties) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new PangleBidder(config.getEndpoint(), mapper)) + .assemble(); + } +} diff --git a/src/main/java/org/prebid/server/spring/config/bidder/PubmaticConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/PubmaticConfiguration.java index 4422e0ad7d6..f003cb50281 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/PubmaticConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/PubmaticConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.pubmatic.PubmaticBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps pubmaticBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new PubmaticBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new PubmaticBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/PubnativeConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/PubnativeConfiguration.java index 6c36b9fdf60..d1644aeb1a2 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/PubnativeConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/PubnativeConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps pubnativeBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new PubnativeBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new PubnativeBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/PulsepointConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/PulsepointConfiguration.java index 1f1df145b4e..7f261d76cce 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/PulsepointConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/PulsepointConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.pulsepoint.PulsepointBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps pulsepointBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new PulsepointBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new PulsepointBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/RevcontentConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/RevcontentConfiguration.java index d17bb79ccf9..5d57c74789c 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/RevcontentConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/RevcontentConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps revcontentBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new RevcontentBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new RevcontentBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/RhythmoneConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/RhythmoneConfiguration.java index d75b646049b..34127b5698d 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/RhythmoneConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/RhythmoneConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps rhythmOneBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new RhythmoneBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new RhythmoneBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/RtbhouseConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/RtbhouseConfiguration.java index affaa13d154..41eb67e486a 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/RtbhouseConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/RtbhouseConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps rtbhouseBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new RtbhouseBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new RtbhouseBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/RubiconConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/RubiconConfiguration.java index da43b388ee3..9bff280a227 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/RubiconConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/RubiconConfiguration.java @@ -5,11 +5,10 @@ import lombok.NoArgsConstructor; import org.prebid.server.bidder.BidderDeps; import org.prebid.server.bidder.rubicon.RubiconBidder; +import org.prebid.server.currency.CurrencyConversionService; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -32,6 +31,9 @@ public class RubiconConfiguration { @Autowired private JacksonMapper mapper; + @Autowired + private CurrencyConversionService currencyConversionService; + @Autowired @Qualifier("rubiconConfigurationProperties") private RubiconConfigurationProperties configProperties; @@ -44,15 +46,16 @@ RubiconConfigurationProperties configurationProperties() { @Bean BidderDeps rubiconBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - - return BidderDepsAssembler.forBidder(BIDDER_NAME) + return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, null)) - .bidderCreator(() -> new RubiconBidder(configProperties.getEndpoint(), - configProperties.getXapi().getUsername(), configProperties.getXapi().getPassword(), - configProperties.getMetaInfo().getSupportedVendors(), configProperties.getGenerateBidId(), + .usersyncerCreator(UsersyncerCreator.create(null)) + .bidderCreator(config -> new RubiconBidder( + config.getEndpoint(), + config.getXapi().getUsername(), + config.getXapi().getPassword(), + config.getMetaInfo().getSupportedVendors(), + config.getGenerateBidId(), + currencyConversionService, mapper)) .assemble(); } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/SharethroughConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/SharethroughConfiguration.java index 43b01c26552..f5aff9dd0ba 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/SharethroughConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/SharethroughConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps sharethroughBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new SharethroughBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new SharethroughBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/SilvermobConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/SilvermobConfiguration.java index 06d30545f85..e40e1a0887d 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/SilvermobConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/SilvermobConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.silvermob.SilvermobBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps silvermobBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new SilvermobBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new SilvermobBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/SmaatoConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/SmaatoConfiguration.java index 364493700f8..044bc17f32a 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/SmaatoConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/SmaatoConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.smaato.SmaatoBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps smaatoBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new SmaatoBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new SmaatoBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/SmartadserverConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/SmartadserverConfiguration.java index 925bd6dda7f..13f71215b5f 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/SmartadserverConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/SmartadserverConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.smartadserver.SmartadserverBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps smartadserverBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new SmartadserverBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new SmartadserverBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/SmartrtbConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/SmartrtbConfiguration.java index c9b670fe582..61c918503ee 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/SmartrtbConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/SmartrtbConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps smartrtbBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new SmartrtbBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new SmartrtbBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/SmartyAdsConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/SmartyAdsConfiguration.java index 5b7d02b3afe..84ca5a69cd5 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/SmartyAdsConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/SmartyAdsConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.smartyads.SmartyAdsBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps smartyadsBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new SmartyAdsBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new SmartyAdsBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/SomoaudienceConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/SomoaudienceConfiguration.java index 9d546b0d666..e25f8962332 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/SomoaudienceConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/SomoaudienceConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps somoaudienceBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new SomoaudienceBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new SomoaudienceBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/SonobiConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/SonobiConfiguration.java index ac9092e18df..4ca7dc80b15 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/SonobiConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/SonobiConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps sonobiBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new SonobiBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new SonobiBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/SovrnConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/SovrnConfiguration.java index d229d0a1b6f..7d1bd4ee486 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/SovrnConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/SovrnConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.sovrn.SovrnBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps sovrnBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new SovrnBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new SovrnBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/SynacormediaConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/SynacormediaConfiguration.java index f6e208cf12e..00f643b950a 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/SynacormediaConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/SynacormediaConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps synacormediaBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new SynacormediaBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new SynacormediaBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/TappxConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/TappxConfiguration.java index bb9722afb15..a9622617819 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/TappxConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/TappxConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps tappxBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new TappxBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new TappxBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/TelariaConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/TelariaConfiguration.java index 31d8b30929a..de2d207077e 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/TelariaConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/TelariaConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps telariaBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new TelariaBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new TelariaBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/TripleliftConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/TripleliftConfiguration.java index fa9fc5f2c60..022a52154bb 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/TripleliftConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/TripleliftConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps tripleliftBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new TripleliftBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new TripleliftBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/TripleliftNativeConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/TripleliftNativeConfiguration.java index d5848e023cd..e4e05980bd1 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/TripleliftNativeConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/TripleliftNativeConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,10 +44,11 @@ BidderConfigurationProperties configurationProperties() { BidderDeps tripleliftNativeBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new TripleliftNativeBidder(configProperties.getEndpoint(), - configProperties.getExtraInfo(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new TripleliftNativeBidder( + config.getEndpoint(), + config.getExtraInfo(), + mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/TtxConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/TtxConfiguration.java index 1f31ac4d3e1..e89269d7995 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/TtxConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/TtxConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps ttxBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new TtxBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new TtxBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/UcfunnelConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/UcfunnelConfiguration.java index 2eecb506205..ddd90c2d904 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/UcfunnelConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/UcfunnelConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps ucfunnelBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new UcfunnelBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new UcfunnelBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/UnicornConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/UnicornConfiguration.java new file mode 100644 index 00000000000..fcd9754f1c2 --- /dev/null +++ b/src/main/java/org/prebid/server/spring/config/bidder/UnicornConfiguration.java @@ -0,0 +1,52 @@ +package org.prebid.server.spring.config.bidder; + +import org.prebid.server.bidder.BidderDeps; +import org.prebid.server.bidder.unicorn.UnicornBidder; +import org.prebid.server.json.JacksonMapper; +import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; +import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; +import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; +import org.prebid.server.spring.env.YamlPropertySourceFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +import javax.validation.constraints.NotBlank; + +@Configuration +@PropertySource(value = "classpath:/bidder-config/unicorn.yaml", factory = YamlPropertySourceFactory.class) +public class UnicornConfiguration { + + private static final String BIDDER_NAME = "unicorn"; + + @Value("${external-url}") + @NotBlank + private String externalUrl; + + @Autowired + private JacksonMapper mapper; + + @Autowired + @Qualifier("unicornConfigurationProperties") + private BidderConfigurationProperties configProperties; + + @Bean("unicornConfigurationProperties") + @ConfigurationProperties("adapters.unicorn") + BidderConfigurationProperties configurationProperties() { + return new BidderConfigurationProperties(); + } + + @Bean + BidderDeps unicornBidderDeps() { + return BidderDepsAssembler.forBidder(BIDDER_NAME) + .withConfig(configProperties) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new UnicornBidder(config.getEndpoint(), mapper)) + .assemble(); + } +} + diff --git a/src/main/java/org/prebid/server/spring/config/bidder/UnrulyConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/UnrulyConfiguration.java index 55106c5c102..55845aad445 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/UnrulyConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/UnrulyConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps unrulyBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new UnrulyBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new UnrulyBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/ValueImpressionConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/ValueImpressionConfiguration.java index 22de2234417..c579e662316 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/ValueImpressionConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/ValueImpressionConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps valueimpressionBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new ValueImpressionBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new ValueImpressionBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/VerizonmediaConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/VerizonmediaConfiguration.java index 748173ed5f3..0d9ff349da6 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/VerizonmediaConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/VerizonmediaConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps verizonmediaBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new VerizonmediaBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new VerizonmediaBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/VisxConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/VisxConfiguration.java index 1bc27162e0e..1e543fae239 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/VisxConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/VisxConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps visxBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new VisxBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new VisxBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/VrtcalConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/VrtcalConfiguration.java index a13468fb0b3..047b2283a71 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/VrtcalConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/VrtcalConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps vrtcalBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new VrtcalBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new VrtcalBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/YieldlabConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/YieldlabConfiguration.java index 9b8d8080e36..cc4d0517374 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/YieldlabConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/YieldlabConfiguration.java @@ -4,9 +4,7 @@ import org.prebid.server.bidder.yieldlab.YieldlabBidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +42,10 @@ BidderConfigurationProperties configurationProperties() { @Bean BidderDeps yieldlabBidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new YieldlabBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new YieldlabBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/YieldmoConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/YieldmoConfiguration.java index 8dcd2fbd33d..0531bdd0777 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/YieldmoConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/YieldmoConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps yieldmoBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new YieldmoBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new YieldmoBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/YieldoneConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/YieldoneConfiguration.java index d54ae67461d..b7bc9a79902 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/YieldoneConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/YieldoneConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps yieldoneBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new YieldoneBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new YieldoneBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/ZeroclickfraudConfiguration.java b/src/main/java/org/prebid/server/spring/config/bidder/ZeroclickfraudConfiguration.java index 3fb7e97d953..c794e627d70 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/ZeroclickfraudConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/ZeroclickfraudConfiguration.java @@ -5,7 +5,6 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,9 +44,8 @@ BidderConfigurationProperties configurationProperties() { BidderDeps zeroclickfraudBidderDeps() { return BidderDepsAssembler.forBidder(BIDDER_NAME) .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) - .bidderCreator(() -> new ZeroclickfraudBidder(configProperties.getEndpoint(), mapper)) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new ZeroclickfraudBidder(config.getEndpoint(), mapper)) .assemble(); } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/model/BidderConfigurationProperties.java b/src/main/java/org/prebid/server/spring/config/bidder/model/BidderConfigurationProperties.java index 3b15c821976..498265e6549 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/model/BidderConfigurationProperties.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/model/BidderConfigurationProperties.java @@ -1,17 +1,16 @@ package org.prebid.server.spring.config.bidder.model; import lombok.Data; -import lombok.NoArgsConstructor; import org.springframework.validation.annotation.Validated; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; +import java.util.Collections; import java.util.List; import java.util.Map; @Validated @Data -@NoArgsConstructor public class BidderConfigurationProperties { @NotNull @@ -33,7 +32,7 @@ public class BidderConfigurationProperties { private List deprecatedNames; @NotNull - private List aliases; + private Map aliases = Collections.emptyMap(); @NotNull private MetaInfo metaInfo; @@ -42,4 +41,10 @@ public class BidderConfigurationProperties { private UsersyncConfigurationProperties usersync; private Map extraInfo; + + private final Class selfClass; + + public BidderConfigurationProperties() { + selfClass = this.getClass(); + } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/model/UsersyncConfigurationProperties.java b/src/main/java/org/prebid/server/spring/config/bidder/model/UsersyncConfigurationProperties.java index 1467a62ec3c..3e1c371e2c2 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/model/UsersyncConfigurationProperties.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/model/UsersyncConfigurationProperties.java @@ -24,4 +24,22 @@ public class UsersyncConfigurationProperties { @NotNull Boolean supportCors; + + SecondaryConfigurationProperties secondary; + + @Validated + @Data + @NoArgsConstructor + public static class SecondaryConfigurationProperties { + + String url; + + String redirectUrl; + + @NotBlank + String type; + + @NotNull + Boolean supportCors; + } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/util/BidderDepsAssembler.java b/src/main/java/org/prebid/server/spring/config/bidder/util/BidderDepsAssembler.java index 768102d41f3..fc25c03e32f 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/util/BidderDepsAssembler.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/util/BidderDepsAssembler.java @@ -1,74 +1,166 @@ package org.prebid.server.spring.config.bidder.util; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.lang3.StringUtils; import org.prebid.server.bidder.Bidder; import org.prebid.server.bidder.BidderDeps; +import org.prebid.server.bidder.BidderInstanceDeps; import org.prebid.server.bidder.DisabledBidder; import org.prebid.server.bidder.Usersyncer; import org.prebid.server.proto.response.BidderInfo; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; +import org.prebid.server.spring.config.bidder.model.MetaInfo; +import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; +import org.prebid.server.spring.env.YamlPropertySourceFactory; +import org.springframework.boot.context.properties.bind.Binder; +import org.springframework.boot.context.properties.source.MapConfigurationPropertySource; +import org.springframework.core.io.InputStreamResource; +import org.yaml.snakeyaml.Yaml; +import java.io.ByteArrayInputStream; +import java.util.ArrayList; import java.util.List; -import java.util.function.Supplier; +import java.util.Map; +import java.util.Properties; +import java.util.function.Function; +import java.util.stream.Collectors; -public class BidderDepsAssembler { +public class BidderDepsAssembler { private static final String ERROR_MESSAGE_TEMPLATE_FOR_DISABLED = "%s is not configured properly on this " + "Prebid Server deploy. If you believe this should work, contact the company hosting the service " + "and tell them to check their configuration."; + private static final ObjectMapper MAPPER = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .setSerializationInclusion(JsonInclude.Include.NON_NULL); + private String bidderName; - private boolean enabled; - private List deprecatedNames; - private List aliases; - private BidderInfo bidderInfo; - private Supplier usersyncerCreator; - private Supplier> bidderCreator; + private CFG configProperties; + private Function usersyncerCreator; + private Function> bidderCreator; private BidderDepsAssembler() { - enabled = false; } - public static BidderDepsAssembler forBidder(String bidderName) { - final BidderDepsAssembler assembler = new BidderDepsAssembler(); + public static BidderDepsAssembler forBidder(String bidderName) { + final BidderDepsAssembler assembler = new BidderDepsAssembler<>(); assembler.bidderName = bidderName; return assembler; } - public BidderDepsAssembler bidderInfo(BidderInfo bidderInfo) { - this.bidderInfo = bidderInfo; - return this; - } + public BidderDepsAssembler usersyncerCreator( + Function usersyncerCreator) { - public BidderDepsAssembler usersyncerCreator(Supplier usersyncerCreator) { this.usersyncerCreator = usersyncerCreator; return this; } - public BidderDepsAssembler bidderCreator(Supplier> bidderCreator) { + public BidderDepsAssembler bidderCreator(Function> bidderCreator) { this.bidderCreator = bidderCreator; return this; } - public BidderDepsAssembler withConfig(BidderConfigurationProperties configProperties) { - enabled = configProperties.getEnabled(); - deprecatedNames = configProperties.getDeprecatedNames(); - aliases = configProperties.getAliases(); + public BidderDepsAssembler withConfig(CFG configProperties) { + this.configProperties = configProperties; return this; } public BidderDeps assemble() { - final Usersyncer usersyncer = enabled ? usersyncerCreator.get() : null; + return BidderDeps.of(coreAndAliasesDeps()); + } - final Bidder bidder = enabled ? bidderCreator.get() - : new DisabledBidder(String.format(ERROR_MESSAGE_TEMPLATE_FOR_DISABLED, bidderName)); + private List coreAndAliasesDeps() { + final List deps = new ArrayList<>(); - return BidderDeps.builder() + deps.add(coreDeps()); + deps.addAll(aliasesDeps()); + + return deps; + } + + private BidderInstanceDeps coreDeps() { + return deps(bidderName, BidderInfoCreator.create(configProperties), configProperties); + } + + private List aliasesDeps() { + return configProperties.getAliases().entrySet().stream() + .map(this::aliasDeps) + .collect(Collectors.toList()); + } + + private BidderInstanceDeps aliasDeps(Map.Entry entry) { + final String alias = entry.getKey(); + final CFG aliasConfigProperties = mergeAliasConfiguration(entry.getValue(), configProperties); + + validateCapabilities(alias, aliasConfigProperties, bidderName, configProperties); + + return deps(alias, BidderInfoCreator.create(aliasConfigProperties, bidderName), aliasConfigProperties); + } + + private BidderInstanceDeps deps(String bidderName, BidderInfo bidderInfo, CFG configProperties) { + return BidderInstanceDeps.builder() .name(bidderName) - .deprecatedNames(deprecatedNames) - .aliases(aliases) + .deprecatedNames(configProperties.getDeprecatedNames()) .bidderInfo(bidderInfo) - .usersyncer(usersyncer) - .bidder(bidder) + .usersyncer(usersyncer(configProperties)) + .bidder(bidder(configProperties)) .build(); } + + private Usersyncer usersyncer(CFG configProperties) { + return configProperties.getEnabled() ? usersyncerCreator.apply(configProperties.getUsersync()) : null; + } + + private Bidder bidder(CFG configProperties) { + return configProperties.getEnabled() + ? bidderCreator.apply(configProperties) + : new DisabledBidder(String.format(ERROR_MESSAGE_TEMPLATE_FOR_DISABLED, bidderName)); + } + + private CFG mergeAliasConfiguration(Object aliasConfiguration, CFG coreConfiguration) { + return mergeConfigurations( + configurationAsPropertiesObject(aliasConfiguration, coreConfiguration.getSelfClass()), + coreConfiguration); + } + + private void validateCapabilities(String alias, CFG aliasConfiguration, String coreBidder, CFG coreConfiguration) { + final MetaInfo coreMetaInfo = coreConfiguration.getMetaInfo(); + final MetaInfo aliasMetaInfo = aliasConfiguration.getMetaInfo(); + final List coreAppMediaTypes = coreMetaInfo.getAppMediaTypes(); + final List coreSiteMediaTypes = coreMetaInfo.getSiteMediaTypes(); + final List aliasAppMediaTypes = aliasMetaInfo.getAppMediaTypes(); + final List aliasSiteMediaTypes = aliasMetaInfo.getSiteMediaTypes(); + + if (!coreAppMediaTypes.containsAll(aliasAppMediaTypes) + || !coreSiteMediaTypes.containsAll(aliasSiteMediaTypes)) { + + throw new IllegalArgumentException(String.format( + "Alias %s supports more capabilities (app: %s, site: %s) " + + "than the core bidder %s (app: %s, site: %s)", + alias, + aliasAppMediaTypes, + aliasSiteMediaTypes, + coreBidder, + coreAppMediaTypes, + coreSiteMediaTypes)); + } + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private CFG configurationAsPropertiesObject(Object configuration, Class targetClass) { + final String configAsYamlString = new Yaml().dump(configuration); + + final Properties configAsProperties = YamlPropertySourceFactory.readPropertiesFromYamlResource( + new InputStreamResource(new ByteArrayInputStream(configAsYamlString.getBytes()))); + final Binder configurationBinder = new Binder(new MapConfigurationPropertySource(configAsProperties)); + + return (CFG) configurationBinder.bind(StringUtils.EMPTY, (Class) targetClass).get(); + } + + private CFG mergeConfigurations(CFG aliasConfiguration, CFG coreConfiguration) { + return coreConfiguration; + } } diff --git a/src/main/java/org/prebid/server/spring/config/bidder/util/BidderInfoCreator.java b/src/main/java/org/prebid/server/spring/config/bidder/util/BidderInfoCreator.java index 1633f0a5824..262220f8d1e 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/util/BidderInfoCreator.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/util/BidderInfoCreator.java @@ -11,9 +11,14 @@ private BidderInfoCreator() { } public static BidderInfo create(BidderConfigurationProperties configurationProperties) { + return create(configurationProperties, null); + } + + public static BidderInfo create(BidderConfigurationProperties configurationProperties, String aliasOf) { final MetaInfo metaInfo = configurationProperties.getMetaInfo(); return BidderInfo.create( configurationProperties.getEnabled(), + aliasOf, metaInfo.getMaintainerEmail(), metaInfo.getAppMediaTypes(), metaInfo.getSiteMediaTypes(), diff --git a/src/main/java/org/prebid/server/spring/config/bidder/util/UsersyncerCreator.java b/src/main/java/org/prebid/server/spring/config/bidder/util/UsersyncerCreator.java index 8a77403476e..0a060ff26c9 100644 --- a/src/main/java/org/prebid/server/spring/config/bidder/util/UsersyncerCreator.java +++ b/src/main/java/org/prebid/server/spring/config/bidder/util/UsersyncerCreator.java @@ -1,23 +1,81 @@ package org.prebid.server.spring.config.bidder.util; +import org.apache.commons.lang3.StringUtils; import org.prebid.server.bidder.Usersyncer; import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; +import org.prebid.server.util.HttpUtil; -import java.util.function.Supplier; +import java.util.Objects; +import java.util.function.Function; public class UsersyncerCreator { private UsersyncerCreator() { + } + public static Function create(String externalUrl) { + return usersyncConfig -> createAndValidate(usersyncConfig, externalUrl); } - public static Supplier create(UsersyncConfigurationProperties usersync, String externalUrl) { - return () -> new Usersyncer( + private static Usersyncer createAndValidate(UsersyncConfigurationProperties usersync, String externalUrl) { + final Usersyncer usersyncer = Usersyncer.of( usersync.getCookieFamilyName(), + toPrimaryMethod(usersync, externalUrl), + toSecondaryMethod(usersync, externalUrl)); + + if (StringUtils.isBlank(usersyncer.getPrimaryMethod().getUsersyncUrl()) + && usersyncer.getSecondaryMethod() != null) { + throw new IllegalArgumentException(String.format( + "Invalid usersync configuration: primary method is missing while secondary is present. " + + "Configuration: %s", + usersync.toString())); + } + + return usersyncer; + } + + private static Usersyncer.UsersyncMethod toPrimaryMethod(UsersyncConfigurationProperties usersync, + String externalUrl) { + return toUsersyncMethod( usersync.getUrl(), usersync.getRedirectUrl(), externalUrl, usersync.getType(), usersync.getSupportCors()); } + + private static Usersyncer.UsersyncMethod toSecondaryMethod(UsersyncConfigurationProperties usersync, + String externalUrl) { + + final UsersyncConfigurationProperties.SecondaryConfigurationProperties secondaryMethodConfig = + usersync.getSecondary(); + + return secondaryMethodConfig != null + ? toUsersyncMethod( + secondaryMethodConfig.getUrl(), + secondaryMethodConfig.getRedirectUrl(), + externalUrl, + secondaryMethodConfig.getType(), + secondaryMethodConfig.getSupportCors()) + : null; + } + + private static Usersyncer.UsersyncMethod toUsersyncMethod(String usersyncUrl, + String redirectUrl, + String externalUri, + String type, + boolean supportCORS) { + + return Usersyncer.UsersyncMethod.of( + type, + Objects.requireNonNull(usersyncUrl), + toRedirectUrl(redirectUrl, externalUri), + supportCORS); + } + + private static String toRedirectUrl(String redirectUrl, String externalUri) { + return StringUtils.isNotBlank(redirectUrl) + ? HttpUtil.validateUrl(externalUri) + redirectUrl + : StringUtils.EMPTY; + } } diff --git a/src/main/java/org/prebid/server/spring/env/YamlPropertySourceFactory.java b/src/main/java/org/prebid/server/spring/env/YamlPropertySourceFactory.java index 2588be21a7a..6e599602b9e 100644 --- a/src/main/java/org/prebid/server/spring/env/YamlPropertySourceFactory.java +++ b/src/main/java/org/prebid/server/spring/env/YamlPropertySourceFactory.java @@ -3,6 +3,7 @@ import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; import org.springframework.core.env.PropertiesPropertySource; import org.springframework.core.env.PropertySource; +import org.springframework.core.io.Resource; import org.springframework.core.io.support.EncodedResource; import org.springframework.core.io.support.PropertySourceFactory; @@ -28,12 +29,17 @@ public PropertySource createPropertySource(@Nullable String name, @Nonnull En return new PropertiesPropertySource(sourceName, propertiesFromYaml); } + public static Properties readPropertiesFromYamlResource(Resource resource) { + final YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean(); + factory.setResources(resource); + factory.afterPropertiesSet(); + + return factory.getObject(); + } + private Properties loadYamlIntoProperties(EncodedResource resource) throws FileNotFoundException { try { - final YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean(); - factory.setResources(resource.getResource()); - factory.afterPropertiesSet(); - return factory.getObject(); + return readPropertiesFromYamlResource(resource.getResource()); } catch (IllegalStateException e) { // for ignoreResourceNotFound final Throwable cause = e.getCause(); diff --git a/src/main/java/org/prebid/server/util/HttpUtil.java b/src/main/java/org/prebid/server/util/HttpUtil.java index 3344f8d0e04..c3f6b3278b1 100644 --- a/src/main/java/org/prebid/server/util/HttpUtil.java +++ b/src/main/java/org/prebid/server/util/HttpUtil.java @@ -5,7 +5,6 @@ import io.vertx.core.MultiMap; import io.vertx.core.http.Cookie; import io.vertx.core.http.HttpHeaders; -import io.vertx.core.http.HttpServerRequest; import io.vertx.core.http.HttpServerResponse; import io.vertx.ext.web.RoutingContext; import org.apache.commons.lang3.StringUtils; @@ -33,6 +32,7 @@ public final class HttpUtil { public static final CharSequence X_REQUEST_AGENT_HEADER = HttpHeaders.createOptimized("X-Request-Agent"); public static final CharSequence ORIGIN_HEADER = HttpHeaders.createOptimized("Origin"); public static final CharSequence ACCEPT_HEADER = HttpHeaders.createOptimized("Accept"); + public static final CharSequence SEC_GPC = HttpHeaders.createOptimized("Sec-GPC"); public static final CharSequence CONTENT_TYPE_HEADER = HttpHeaders.createOptimized("Content-Type"); public static final CharSequence X_REQUESTED_WITH_HEADER = HttpHeaders.createOptimized("X-Requested-With"); public static final CharSequence REFERER_HEADER = HttpHeaders.createOptimized("Referer"); @@ -109,24 +109,7 @@ public static void addHeaderIfValueIsNotEmpty(MultiMap headers, CharSequence hea } } - /** - * Determines IP-Address by checking "X-Forwarded-For", "X-Real-IP" http headers or remote host address - * if both are empty. - */ - public static String ipFrom(HttpServerRequest request) { - // X-Forwarded-For: client1, proxy1, proxy2 - String ip = StringUtils.trimToNull( - StringUtils.substringBefore(request.headers().get("X-Forwarded-For"), ",")); - if (ip == null) { - ip = StringUtils.trimToNull(request.headers().get("X-Real-IP")); - } - if (ip == null) { - ip = StringUtils.trimToNull(request.remoteAddress().host()); - } - return ip; - } - - public static String getDomainFromUrl(String url) { + public static String getHostFromUrl(String url) { if (StringUtils.isBlank(url)) { return null; } @@ -147,7 +130,7 @@ public static String toSetCookieHeaderValue(Cookie cookie) { } /** - * Sends HTTP response according to the given status and body + * Sends HTTP response according to the given status and body. */ public static void respondWith(RoutingContext context, HttpResponseStatus status, String body) { final HttpServerResponse response = context.response().setStatusCode(status.code()); diff --git a/src/main/java/org/prebid/server/validation/BidderParamValidator.java b/src/main/java/org/prebid/server/validation/BidderParamValidator.java index 733baea9d72..13a405bd2db 100644 --- a/src/main/java/org/prebid/server/validation/BidderParamValidator.java +++ b/src/main/java/org/prebid/server/validation/BidderParamValidator.java @@ -5,6 +5,7 @@ import com.networknt.schema.JsonSchemaException; import com.networknt.schema.JsonSchemaFactory; import com.networknt.schema.ValidationMessage; +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.json.EncodeException; @@ -83,9 +84,8 @@ public static BidderParamValidator create( final Map bidderRawSchemas = new LinkedHashMap<>(); - bidderCatalog.names() - .forEach(bidderRequester -> bidderRawSchemas.put(bidderRequester, - createSchemaNode(schemaDirectory, bidderRequester, mapper))); + bidderCatalog.names().forEach(bidder -> bidderRawSchemas.put( + bidder, createSchemaNode(schemaDirectory, maybeResolveAlias(bidderCatalog, bidder), mapper))); return new BidderParamValidator(toBidderSchemas(bidderRawSchemas), toSchemas(bidderRawSchemas, mapper)); } @@ -113,6 +113,10 @@ private static JsonSchema toBidderSchema(JsonNode schema, String bidder) { return result; } + private static String maybeResolveAlias(BidderCatalog bidderCatalog, String bidder) { + return ObjectUtils.defaultIfNull(bidderCatalog.bidderInfoByName(bidder).getAliasOf(), bidder); + } + private static JsonNode createSchemaNode(String schemaDirectory, String bidder, JacksonMapper mapper) { final JsonNode result; final String path = schemaDirectory + FILE_SEP + bidder + JSON_FILE_EXT; diff --git a/src/main/java/org/prebid/server/validation/RequestValidator.java b/src/main/java/org/prebid/server/validation/RequestValidator.java index 363ed6941ab..079b45a4ecc 100644 --- a/src/main/java/org/prebid/server/validation/RequestValidator.java +++ b/src/main/java/org/prebid/server/validation/RequestValidator.java @@ -36,6 +36,7 @@ import org.apache.commons.lang3.StringUtils; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.json.JacksonMapper; +import org.prebid.server.proto.openrtb.ext.request.BidAdjustmentMediaType; import org.prebid.server.proto.openrtb.ext.request.ExtDevice; import org.prebid.server.proto.openrtb.ext.request.ExtDeviceInt; import org.prebid.server.proto.openrtb.ext.request.ExtDevicePrebid; @@ -45,6 +46,7 @@ import org.prebid.server.proto.openrtb.ext.request.ExtPriceGranularity; import org.prebid.server.proto.openrtb.ext.request.ExtRegs; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestBidadjustmentfactors; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidData; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidDataEidPermissions; @@ -136,9 +138,7 @@ public ValidationResult validate(BidRequest bidRequest) { } aliases = ObjectUtils.defaultIfNull(extRequestPrebid.getAliases(), Collections.emptyMap()); validateAliases(aliases); - validateBidAdjustmentFactors( - ObjectUtils.defaultIfNull(extRequestPrebid.getBidadjustmentfactors(), Collections.emptyMap()), - aliases); + validateBidAdjustmentFactors(extRequestPrebid.getBidadjustmentfactors(), aliases); validateExtBidPrebidData(extRequestPrebid.getData(), aliases); validateSchains(extRequestPrebid.getSchains()); } @@ -194,10 +194,14 @@ private void validateCur(List currencies) throws ValidationException { } } - private void validateBidAdjustmentFactors(Map adjustmentFactors, Map aliases) - throws ValidationException { + private void validateBidAdjustmentFactors(ExtRequestBidadjustmentfactors adjustmentFactors, + Map aliases) throws ValidationException { + + final Map bidderAdjustments = adjustmentFactors != null + ? adjustmentFactors.getAdjustments() + : Collections.emptyMap(); - for (Map.Entry bidderAdjustment : adjustmentFactors.entrySet()) { + for (Map.Entry bidderAdjustment : bidderAdjustments.entrySet()) { final String bidder = bidderAdjustment.getKey(); if (isUnknownBidderOrAlias(bidder, aliases)) { @@ -212,6 +216,41 @@ private void validateBidAdjustmentFactors(Map adjustmentFact bidder, format(adjustmentFactor)); } } + final Map> adjustmentsMediaTypeFactors = + adjustmentFactors != null + ? adjustmentFactors.getMediatypes() + : null; + + if (adjustmentsMediaTypeFactors == null) { + return; + } + + for (Map.Entry> entry + : adjustmentsMediaTypeFactors.entrySet()) { + validateBidAdjustmentFactorsByMediatype(entry.getKey(), entry.getValue(), aliases); + } + } + + private void validateBidAdjustmentFactorsByMediatype(BidAdjustmentMediaType mediaType, + Map bidderAdjustments, + Map aliases) throws ValidationException { + + for (Map.Entry bidderAdjustment : bidderAdjustments.entrySet()) { + final String bidder = bidderAdjustment.getKey(); + + if (isUnknownBidderOrAlias(bidder, aliases)) { + throw new ValidationException( + "request.ext.prebid.bidadjustmentfactors.%s.%s is not a known bidder or alias", + mediaType, bidder); + } + + final BigDecimal adjustmentFactor = bidderAdjustment.getValue(); + if (adjustmentFactor.compareTo(BigDecimal.ZERO) <= 0) { + throw new ValidationException( + "request.ext.prebid.bidadjustmentfactors.%s.%s must be a positive number. Got %s", + mediaType, bidder, format(adjustmentFactor)); + } + } } private void validateSchains(List schains) throws ValidationException { @@ -306,7 +345,7 @@ private void validateEidPermissionBidders(List bidders, } private boolean isUnknownBidderOrAlias(String bidder, Map aliases) { - return !bidderCatalog.isValidName(bidder) && !bidderCatalog.isAlias(bidder) && !aliases.containsKey(bidder); + return !bidderCatalog.isValidName(bidder) && !aliases.containsKey(bidder); } private static String format(BigDecimal value) { @@ -953,7 +992,7 @@ private void validateImpBidderExtName(int impIndex, Map.Entry throw new ValidationException("request.imp[%d].ext.prebid.bidder.%s failed validation.\n%s", impIndex, bidderName, String.join("\n", messages)); } - } else if (!bidderCatalog.isDeprecatedName(bidderName) && !bidderCatalog.isAlias(bidderName)) { + } else if (!bidderCatalog.isDeprecatedName(bidderName)) { throw new ValidationException( "request.imp[%d].ext.prebid.bidder contains unknown bidder: %s", impIndex, bidderName); } diff --git a/src/main/java/org/prebid/server/validation/ResponseBidValidator.java b/src/main/java/org/prebid/server/validation/ResponseBidValidator.java index 2b2388e5d57..b1baca9f52a 100644 --- a/src/main/java/org/prebid/server/validation/ResponseBidValidator.java +++ b/src/main/java/org/prebid/server/validation/ResponseBidValidator.java @@ -5,12 +5,15 @@ import com.iab.openrtb.request.Format; import com.iab.openrtb.request.Imp; import com.iab.openrtb.response.Bid; +import io.vertx.core.logging.Logger; +import io.vertx.core.logging.LoggerFactory; import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.prebid.server.auction.BidderAliases; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.log.ConditionalLogger; import org.prebid.server.metric.MetricName; import org.prebid.server.metric.Metrics; import org.prebid.server.proto.openrtb.ext.response.BidType; @@ -32,6 +35,9 @@ */ public class ResponseBidValidator { + private static final Logger logger = LoggerFactory.getLogger(ResponseBidValidator.class); + private static final ConditionalLogger UNRELATED_BID_LOGGER = new ConditionalLogger("not_matched_bid", logger); + private static final String[] INSECURE_MARKUP_MARKERS = {"http:", "http%3A"}; private static final String[] SECURE_MARKUP_MARKERS = {"https:", "https%3A"}; @@ -48,21 +54,27 @@ public ResponseBidValidator(BidValidationEnforcement bannerMaxSizeEnforcement, this.metrics = Objects.requireNonNull(metrics); } - public ValidationResult validate( - BidderBid bidderBid, String bidder, AuctionContext auctionContext, BidderAliases aliases) { + public ValidationResult validate(BidderBid bidderBid, + String bidder, + AuctionContext auctionContext, + BidderAliases aliases) { + final Bid bid = bidderBid.getBid(); + final BidRequest bidRequest = auctionContext.getBidRequest(); + final Account account = auctionContext.getAccount(); final List warnings = new ArrayList<>(); try { - validateCommonFields(bidderBid.getBid()); + validateCommonFields(bid); validateTypeSpecific(bidderBid); validateCurrency(bidderBid.getBidCurrency()); + final Imp correspondingImp = findCorrespondingImp(bid, bidRequest); if (bidderBid.getType() == BidType.banner) { - warnings.addAll(validateBannerFields(bidderBid, bidder, auctionContext, aliases)); + warnings.addAll(validateBannerFields(bidderBid, bidder, account, correspondingImp, aliases)); } - warnings.addAll(validateSecureMarkup(bidderBid, bidder, auctionContext, aliases)); + warnings.addAll(validateSecureMarkup(bidderBid, bidder, account, correspondingImp, aliases)); } catch (ValidationException e) { return ValidationResult.error(warnings, e.getMessage()); } @@ -71,7 +83,7 @@ public ValidationResult validate( private static void validateCommonFields(Bid bid) throws ValidationException { if (bid == null) { - throw new ValidationException("Empty bid object submitted."); + throw new ValidationException("Empty bid object submitted"); } final String bidId = bid.getId(); @@ -104,32 +116,33 @@ private static void validateCommonFields(Bid bid) throws ValidationException { private static void validateTypeSpecific(BidderBid bidderBid) throws ValidationException { final Bid bid = bidderBid.getBid(); final boolean isVastSpecificAbsent = bid.getAdm() == null && bid.getNurl() == null; + if (Objects.equals(bidderBid.getType(), BidType.video) && isVastSpecificAbsent) { throw new ValidationException("Bid \"%s\" with video type missing adm and nurl", bid.getId()); } } - private static void validateCurrency(String currency) { + private static void validateCurrency(String currency) throws ValidationException { try { if (StringUtils.isNotBlank(currency)) { Currency.getInstance(currency); } } catch (IllegalArgumentException e) { - throw new IllegalArgumentException(String.format("BidResponse currency is not valid: %s", currency), e); + throw new ValidationException("BidResponse currency \"%s\" is not valid", currency); } } private List validateBannerFields(BidderBid bidderBid, String bidder, - AuctionContext auctionContext, + Account account, + Imp correspondingImp, BidderAliases aliases) throws ValidationException { final Bid bid = bidderBid.getBid(); - final Account account = auctionContext.getAccount(); final BidValidationEnforcement bannerMaxSizeEnforcement = effectiveBannerMaxSizeEnforcement(account); if (bannerMaxSizeEnforcement != BidValidationEnforcement.skip - && bannerSizeIsNotValid(bid, auctionContext.getBidRequest())) { + && bannerSizeIsNotValid(bid, correspondingImp)) { return singleWarningOrValidationException( bannerMaxSizeEnforcement, @@ -150,8 +163,8 @@ private BidValidationEnforcement effectiveBannerMaxSizeEnforcement(Account accou return ObjectUtils.defaultIfNull(accountBannerMaxSizeEnforcement, bannerMaxSizeEnforcement); } - private static boolean bannerSizeIsNotValid(Bid bid, BidRequest bidRequest) throws ValidationException { - final Format maxSize = maxSizeForBanner(bid, bidRequest); + private static boolean bannerSizeIsNotValid(Bid bid, Imp correspondingImp) { + final Format maxSize = maxSizeForBanner(correspondingImp); final Integer bidW = bid.getW(); final Integer bidH = bid.getH(); @@ -159,10 +172,10 @@ private static boolean bannerSizeIsNotValid(Bid bid, BidRequest bidRequest) thro || bidH == null || bidH > maxSize.getH(); } - private static Format maxSizeForBanner(Bid bid, BidRequest bidRequest) throws ValidationException { + private static Format maxSizeForBanner(Imp correspondingImp) { int maxW = 0; int maxH = 0; - for (final Format size : bannerFormats(bid, bidRequest)) { + for (final Format size : bannerFormats(correspondingImp)) { maxW = Math.max(0, size.getW()); maxH = Math.max(0, size.getH()); } @@ -170,16 +183,15 @@ private static Format maxSizeForBanner(Bid bid, BidRequest bidRequest) throws Va return Format.builder().w(maxW).h(maxH).build(); } - private static List bannerFormats(Bid bid, BidRequest bidRequest) throws ValidationException { - final Imp imp = findCorrespondingImp(bidRequest, bid); - final Banner banner = imp.getBanner(); - + private static List bannerFormats(Imp correspondingImp) { + final Banner banner = correspondingImp.getBanner(); return ListUtils.emptyIfNull(banner != null ? banner.getFormat() : null); } private List validateSecureMarkup(BidderBid bidderBid, String bidder, - AuctionContext auctionContext, + Account account, + Imp correspondingImp, BidderAliases aliases) throws ValidationException { if (secureMarkupEnforcement == BidValidationEnforcement.skip) { @@ -187,13 +199,12 @@ private List validateSecureMarkup(BidderBid bidderBid, } final Bid bid = bidderBid.getBid(); - final Imp imp = findCorrespondingImp(auctionContext.getBidRequest(), bidderBid.getBid()); - if (isImpSecure(imp) && markupIsNotSecure(bid)) { + if (isImpSecure(correspondingImp) && markupIsNotSecure(bid)) { return singleWarningOrValidationException( secureMarkupEnforcement, metricName -> metrics.updateSecureValidationMetrics( - aliases.resolveBidder(bidder), auctionContext.getAccount().getId(), metricName), + aliases.resolveBidder(bidder), account.getId(), metricName), "Bid \"%s\" has insecure creative but should be in secure context", bid.getId()); } @@ -201,15 +212,20 @@ private List validateSecureMarkup(BidderBid bidderBid, return Collections.emptyList(); } - private static Imp findCorrespondingImp(BidRequest bidRequest, Bid bid) throws ValidationException { + private static Imp findCorrespondingImp(Bid bid, BidRequest bidRequest) throws ValidationException { return bidRequest.getImp().stream() - .filter(curImp -> Objects.equals(curImp.getId(), bid.getImpid())) + .filter(imp -> Objects.equals(imp.getId(), bid.getImpid())) .findFirst() - .orElseThrow(() -> new ValidationException( - "Bid \"%s\" has no corresponding imp in request", bid.getId())); + .orElseThrow(() -> exceptionAndLogOnePercent( + String.format("Bid \"%s\" has no corresponding imp in request", bid.getId()))); } - public static boolean isImpSecure(Imp imp) { + private static ValidationException exceptionAndLogOnePercent(String message) { + UNRELATED_BID_LOGGER.warn(message, 0.01); + return new ValidationException(message); + } + + private static boolean isImpSecure(Imp imp) { return Objects.equals(imp.getSecure(), 1); } @@ -224,7 +240,6 @@ private static List singleWarningOrValidationException(BidValidationEnfo Consumer metricsRecorder, String message, Object... args) throws ValidationException { - switch (enforcement) { case enforce: metricsRecorder.accept(MetricName.err); diff --git a/src/main/java/org/prebid/server/validation/VideoRequestValidator.java b/src/main/java/org/prebid/server/validation/VideoRequestValidator.java index 8bca4bbf02a..02e1e353bb6 100644 --- a/src/main/java/org/prebid/server/validation/VideoRequestValidator.java +++ b/src/main/java/org/prebid/server/validation/VideoRequestValidator.java @@ -166,5 +166,4 @@ private static List validateEachPod(List pods) { } return podErrorsResult; } - } diff --git a/src/main/resources/bidder-config/acuityads.yaml b/src/main/resources/bidder-config/acuityads.yaml index 8847e12856c..01113d5a930 100644 --- a/src/main/resources/bidder-config/acuityads.yaml +++ b/src/main/resources/bidder-config/acuityads.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: integrations@acuityads.com app-media-types: diff --git a/src/main/resources/bidder-config/adform.yaml b/src/main/resources/bidder-config/adform.yaml index 2924ef3707a..b9d10ca014d 100644 --- a/src/main/resources/bidder-config/adform.yaml +++ b/src/main/resources/bidder-config/adform.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: scope.sspp@adform.com app-media-types: diff --git a/src/main/resources/bidder-config/adgeneration.yaml b/src/main/resources/bidder-config/adgeneration.yaml index 136809a7e3a..37e26b93fcd 100644 --- a/src/main/resources/bidder-config/adgeneration.yaml +++ b/src/main/resources/bidder-config/adgeneration.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: ssp-ope@supership.jp app-media-types: diff --git a/src/main/resources/bidder-config/adhese.yaml b/src/main/resources/bidder-config/adhese.yaml index 31fc7f928cc..2f2f8cdd15b 100644 --- a/src/main/resources/bidder-config/adhese.yaml +++ b/src/main/resources/bidder-config/adhese.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: info@adhese.com app-media-types: diff --git a/src/main/resources/bidder-config/adkernel.yaml b/src/main/resources/bidder-config/adkernel.yaml index 9f00b37cbd3..7579337265c 100644 --- a/src/main/resources/bidder-config/adkernel.yaml +++ b/src/main/resources/bidder-config/adkernel.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid-dev@adkernel.com app-media-types: diff --git a/src/main/resources/bidder-config/adkerneladn.yaml b/src/main/resources/bidder-config/adkerneladn.yaml index 2c0f93c7c66..fc9f7ae41ee 100644 --- a/src/main/resources/bidder-config/adkerneladn.yaml +++ b/src/main/resources/bidder-config/adkerneladn.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid-dev@adkernel.com app-media-types: diff --git a/src/main/resources/bidder-config/adman.yaml b/src/main/resources/bidder-config/adman.yaml index 2eea6558af4..031694850f4 100644 --- a/src/main/resources/bidder-config/adman.yaml +++ b/src/main/resources/bidder-config/adman.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@admanmedia.com app-media-types: diff --git a/src/main/resources/bidder-config/admixer.yaml b/src/main/resources/bidder-config/admixer.yaml index 244dbccdcb6..291427b4940 100644 --- a/src/main/resources/bidder-config/admixer.yaml +++ b/src/main/resources/bidder-config/admixer.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: "prebid@admixer.net" app-media-types: diff --git a/src/main/resources/bidder-config/adocean.yaml b/src/main/resources/bidder-config/adocean.yaml index 146b12edacb..343495542d8 100644 --- a/src/main/resources/bidder-config/adocean.yaml +++ b/src/main/resources/bidder-config/adocean.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: aoteam@gemius.com app-media-types: diff --git a/src/main/resources/bidder-config/adoppler.yaml b/src/main/resources/bidder-config/adoppler.yaml index 203ae18907e..2da613a35a7 100644 --- a/src/main/resources/bidder-config/adoppler.yaml +++ b/src/main/resources/bidder-config/adoppler.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: "info@adoppler.com" app-media-types: diff --git a/src/main/resources/bidder-config/adot.yaml b/src/main/resources/bidder-config/adot.yaml index dd946ce11c7..b8591168da6 100644 --- a/src/main/resources/bidder-config/adot.yaml +++ b/src/main/resources/bidder-config/adot.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: false deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: admin@we-are-adot.com" app-media-types: diff --git a/src/main/resources/bidder-config/adpone.yaml b/src/main/resources/bidder-config/adpone.yaml index c34a33e49a4..29008b957d3 100644 --- a/src/main/resources/bidder-config/adpone.yaml +++ b/src/main/resources/bidder-config/adpone.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: tech@adpone.com app-media-types: diff --git a/src/main/resources/bidder-config/adprime.yaml b/src/main/resources/bidder-config/adprime.yaml index 5ac2c4c0eca..005768b385c 100644 --- a/src/main/resources/bidder-config/adprime.yaml +++ b/src/main/resources/bidder-config/adprime.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@adprime.com app-media-types: diff --git a/src/main/resources/bidder-config/adtarget.yaml b/src/main/resources/bidder-config/adtarget.yaml index 82df7f78e53..5858c3aa2ab 100644 --- a/src/main/resources/bidder-config/adtarget.yaml +++ b/src/main/resources/bidder-config/adtarget.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: kamil@adtarget.com.tr app-media-types: @@ -18,8 +18,8 @@ adapters: supported-vendors: vendor-id: 779 usersync: - url: https://sync.console.adtarget.com.tr/csync?t=p&ep=0&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&redir= - redirect-url: /setuid?bidder=adtarget&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&uid={uid} + url: + redirect-url: cookie-family-name: adtarget - type: redirect + type: iframe support-cors: false diff --git a/src/main/resources/bidder-config/adtelligent.yaml b/src/main/resources/bidder-config/adtelligent.yaml index c43f508cee2..e1f65e32470 100644 --- a/src/main/resources/bidder-config/adtelligent.yaml +++ b/src/main/resources/bidder-config/adtelligent.yaml @@ -7,6 +7,16 @@ adapters: modifying-vast-xml-allowed: true deprecated-names: aliases: + mediafuse: + enabled: false + endpoint: http://ghb.hbmp.mediafuse.com/pbs/ortb + meta-info: + maintainer-email: support@mediafuse.com + vendor-id: 411 + usersync: + url: + redirect-url: + cookie-family-name: mediafuse meta-info: maintainer-email: hb@adtelligent.com app-media-types: @@ -18,8 +28,8 @@ adapters: supported-vendors: vendor-id: 410 usersync: - url: https://sync.adtelligent.com/csync?t=p&ep=0&gdpr={{gdpr}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&redir= - redirect-url: /setuid?bidder=adtelligent&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&uid={uid} + url: + redirect-url: cookie-family-name: adtelligent - type: redirect + type: iframe support-cors: false diff --git a/src/main/resources/bidder-config/advangelists.yaml b/src/main/resources/bidder-config/advangelists.yaml index 581fc579cd4..317f677cf8a 100644 --- a/src/main/resources/bidder-config/advangelists.yaml +++ b/src/main/resources/bidder-config/advangelists.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@advangelists.com app-media-types: diff --git a/src/main/resources/bidder-config/adyoulike.yaml b/src/main/resources/bidder-config/adyoulike.yaml new file mode 100644 index 00000000000..c04390734e1 --- /dev/null +++ b/src/main/resources/bidder-config/adyoulike.yaml @@ -0,0 +1,24 @@ +adapters: + adyoulike: + enabled: false + endpoint: https://broker.omnitagjs.com/broker/bid?partnerId=19340f4f097d16f41f34fc0274981ca4 + pbs-enforces-gdpr: true + pbs-enforces-ccpa: true + modifying-vast-xml-allowed: true + deprecated-names: + aliases: {} + meta-info: + maintainer-email: core@adyoulike.com + app-media-types: + site-media-types: + - banner + - video + - native + supported-vendors: + vendor-id: 259 + usersync: + url: http://visitor.omnitagjs.com/visitor/bsync?uid=19340f4f097d16f41f34fc0274981ca4&name=PrebidServer&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&url= + redirect-url: /setuid?bidder=adyoulike&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&uid=[BUYER_USERID] + cookie-family-name: adyoulike + type: redirect + support-cors: false diff --git a/src/main/resources/bidder-config/aja.yaml b/src/main/resources/bidder-config/aja.yaml index 24dc12310fc..6a30e64d555 100644 --- a/src/main/resources/bidder-config/aja.yaml +++ b/src/main/resources/bidder-config/aja.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: dev@aja-kk.co.jp app-media-types: diff --git a/src/main/resources/bidder-config/amx.yaml b/src/main/resources/bidder-config/amx.yaml index 2b59825225b..86d479e7f88 100644 --- a/src/main/resources/bidder-config/amx.yaml +++ b/src/main/resources/bidder-config/amx.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@amxrtb.com app-media-types: diff --git a/src/main/resources/bidder-config/applogy.yaml b/src/main/resources/bidder-config/applogy.yaml index a8f0ec4119a..5ab676d8eb5 100644 --- a/src/main/resources/bidder-config/applogy.yaml +++ b/src/main/resources/bidder-config/applogy.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: work@applogy.com app-media-types: diff --git a/src/main/resources/bidder-config/appnexus.yaml b/src/main/resources/bidder-config/appnexus.yaml index f78f4cd26a8..a701a054cc9 100644 --- a/src/main/resources/bidder-config/appnexus.yaml +++ b/src/main/resources/bidder-config/appnexus.yaml @@ -6,7 +6,9 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: districtm + aliases: + districtm: + enabled: false meta-info: maintainer-email: prebid-server@xandr.com app-media-types: diff --git a/src/main/resources/bidder-config/avocet.yaml b/src/main/resources/bidder-config/avocet.yaml index e69decbfcc6..f85bb70f0dc 100644 --- a/src/main/resources/bidder-config/avocet.yaml +++ b/src/main/resources/bidder-config/avocet.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: developers@avocet.io app-media-types: diff --git a/src/main/resources/bidder-config/beachfront.yaml b/src/main/resources/bidder-config/beachfront.yaml index 61bbdbcbfd5..36f929269c8 100644 --- a/src/main/resources/bidder-config/beachfront.yaml +++ b/src/main/resources/bidder-config/beachfront.yaml @@ -7,7 +7,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@beachfront.com app-media-types: diff --git a/src/main/resources/bidder-config/beintoo.yaml b/src/main/resources/bidder-config/beintoo.yaml index 2b893499f07..fcf94a6285c 100644 --- a/src/main/resources/bidder-config/beintoo.yaml +++ b/src/main/resources/bidder-config/beintoo.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: adops@beintoo.com app-media-types: diff --git a/src/main/resources/bidder-config/between.yaml b/src/main/resources/bidder-config/between.yaml index 954d9ffeb5b..1ba64253844 100644 --- a/src/main/resources/bidder-config/between.yaml +++ b/src/main/resources/bidder-config/between.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: buying@betweenx.com app-media-types: @@ -16,7 +16,7 @@ adapters: supported-vendors: vendor-id: 724 usersync: - url: https://ads.betweendigital.com/match?bidder_id=pbs&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&callback_url= + url: https://ads.betweendigital.com/match?bidder_id=pbs&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&callback_url= redirect-url: /setuid?bidder=between&gdpr=0&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}&uid=${USER_ID} cookie-family-name: between type: redirect diff --git a/src/main/resources/bidder-config/brightroll.yaml b/src/main/resources/bidder-config/brightroll.yaml index 4025deeaffa..62b83d3cfd3 100644 --- a/src/main/resources/bidder-config/brightroll.yaml +++ b/src/main/resources/bidder-config/brightroll.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: dsp-supply-prebid@verizonmedia.com app-media-types: diff --git a/src/main/resources/bidder-config/colossus.yaml b/src/main/resources/bidder-config/colossus.yaml index af0a71ff8fc..532c9d7abf6 100644 --- a/src/main/resources/bidder-config/colossus.yaml +++ b/src/main/resources/bidder-config/colossus.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: support@huddledmasses.com app-media-types: diff --git a/src/main/resources/bidder-config/connectad.yaml b/src/main/resources/bidder-config/connectad.yaml index 77ef5fe20ea..679682927c3 100644 --- a/src/main/resources/bidder-config/connectad.yaml +++ b/src/main/resources/bidder-config/connectad.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: support@connectad.io app-media-types: diff --git a/src/main/resources/bidder-config/consumable.yaml b/src/main/resources/bidder-config/consumable.yaml index 173a813205c..df35aa02551 100644 --- a/src/main/resources/bidder-config/consumable.yaml +++ b/src/main/resources/bidder-config/consumable.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: naffis@consumable.com app-media-types: diff --git a/src/main/resources/bidder-config/conversant.yaml b/src/main/resources/bidder-config/conversant.yaml index ac2caabe8ce..bbb2cf28bb7 100644 --- a/src/main/resources/bidder-config/conversant.yaml +++ b/src/main/resources/bidder-config/conversant.yaml @@ -7,7 +7,7 @@ adapters: modifying-vast-xml-allowed: true generate-bid-id: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: CNVR_PublisherIntegration@conversantmedia.com app-media-types: diff --git a/src/main/resources/bidder-config/cpmstar.yaml b/src/main/resources/bidder-config/cpmstar.yaml index d85db422ef1..6577b5d39b4 100644 --- a/src/main/resources/bidder-config/cpmstar.yaml +++ b/src/main/resources/bidder-config/cpmstar.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@cpmstar.com app-media-types: diff --git a/src/main/resources/bidder-config/datablocks.yaml b/src/main/resources/bidder-config/datablocks.yaml index e97fecb40b5..bd697165e1f 100644 --- a/src/main/resources/bidder-config/datablocks.yaml +++ b/src/main/resources/bidder-config/datablocks.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@datablocks.net app-media-types: diff --git a/src/main/resources/bidder-config/decenterads.yaml b/src/main/resources/bidder-config/decenterads.yaml new file mode 100644 index 00000000000..ea72423d6da --- /dev/null +++ b/src/main/resources/bidder-config/decenterads.yaml @@ -0,0 +1,27 @@ +adapters: + decenterads: + enabled: false + endpoint: http://supply.decenterads.com/?c=o&m=rtb + pbs-enforces-gdpr: true + pbs-enforces-ccpa: true + modifying-vast-xml-allowed: true + deprecated-names: + aliases: {} + meta-info: + maintainer-email: support@decenterads.com + app-media-types: + - banner + - video + - native + site-media-types: + - banner + - video + - native + supported-vendors: + vendor-id: 0 + usersync: + url: + redirect-url: + cookie-family-name: decenterads + type: redirect + support-cors: false diff --git a/src/main/resources/bidder-config/deepintent.yaml b/src/main/resources/bidder-config/deepintent.yaml index b140708beb3..5f59148f1a2 100644 --- a/src/main/resources/bidder-config/deepintent.yaml +++ b/src/main/resources/bidder-config/deepintent.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: sourabh@deepintent.com app-media-types: @@ -17,7 +17,7 @@ adapters: vendor-id: 541 usersync: url: https://match.deepintent.com/usersync/136?id=unk&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&redir= - redirect-url: /setuid?bidder=deepintent&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&uid=[UID] + redirect-url: /setuid?bidder=deepintent&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&uid=${DI_USER_ID} cookie-family-name: deepintent type: iframe support-cors: false diff --git a/src/main/resources/bidder-config/dmx.yaml b/src/main/resources/bidder-config/dmx.yaml index 0086d0c36d4..4bab8e05e2c 100644 --- a/src/main/resources/bidder-config/dmx.yaml +++ b/src/main/resources/bidder-config/dmx.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@districtm.net app-media-types: diff --git a/src/main/resources/bidder-config/emxdigital.yaml b/src/main/resources/bidder-config/emxdigital.yaml index 47434023da3..a734fedc8e3 100644 --- a/src/main/resources/bidder-config/emxdigital.yaml +++ b/src/main/resources/bidder-config/emxdigital.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: adops@emxdigital.com app-media-types: diff --git a/src/main/resources/bidder-config/engagebdr.yaml b/src/main/resources/bidder-config/engagebdr.yaml index d6fdf49f6fd..e3a4237e80c 100644 --- a/src/main/resources/bidder-config/engagebdr.yaml +++ b/src/main/resources/bidder-config/engagebdr.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: tech@engagebdr.com app-media-types: @@ -17,8 +17,8 @@ adapters: supported-vendors: vendor-id: 62 usersync: - url: https://match.bnmla.com/usersync/s2s_sync?gdpr={{gdpr}}&gdpr_consent={gdpr_consent}}&us_privacy={{us_privacy}}&r= - redirect-url: /setuid?bidder=visx&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&uid={UUID} + url: https://match.bnmla.com/usersync?sspid=1000363&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&redir= + redirect-url: /setuid?bidder=engagebdr&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&uid={UUID} cookie-family-name: engagebdr type: iframe support-cors: false diff --git a/src/main/resources/bidder-config/eplanning.yaml b/src/main/resources/bidder-config/eplanning.yaml index 4a0e76766fd..6e316e04cfb 100644 --- a/src/main/resources/bidder-config/eplanning.yaml +++ b/src/main/resources/bidder-config/eplanning.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: producto@e-planning.net app-media-types: diff --git a/src/main/resources/bidder-config/epom.yaml b/src/main/resources/bidder-config/epom.yaml new file mode 100644 index 00000000000..b633dec1b31 --- /dev/null +++ b/src/main/resources/bidder-config/epom.yaml @@ -0,0 +1,27 @@ +adapters: + epom: + enabled: false + endpoint: https://an.epom.com/ortb + pbs-enforces-gdpr: true + pbs-enforces-ccpa: true + modifying-vast-xml-allowed: true + deprecated-names: + aliases: {} + meta-info: + maintainer-email: support@epom.com + app-media-types: + - banner + - video + - native + site-media-types: + - banner + - video + - native + supported-vendors: + vendor-id: 849 + usersync: + url: + redirect-url: + cookie-family-name: epom + type: iframe + support-cors: false diff --git a/src/main/resources/bidder-config/facebook.yaml b/src/main/resources/bidder-config/facebook.yaml index abbd50098c4..5d6c22a9928 100644 --- a/src/main/resources/bidder-config/facebook.yaml +++ b/src/main/resources/bidder-config/facebook.yaml @@ -9,7 +9,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: none app-media-types: diff --git a/src/main/resources/bidder-config/gamma.yaml b/src/main/resources/bidder-config/gamma.yaml index 26646687c60..47ff4c491f9 100644 --- a/src/main/resources/bidder-config/gamma.yaml +++ b/src/main/resources/bidder-config/gamma.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: support@gammassp.com app-media-types: diff --git a/src/main/resources/bidder-config/gamoshi.yaml b/src/main/resources/bidder-config/gamoshi.yaml index 397d77f6682..e0ab8775717 100644 --- a/src/main/resources/bidder-config/gamoshi.yaml +++ b/src/main/resources/bidder-config/gamoshi.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: dev@gamoshi.com app-media-types: diff --git a/src/main/resources/bidder-config/grid.yaml b/src/main/resources/bidder-config/grid.yaml index 6f8de26c1a4..f8cfb77b6c5 100644 --- a/src/main/resources/bidder-config/grid.yaml +++ b/src/main/resources/bidder-config/grid.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: grid-tech@themediagrid.com app-media-types: diff --git a/src/main/resources/bidder-config/gumgum.yaml b/src/main/resources/bidder-config/gumgum.yaml index 275c725872c..eb8bf5fb9e5 100644 --- a/src/main/resources/bidder-config/gumgum.yaml +++ b/src/main/resources/bidder-config/gumgum.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@gumgum.com app-media-types: diff --git a/src/main/resources/bidder-config/improvedigital.yaml b/src/main/resources/bidder-config/improvedigital.yaml index 776c1565851..b4ee74bd8c2 100644 --- a/src/main/resources/bidder-config/improvedigital.yaml +++ b/src/main/resources/bidder-config/improvedigital.yaml @@ -6,15 +6,17 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: hb@azerion.com app-media-types: - banner - video + - native site-media-types: - banner - video + - native supported-vendors: vendor-id: 253 usersync: diff --git a/src/main/resources/bidder-config/inmobi.yaml b/src/main/resources/bidder-config/inmobi.yaml index 275968871a7..a821ab11cff 100644 --- a/src/main/resources/bidder-config/inmobi.yaml +++ b/src/main/resources/bidder-config/inmobi.yaml @@ -6,13 +6,15 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid-support@inmobi.com app-media-types: - banner - video site-media-types: + - banner + - video supported-vendors: vendor-id: 333 usersync: diff --git a/src/main/resources/bidder-config/invibes.yaml b/src/main/resources/bidder-config/invibes.yaml index 677164c1a18..f133b423930 100644 --- a/src/main/resources/bidder-config/invibes.yaml +++ b/src/main/resources/bidder-config/invibes.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: system_operations@invibes.com site-media-types: diff --git a/src/main/resources/bidder-config/ix.yaml b/src/main/resources/bidder-config/ix.yaml index 3a193f920e5..85483b59718 100644 --- a/src/main/resources/bidder-config/ix.yaml +++ b/src/main/resources/bidder-config/ix.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: indexExchange - aliases: + aliases: {} meta-info: maintainer-email: pdu-supply-prebid@indexexchange.com app-media-types: diff --git a/src/main/resources/bidder-config/jixie.yaml b/src/main/resources/bidder-config/jixie.yaml new file mode 100644 index 00000000000..b88c2357550 --- /dev/null +++ b/src/main/resources/bidder-config/jixie.yaml @@ -0,0 +1,23 @@ +adapters: + jixie: + enabled: false + endpoint: https://hb.jixie.io/v2/hbsvrpost + pbs-enforces-gdpr: true + pbs-enforces-ccpa: true + modifying-vast-xml-allowed: true + deprecated-names: + aliases: {} + meta-info: + maintainer-email: contact@jixie.io + app-media-types: + site-media-types: + - banner + - video + supported-vendors: + vendor-id: 0 + usersync: + url: https://id.jixie.io/api/sync?pid=&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&redirect= + redirect-url: /setuid?bidder=jixie&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&uid=%%JXUID%% + cookie-family-name: jixie + type: redirect + support-cors: false diff --git a/src/main/resources/bidder-config/kidoz.yaml b/src/main/resources/bidder-config/kidoz.yaml index b014675efd0..5474b27c725 100644 --- a/src/main/resources/bidder-config/kidoz.yaml +++ b/src/main/resources/bidder-config/kidoz.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid-support@kidoz.net app-media-types: diff --git a/src/main/resources/bidder-config/krushmedia.yaml b/src/main/resources/bidder-config/krushmedia.yaml index 94f1ac14122..cc1f8ddd784 100644 --- a/src/main/resources/bidder-config/krushmedia.yaml +++ b/src/main/resources/bidder-config/krushmedia.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: adapter@krushmedia.com app-media-types: diff --git a/src/main/resources/bidder-config/kubient.yaml b/src/main/resources/bidder-config/kubient.yaml index b8856f0ff40..2dc8e27374d 100644 --- a/src/main/resources/bidder-config/kubient.yaml +++ b/src/main/resources/bidder-config/kubient.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@kubient.com app-media-types: diff --git a/src/main/resources/bidder-config/lifestreet.yaml b/src/main/resources/bidder-config/lifestreet.yaml index 446a6f79b03..89ba60eccaa 100644 --- a/src/main/resources/bidder-config/lifestreet.yaml +++ b/src/main/resources/bidder-config/lifestreet.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: mobile.tech@lifestreet.com app-media-types: diff --git a/src/main/resources/bidder-config/lockerdome.yaml b/src/main/resources/bidder-config/lockerdome.yaml index b693b2c8489..a3636da97fd 100644 --- a/src/main/resources/bidder-config/lockerdome.yaml +++ b/src/main/resources/bidder-config/lockerdome.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: bidding@lockerdome.com app-media-types: diff --git a/src/main/resources/bidder-config/logicad.yaml b/src/main/resources/bidder-config/logicad.yaml index 659e8a9be15..27f6e6388eb 100644 --- a/src/main/resources/bidder-config/logicad.yaml +++ b/src/main/resources/bidder-config/logicad.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@so-netmedia.jp app-media-types: diff --git a/src/main/resources/bidder-config/lunamedia.yaml b/src/main/resources/bidder-config/lunamedia.yaml index 04a58ecc482..27be0aa060a 100644 --- a/src/main/resources/bidder-config/lunamedia.yaml +++ b/src/main/resources/bidder-config/lunamedia.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: josh@lunamedia.io app-media-types: diff --git a/src/main/resources/bidder-config/marsmedia.yaml b/src/main/resources/bidder-config/marsmedia.yaml index 6bcff853d1b..4dea715eb0e 100644 --- a/src/main/resources/bidder-config/marsmedia.yaml +++ b/src/main/resources/bidder-config/marsmedia.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@mars.media app-media-types: diff --git a/src/main/resources/bidder-config/mgid.yaml b/src/main/resources/bidder-config/mgid.yaml index 091085b4b56..54f0e4b83a7 100644 --- a/src/main/resources/bidder-config/mgid.yaml +++ b/src/main/resources/bidder-config/mgid.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@mgid.com app-media-types: diff --git a/src/main/resources/bidder-config/mobfoxpb.yaml b/src/main/resources/bidder-config/mobfoxpb.yaml index e19a2042a94..138de40585f 100644 --- a/src/main/resources/bidder-config/mobfoxpb.yaml +++ b/src/main/resources/bidder-config/mobfoxpb.yaml @@ -1,12 +1,12 @@ adapters: mobfoxpb: enabled: false - endpoint: http://bes.mobfox.com/?c=o&m=ortb + endpoint: http://bes.mobfox.com/?c=__route__&m=__method__&key=__key__ pbs-enforces-gdpr: true pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: platform@mobfox.com app-media-types: diff --git a/src/main/resources/bidder-config/mobilefuse.yaml b/src/main/resources/bidder-config/mobilefuse.yaml index 2f47ae1796c..c894ec28e5d 100644 --- a/src/main/resources/bidder-config/mobilefuse.yaml +++ b/src/main/resources/bidder-config/mobilefuse.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@mobilefuse.com app-media-types: diff --git a/src/main/resources/bidder-config/nanointeractive.yaml b/src/main/resources/bidder-config/nanointeractive.yaml index 88099ec6440..5ed47efd535 100644 --- a/src/main/resources/bidder-config/nanointeractive.yaml +++ b/src/main/resources/bidder-config/nanointeractive.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: development@nanointeractive.com app-media-types: diff --git a/src/main/resources/bidder-config/ninthdecimal.yaml b/src/main/resources/bidder-config/ninthdecimal.yaml index ac27d2b59c7..2b6f6790fd3 100644 --- a/src/main/resources/bidder-config/ninthdecimal.yaml +++ b/src/main/resources/bidder-config/ninthdecimal.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: abudig@ninthdecimal.com app-media-types: diff --git a/src/main/resources/bidder-config/nobid.yaml b/src/main/resources/bidder-config/nobid.yaml index 2312d7f3469..b464cf5dfa7 100644 --- a/src/main/resources/bidder-config/nobid.yaml +++ b/src/main/resources/bidder-config/nobid.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: developers@nobid.io app-media-types: diff --git a/src/main/resources/bidder-config/onetag.yaml b/src/main/resources/bidder-config/onetag.yaml new file mode 100644 index 00000000000..ad6a5be202b --- /dev/null +++ b/src/main/resources/bidder-config/onetag.yaml @@ -0,0 +1,27 @@ +adapters: + onetag: + enabled: false + endpoint: https://prebid-server.onetag-sys.com/prebid-server/{{publisherId}} + pbs-enforces-gdpr: true + pbs-enforces-ccpa: true + modifying-vast-xml-allowed: true + deprecated-names: + aliases: {} + meta-info: + maintainer-email: devops@onetag.com + app-media-types: + - banner + - video + - native + site-media-types: + - banner + - video + - native + supported-vendors: + vendor-id: 241 + usersync: + url: https://onetag-sys.com/usync/?redir= + redirect-url: /setuid?bidder=onetag&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&uid=${USER_TOKEN} + cookie-family-name: onetag + type: iframe + support-cors: false diff --git a/src/main/resources/bidder-config/openx.yaml b/src/main/resources/bidder-config/openx.yaml index fd1064c5142..9f52c68146c 100644 --- a/src/main/resources/bidder-config/openx.yaml +++ b/src/main/resources/bidder-config/openx.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@openx.com app-media-types: diff --git a/src/main/resources/bidder-config/orbidder.yaml b/src/main/resources/bidder-config/orbidder.yaml index 846ecd38f6e..612d24275bf 100644 --- a/src/main/resources/bidder-config/orbidder.yaml +++ b/src/main/resources/bidder-config/orbidder.yaml @@ -6,15 +6,14 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: realtime-siggi@otto.de app-media-types: - banner site-media-types: - - banner supported-vendors: - vendor-id: 0 + vendor-id: 559 usersync: url: redirect-url: diff --git a/src/main/resources/bidder-config/outbrain.yaml b/src/main/resources/bidder-config/outbrain.yaml new file mode 100644 index 00000000000..40454e1d9aa --- /dev/null +++ b/src/main/resources/bidder-config/outbrain.yaml @@ -0,0 +1,25 @@ +adapters: + outbrain: + enabled: false + endpoint: https://prebidtest.zemanta.com/api/bidder/prebidtest/bid/ + pbs-enforces-gdpr: true + pbs-enforces-ccpa: true + modifying-vast-xml-allowed: true + deprecated-names: + aliases: {} + meta-info: + maintainer-email: prog-ops-team@outbrain.com + app-media-types: + - banner + - native + site-media-types: + - banner + - native + supported-vendors: + vendor-id: 164 + usersync: + url: https://prebidtest.zemanta.com/usersync/prebidtest?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&cb= + redirect-url: /setuid?bidder=outbrain&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&uid=__ZUID__ + cookie-family-name: outbrain + type: redirect + support-cors: false diff --git a/src/main/resources/bidder-config/pangle.yaml b/src/main/resources/bidder-config/pangle.yaml new file mode 100644 index 00000000000..2447d2edbb7 --- /dev/null +++ b/src/main/resources/bidder-config/pangle.yaml @@ -0,0 +1,24 @@ +adapters: + pangle: + enabled: false + endpoint: https:// + pbs-enforces-gdpr: true + pbs-enforces-ccpa: true + modifying-vast-xml-allowed: true + deprecated-names: + aliases: {} + meta-info: + maintainer-email: pangle_dsp@bytedance.com + app-media-types: + - banner + - video + - native + site-media-types: + supported-vendors: + vendor-id: 0 + usersync: + url: + redirect-url: + cookie-family-name: pangle + type: redirect + support-cors: false diff --git a/src/main/resources/bidder-config/pubmatic.yaml b/src/main/resources/bidder-config/pubmatic.yaml index a9542884382..cf8c21b9206 100644 --- a/src/main/resources/bidder-config/pubmatic.yaml +++ b/src/main/resources/bidder-config/pubmatic.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: header-bidding@pubmatic.com app-media-types: diff --git a/src/main/resources/bidder-config/pubnative.yaml b/src/main/resources/bidder-config/pubnative.yaml index b7c8c0cc7bc..1774325bb29 100644 --- a/src/main/resources/bidder-config/pubnative.yaml +++ b/src/main/resources/bidder-config/pubnative.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: product@pubnative.net app-media-types: diff --git a/src/main/resources/bidder-config/pulsepoint.yaml b/src/main/resources/bidder-config/pulsepoint.yaml index 0b9a11f11ff..3aae50737f2 100644 --- a/src/main/resources/bidder-config/pulsepoint.yaml +++ b/src/main/resources/bidder-config/pulsepoint.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: ExchangeTeam@pulsepoint.com app-media-types: diff --git a/src/main/resources/bidder-config/revcontent.yaml b/src/main/resources/bidder-config/revcontent.yaml index 8077ff27c8a..7783b2ba26d 100644 --- a/src/main/resources/bidder-config/revcontent.yaml +++ b/src/main/resources/bidder-config/revcontent.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: developers@revcontent.com app-media-types: diff --git a/src/main/resources/bidder-config/rhythmone.yaml b/src/main/resources/bidder-config/rhythmone.yaml index dea2ebc3a3f..5b65221b008 100644 --- a/src/main/resources/bidder-config/rhythmone.yaml +++ b/src/main/resources/bidder-config/rhythmone.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: support@rhythmone.com app-media-types: diff --git a/src/main/resources/bidder-config/rtbhouse.yaml b/src/main/resources/bidder-config/rtbhouse.yaml index b1ea36d685a..5e59957c9c3 100644 --- a/src/main/resources/bidder-config/rtbhouse.yaml +++ b/src/main/resources/bidder-config/rtbhouse.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@rtbhouse.com app-media-types: diff --git a/src/main/resources/bidder-config/rubicon.yaml b/src/main/resources/bidder-config/rubicon.yaml index 81d1e0b82b2..95b53acc19b 100644 --- a/src/main/resources/bidder-config/rubicon.yaml +++ b/src/main/resources/bidder-config/rubicon.yaml @@ -5,7 +5,7 @@ adapters: pbs-enforces-gdpr: true pbs-enforces-ccpa: true deprecated-names: - aliases: + aliases: {} modifying-vast-xml-allowed: true generate-bid-id: false XAPI: diff --git a/src/main/resources/bidder-config/sharethrough.yaml b/src/main/resources/bidder-config/sharethrough.yaml index f0433dc101e..13ac86dc7d0 100644 --- a/src/main/resources/bidder-config/sharethrough.yaml +++ b/src/main/resources/bidder-config/sharethrough.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: pubgrowth.engineering@sharethrough.com app-media-types: diff --git a/src/main/resources/bidder-config/silvermob.yaml b/src/main/resources/bidder-config/silvermob.yaml index a5a3738e2e5..e5a7a392467 100644 --- a/src/main/resources/bidder-config/silvermob.yaml +++ b/src/main/resources/bidder-config/silvermob.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: support@silvermob.com app-media-types: diff --git a/src/main/resources/bidder-config/smaato.yaml b/src/main/resources/bidder-config/smaato.yaml index 1600a328546..d5dbe5fc20a 100644 --- a/src/main/resources/bidder-config/smaato.yaml +++ b/src/main/resources/bidder-config/smaato.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@smaato.com app-media-types: diff --git a/src/main/resources/bidder-config/smartadserver.yaml b/src/main/resources/bidder-config/smartadserver.yaml index 00674a88e22..8ba06f8c65b 100644 --- a/src/main/resources/bidder-config/smartadserver.yaml +++ b/src/main/resources/bidder-config/smartadserver.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: support@smartadserver.com app-media-types: diff --git a/src/main/resources/bidder-config/smartrtb.yaml b/src/main/resources/bidder-config/smartrtb.yaml index 938ab996713..c5d9e0a1a68 100644 --- a/src/main/resources/bidder-config/smartrtb.yaml +++ b/src/main/resources/bidder-config/smartrtb.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: "engineering@smrtb.com" app-media-types: diff --git a/src/main/resources/bidder-config/smartyads.yaml b/src/main/resources/bidder-config/smartyads.yaml index 4932e4725b5..79f9317a892 100644 --- a/src/main/resources/bidder-config/smartyads.yaml +++ b/src/main/resources/bidder-config/smartyads.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: support@smartyads.com app-media-types: @@ -20,8 +20,8 @@ adapters: supported-vendors: vendor-id: 0 usersync: - url: https://as.ck-ie.com/prebid.gif?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&redir= - redirect-url: /setuid?bidder=smartyads&uid=[uid] + url: https://us.ck-ie.com/yhsfle286.gif?redir= + redirect-url: /setuid?bidder=smartyads&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&uid={$PARTNER_UID} cookie-family-name: smartyads type: redirect support-cors: false diff --git a/src/main/resources/bidder-config/somoaudience.yaml b/src/main/resources/bidder-config/somoaudience.yaml index afde7ccb5b4..abe0c21c7f8 100644 --- a/src/main/resources/bidder-config/somoaudience.yaml +++ b/src/main/resources/bidder-config/somoaudience.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: publishers@somoaudience.com app-media-types: diff --git a/src/main/resources/bidder-config/sonobi.yaml b/src/main/resources/bidder-config/sonobi.yaml index a1fc1702850..226db071560 100644 --- a/src/main/resources/bidder-config/sonobi.yaml +++ b/src/main/resources/bidder-config/sonobi.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: apex.prebid@sonobi.com app-media-types: diff --git a/src/main/resources/bidder-config/sovrn.yaml b/src/main/resources/bidder-config/sovrn.yaml index a588d16ed8c..be30f724803 100644 --- a/src/main/resources/bidder-config/sovrn.yaml +++ b/src/main/resources/bidder-config/sovrn.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: sovrnoss@sovrn.com app-media-types: diff --git a/src/main/resources/bidder-config/synacormedia.yaml b/src/main/resources/bidder-config/synacormedia.yaml index b82564e32b0..88c00ec13f8 100644 --- a/src/main/resources/bidder-config/synacormedia.yaml +++ b/src/main/resources/bidder-config/synacormedia.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: eng-demand@synacor.com app-media-types: diff --git a/src/main/resources/bidder-config/tappx.yaml b/src/main/resources/bidder-config/tappx.yaml index ba6019409ce..1b87ce81278 100644 --- a/src/main/resources/bidder-config/tappx.yaml +++ b/src/main/resources/bidder-config/tappx.yaml @@ -6,18 +6,20 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: tappx@tappx.com app-media-types: + - banner + - video site-media-types: - banner - video supported-vendors: vendor-id: 628 usersync: - url: - redirect-url: + url: https://ssp.api.tappx.com/cs/usersync.php?gdpr_optin={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&type=iframe&ruid= + redirect-url: /setuid?bidder=tappx&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&uid={{TPPXUID}} cookie-family-name: tappx - type: redirect + type: iframe support-cors: false diff --git a/src/main/resources/bidder-config/telaria.yaml b/src/main/resources/bidder-config/telaria.yaml index 0de53e17589..6dc41133697 100644 --- a/src/main/resources/bidder-config/telaria.yaml +++ b/src/main/resources/bidder-config/telaria.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: github@telaria.com app-media-types: diff --git a/src/main/resources/bidder-config/triplelift.yaml b/src/main/resources/bidder-config/triplelift.yaml index 4074ae75ff1..ac984af1295 100644 --- a/src/main/resources/bidder-config/triplelift.yaml +++ b/src/main/resources/bidder-config/triplelift.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@triplelift.com app-media-types: diff --git a/src/main/resources/bidder-config/tripleliftnative.yaml b/src/main/resources/bidder-config/tripleliftnative.yaml index 2b7856cec04..5b0fac21483 100644 --- a/src/main/resources/bidder-config/tripleliftnative.yaml +++ b/src/main/resources/bidder-config/tripleliftnative.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@triplelift.com app-media-types: diff --git a/src/main/resources/bidder-config/ttx.yaml b/src/main/resources/bidder-config/ttx.yaml index c57ac2f027d..1a61d3122b8 100644 --- a/src/main/resources/bidder-config/ttx.yaml +++ b/src/main/resources/bidder-config/ttx.yaml @@ -7,7 +7,9 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: 33across + aliases: + '33across': + enabled: false meta-info: maintainer-email: headerbidding@33across.com app-media-types: diff --git a/src/main/resources/bidder-config/ucfunnel.yaml b/src/main/resources/bidder-config/ucfunnel.yaml index acec14ae741..1cd80e39319 100644 --- a/src/main/resources/bidder-config/ucfunnel.yaml +++ b/src/main/resources/bidder-config/ucfunnel.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: "support@ucfunnel.com" app-media-types: diff --git a/src/main/resources/bidder-config/unicorn.yaml b/src/main/resources/bidder-config/unicorn.yaml new file mode 100644 index 00000000000..116ea7d0244 --- /dev/null +++ b/src/main/resources/bidder-config/unicorn.yaml @@ -0,0 +1,22 @@ +adapters: + unicorn: + enabled: false + endpoint: https://ds.uncn.jp/pb/0/bid.json + pbs-enforces-gdpr: true + pbs-enforces-ccpa: true + modifying-vast-xml-allowed: true + deprecated-names: + aliases: {} + meta-info: + maintainer-email: prebid@unicorn.inc + app-media-types: + - banner + site-media-types: + supported-vendors: + vendor-id: 0 + usersync: + url: + redirect-url: + cookie-family-name: unicorn + type: iframe + support-cors: false diff --git a/src/main/resources/bidder-config/unruly.yaml b/src/main/resources/bidder-config/unruly.yaml index 0304e40e7cc..87b01e96dcb 100644 --- a/src/main/resources/bidder-config/unruly.yaml +++ b/src/main/resources/bidder-config/unruly.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: adspaces@unrulygroup.com app-media-types: diff --git a/src/main/resources/bidder-config/valueimpression.yaml b/src/main/resources/bidder-config/valueimpression.yaml index e14ee9294c5..fbe3a5e9a34 100644 --- a/src/main/resources/bidder-config/valueimpression.yaml +++ b/src/main/resources/bidder-config/valueimpression.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: info@valueimpression.com app-media-types: diff --git a/src/main/resources/bidder-config/verizonmedia.yaml b/src/main/resources/bidder-config/verizonmedia.yaml index 784c33c963f..6f5be2c81a1 100644 --- a/src/main/resources/bidder-config/verizonmedia.yaml +++ b/src/main/resources/bidder-config/verizonmedia.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: dsp-supply-prebid@verizonmedia.com app-media-types: diff --git a/src/main/resources/bidder-config/visx.yaml b/src/main/resources/bidder-config/visx.yaml index 1877a2eb9ef..45bf55e7cd3 100644 --- a/src/main/resources/bidder-config/visx.yaml +++ b/src/main/resources/bidder-config/visx.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: supply.partners@yoc.com app-media-types: diff --git a/src/main/resources/bidder-config/vrtcal.yaml b/src/main/resources/bidder-config/vrtcal.yaml index 2a632b7b440..c9701c97652 100644 --- a/src/main/resources/bidder-config/vrtcal.yaml +++ b/src/main/resources/bidder-config/vrtcal.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: support@vrtcal.com app-media-types: diff --git a/src/main/resources/bidder-config/yeahmobi.yaml b/src/main/resources/bidder-config/yeahmobi.yaml index 4c982fd50b4..03d92c968fb 100644 --- a/src/main/resources/bidder-config/yeahmobi.yaml +++ b/src/main/resources/bidder-config/yeahmobi.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: junping.zhao@yeahmobi.com app-media-types: diff --git a/src/main/resources/bidder-config/yieldlab.yaml b/src/main/resources/bidder-config/yieldlab.yaml index a353396af6d..ca930938364 100644 --- a/src/main/resources/bidder-config/yieldlab.yaml +++ b/src/main/resources/bidder-config/yieldlab.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: solutions@yieldlab.de app-media-types: diff --git a/src/main/resources/bidder-config/yieldmo.yaml b/src/main/resources/bidder-config/yieldmo.yaml index c3065f3d0f0..6b4f8596a9f 100644 --- a/src/main/resources/bidder-config/yieldmo.yaml +++ b/src/main/resources/bidder-config/yieldmo.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: prebid@yieldmo.com app-media-types: diff --git a/src/main/resources/bidder-config/yieldone.yaml b/src/main/resources/bidder-config/yieldone.yaml index 43f615ed011..53b684e8359 100644 --- a/src/main/resources/bidder-config/yieldone.yaml +++ b/src/main/resources/bidder-config/yieldone.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: y1dev@platform-one.co.jp app-media-types: diff --git a/src/main/resources/bidder-config/zeroclickfraud.yaml b/src/main/resources/bidder-config/zeroclickfraud.yaml index 0795fa800c1..93fb1b35644 100644 --- a/src/main/resources/bidder-config/zeroclickfraud.yaml +++ b/src/main/resources/bidder-config/zeroclickfraud.yaml @@ -6,7 +6,7 @@ adapters: pbs-enforces-ccpa: true modifying-vast-xml-allowed: true deprecated-names: - aliases: + aliases: {} meta-info: maintainer-email: support@datablocks.net app-media-types: diff --git a/src/main/resources/static/bidder-params/adyoulike.json b/src/main/resources/static/bidder-params/adyoulike.json new file mode 100644 index 00000000000..448de344739 --- /dev/null +++ b/src/main/resources/static/bidder-params/adyoulike.json @@ -0,0 +1,33 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "AdYouLike Adapter Params", + "description": "A schema which validates params accepted by the AdYouLike adapter", + "type": "object", + "properties": { + "placement": { + "type": "string", + "description": "Placement Id" + }, + "campaign": { + "type": "string", + "description": "Id of a forced campaign" + }, + "track": { + "type": "string", + "description": "Id of a forced Track" + }, + "creative": { + "type": "string", + "description": "Id of a forced creative" + }, + "source": { + "type": "string", + "description": "context of the campaign" + }, + "debug": { + "type": "string", + "description": "Arbitrary id used for debug purpose" + } + }, + "required": ["placement"] +} diff --git a/src/main/resources/static/bidder-params/decenterads.json b/src/main/resources/static/bidder-params/decenterads.json new file mode 100644 index 00000000000..970e99038a0 --- /dev/null +++ b/src/main/resources/static/bidder-params/decenterads.json @@ -0,0 +1,18 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "DecenterAds Adapter Params", + "description": "A schema which validates params accepted by the DecenterAds adapter", + "type": "object", + "properties": { + "placementId": { + "type": "string", + "minLength": 1, + "description": "An ID which identifies the DecenterAds placement" + }, + "customParams": { + "type": "object", + "description": "User-defined targeting key-value pairs." + } + }, + "required" : [ "placementId" ] +} diff --git a/src/main/resources/static/bidder-params/epom.json b/src/main/resources/static/bidder-params/epom.json new file mode 100644 index 00000000000..ee8c14e4f7e --- /dev/null +++ b/src/main/resources/static/bidder-params/epom.json @@ -0,0 +1,8 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Epom Adapter Params", + "description": "A schema which validates params accepted by the Epom adapter", + "type": "object", + + "properties": {} +} diff --git a/src/main/resources/static/bidder-params/gumgum.json b/src/main/resources/static/bidder-params/gumgum.json index 7ee07474cc1..3a8f7a7c6dc 100644 --- a/src/main/resources/static/bidder-params/gumgum.json +++ b/src/main/resources/static/bidder-params/gumgum.json @@ -8,9 +8,27 @@ "type": "string", "description": "A tracking id used to identify GumGum zone.", "minLength": 8 + }, + "pubId": { + "type": "integer", + "description": "A tracking id used to identify GumGum publisher" + }, + "irisid": { + "type": "string", + "description": "A hashed IRIS.TV Content ID" } }, - "required": [ - "zone" + "anyOf": [ + { + "required": [ + "zone" + ] + }, + { + "required": [ + "pubId" + ] + } ] } + diff --git a/src/main/resources/static/bidder-params/jixie.json b/src/main/resources/static/bidder-params/jixie.json new file mode 100644 index 00000000000..732b05f8ca7 --- /dev/null +++ b/src/main/resources/static/bidder-params/jixie.json @@ -0,0 +1,26 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Jixie Adapter Params", + "description": "A schema which validates params accepted by the Jixie adapter", + "type": "object", + "properties": { + "unit" : { + "type": "string", + "description": "The unit code of an inventory target", + "minLength": 18 + }, + "accountid" : { + "type": "string", + "description": "The accountid of an inventory target" + }, + "jxprop1" : { + "type": "string", + "description": "jxprop1 of an inventory target" + }, + "jxprop2" : { + "type": "string", + "description": "jxprop2 of an inventory target" + } + }, + "required": ["unit"] +} diff --git a/src/main/resources/static/bidder-params/kidoz.json b/src/main/resources/static/bidder-params/kidoz.json index 25a5c94e704..dcd31e28bda 100644 --- a/src/main/resources/static/bidder-params/kidoz.json +++ b/src/main/resources/static/bidder-params/kidoz.json @@ -5,18 +5,14 @@ "type": "object", "properties": { "access_token": { - "$ref": "#/definitions/non-empty-string", + "type": "string", + "minLength": 1, "description": "Kidoz access_token" }, "publisher_id": { - "$ref": "#/definitions/non-empty-string", - "description": "Kidoz publisher_id" - } - }, - "definitions": { - "non-empty-string": { "type": "string", - "minLength": 1 + "minLength": 1, + "description": "Kidoz publisher_id" } }, "required": [ diff --git a/src/main/resources/static/bidder-params/mobfoxpb.json b/src/main/resources/static/bidder-params/mobfoxpb.json index 6ecb7e87127..0542b89f4dd 100644 --- a/src/main/resources/static/bidder-params/mobfoxpb.json +++ b/src/main/resources/static/bidder-params/mobfoxpb.json @@ -8,9 +8,23 @@ "type": "string", "minLength": 1, "description": "An ID which identifies the mobfox ad tag" + }, + "key": { + "type": "string", + "minLength": 1, + "description": "An ID which identifies the mobfox adexchange partner" } }, - "required": [ - "TagID" + "oneOf": [ + { + "required": [ + "TagID" + ] + }, + { + "required": [ + "key" + ] + } ] } diff --git a/src/main/resources/static/bidder-params/onetag.json b/src/main/resources/static/bidder-params/onetag.json new file mode 100644 index 00000000000..65fca3428f1 --- /dev/null +++ b/src/main/resources/static/bidder-params/onetag.json @@ -0,0 +1,20 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Onetag Adapter Params", + "description": "A schema which validates params accepted by the Onetag adapter", + "type": "object", + + "properties": { + "pubId": { + "type": "string", + "minLength": 1, + "description": "The publisher’s ID provided by OneTag" + }, + "ext": { + "type": "object", + "description": "A set of custom key-value pairs" + } + }, + + "required": ["pubId"] +} diff --git a/src/main/resources/static/bidder-params/outbrain.json b/src/main/resources/static/bidder-params/outbrain.json new file mode 100644 index 00000000000..8cfb8bbdf28 --- /dev/null +++ b/src/main/resources/static/bidder-params/outbrain.json @@ -0,0 +1,40 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Outbrain Adapter Params", + "description": "A schema which validates params accepted by the Outbrain adapter", + + "type": "object", + "properties": { + "publisher": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "domain": { + "type": "string" + } + }, + "required": ["id"] + }, + "tagid": { + "type": "string" + }, + "bcat": { + "type": "array", + "items": { + "type": "string" + } + }, + "badv": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["publisher"] +} diff --git a/src/main/resources/static/bidder-params/pangle.json b/src/main/resources/static/bidder-params/pangle.json new file mode 100644 index 00000000000..74085cb5e65 --- /dev/null +++ b/src/main/resources/static/bidder-params/pangle.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Pangle Adapter Params", + "description": "A schema which validates params accepted by the Pangle adapter", + "type": "object", + "properties": { + "token": { + "type": "string", + "description": "Access Token", + "pattern": ".+" + } + }, + "required": [ + "token" + ] +} diff --git a/src/main/resources/static/bidder-params/rtbhouse.json b/src/main/resources/static/bidder-params/rtbhouse.json index 10b40b39394..43d223dc76b 100644 --- a/src/main/resources/static/bidder-params/rtbhouse.json +++ b/src/main/resources/static/bidder-params/rtbhouse.json @@ -1,10 +1,13 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Rtbhouse Params", - "description": "A schema which validates params accepted by the Rtbhouse", + "title": "RTB House Adapter Params", + "description": "A schema which validates params accepted by the RTB House adapter", "type": "object", "properties": { + "publisherId": { + "type": "string", + "description": "The publisher’s ID provided by RTB House" + } }, - "required": [ - ] + "required": ["publisherId"] } diff --git a/src/main/resources/static/bidder-params/unicorn.json b/src/main/resources/static/bidder-params/unicorn.json new file mode 100644 index 00000000000..90ff919e4fa --- /dev/null +++ b/src/main/resources/static/bidder-params/unicorn.json @@ -0,0 +1,25 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "UNICORN Adapter Params", + "description": "A schema which validates params accepted by the UNICORN adapter", + "type": "object", + "properties": { + "placementId": { + "type": "string", + "description": "In Application, if placementId is empty, prebid server configuration id will be used as placementId." + }, + "publisherId": { + "type": "integer", + "description": "Account specific publisher id" + }, + "mediaId": { + "type": "string", + "description": "Publisher specific media id" + }, + "accountId": { + "type": "integer", + "description": "Account ID for charge request" + } + }, + "required" : ["mediaId", "accountId"] +} diff --git a/src/test/java/org/prebid/server/analytics/AnalyticsReporterDelegatorTest.java b/src/test/java/org/prebid/server/analytics/AnalyticsReporterDelegatorTest.java index 27a19f77544..aad27348680 100644 --- a/src/test/java/org/prebid/server/analytics/AnalyticsReporterDelegatorTest.java +++ b/src/test/java/org/prebid/server/analytics/AnalyticsReporterDelegatorTest.java @@ -1,5 +1,10 @@ package org.prebid.server.analytics; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.IntNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.TextNode; +import com.iab.openrtb.request.BidRequest; import io.vertx.core.Future; import io.vertx.core.Handler; import io.vertx.core.Vertx; @@ -12,14 +17,19 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.mockito.stubbing.Answer; +import org.prebid.server.analytics.model.AuctionEvent; import org.prebid.server.auction.PrivacyEnforcementService; +import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.privacy.gdpr.model.PrivacyEnforcementAction; import org.prebid.server.privacy.gdpr.model.TcfContext; +import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; import java.util.HashMap; import java.util.Map; import static java.util.Arrays.asList; +import static java.util.Collections.singleton; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; @@ -53,9 +63,11 @@ public class AnalyticsReporterDelegatorTest { public void setUp() { firstReporter = mock(AnalyticsReporter.class); given(firstReporter.vendorId()).willReturn(FIRST_REPORTER_ID); + given(firstReporter.name()).willReturn("logAnalytics"); secondReporter = mock(AnalyticsReporter.class); given(secondReporter.vendorId()).willReturn(SECOND_REPORTER_ID); + given(secondReporter.name()).willReturn("adapter"); target = new AnalyticsReporterDelegator(asList(firstReporter, secondReporter), vertx, privacyEnforcementService); @@ -75,6 +87,51 @@ public void shouldPassEventToAllDelegates() { assertThat(captureEvent(secondReporter)).isSameAs(EVENT); } + @Test + public void shouldPassOnlyAdapterRelatedEntriesToAnalyticReporters() { + // given + willAnswer(withNullAndInvokeHandler()).given(vertx).runOnContext(any()); + final Map enforcementActionMap = new HashMap<>(); + enforcementActionMap.put(SECOND_REPORTER_ID, PrivacyEnforcementAction.allowAll()); + enforcementActionMap.put(FIRST_REPORTER_ID, PrivacyEnforcementAction.allowAll()); + + given(privacyEnforcementService.resultForVendorIds(any(), any())) + .willReturn(Future.succeededFuture(enforcementActionMap)); + final ObjectNode analyticsNode = new ObjectMapper().createObjectNode(); + analyticsNode.set("adapter", new TextNode("someValue")); + analyticsNode.set("anotherAdapter", new IntNode(2)); + final BidRequest bidRequest = BidRequest.builder() + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .analytics(analyticsNode) + .build())).build(); + final AuctionEvent givenAuctionEvent = AuctionEvent.builder() + .auctionContext(AuctionContext.builder() + .bidRequest(bidRequest).build()) + .build(); + + // when + target.processEvent(givenAuctionEvent, TcfContext.empty()); + + // then + verify(vertx, times(2)).runOnContext(any()); + assertThat(singleton(captureAuctionEvent(firstReporter))) + .extracting(AuctionEvent::getAuctionContext) + .extracting(AuctionContext::getBidRequest) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getAnalytics) + .containsExactly(analyticsNode); + final ObjectNode expectedAnalytics = new ObjectMapper().createObjectNode(); + expectedAnalytics.set("adapter", new TextNode("someValue")); + assertThat(singleton(captureAuctionEvent(secondReporter))) + .extracting(AuctionEvent::getAuctionContext) + .extracting(AuctionContext::getBidRequest) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getAnalytics) + .containsExactly(expectedAnalytics); + } + @Test public void shouldPassEventToAllowedDelegatesWhenSomeVendorIdWasAllowed() { // given @@ -127,4 +184,10 @@ private static String captureEvent(AnalyticsReporter reporter) { verify(reporter).processEvent(auctionEventCaptor.capture()); return auctionEventCaptor.getValue(); } + + private static AuctionEvent captureAuctionEvent(AnalyticsReporter reporter) { + final ArgumentCaptor auctionEventCaptor = ArgumentCaptor.forClass(AuctionEvent.class); + verify(reporter).processEvent(auctionEventCaptor.capture()); + return auctionEventCaptor.getValue(); + } } diff --git a/src/test/java/org/prebid/server/auction/AuctionRequestFactoryTest.java b/src/test/java/org/prebid/server/auction/AuctionRequestFactoryTest.java deleted file mode 100644 index dc0e2b8e2d7..00000000000 --- a/src/test/java/org/prebid/server/auction/AuctionRequestFactoryTest.java +++ /dev/null @@ -1,2554 +0,0 @@ -package org.prebid.server.auction; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.fasterxml.jackson.databind.node.TextNode; -import com.iab.openrtb.request.App; -import com.iab.openrtb.request.Banner; -import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Device; -import com.iab.openrtb.request.Geo; -import com.iab.openrtb.request.Imp; -import com.iab.openrtb.request.Publisher; -import com.iab.openrtb.request.Site; -import com.iab.openrtb.request.Source; -import com.iab.openrtb.request.User; -import com.iab.openrtb.request.Video; -import io.vertx.core.Future; -import io.vertx.core.buffer.Buffer; -import io.vertx.core.http.CaseInsensitiveHeaders; -import io.vertx.core.http.HttpServerRequest; -import io.vertx.ext.web.RoutingContext; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.auction.model.IpAddress; -import org.prebid.server.bidder.BidderCatalog; -import org.prebid.server.cookie.UidsCookie; -import org.prebid.server.cookie.UidsCookieService; -import org.prebid.server.cookie.model.UidWithExpiry; -import org.prebid.server.cookie.proto.Uids; -import org.prebid.server.exception.BlacklistedAccountException; -import org.prebid.server.exception.BlacklistedAppException; -import org.prebid.server.exception.InvalidRequestException; -import org.prebid.server.exception.PreBidException; -import org.prebid.server.exception.UnauthorizedAccountException; -import org.prebid.server.execution.Timeout; -import org.prebid.server.execution.TimeoutFactory; -import org.prebid.server.geolocation.model.GeoInfo; -import org.prebid.server.identity.IdGenerator; -import org.prebid.server.metric.MetricName; -import org.prebid.server.privacy.ccpa.Ccpa; -import org.prebid.server.privacy.gdpr.model.TcfContext; -import org.prebid.server.privacy.model.Privacy; -import org.prebid.server.privacy.model.PrivacyContext; -import org.prebid.server.proto.openrtb.ext.ExtIncludeBrandCategory; -import org.prebid.server.proto.openrtb.ext.request.ExtDevice; -import org.prebid.server.proto.openrtb.ext.request.ExtGranularityRange; -import org.prebid.server.proto.openrtb.ext.request.ExtMediaTypePriceGranularity; -import org.prebid.server.proto.openrtb.ext.request.ExtPriceGranularity; -import org.prebid.server.proto.openrtb.ext.request.ExtPublisher; -import org.prebid.server.proto.openrtb.ext.request.ExtPublisherPrebid; -import org.prebid.server.proto.openrtb.ext.request.ExtRequest; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidCache; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidCacheBids; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidCacheVastxml; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidChannel; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidData; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidDataEidPermissions; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestTargeting; -import org.prebid.server.proto.openrtb.ext.request.ExtSite; -import org.prebid.server.settings.ApplicationSettings; -import org.prebid.server.settings.model.Account; -import org.prebid.server.settings.model.AccountStatus; -import org.prebid.server.validation.RequestValidator; -import org.prebid.server.validation.model.ValidationResult; - -import java.math.BigDecimal; -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneId; -import java.util.List; -import java.util.Map; - -import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; -import static java.util.Collections.singleton; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static org.apache.commons.lang3.StringUtils.EMPTY; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.tuple; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.prebid.server.assertion.FutureAssertion.assertThat; - -public class AuctionRequestFactoryTest extends VertxTest { - - private static final List BLACKLISTED_APPS = singletonList("bad_app"); - private static final List BLACKLISTED_ACCOUNTS = singletonList("bad_acc"); - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private StoredRequestProcessor storedRequestProcessor; - @Mock - private ImplicitParametersExtractor paramsExtractor; - @Mock - private IpAddressHelper ipAddressHelper; - @Mock - private UidsCookieService uidsCookieService; - @Mock - private BidderCatalog bidderCatalog; - @Mock - private RequestValidator requestValidator; - @Mock - private InterstitialProcessor interstitialProcessor; - @Mock - private ApplicationSettings applicationSettings; - @Mock - private IdGenerator idGenerator; - @Mock - private PrivacyEnforcementService privacyEnforcementService; - - private AuctionRequestFactory factory; - @Mock - private RoutingContext routingContext; - @Mock - private HttpServerRequest httpRequest; - @Mock - private OrtbTypesResolver ortbTypesResolver; - @Mock - private TimeoutResolver timeoutResolver; - @Mock - private TimeoutFactory timeoutFactory; - - @Before - public void setUp() { - given(interstitialProcessor.process(any())).will(invocationOnMock -> invocationOnMock.getArgument(0)); - given(idGenerator.generateId()).willReturn(null); - - given(routingContext.request()).willReturn(httpRequest); - given(httpRequest.headers()).willReturn(new CaseInsensitiveHeaders()); - - given(timeoutResolver.resolve(any())).willReturn(2000L); - given(timeoutResolver.adjustTimeout(anyLong())).willReturn(1900L); - - given(privacyEnforcementService.contextFromBidRequest(any(), any(), any(), any(), any())) - .willReturn(Future.succeededFuture(PrivacyContext.of( - Privacy.of("0", EMPTY, Ccpa.EMPTY, 0), - TcfContext.empty()))); - - factory = new AuctionRequestFactory( - Integer.MAX_VALUE, - false, - false, - "USD", - BLACKLISTED_APPS, - BLACKLISTED_ACCOUNTS, - storedRequestProcessor, - paramsExtractor, - ipAddressHelper, - uidsCookieService, - bidderCatalog, - requestValidator, - interstitialProcessor, - ortbTypesResolver, - timeoutResolver, - timeoutFactory, - applicationSettings, - idGenerator, - privacyEnforcementService, - jacksonMapper); - } - - @Test - public void shouldReturnFailedFutureIfRequestBodyIsMissing() { - // given - given(routingContext.getBody()).willReturn(null); - - // when - final Future future = factory.fromRequest(routingContext, 0L); - - // then - assertThat(future.failed()).isTrue(); - assertThat(future.cause()) - .isInstanceOf(InvalidRequestException.class) - .hasMessage("Incoming request has no body"); - } - - @Test - public void shouldReturnFailedFutureIfAccountIsEnforcedAndIdIsNotProvided() { - // given - factory = new AuctionRequestFactory( - 1000, - true, - false, - "USD", - BLACKLISTED_APPS, - BLACKLISTED_ACCOUNTS, - storedRequestProcessor, - paramsExtractor, - ipAddressHelper, - uidsCookieService, - bidderCatalog, - requestValidator, - interstitialProcessor, - ortbTypesResolver, - timeoutResolver, - timeoutFactory, - applicationSettings, - idGenerator, - privacyEnforcementService, - jacksonMapper); - - givenValidBidRequest(); - - // when - final Future future = factory.fromRequest(routingContext, 0L); - - // then - verify(applicationSettings, never()).getAccountById(any(), any()); - - assertThat(future.failed()).isTrue(); - assertThat(future.cause()) - .isInstanceOf(UnauthorizedAccountException.class) - .hasMessage("Unauthorized account id: "); - } - - @Test - public void shouldReturnFailedFutureIfAccountIsEnforcedAndFailedGetAccountById() { - // given - factory = new AuctionRequestFactory( - 1000, - true, - false, - "USD", - BLACKLISTED_APPS, - BLACKLISTED_ACCOUNTS, - storedRequestProcessor, - paramsExtractor, - ipAddressHelper, - uidsCookieService, - bidderCatalog, - requestValidator, - interstitialProcessor, - ortbTypesResolver, - timeoutResolver, - timeoutFactory, - applicationSettings, - idGenerator, - privacyEnforcementService, - jacksonMapper); - - given(applicationSettings.getAccountById(any(), any())) - .willReturn(Future.failedFuture(new PreBidException("Not found"))); - - final BidRequest bidRequest = BidRequest.builder() - .app(App.builder() - .publisher(Publisher.builder().id("absentId").build()) - .build()) - .build(); - - givenBidRequest(bidRequest); - - // when - final Future future = factory.fromRequest(routingContext, 0L); - - // then - verify(applicationSettings).getAccountById(eq("absentId"), any()); - - assertThat(future.failed()).isTrue(); - assertThat(future.cause()) - .isInstanceOf(UnauthorizedAccountException.class) - .hasMessage("Unauthorized account id: absentId"); - } - - @Test - public void shouldReturnFailedFutureIfAccountIsInactive() { - // given - given(applicationSettings.getAccountById(any(), any())).willReturn(Future.succeededFuture(Account.builder() - .id("accountId") - .status(AccountStatus.inactive) - .build())); - - final BidRequest bidRequest = BidRequest.builder() - .app(App.builder() - .publisher(Publisher.builder().id("accountId").build()) - .build()) - .build(); - - givenBidRequest(bidRequest); - - // when - final Future future = factory.fromRequest(routingContext, 0L); - - // then - assertThat(future).isFailed(); - assertThat(future.cause()) - .isInstanceOf(UnauthorizedAccountException.class) - .hasMessage("Account accountId is inactive"); - } - - @Test - public void shouldReturnFailedFutureIfRequestBodyExceedsMaxRequestSize() { - // given - factory = new AuctionRequestFactory( - 1, - false, - false, - "USD", - BLACKLISTED_APPS, - BLACKLISTED_ACCOUNTS, - storedRequestProcessor, - paramsExtractor, - ipAddressHelper, - uidsCookieService, - bidderCatalog, - requestValidator, - interstitialProcessor, - ortbTypesResolver, - timeoutResolver, - timeoutFactory, - applicationSettings, - idGenerator, - privacyEnforcementService, - jacksonMapper); - - given(routingContext.getBody()).willReturn(Buffer.buffer("body")); - - // when - final Future future = factory.fromRequest(routingContext, 0L); - - // then - assertThat(future.failed()).isTrue(); - assertThat(future.cause()) - .isInstanceOf(InvalidRequestException.class) - .hasMessage("Request size exceeded max size of 1 bytes."); - } - - @Test - public void shouldReturnFailedFutureIfRequestBodyCouldNotBeParsed() { - // given - given(routingContext.getBody()).willReturn(Buffer.buffer("body")); - - // when - final Future future = factory.fromRequest(routingContext, 0L); - - // then - assertThat(future.failed()).isTrue(); - assertThat(future.cause()).isInstanceOf(InvalidRequestException.class); - assertThat(((InvalidRequestException) future.cause()).getMessages()).hasSize(1) - .element(0).asString().startsWith("Error decoding bidRequest: Unrecognized token 'body'"); - } - - @Test - public void shouldCallOrtbFieldsResolver() { - // given - givenValidBidRequest(); - - // when - factory.fromRequest(routingContext, 0L).result(); - - // then - verify(ortbTypesResolver).normalizeBidRequest(any(), any(), any()); - } - - @Test - public void shouldSetFieldsFromHeadersIfBodyFieldsEmptyForIpv4() { - // given - givenValidBidRequest(); - - givenImplicitParams("http://example.com", "example.com", "192.168.244.1", IpAddress.IP.v4, "UnitTest"); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getSite()).isEqualTo(Site.builder() - .page("http://example.com") - .domain("example.com") - .ext(ExtSite.of(0, null)) - .build()); - assertThat(request.getDevice()) - .isEqualTo(Device.builder().ip("192.168.244.1").ua("UnitTest").build()); - } - - @Test - public void shouldSetFieldsFromHeadersIfBodyFieldsInvalidForIpv4() { - // given - final BidRequest bidRequest = BidRequest.builder() - .device(Device.builder().ip("127.0.0.1").build()) - .build(); - - givenBidRequest(bidRequest); - - given(ipAddressHelper.toIpAddress(eq("127.0.0.1"))).willReturn(null); - - givenImplicitParams("http://example.com", "example.com", "192.168.244.1", IpAddress.IP.v4, "UnitTest"); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getSite()).isEqualTo(Site.builder() - .page("http://example.com") - .domain("example.com") - .ext(ExtSite.of(0, null)) - .build()); - assertThat(request.getDevice()) - .isEqualTo(Device.builder().ip("192.168.244.1").ua("UnitTest").build()); - } - - @Test - public void shouldSetFieldsFromHeadersIfBodyFieldsEmptyForIpv6() { - // given - givenValidBidRequest(); - - givenImplicitParams( - "http://example.com", - "example.com", - "2001:0db8:85a3:0000:0000:8a2e:0370:7334", - IpAddress.IP.v6, - "UnitTest"); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getSite()).isEqualTo(Site.builder() - .page("http://example.com") - .domain("example.com") - .ext(ExtSite.of(0, null)) - .build()); - assertThat(request.getDevice()) - .isEqualTo(Device.builder().ipv6("2001:0db8:85a3:0000:0000:8a2e:0370:7334").ua("UnitTest").build()); - } - - @Test - public void shouldSetFieldsFromHeadersIfBodyFieldsInvalidForIpv6() { - // given - final BidRequest bidRequest = BidRequest.builder() - .device(Device.builder().ipv6("::1").build()) - .build(); - - givenBidRequest(bidRequest); - - given(ipAddressHelper.toIpAddress(eq("::1"))).willReturn(null); - - givenImplicitParams( - "http://example.com", - "example.com", - "2001:0db8:85a3:0000:0000:8a2e:0370:7334", - IpAddress.IP.v6, - "UnitTest"); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getSite()).isEqualTo(Site.builder() - .page("http://example.com") - .domain("example.com") - .ext(ExtSite.of(0, null)) - .build()); - assertThat(request.getDevice()) - .isEqualTo(Device.builder().ipv6("2001:0db8:85a3:0000:0000:8a2e:0370:7334").ua("UnitTest").build()); - } - - @Test - public void shouldSetAnonymizedIpv6FromField() { - // given - final BidRequest bidRequest = BidRequest.builder() - .device(Device.builder().ipv6("2001:0db8:85a3:0000:0000:8a2e:0370:7334").build()) - .build(); - - givenBidRequest(bidRequest); - - given(ipAddressHelper.toIpAddress(eq("2001:0db8:85a3:0000:0000:8a2e:0370:7334"))) - .willReturn(IpAddress.of("2001:0db8:85a3:0000::", IpAddress.IP.v6)); - - givenImplicitParams( - "http://example.com", - "example.com", - "1111:2222:3333:4444:5555:6666:7777:8888", - IpAddress.IP.v6, - "UnitTest"); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getSite()).isEqualTo(Site.builder() - .page("http://example.com") - .domain("example.com") - .ext(ExtSite.of(0, null)) - .build()); - assertThat(request.getDevice()) - .isEqualTo(Device.builder().ipv6("2001:0db8:85a3:0000::").ua("UnitTest").build()); - } - - @Test - public void shouldNotSetDeviceDntIfHeaderHasInvalidValue() { - // given - given(httpRequest.getHeader("DNT")).willReturn("invalid"); - givenValidBidRequest(); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getDnt()).isNull(); - } - - @Test - public void shouldSetDeviceDntIfHeaderExists() { - // given - given(httpRequest.getHeader("DNT")).willReturn("1"); - givenValidBidRequest(); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getDnt()).isOne(); - } - - @Test - public void shouldOverrideDeviceDntIfHeaderExists() { - // given - given(httpRequest.getHeader("DNT")).willReturn("0"); - givenBidRequest(BidRequest.builder() - .device(Device.builder().dnt(1).build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getDnt()).isZero(); - } - - @Test - public void shouldNotSetDeviceLmtForIos14IfNoApp() { - // given - givenBidRequest(BidRequest.builder() - .device(Device.builder() - .os("iOS") - .osv("14.0") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isNull(); - } - - @Test - public void shouldNotSetDeviceLmtForNonIos() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("plan9") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isNull(); - } - - @Test - public void shouldNotSetDeviceLmtForIosInvalidVersion() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("invalid-version") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isNull(); - } - - @Test - public void shouldNotSetDeviceLmtForIosInvalidVersionMajor() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("invalid-major.0") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isNull(); - } - - @Test - public void shouldNotSetDeviceLmtForIosInvalidVersionMinor() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("14.invalid-minor") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isNull(); - } - - @Test - public void shouldNotSetDeviceLmtForIosMissingVersionMinor() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("14") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isNull(); - } - - @Test - public void shouldNotSetDeviceLmtForIosLowerThan14() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("13.4") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isNull(); - } - - @Test - public void shouldSetDeviceLmtOneForIos14WithPatchVersion() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("14.0.patch-version") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isOne(); - } - - @Test - public void shouldSetDeviceLmtOneForIos14Minor0() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("14.0") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isOne(); - } - - @Test - public void shouldSetDeviceLmtOneForIos14Minor0AndEmptyIfa() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("14.0") - .ifa("") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isOne(); - } - - @Test - public void shouldOverrideDeviceLmtForIos14Minor0AndEmptyIfa() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .lmt(0) - .os("iOS") - .osv("14.0") - .ifa("") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isOne(); - } - - @Test - public void shouldSetDeviceLmtOneForIos14Minor0AndZerosIfa() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("14.0") - .ifa("00000000-0000-0000-0000-000000000000") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isOne(); - } - - @Test - public void shouldSetDeviceLmtZeroForIos14Minor0AndNonZerosIfa() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("14.1") - .ifa("12345") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isZero(); - } - - @Test - public void shouldNotOverrideDeviceLmtForIos14Minor0AndNonZerosIfaWhenLmtAlreadySet() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .lmt(1) - .os("iOS") - .osv("14.0") - .ifa("12345") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isOne(); - } - - @Test - public void shouldSetDeviceLmtOneForIos14Minor1() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("14.1") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isOne(); - } - - @Test - public void shouldSetDeviceLmtOneForIos14Minor1AndEmptyIfa() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("14.1") - .ifa("") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isOne(); - } - - @Test - public void shouldOverrideDeviceLmtForIos14Minor1AndEmptyIfa() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .lmt(0) - .os("iOS") - .osv("14.1") - .ifa("") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isOne(); - } - - @Test - public void shouldSetDeviceLmtOneForIos14Minor1AndZerosIfa() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("14.1") - .ifa("00000000-0000-0000-0000-000000000000") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isOne(); - } - - @Test - public void shouldSetDeviceLmtZeroForIos14Minor1AndNonZerosIfa() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("14.1") - .ifa("12345") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isZero(); - } - - @Test - public void shouldNotOverrideDeviceLmtForIos14Minor1AndNonZerosIfaWhenLmtAlreadySet() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .lmt(1) - .os("iOS") - .osv("14.1") - .ifa("12345") - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isOne(); - } - - @Test - public void shouldSetDeviceLmtZeroForIos14Minor2AndAtts0() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("14.2") - .ext(ExtDevice.of(0, null)) - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isZero(); - } - - @Test - public void shouldNotOverrideDeviceLmtForIos14Minor2AndAtts0() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .lmt(1) - .os("iOS") - .osv("14.2") - .ext(ExtDevice.of(0, null)) - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isOne(); - } - - @Test - public void shouldSetDeviceLmtOneForIos14Minor2AndAtts1() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("14.2") - .ext(ExtDevice.of(1, null)) - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isOne(); - } - - @Test - public void shouldNotOverrideDeviceLmtForIos14Minor2AndAtts1() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .lmt(0) - .os("iOS") - .osv("14.2") - .ext(ExtDevice.of(1, null)) - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isZero(); - } - - @Test - public void shouldSetDeviceLmtOneForIos15Minor0AndAtts1() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("15.0") - .ext(ExtDevice.of(1, null)) - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isOne(); - } - - @Test - public void shouldSetDeviceLmtOneForIos15Minor0AndAtts2() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("15.0") - .ext(ExtDevice.of(2, null)) - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isOne(); - } - - @Test - public void shouldNotOverrideDeviceLmtForIos14Minor2AndAtts2() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .lmt(0) - .os("iOS") - .osv("14.2") - .ext(ExtDevice.of(2, null)) - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isZero(); - } - - @Test - public void shouldSetDeviceLmtZeroForIos14Minor2AndAtts3() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("14.2") - .ext(ExtDevice.of(3, null)) - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isZero(); - } - - @Test - public void shouldNotOverrideDeviceLmtForIos14Minor2AndAtts3() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .lmt(1) - .os("iOS") - .osv("14.2") - .ext(ExtDevice.of(3, null)) - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isOne(); - } - - @Test - public void shouldNotSetDeviceLmtForIos14Minor3AndAtts4() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("14.3") - .ext(ExtDevice.of(4, null)) - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isNull(); - } - - @Test - public void shouldNotSetDeviceLmtForIos14Minor3AndAttsNull() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .device(Device.builder() - .os("iOS") - .osv("14.3") - .ext(ExtDevice.of(null, null)) - .build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getDevice().getLmt()).isNull(); - } - - @Test - public void shouldUpdateImpsWithSecurityOneIfRequestIsSecuredAndImpSecurityNotDefined() { - // given - givenBidRequest(BidRequest.builder().imp(singletonList(Imp.builder().build())).build()); - given(paramsExtractor.secureFrom(any())).willReturn(1); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getImp()).extracting(Imp::getSecure).containsOnly(1); - } - - @Test - public void shouldNotUpdateImpsWithSecurityOneIfRequestIsSecureAndImpSecurityIsZero() { - // given - final List imps = singletonList(Imp.builder().secure(0).build()); - - givenBidRequest(BidRequest.builder().imp(imps).build()); - - given(paramsExtractor.secureFrom(any())).willReturn(1); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getImp()).isSameAs(imps); - } - - @Test - public void shouldUpdateImpsOnlyWithNotDefinedSecurityWithSecurityOneIfRequestIsSecure() { - // given - givenBidRequest(BidRequest.builder() - .imp(asList(Imp.builder().build(), Imp.builder().secure(0).build())) - .build()); - given(paramsExtractor.secureFrom(any())).willReturn(1); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getImp()).extracting(Imp::getSecure).containsOnly(1, 0); - } - - @Test - public void shouldNotUpdateImpsWithSecurityOneIfRequestIsNotSecureAndImpSecurityIsNotDefined() { - // given - final List imps = singletonList(Imp.builder().build()); - - givenBidRequest(BidRequest.builder().imp(imps).build()); - - given(paramsExtractor.secureFrom(any())).willReturn(0); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getImp()).isSameAs(imps); - } - - @Test - public void shouldMoveBidderParametersToImpExtPrebidBidderAndMergeWithExisting() { - // given - final List imps = singletonList( - Imp.builder() - .ext(mapper.createObjectNode() - .set("bidder1", mapper.createObjectNode().put("param1", "value1")) - .set("bidder2", mapper.createObjectNode().put("param2", "value2")) - .set("context", mapper.createObjectNode().put("data", "datavalue")) - .set("all", mapper.createObjectNode().put("all-data", "all-value")) - .set("general", mapper.createObjectNode() - .put("general-data", "general-value")) - .set("skadn", mapper.createObjectNode() - .put("skadn-data", "skadn-value")) - .set("data", mapper.createObjectNode() - .put("data-data", "data-value")) - .set("prebid", mapper.createObjectNode() - .set("bidder", mapper.createObjectNode() - .set("bidder2", mapper.createObjectNode().put("param22", "value22"))) - .set("storedrequest", mapper.createObjectNode().put("id", "storedreq1")))) - .build()); - - givenBidRequest(BidRequest.builder().imp(imps).build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getImp()).containsOnly( - Imp.builder() - .ext(mapper.createObjectNode() - .set("context", mapper.createObjectNode().put("data", "datavalue")) - .set("all", mapper.createObjectNode().put("all-data", "all-value")) - .set("general", mapper.createObjectNode() - .put("general-data", "general-value")) - .set("skadn", mapper.createObjectNode() - .put("skadn-data", "skadn-value")) - .set("data", mapper.createObjectNode() - .put("data-data", "data-value")) - .set("prebid", mapper.createObjectNode() - .set("bidder", mapper.createObjectNode() - .set( - "bidder1", mapper.createObjectNode().put("param1", "value1")) - .set( - "bidder2", mapper.createObjectNode() - .put("param2", "value2") - .put("param22", "value22"))) - .set("storedrequest", mapper.createObjectNode().put("id", "storedreq1")))) - .build()); - } - - @Test - public void shouldMoveBidderParametersToImpExtPrebidBidderWhenImpExtPrebidAbsent() { - // given - final List imps = singletonList( - Imp.builder() - .ext(mapper.createObjectNode() - .set("bidder1", mapper.createObjectNode().put("param1", "value1")) - .set("bidder2", mapper.createObjectNode().put("param2", "value2"))) - .build()); - - givenBidRequest(BidRequest.builder().imp(imps).build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getImp()).containsOnly( - Imp.builder() - .ext(mapper.createObjectNode() - .set("prebid", mapper.createObjectNode() - .set("bidder", mapper.createObjectNode() - .set( - "bidder1", mapper.createObjectNode().put("param1", "value1")) - .set( - "bidder2", mapper.createObjectNode().put("param2", "value2"))))) - .build()); - } - - @Test - public void shouldNotChangeImpExtWhenBidderParametersAreAtImpExtPrebidBidderOnly() { - // given - final List imps = singletonList( - Imp.builder() - .ext(mapper.createObjectNode() - .set("prebid", mapper.createObjectNode() - .set("bidder", mapper.createObjectNode() - .set( - "bidder1", mapper.createObjectNode().put("param1", "value1")) - .set( - "bidder2", mapper.createObjectNode().put("param2", "value2"))))) - .build()); - - givenBidRequest(BidRequest.builder().imp(imps).build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getImp()).isSameAs(imps); - } - - @Test - public void shouldNotSetFieldsFromHeadersIfRequestFieldsNotEmpty() { - // given - final BidRequest bidRequest = BidRequest.builder() - .site(Site.builder().domain("test.com").page("http://test.com") - .ext(ExtSite.of(0, null)).build()) - .device(Device.builder().ua("UnitTestUA").ip("56.76.12.3").build()) - .user(User.builder().id("userId").build()) - .cur(singletonList("USD")) - .tmax(2000L) - .at(1) - .build(); - - givenBidRequest(bidRequest); - - given(ipAddressHelper.toIpAddress(eq("56.76.12.3"))) - .willReturn(IpAddress.of("56.76.12.3", IpAddress.IP.v4)); - - givenImplicitParams( - "http://anotherexample.com", "anotherexample.com", "192.168.244.2", IpAddress.IP.v4, "UnitTest2"); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request).isSameAs(bidRequest); - } - - @Test - public void shouldSetSiteExtIfNoReferer() { - // given - givenValidBidRequest(); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getSite()) - .extracting(Site::getExt) - .containsOnly(ExtSite.of(0, null)); - } - - @Test - public void shouldNotSetSitePageIfNoReferer() { - // given - givenBidRequest(BidRequest.builder() - .site(Site.builder().domain("home.com").build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getSite()).isEqualTo( - Site.builder().domain("home.com").ext(ExtSite.of(0, null)).build()); - } - - @Test - public void shouldNotSetSitePageIfDomainCouldNotBeDerived() { - // given - givenValidBidRequest(); - - given(paramsExtractor.refererFrom(any())).willReturn("http://not-valid-site"); - given(paramsExtractor.domainFrom(anyString())).willThrow(new PreBidException("Couldn't derive domain")); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getSite()).isEqualTo( - Site.builder().ext(ExtSite.of(0, null)).build()); - } - - @Test - public void shouldSetDomainFromPageInsteadOfReferer() { - // given - givenBidRequest(BidRequest.builder() - .site(Site.builder().page("http://page.site.com/page1.html").build()) - .build()); - - given(paramsExtractor.refererFrom(any())).willReturn("http://any-site/referer.html"); - given(paramsExtractor.domainFrom(anyString())).willReturn("site.com"); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - verify(paramsExtractor).domainFrom(eq("http://page.site.com/page1.html")); - - assertThat(singleton(request.getSite())) - .extracting(Site::getPage, Site::getDomain) - .containsOnly(tuple("http://page.site.com/page1.html", "site.com")); - } - - @Test - public void shouldSetSiteExtAmpIfSiteHasNoExt() { - // given - givenBidRequest(BidRequest.builder() - .site(Site.builder().domain("test.com").page("http://test.com").build()) - .build()); - givenImplicitParams( - "http://anotherexample.com", "anotherexample.com", "192.168.244.2", IpAddress.IP.v4, "UnitTest2"); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getSite()).isEqualTo( - Site.builder().domain("test.com").page("http://test.com") - .ext(ExtSite.of(0, null)).build()); - } - - @Test - public void shouldSetSiteExtAmpIfSiteExtHasNoAmp() { - // given - givenBidRequest(BidRequest.builder() - .site(Site.builder().domain("test.com").page("http://test.com") - .ext(ExtSite.of(null, null)).build()) - .build()); - givenImplicitParams( - "http://anotherexample.com", "anotherexample.com", "192.168.244.2", IpAddress.IP.v4, "UnitTest2"); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getSite()).isEqualTo( - Site.builder().domain("test.com").page("http://test.com") - .ext(ExtSite.of(0, null)).build()); - } - - @Test - public void shouldSetSiteExtAmpIfNoReferer() { - // given - givenBidRequest(BidRequest.builder() - .site(Site.builder().domain("test.com").page("http://test.com").build()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getSite()).isEqualTo( - Site.builder().domain("test.com").page("http://test.com") - .ext(ExtSite.of(0, null)).build()); - } - - @Test - public void shouldSetSourceTidIfNotDefined() { - // given - given(idGenerator.generateId()).willReturn("f6965ea7-f281-4eb9-9de2-560a52d954a3"); - - givenBidRequest(BidRequest.builder().build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getSource()) - .isEqualTo(Source.builder().tid("f6965ea7-f281-4eb9-9de2-560a52d954a3").build()); - } - - @Test - public void shouldSetDefaultAtIfInitialValueIsEqualsToZero() { - // given - givenBidRequest(BidRequest.builder().at(0).build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getAt()).isEqualTo(1); - } - - @Test - public void shouldSetDefaultAtIfInitialValueIsEqualsToNull() { - // given - givenBidRequest(BidRequest.builder().at(null).build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getAt()).isEqualTo(1); - } - - @Test - public void shouldSetCurrencyIfMissedInRequestAndPresentInAdServerCurrencyConfig() { - // given - givenBidRequest(BidRequest.builder().cur(null).build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getCur()).isEqualTo(singletonList("USD")); - } - - @Test - public void shouldSetTimeoutFromTimeoutResolver() { - // given - givenBidRequest(BidRequest.builder().build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getTmax()).isEqualTo(2000L); - } - - @Test - public void shouldConvertStringPriceGranularityViewToCustom() { - // given - givenBidRequest(BidRequest.builder() - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .targeting(ExtRequestTargeting.builder().pricegranularity(new TextNode("low")).build()) - .build())) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - // request was wrapped to list because extracting method works different on iterable and not iterable objects, - // which force to make type casting or exception handling in lambdas - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getTargeting) - .extracting(ExtRequestTargeting::getPricegranularity) - .containsOnly(mapper.valueToTree(ExtPriceGranularity.of(2, singletonList(ExtGranularityRange.of( - BigDecimal.valueOf(5), BigDecimal.valueOf(0.5)))))); - } - - @Test - public void shouldReturnFailedFutureWithInvalidRequestExceptionWhenStringPriceGranularityInvalid() { - // given - givenBidRequest(BidRequest.builder() - .imp(singletonList(Imp.builder().build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .targeting(ExtRequestTargeting.builder().pricegranularity(new TextNode("invalid")).build()) - .build())) - .build()); - - // when - final Future future = factory.fromRequest(routingContext, 0L); - - // then - assertThat(future.failed()).isTrue(); - assertThat(future.cause()) - .isInstanceOf(InvalidRequestException.class) - .hasMessage("Invalid string price granularity with value: invalid"); - } - - @Test - public void shouldSetDefaultPriceGranularityIfPriceGranularityAndMediaTypePriceGranularityIsMissing() { - // given - givenBidRequest(BidRequest.builder() - .imp(singletonList(Imp.builder().video(Video.builder().build()).ext(mapper.createObjectNode()).build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .targeting(ExtRequestTargeting.builder().build()) - .build())) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getTargeting) - .extracting(ExtRequestTargeting::getPricegranularity) - .containsOnly(mapper.valueToTree(ExtPriceGranularity.of(2, singletonList(ExtGranularityRange.of( - BigDecimal.valueOf(20), BigDecimal.valueOf(0.1)))))); - } - - @Test - public void shouldNotSetDefaultPriceGranularityIfThereIsAMediaTypePriceGranularityForImpType() { - // given - final ExtMediaTypePriceGranularity mediaTypePriceGranularity = ExtMediaTypePriceGranularity.of( - mapper.valueToTree(ExtPriceGranularity.of(2, singletonList(ExtGranularityRange.of( - BigDecimal.valueOf(20), BigDecimal.valueOf(0.1))))), null, null); - givenBidRequest(BidRequest.builder() - .imp(singletonList(Imp.builder().banner(Banner.builder().build()) - .ext(mapper.createObjectNode()).build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .targeting(ExtRequestTargeting.builder() - .mediatypepricegranularity(mediaTypePriceGranularity) - .build()) - .build())) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getTargeting) - .extracting(ExtRequestTargeting::getPricegranularity) - .containsOnly((JsonNode) null); - } - - @Test - public void shouldSetDefaultIncludeWinnersIfIncludeWinnersIsMissed() { - // given - givenBidRequest(BidRequest.builder() - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .targeting(ExtRequestTargeting.builder().build()) - .build())) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getTargeting) - .extracting(ExtRequestTargeting::getIncludewinners) - .containsOnly(true); - } - - @Test - public void shouldSetDefaultIncludeBidderKeysIfIncludeBidderKeysIsMissed() { - // given - givenBidRequest(BidRequest.builder() - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .targeting(ExtRequestTargeting.builder().build()) - .build())) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getTargeting) - .extracting(ExtRequestTargeting::getIncludebidderkeys) - .containsOnly(true); - } - - @Test - public void shouldSetDefaultIncludeBidderKeysToFalseIfIncludeBidderKeysIsMissedAndWinningonlyIsTrue() { - // given - givenBidRequest(BidRequest.builder() - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .targeting(ExtRequestTargeting.builder().build()) - .cache(ExtRequestPrebidCache.of(null, null, true)) - .build())) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getTargeting) - .extracting(ExtRequestTargeting::getIncludebidderkeys) - .containsOnly(false); - } - - @Test - public void shouldSetDefaultIncludeBidderKeysToFalseIfIncludeBidderKeysIsMissedAndWinningonlyIsTrueInConfig() { - // given - factory = new AuctionRequestFactory( - Integer.MAX_VALUE, - false, - true, - "USD", - BLACKLISTED_APPS, - BLACKLISTED_ACCOUNTS, - storedRequestProcessor, - paramsExtractor, - ipAddressHelper, - uidsCookieService, - bidderCatalog, - requestValidator, - interstitialProcessor, - ortbTypesResolver, - timeoutResolver, - timeoutFactory, - applicationSettings, - idGenerator, - privacyEnforcementService, - jacksonMapper); - givenBidRequest(BidRequest.builder() - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .targeting(ExtRequestTargeting.builder().build()) - .build())) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getTargeting) - .extracting(ExtRequestTargeting::getIncludebidderkeys) - .containsOnly(false); - } - - @Test - public void shouldSetCacheWinningonlyFromConfigWhenExtRequestPrebidIsNull() { - // given - factory = new AuctionRequestFactory( - Integer.MAX_VALUE, - false, - true, - "USD", - BLACKLISTED_APPS, - BLACKLISTED_ACCOUNTS, - storedRequestProcessor, - paramsExtractor, - ipAddressHelper, - uidsCookieService, - bidderCatalog, - requestValidator, - interstitialProcessor, - ortbTypesResolver, - timeoutResolver, - timeoutFactory, - applicationSettings, - idGenerator, - privacyEnforcementService, - jacksonMapper); - - givenBidRequest(BidRequest.builder() - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .ext(ExtRequest.empty()) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getCache) - .extracting(ExtRequestPrebidCache::getWinningonly) - .containsOnly(true); - } - - @Test - public void shouldSetCacheWinningonlyFromConfigWhenExtRequestPrebidCacheIsNull() { - // given - factory = new AuctionRequestFactory( - Integer.MAX_VALUE, - false, - true, - "USD", - BLACKLISTED_APPS, - BLACKLISTED_ACCOUNTS, - storedRequestProcessor, - paramsExtractor, - ipAddressHelper, - uidsCookieService, - bidderCatalog, - requestValidator, - interstitialProcessor, - ortbTypesResolver, - timeoutResolver, - timeoutFactory, - applicationSettings, - idGenerator, - privacyEnforcementService, - jacksonMapper); - - givenBidRequest(BidRequest.builder() - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder().build())) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getCache) - .extracting(ExtRequestPrebidCache::getWinningonly) - .containsOnly(true); - } - - @Test - public void shouldSetCacheWinningonlyFromConfigWhenCacheWinningonlyIsNull() { - // given - factory = new AuctionRequestFactory( - Integer.MAX_VALUE, - false, - true, - "USD", - BLACKLISTED_APPS, - BLACKLISTED_ACCOUNTS, - storedRequestProcessor, - paramsExtractor, - ipAddressHelper, - uidsCookieService, - bidderCatalog, - requestValidator, - interstitialProcessor, - ortbTypesResolver, - timeoutResolver, - timeoutFactory, - applicationSettings, - idGenerator, - privacyEnforcementService, - jacksonMapper); - - givenBidRequest(BidRequest.builder() - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .cache(ExtRequestPrebidCache.of(null, null, null)) - .build())) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getCache) - .extracting(ExtRequestPrebidCache::getWinningonly) - .containsOnly(true); - } - - @Test - public void shouldNotChangeAnyOtherExtRequestPrebidCacheFields() { - // given - final ExtRequestPrebidCacheBids cacheBids = ExtRequestPrebidCacheBids.of(100, true); - final ExtRequestPrebidCacheVastxml cacheVastxml = ExtRequestPrebidCacheVastxml.of(100, true); - givenBidRequest(BidRequest.builder() - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .cache(ExtRequestPrebidCache.of(cacheBids, cacheVastxml, null)) - .build())) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getCache) - .extracting(ExtRequestPrebidCache::getBids, ExtRequestPrebidCache::getVastxml) - .containsOnly(tuple(cacheBids, cacheVastxml)); - } - - @Test - public void shouldNotChangeAnyOtherExtRequestPrebidTargetingFields() { - // given - givenBidRequest(BidRequest.builder() - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .targeting(ExtRequestTargeting.builder() - .includebrandcategory(ExtIncludeBrandCategory.of(1, "publisher", true)) - .truncateattrchars(10) - .build()) - .build())) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getTargeting) - .extracting(ExtRequestTargeting::getIncludebrandcategory, ExtRequestTargeting::getTruncateattrchars) - .containsOnly(tuple(ExtIncludeBrandCategory.of(1, "publisher", true), 10)); - } - - @Test - public void shouldSetCacheWinningonlyFromRequestWhenCacheWinningonlyIsPresent() { - // given - factory = new AuctionRequestFactory( - Integer.MAX_VALUE, - false, - true, - "USD", - BLACKLISTED_APPS, - BLACKLISTED_ACCOUNTS, - storedRequestProcessor, - paramsExtractor, - ipAddressHelper, - uidsCookieService, - bidderCatalog, - requestValidator, - interstitialProcessor, - ortbTypesResolver, - timeoutResolver, - timeoutFactory, - applicationSettings, - idGenerator, - privacyEnforcementService, - jacksonMapper); - - givenBidRequest(BidRequest.builder() - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .cache(ExtRequestPrebidCache.of(null, null, false)) - .build())) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getCache) - .extracting(ExtRequestPrebidCache::getWinningonly) - .containsOnly(false); - } - - @Test - public void shouldNotSetCacheWinningonlyFromConfigWhenCacheWinningonlyIsNullAndConfigValueIsFalse() { - // given - factory = new AuctionRequestFactory( - Integer.MAX_VALUE, - false, - false, - "USD", - BLACKLISTED_APPS, - BLACKLISTED_ACCOUNTS, - storedRequestProcessor, - paramsExtractor, - ipAddressHelper, - uidsCookieService, - bidderCatalog, - requestValidator, - interstitialProcessor, - ortbTypesResolver, - timeoutResolver, - timeoutFactory, - applicationSettings, - idGenerator, - privacyEnforcementService, - jacksonMapper); - - final ExtRequest extBidRequest = ExtRequest.of(ExtRequestPrebid.builder() - .cache(ExtRequestPrebidCache.of(null, null, null)) - .build()); - - givenBidRequest(BidRequest.builder() - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .ext(extBidRequest) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(request.getExt()).isSameAs(extBidRequest); - } - - @Test - public void shouldAddMissingAliases() { - // given - final Imp imp1 = Imp.builder() - .ext(mapper.createObjectNode() - .set("requestScopedBidderAlias", mapper.createObjectNode())) - .build(); - final Imp imp2 = Imp.builder() - .ext(mapper.createObjectNode() - .set("configScopedBidderAlias", mapper.createObjectNode())) - .build(); - - givenBidRequest(BidRequest.builder() - .imp(asList(imp1, imp2)) - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .aliases(singletonMap("requestScopedBidderAlias", "bidder1")) - .targeting(ExtRequestTargeting.builder().build()) - .build())) - .build()); - - given(bidderCatalog.isAlias("configScopedBidderAlias")).willReturn(true); - given(bidderCatalog.nameByAlias("configScopedBidderAlias")).willReturn("bidder2"); - - // when - final Future auctionContextFuture = factory.fromRequest(routingContext, 0L); - final BidRequest request = auctionContextFuture.result().getBidRequest(); - - // then - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .flatExtracting(extRequestPrebid -> extRequestPrebid.getAliases().entrySet()) - .extracting(Map.Entry::getKey, Map.Entry::getValue) - .containsOnly( - tuple("requestScopedBidderAlias", "bidder1"), - tuple("configScopedBidderAlias", "bidder2")); - } - - @Test - public void shouldSetRequestPrebidChannelWhenMissingInRequestAndSite() { - // given - givenBidRequest(BidRequest.builder() - .site(Site.builder().build()) - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder().build())) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getChannel) - .containsOnly(ExtRequestPrebidChannel.of("web")); - } - - @Test - public void shouldSetRequestPrebidChannelWhenMissingInRequestAndApp() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder().build())) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getChannel) - .containsOnly(ExtRequestPrebidChannel.of("app")); - } - - @Test - public void shouldNotSetRequestPrebidChannelWhenMissingInRequestAndNotSiteOrApp() { - // given - givenBidRequest(BidRequest.builder() - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder().build())) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getChannel) - .containsOnly((ExtRequestPrebidChannel) null); - } - - @Test - public void shouldNotSetRequestPrebidChannelWhenPresentInRequestAndApp() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().build()) - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .channel(ExtRequestPrebidChannel.of("custom")) - .build())) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getChannel) - .containsOnly(ExtRequestPrebidChannel.of("custom")); - } - - @Test - public void shouldTolerateMissingImpExtWhenProcessingAliases() { - // given - givenBidRequest(BidRequest.builder() - .imp(singletonList(Imp.builder().ext(null).build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .aliases(singletonMap("alias", "bidder")) - .build())) - .build()); - - // when - final Future future = factory.fromRequest(routingContext, 0L); - - // then - assertThat(future.succeeded()).isTrue(); - } - - @Test - public void shouldPassExtPrebidDebugFlagIfPresent() { - // given - givenBidRequest(BidRequest.builder() - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .debug(1) - .build())) - .build()); - - // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - - // then - assertThat(singletonList(request)) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getDebug) - .containsOnly(1); - } - - @Test - public void shouldReturnFailedFutureIfRequestValidationFailed() { - // given - given(routingContext.getBody()).willReturn(Buffer.buffer("{}")); - - given(storedRequestProcessor.processStoredRequests(any(), any())) - .willReturn(Future.succeededFuture(BidRequest.builder().build())); - - given(requestValidator.validate(any())) - .willReturn(new ValidationResult(emptyList(), asList("error1", "error2"))); - - // when - final Future future = factory.fromRequest(routingContext, 0L); - - // then - assertThat(future.failed()).isTrue(); - assertThat(future.cause()).isInstanceOf(InvalidRequestException.class); - assertThat(((InvalidRequestException) future.cause()).getMessages()).containsOnly("error1", "error2"); - } - - @Test - public void shouldReturnFailedFutureIfEidsPermissionsContainsWrongDataType() throws JsonProcessingException { - // given - final BidRequest bidRequest = BidRequest.builder() - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .data(ExtRequestPrebidData.of(emptyList(), null)) - .build())) - .build(); - - final ObjectNode requestNode = mapper.convertValue(bidRequest, ObjectNode.class); - final JsonNode eidPermissionNode = mapper.convertValue( - ExtRequestPrebidDataEidPermissions.of("source", emptyList()), JsonNode.class); - - requestNode.with("ext").with("prebid").with("data").set("eidpermissions", eidPermissionNode); - - given(routingContext.getBody()).willReturn(Buffer.buffer(requestNode.toString())); - - // when - final Future future = factory.fromRequest(routingContext, 0L); - - // then - assertThat(future.failed()).isTrue(); - assertThat(future.cause()).isInstanceOf(InvalidRequestException.class); - assertThat(((InvalidRequestException) future.cause()).getMessages()) - .hasSize(1) - .allSatisfy(message -> - assertThat(message).startsWith("Error decoding bidRequest: Cannot deserialize instance")); - } - - @Test - public void shouldReturnFailedFutureIfEidsPermissionsBiddersContainsWrongDataType() throws JsonProcessingException { - // given - final BidRequest bidRequest = BidRequest.builder() - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .data(ExtRequestPrebidData.of(emptyList(), null)) - .build())) - .build(); - - final ObjectNode requestNode = mapper.convertValue(bidRequest, ObjectNode.class); - - final ObjectNode eidPermissionNode = mapper.convertValue( - ExtRequestPrebidDataEidPermissions.of("source", emptyList()), ObjectNode.class); - - eidPermissionNode.put("bidders", "notArrayValue"); - - final ArrayNode arrayNode = requestNode - .with("ext") - .with("prebid") - .with("data") - .putArray("eidpermissions"); - arrayNode.add(eidPermissionNode); - - given(routingContext.getBody()).willReturn(Buffer.buffer(requestNode.toString())); - - // when - final Future future = factory.fromRequest(routingContext, 0L); - - // then - assertThat(future.failed()).isTrue(); - assertThat(future.cause()).isInstanceOf(InvalidRequestException.class); - assertThat(((InvalidRequestException) future.cause()).getMessages()) - .hasSize(1) - .allSatisfy(message -> - assertThat(message).startsWith("Error decoding bidRequest: Cannot deserialize instance")); - } - - @Test - public void shouldReturnAuctionContextWithRoutingContext() { - // given - givenValidBidRequest(); - - // when - final RoutingContext context = factory.fromRequest(routingContext, 0L).result().getRoutingContext(); - - // then - assertThat(context).isSameAs(routingContext); - } - - @Test - public void shouldReturnAuctionContextWithUidsCookie() { - // given - givenValidBidRequest(); - - final UidsCookie givenUidsCookie = new UidsCookie(Uids.builder() - .uids(singletonMap("bidder", UidWithExpiry.live("uid"))) - .build(), jacksonMapper); - given(uidsCookieService.parseFromRequest(any())).willReturn(givenUidsCookie); - - // when - final UidsCookie uidsCookie = factory.fromRequest(routingContext, 0L).result().getUidsCookie(); - - // then - assertThat(uidsCookie).isSameAs(givenUidsCookie); - } - - @Test - public void shouldReturnAuctionContextWithTimeout() { - // given - givenValidBidRequest(); - - given(timeoutFactory.create(anyLong(), anyLong())).willReturn(mock(Timeout.class)); - - final long startTime = Clock.fixed(Instant.now(), ZoneId.systemDefault()).millis(); - - // when - final Timeout timeout = factory.fromRequest(routingContext, startTime).result().getTimeout(); - - // then - verify(timeoutFactory).create(eq(startTime), anyLong()); - assertThat(timeout).isNotNull(); - } - - @Test - public void shouldReturnFailedFutureWhenAccountIdIsBlacklisted() { - // given - givenBidRequest(BidRequest.builder() - .site(Site.builder() - .publisher(Publisher.builder().id("bad_acc").build()).build()) - .build()); - - // when - final Future result = factory.fromRequest(routingContext, 0); - - // then - assertThat(result.failed()).isTrue(); - assertThat(result.cause()) - .isInstanceOf(BlacklistedAccountException.class) - .hasMessage("Prebid-server has blacklisted Account ID: bad_acc, please reach out to the prebid " - + "server host."); - } - - @Test - public void shouldReturnFailedFutureWhenAppIdIsBlacklisted() { - // given - givenBidRequest(BidRequest.builder() - .app(App.builder().id("bad_app").build()) - .build()); - - // when - final Future result = factory.fromRequest(routingContext, 0); - - // then - assertThat(result.failed()).isTrue(); - assertThat(result.cause()) - .isInstanceOf(BlacklistedAppException.class) - .hasMessage("Prebid-server does not process requests from App ID: bad_app"); - } - - @Test - public void shouldReturnAuctionContextWithAccountIdTakenFromPublisherExt() { - // given - givenBidRequest(BidRequest.builder() - .site(Site.builder() - .publisher(Publisher.builder().id("accountId") - .ext(ExtPublisher.of(ExtPublisherPrebid.of("parentAccount"))) - .build()) - .build()) - .build()); - - final Account givenAccount = Account.builder().id("parentAccount").build(); - given(applicationSettings.getAccountById(any(), any())) - .willReturn(Future.succeededFuture(givenAccount)); - - // when - final Account account = factory.fromRequest(routingContext, 0L).result().getAccount(); - - // then - verify(applicationSettings).getAccountById(eq("parentAccount"), any()); - - assertThat(account).isSameAs(givenAccount); - } - - @Test - public void shouldReturnAuctionContextWithAccountIdTakenFromPublisherIdWhenExtIsNull() { - // given - givenBidRequest(BidRequest.builder() - .site(Site.builder() - .publisher(Publisher.builder().id("accountId").ext(null).build()) - .build()) - .build()); - - final Account givenAccount = Account.builder().id("accountId").build(); - given(applicationSettings.getAccountById(any(), any())) - .willReturn(Future.succeededFuture(givenAccount)); - - // when - final Account account = factory.fromRequest(routingContext, 0L).result().getAccount(); - - // then - verify(applicationSettings).getAccountById(eq("accountId"), any()); - - assertThat(account).isSameAs(givenAccount); - } - - @Test - public void shouldReturnAuctionContextWithAccountIdTakenFromPublisherIdWhenExtPublisherPrebidIsNull() { - // given - givenBidRequest(BidRequest.builder() - .site(Site.builder() - .publisher(Publisher.builder().id("accountId") - .ext(ExtPublisher.empty()) - .build()) - .build()) - .build()); - - final Account givenAccount = Account.builder().id("accountId").build(); - given(applicationSettings.getAccountById(any(), any())) - .willReturn(Future.succeededFuture(givenAccount)); - - // when - final Account account = factory.fromRequest(routingContext, 0L).result().getAccount(); - - // then - verify(applicationSettings).getAccountById(eq("accountId"), any()); - - assertThat(account).isSameAs(givenAccount); - } - - @Test - public void shouldReturnAuctionContextWithAccountIdTakenFromPublisherIdWhenExtParentIsEmpty() { - // given - givenBidRequest(BidRequest.builder() - .site(Site.builder() - .publisher(Publisher.builder().id("accountId") - .ext(ExtPublisher.of(ExtPublisherPrebid.of(""))) - .build()) - .build()) - .build()); - - final Account givenAccount = Account.builder().id("accountId").build(); - given(applicationSettings.getAccountById(any(), any())) - .willReturn(Future.succeededFuture(givenAccount)); - - // when - final Account account = factory.fromRequest(routingContext, 0L).result().getAccount(); - - // then - verify(applicationSettings).getAccountById(eq("accountId"), any()); - - assertThat(account).isSameAs(givenAccount); - } - - @Test - public void shouldReturnAuctionContextWithEmptyAccountIfNotFound() { - // given - givenBidRequest(BidRequest.builder() - .site(Site.builder() - .publisher(Publisher.builder().id("accountId") - .ext(ExtPublisher.of(ExtPublisherPrebid.of("parentAccount"))) - .build()) - .build()) - .build()); - - given(applicationSettings.getAccountById(any(), any())) - .willReturn(Future.failedFuture(new PreBidException("not found"))); - - // when - final Account account = factory.fromRequest(routingContext, 0L).result().getAccount(); - - // then - verify(applicationSettings).getAccountById(eq("parentAccount"), any()); - - assertThat(account).isEqualTo(Account.builder().id("parentAccount").build()); - } - - @Test - public void shouldReturnAuctionContextWithEmptyAccountIfExceptionOccurred() { - // given - givenBidRequest(BidRequest.builder() - .site(Site.builder() - .publisher(Publisher.builder().id("accountId").build()) - .build()) - .build()); - - given(applicationSettings.getAccountById(any(), any())) - .willReturn(Future.failedFuture(new RuntimeException("error"))); - - // when - final Account account = factory.fromRequest(routingContext, 0L).result().getAccount(); - - // then - verify(applicationSettings).getAccountById(eq("accountId"), any()); - - assertThat(account).isEqualTo(Account.builder().id("accountId").build()); - } - - @Test - public void shouldReturnAuctionContextWithEmptyAccountIfItIsMissingInRequest() { - // given - givenValidBidRequest(); - - // when - final Account account = factory.fromRequest(routingContext, 0L).result().getAccount(); - - // then - assertThat(account).isEqualTo(Account.builder().id("").build()); - verifyZeroInteractions(applicationSettings); - } - - @Test - public void shouldReturnAuctionContextWithIntegrationFromAccount() { - // given - givenBidRequest(BidRequest.builder() - .imp(emptyList()) - .site(Site.builder() - .publisher(Publisher.builder().id("123").build()) - .build()) - .ext(ExtRequest.of(ExtRequestPrebid.builder().build())) - .build()); - - final Account givenAccount = Account.builder().id("123").defaultIntegration("integration").build(); - given(applicationSettings.getAccountById(any(), any())) - .willReturn(Future.succeededFuture(givenAccount)); - - // when - final AuctionContext auctionContext = factory.fromRequest(routingContext, 0L).result(); - - // then - assertThat(singletonList(auctionContext.getBidRequest())) - .extracting(BidRequest::getExt) - .extracting(ExtRequest::getPrebid) - .extracting(ExtRequestPrebid::getIntegration) - .containsOnly("integration"); - } - - @Test - public void shouldReturnAuctionContextWithWebRequestTypeMetric() { - // given - givenValidBidRequest(); - - // when - final Future auctionContextFuture = factory.fromRequest(routingContext, 0L); - - // then - assertThat(auctionContextFuture).isSucceeded(); - assertThat(auctionContextFuture.result().getRequestTypeMetric()).isEqualTo(MetricName.openrtb2web); - } - - @Test - public void shouldReturnAuctionContextWithAppRequestTypeMetric() { - // given - givenBidRequest(BidRequest.builder().app(App.builder().build()).build()); - - // when - final Future auctionContextFuture = factory.fromRequest(routingContext, 0L); - - // then - assertThat(auctionContextFuture).isSucceeded(); - assertThat(auctionContextFuture.result().getRequestTypeMetric()).isEqualTo(MetricName.openrtb2app); - } - - @Test - public void shouldEnrichRequestWithIpAddressAndCountryAndSaveAuctionContext() { - // given - givenBidRequest(BidRequest.builder().build()); - - final PrivacyContext privacyContext = PrivacyContext.of( - Privacy.of(EMPTY, EMPTY, Ccpa.EMPTY, 0), - TcfContext.builder() - .geoInfo(GeoInfo.builder().vendor("v").country("ua").build()) - .build(), - "ip"); - given(privacyEnforcementService.contextFromBidRequest(any(), any(), any(), any(), any())) - .willReturn(Future.succeededFuture(privacyContext)); - - // when - final Future auctionContextFuture = factory.fromRequest(routingContext, 0L); - - // then - assertThat(auctionContextFuture).isSucceeded(); - - final AuctionContext auctionContext = auctionContextFuture.result(); - assertThat(auctionContext.getBidRequest().getDevice()).isEqualTo( - Device.builder() - .ip("ip") - .geo(Geo.builder().country("ua").build()) - .build()); - assertThat(auctionContext.getPrivacyContext()).isSameAs(privacyContext); - } - - private void givenImplicitParams(String referer, String domain, String ip, IpAddress.IP ipVersion, String ua) { - given(paramsExtractor.refererFrom(any())).willReturn(referer); - given(paramsExtractor.domainFrom(anyString())).willReturn(domain); - given(paramsExtractor.ipFrom(any())).willReturn(singletonList(ip)); - given(ipAddressHelper.toIpAddress(eq(ip))).willReturn(IpAddress.of(ip, ipVersion)); - given(paramsExtractor.uaFrom(any())).willReturn(ua); - } - - private void givenBidRequest(BidRequest bidRequest) { - try { - given(routingContext.getBody()).willReturn(Buffer.buffer(mapper.writeValueAsString(bidRequest))); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - - given(storedRequestProcessor.processStoredRequests(any(), any())) - .willReturn(Future.succeededFuture(bidRequest)); - - given(requestValidator.validate(any())).willReturn(ValidationResult.success()); - } - - private void givenValidBidRequest() { - givenBidRequest(BidRequest.builder().build()); - } -} diff --git a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java index 6e1d08f71d8..e6f9a563ce7 100644 --- a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java +++ b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java @@ -18,7 +18,6 @@ import com.iab.openrtb.response.Response; import com.iab.openrtb.response.SeatBid; import io.vertx.core.Future; -import org.apache.commons.collections4.CollectionUtils; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -32,6 +31,7 @@ import org.prebid.server.auction.model.BidRequestCacheInfo; import org.prebid.server.auction.model.BidderResponse; import org.prebid.server.auction.model.MultiBidConfig; +import org.prebid.server.auction.model.TargetingInfo; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderError; @@ -174,6 +174,45 @@ public void setUp() { timeout = new TimeoutFactory(Clock.fixed(Instant.now(), ZoneId.systemDefault())).create(500); } + @Test + public void shouldPassBidWithGeneratedIdAndNotOverrideExtFieldsWhenIdGeneratorTypeUuid() { + // given + final Imp imp = givenImp(); + final AuctionContext auctionContext = givenAuctionContext(givenBidRequest(imp)); + final String generatedId = "generatedId"; + given(idGenerator.getType()).willReturn(IdGeneratorType.uuid); + given(idGenerator.generateId()).willReturn(generatedId); + + final ObjectNode recievedBidExt = mapper.createObjectNode().put("origbidcur", "test"); + final Bid bid = Bid.builder() + .id("bidId1") + .impid(IMP_ID) + .price(BigDecimal.valueOf(5.67)) + .ext(recievedBidExt) + .build(); + final String bidder = "bidder1"; + final List bidderResponses = singletonList( + BidderResponse.of(bidder, givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); + + final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder().doCaching(true).build(); + + givenCacheServiceResult(singletonMap(bid, CacheInfo.empty())); + + // when + bidResponseCreator.create(bidderResponses, auctionContext, cacheInfo, MULTI_BIDS, false); + + // then + final ExtBidPrebid extBidPrebid = ExtBidPrebid.builder() + .bidid(generatedId) + .build(); + final Bid expectedBid = bid.toBuilder() + .ext(recievedBidExt.set("prebid", mapper.valueToTree(extBidPrebid))) + .build(); + final TargetingInfo targetingInfo = toTargetingInfo(bidder, true); + final BidInfo bidInfo = toBidInfo(expectedBid, imp, bidder, banner, targetingInfo); + verify(cacheService).cacheBidsOpenrtb(eq(singletonList(bidInfo)), any(), any(), any()); + } + @Test public void shouldPassOriginalTimeoutToCacheServiceIfCachingIsRequested() { // given @@ -246,8 +285,9 @@ public void shouldRequestCacheServiceWithExpectedArguments() { // then final BidInfo bidInfo1 = toBidInfo(bid1, imp1, "bidder1", banner); final BidInfo bidInfo2 = toBidInfo(bid2, imp2, "bidder1", banner); - final BidInfo bidInfo3 = toBidInfo(bid3, imp1, "bidder2", banner); - final BidInfo bidInfo4 = toBidInfo(bid4, imp2, "bidder2", banner); + final TargetingInfo loosedTargetingInfo = toTargetingInfo("bidder2", false); + final BidInfo bidInfo3 = toBidInfo(bid3, imp1, "bidder2", banner, loosedTargetingInfo); + final BidInfo bidInfo4 = toBidInfo(bid4, imp2, "bidder2", banner, loosedTargetingInfo); ArgumentCaptor contextArgumentCaptor = ArgumentCaptor.forClass(CacheContext.class); verify(cacheService).cacheBidsOpenrtb( argThat(t -> t.containsAll(asList(bidInfo1, bidInfo2, bidInfo3, bidInfo4))), @@ -306,19 +346,22 @@ public void shouldRequestCacheServiceWithWinningBidsOnlyWhenWinningonlyIsTrue() bidResponseCreator.create(bidderResponses, auctionContext, cacheInfo, MULTI_BIDS, false); // then + final BidInfo bidInfo1 = toBidInfo(bid1, imp1, "bidder1", banner); final BidInfo bidInfo2 = toBidInfo(bid2, imp2, "bidder1", banner); verify(cacheService).cacheBidsOpenrtb( - argThat(t -> t.containsAll(asList(bidInfo1, bidInfo2))), + argThat(t -> t.containsAll(asList(bidInfo2, bidInfo1))), same(auctionContext), any(), eq(EventsContext.builder().auctionTimestamp(1000L).build())); } + @SuppressWarnings("unchecked") @Test public void shouldRequestCacheServiceWithVideoBidsToModify() { // given - final Account account = Account.builder().id("accountId").eventsEnabled(true).build(); + final String accountId = "accountId"; + final Account account = Account.builder().id(accountId).eventsEnabled(true).build(); final Imp imp1 = givenImp("impId1"); final Imp imp2 = givenImp("impId2"); @@ -329,10 +372,14 @@ public void shouldRequestCacheServiceWithVideoBidsToModify() { imp1, imp2), contextBuilder -> contextBuilder.account(account)); - final Bid bid1 = Bid.builder().id("bidId1").impid("impId1").price(BigDecimal.valueOf(5.67)).build(); + final String bidId1 = "bidId1"; + final Bid bid1 = Bid.builder().id(bidId1).impid("impId1").price(BigDecimal.valueOf(5.67)).nurl(BID_NURL) + .build(); final Bid bid2 = Bid.builder().id("bidId2").impid("impId2").price(BigDecimal.valueOf(7.19)).build(); + + final String bidder1 = "bidder1"; final List bidderResponses = asList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid1, video, "USD")), 100), + BidderResponse.of(bidder1, givenSeatBid(BidderBid.of(bid1, video, "USD")), 100), BidderResponse.of("bidder2", givenSeatBid(BidderBid.of(bid2, banner, "USD")), 100)); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder() @@ -340,6 +387,9 @@ public void shouldRequestCacheServiceWithVideoBidsToModify() { .shouldCacheVideoBids(true) .build(); + final String modifiedAdm = "modifiedAdm"; + given(vastModifier.createBidVastXml(any(), any(), any(), any(), any(), any())).willReturn(modifiedAdm); + // just a stub to get through method call chain givenCacheServiceResult(singletonMap(bid1, CacheInfo.empty())); @@ -347,17 +397,63 @@ public void shouldRequestCacheServiceWithVideoBidsToModify() { bidResponseCreator.create(bidderResponses, auctionContext, cacheInfo, MULTI_BIDS, false); // then - final BidInfo bidInfo1 = toBidInfo(bid1, imp1, "bidder1", video); - final BidInfo bidInfo2 = toBidInfo(bid2, imp2, "bidder2", banner); + final EventsContext expectedEventContext = EventsContext.builder() + .enabledForAccount(true) + .enabledForRequest(true) + .auctionTimestamp(1000L) + .build(); + + verify(vastModifier).createBidVastXml(bidder1, null, BID_NURL, bidId1, accountId, expectedEventContext); + + final ArgumentCaptor> bidInfoCaptor = ArgumentCaptor.forClass(List.class); verify(cacheService).cacheBidsOpenrtb( - argThat(argument -> CollectionUtils.isEqualCollection(argument, asList(bidInfo1, bidInfo2))), + bidInfoCaptor.capture(), same(auctionContext), eq(CacheContext.builder().shouldCacheVideoBids(true).build()), - eq(EventsContext.builder() - .enabledForAccount(true) - .enabledForRequest(true) - .auctionTimestamp(1000L) - .build())); + eq(expectedEventContext)); + + final Bid expectedUpdatedBid1 = bid1.toBuilder().adm(modifiedAdm).build(); + final BidInfo bidInfo1 = toBidInfo(expectedUpdatedBid1, imp1, bidder1, video); + final BidInfo bidInfo2 = toBidInfo(bid2, imp2, "bidder2", banner); + assertThat(bidInfoCaptor.getValue()).containsOnly(bidInfo1, bidInfo2); + } + + @Test + public void shouldModifyBidAdmWhenBidVideoAndVastModifierReturnValue() { + // given + final AuctionContext auctionContext = givenAuctionContext(givenBidRequest( + identity(), + extBuilder -> extBuilder.targeting(givenTargeting()), + givenImp())); + + final String bidId = "bid_id"; + final Bid bid = Bid.builder() + .id(bidId) + .price(BigDecimal.ONE) + .adm(BID_ADM) + .nurl(BID_NURL) + .impid(IMP_ID) + .build(); + + final String bidder = "bidder1"; + final List bidderResponses = singletonList( + BidderResponse.of(bidder, givenSeatBid(BidderBid.of(bid, video, "USD")), 100)); + + final String modifiedVast = "modifiedVast"; + given(vastModifier.createBidVastXml(anyString(), anyString(), anyString(), anyString(), anyString(), any())) + .willReturn(modifiedVast); + + // when + final BidResponse bidResponse = + bidResponseCreator.create(bidderResponses, auctionContext, CACHE_INFO, MULTI_BIDS, false).result(); + + // then + assertThat(bidResponse.getSeatbid()) + .flatExtracting(SeatBid::getBid).hasSize(1) + .extracting(Bid::getAdm) + .containsOnly(modifiedVast); + + verify(vastModifier).createBidVastXml(eq(bidder), eq(BID_ADM), eq(BID_NURL), eq(bidId), eq("accountId"), any()); } @Test @@ -550,9 +646,9 @@ public void shouldUseGeneratedBidIdForEventAndCacheWhenIdGeneratorIsUUIDAndEvent final List bidderResponses = singletonList( BidderResponse.of(bidder, givenSeatBid(BidderBid.of(bid, banner, "USD")), 0)); - final String generatedBid = "de7fc739-0a6e-41ad-8961-701c30c82166"; + final String generatedBidId = "de7fc739-0a6e-41ad-8961-701c30c82166"; given(idGenerator.getType()).willReturn(IdGeneratorType.uuid); - given(idGenerator.generateId()).willReturn(generatedBid); + given(idGenerator.generateId()).willReturn(generatedBidId); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder().doCaching(true).build(); givenCacheServiceResult(singletonMap(bid, CacheInfo.of("id", null, null, null))); @@ -561,22 +657,32 @@ public void shouldUseGeneratedBidIdForEventAndCacheWhenIdGeneratorIsUUIDAndEvent bidResponseCreator.create(bidderResponses, auctionContext, cacheInfo, MULTI_BIDS, false).result(); // then - final BidInfo expectedBidInfo = toBidInfo(bid, generatedBid, imp, bidder, banner); + final ExtBidPrebid extBidPrebid = ExtBidPrebid.builder().bidid(generatedBidId).type(banner).build(); + final ExtPrebid expectedPrebid = ExtPrebid.of(extBidPrebid, null); + final Bid expectedBid = bid.toBuilder() + .ext(mapper.valueToTree(expectedPrebid)) + .build(); + + final TargetingInfo targetingInfo = toTargetingInfo(bidder, true); + final BidInfo expectedBidInfo = toBidInfo(expectedBid, imp, bidder, banner, targetingInfo); verify(cacheService).cacheBidsOpenrtb(eq(singletonList(expectedBidInfo)), any(), any(), any()); - verify(eventsService).createEvent(eq(generatedBid), anyString(), anyString(), anyLong(), anyString()); + verify(eventsService).createEvent(eq(generatedBidId), anyString(), anyString(), anyLong(), anyString()); } @Test public void shouldSetExpectedResponseSeatBidAndBidFields() { // given final AuctionContext auctionContext = givenAuctionContext(givenBidRequest(givenImp())); + final ObjectNode bidExt = mapper.valueToTree(singletonMap("bidExt", 1)); + bidExt.put("origbidcpm", BigDecimal.ONE); + bidExt.put("origbidcur", "USD"); final Bid bid = Bid.builder() .id("bidId") .price(BigDecimal.ONE) .adm(BID_ADM) .impid(IMP_ID) - .ext(mapper.valueToTree(singletonMap("bidExt", 1))) + .ext(bidExt) .build(); final String bidder = "bidder1"; @@ -588,6 +694,11 @@ public void shouldSetExpectedResponseSeatBidAndBidFields() { bidResponseCreator.create(bidderResponses, auctionContext, CACHE_INFO, MULTI_BIDS, false).result(); // then + final ObjectNode expectedBidExt = mapper.valueToTree(ExtPrebid.of(ExtBidPrebid.builder().type(banner).build(), + singletonMap("bidExt", 1))); + expectedBidExt.put("origbidcpm", BigDecimal.ONE); + expectedBidExt.put("origbidcur", "USD"); + assertThat(bidResponse.getSeatbid()) .containsOnly(SeatBid.builder() .seat(bidder) @@ -597,9 +708,7 @@ public void shouldSetExpectedResponseSeatBidAndBidFields() { .impid(IMP_ID) .price(BigDecimal.ONE) .adm(BID_ADM) - .ext(mapper.valueToTree(ExtPrebid.of( - ExtBidPrebid.builder().type(banner).build(), - singletonMap("bidExt", 1)))) + .ext(expectedBidExt) .build())) .build()); @@ -613,6 +722,7 @@ public void shouldNotWriteSkadnAttributeToBidderSection() { final Map bidExtProperties = new HashMap<>(); bidExtProperties.put("skadn", singletonMap("skadnKey", "skadnValue")); bidExtProperties.put("anotherProp", "anotherPropValue"); + bidExtProperties.put("origbidcur", "USD"); final Bid bid = Bid.builder() .id("bidId") .price(BigDecimal.ONE) @@ -633,7 +743,9 @@ public void shouldNotWriteSkadnAttributeToBidderSection() { final ObjectNode expectedBidExt = mapper.valueToTree(ExtPrebid.of( ExtBidPrebid.builder().type(banner).build(), singletonMap("anotherProp", "anotherPropValue"))); + expectedBidExt.put("origbidcur", "USD"); expectedBidExt.set("skadn", mapper.convertValue(singletonMap("skadnKey", "skadnValue"), JsonNode.class)); + assertThat(bidResponse.getSeatbid()) .flatExtracting(SeatBid::getBid) .extracting(Bid::getExt) @@ -865,44 +977,6 @@ public void shouldSetBidAdmToNullIfVideoCacheIdIsPresentAndReturnCreativeVideoBi verify(cacheService).cacheBidsOpenrtb(anyList(), any(), any(), any()); } - @Test - public void shouldModifyBidAdmWhenBidVideoAndVastModifierReturnValue() { - // given - final AuctionContext auctionContext = givenAuctionContext(givenBidRequest( - identity(), - extBuilder -> extBuilder.targeting(givenTargeting()), - givenImp())); - - final String bidId = "bid_id"; - final Bid bid = Bid.builder() - .id(bidId) - .price(BigDecimal.ONE) - .adm(BID_ADM) - .nurl(BID_NURL) - .impid(IMP_ID) - .build(); - - final String bidder = "bidder1"; - final List bidderResponses = singletonList( - BidderResponse.of(bidder, givenSeatBid(BidderBid.of(bid, video, "USD")), 100)); - - final String modifiedVast = "modifiedVast"; - given(vastModifier.createBidVastXml(anyString(), anyString(), anyString(), anyString(), anyString(), any())) - .willReturn(modifiedVast); - - // when - final BidResponse bidResponse = - bidResponseCreator.create(bidderResponses, auctionContext, CACHE_INFO, MULTI_BIDS, false).result(); - - // then - assertThat(bidResponse.getSeatbid()) - .flatExtracting(SeatBid::getBid).hasSize(1) - .extracting(Bid::getAdm) - .containsOnly(modifiedVast); - - verify(vastModifier).createBidVastXml(eq(bidder), eq(BID_ADM), eq(BID_NURL), eq(bidId), eq("accountId"), any()); - } - @Test public void shouldSetBidExpWhenCacheIdIsMatched() { // given @@ -975,14 +1049,16 @@ public void shouldTolerateMissingExtInSeatBidAndBid() { bidResponseCreator.create(bidderResponses, auctionContext, CACHE_INFO, MULTI_BIDS, false).result(); // then + final ObjectNode expectedBidExt = mapper.valueToTree( + ExtPrebid.of(ExtBidPrebid.builder().type(banner).build(), null)); + assertThat(bidResponse.getSeatbid()).hasSize(1) .flatExtracting(SeatBid::getBid) .containsOnly(Bid.builder() .id("bidId") .impid(IMP_ID) .price(BigDecimal.ONE) - .ext(mapper.valueToTree( - ExtPrebid.of(ExtBidPrebid.builder().type(banner).build(), null))) + .ext(expectedBidExt) .build()); verify(cacheService, never()).cacheBidsOpenrtb(anyList(), any(), any(), any()); @@ -1250,9 +1326,8 @@ public void shouldReduceAndPopulateTargetingKeywordsForExtraBidsWhenCodePrefixIs final Bid expectedBidder1Bid5 = bidder1Bid5.toBuilder().ext(bidder1Bid5Ext).build(); assertThat(result.getSeatbid()) - .flatExtracting(SeatBid::getBid).hasSize(4) - .containsOnly(expectedBidder1Bid4, expectedBidder1Bid2, expectedBidder1Bid1, expectedBidder1Bid5); - + .flatExtracting(SeatBid::getBid) + .contains(expectedBidder1Bid4, expectedBidder1Bid2, expectedBidder1Bid1, expectedBidder1Bid5); verify(cacheService, never()).cacheBidsOpenrtb(anyList(), any(), any(), any()); } @@ -2217,21 +2292,40 @@ private void givenCacheServiceResult(CacheServiceResult cacheServiceResult) { .willReturn(Future.succeededFuture(cacheServiceResult)); } - private static BidInfo toBidInfo(Bid bid, Imp correspondingImp, String bidder, BidType bidType) { - return BidInfo.builder().bid(bid).correspondingImp(correspondingImp).bidder(bidder).bidType(bidType).build(); + private static BidInfo toBidInfo(Bid bid, + Imp correspondingImp, + String bidder, + BidType bidType) { + return BidInfo.builder() + .bid(bid) + .correspondingImp(correspondingImp) + .bidder(bidder) + .bidType(bidType) + .targetingInfo(toTargetingInfo(bidder, true)) + .build(); } private static BidInfo toBidInfo(Bid bid, - String generatedBidId, Imp correspondingImp, String bidder, - BidType bidType) { + BidType bidType, + TargetingInfo targetingInfo) { return BidInfo.builder() - .generatedBidId(generatedBidId) .bid(bid) .correspondingImp(correspondingImp) .bidder(bidder) .bidType(bidType) + .targetingInfo(targetingInfo) + .build(); + } + + private static TargetingInfo toTargetingInfo(String bidder, boolean isWinningBid) { + return TargetingInfo.builder() + .bidderCode(bidder) + .isTargetingEnabled(true) + .isWinningBid(isWinningBid) + .isBidderWinningBid(true) + .isAddTargetBidderCode(false) .build(); } diff --git a/src/test/java/org/prebid/server/auction/BidderAliasesTest.java b/src/test/java/org/prebid/server/auction/BidderAliasesTest.java index 8a56d41945a..7461fff4fe6 100644 --- a/src/test/java/org/prebid/server/auction/BidderAliasesTest.java +++ b/src/test/java/org/prebid/server/auction/BidderAliasesTest.java @@ -1,6 +1,5 @@ package org.prebid.server.auction; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; @@ -10,11 +9,6 @@ import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verifyZeroInteractions; public class BidderAliasesTest { @@ -24,31 +18,22 @@ public class BidderAliasesTest { @Mock private BidderCatalog bidderCatalog; - @Before - public void setUp() { - given(bidderCatalog.isActive(anyString())).willReturn(true); - } - @Test - public void isAliasDefinedShouldQueryCatalogWhenNoAliasesInRequest() { + public void isAliasDefinedShouldReturnFalseWhenNoAliasesInRequest() { // given - given(bidderCatalog.isAlias(anyString())).willReturn(true); - - final BidderAliases aliases = BidderAliases.of(bidderCatalog); + final BidderAliases aliases = BidderAliases.of(null, null, bidderCatalog); // when and then - assertThat(aliases.isAliasDefined("alias")).isTrue(); + assertThat(aliases.isAliasDefined("alias")).isFalse(); } @Test - public void isAliasDefinedShouldQueryCatalogWhenAliasIsNotDefinedInRequest() { + public void isAliasDefinedShouldReturnFalseWhenAliasIsNotDefinedInRequest() { // given - given(bidderCatalog.isAlias(anyString())).willReturn(true); - final BidderAliases aliases = BidderAliases.of(singletonMap("anotherAlias", "bidder"), null, bidderCatalog); // when and then - assertThat(aliases.isAliasDefined("alias")).isTrue(); + assertThat(aliases.isAliasDefined("alias")).isFalse(); } @Test @@ -58,53 +43,24 @@ public void isAliasDefinedShouldDetectAliasInRequest() { // when and then assertThat(aliases.isAliasDefined("alias")).isTrue(); - - verifyZeroInteractions(bidderCatalog); } @Test - public void resolveBidderShouldReturnInputWhenNoAliasesInRequestAndInCatalog() { + public void resolveBidderShouldReturnInputWhenNoAliasesInRequest() { // given - given(bidderCatalog.nameByAlias(anyString())).willReturn(null); - - final BidderAliases aliases = BidderAliases.of(bidderCatalog); + final BidderAliases aliases = BidderAliases.of(null, null, bidderCatalog); // when and then assertThat(aliases.resolveBidder("alias")).isEqualTo("alias"); } @Test - public void resolveBidderShouldReturnInputWhenNoAliasesInRequestAndInactiveInCatalog() { + public void resolveBidderShouldReturnInputWhenAliasIsNotDefinedInRequest() { // given - given(bidderCatalog.nameByAlias(anyString())).willReturn("bidder"); - given(bidderCatalog.isActive(any())).willReturn(false); - - final BidderAliases aliases = BidderAliases.of(bidderCatalog); - - // when and then - assertThat(aliases.resolveBidder("alias")).isEqualTo("alias"); - } - - @Test - public void resolveBidderShouldQueryCatalogWhenNoAliasesInRequest() { - // given - given(bidderCatalog.nameByAlias(anyString())).willReturn("bidder"); - - final BidderAliases aliases = BidderAliases.of(bidderCatalog); - - // when and then - assertThat(aliases.resolveBidder("alias")).isEqualTo("bidder"); - } - - @Test - public void resolveBidderShouldQueryCatalogWhenAliasIsNotDefinedInRequest() { - // given - given(bidderCatalog.nameByAlias(eq("alias"))).willReturn("bidder"); - final BidderAliases aliases = BidderAliases.of(singletonMap("anotherAlias", "bidder"), null, bidderCatalog); // when and then - assertThat(aliases.resolveBidder("alias")).isEqualTo("bidder"); + assertThat(aliases.resolveBidder("alias")).isEqualTo("alias"); } @Test @@ -114,54 +70,24 @@ public void resolveBidderShouldDetectAliasInRequest() { // when and then assertThat(aliases.resolveBidder("alias")).isEqualTo("bidder"); - - verifyZeroInteractions(bidderCatalog); - } - - @Test - public void resolveAliasVendorIdShouldReturnNullWhenNoVendorIdsInRequestAndInCatalog() { - // given - given(bidderCatalog.vendorIdByName(anyString())).willReturn(null); - - final BidderAliases aliases = BidderAliases.of(bidderCatalog); - - // when and then - assertThat(aliases.resolveAliasVendorId("alias")).isNull(); } @Test - public void resolveAliasVendorIdShouldReturnNullWhenNoVendorIdsInRequestAndInactiveInCatalog() { + public void resolveAliasVendorIdShouldReturnNullWhenNoVendorIdsInRequest() { // given - given(bidderCatalog.vendorIdByName(anyString())).willReturn(1); - given(bidderCatalog.isActive(anyString())).willReturn(false); - - final BidderAliases aliases = BidderAliases.of(bidderCatalog); + final BidderAliases aliases = BidderAliases.of(null, null, bidderCatalog); // when and then assertThat(aliases.resolveAliasVendorId("alias")).isNull(); } @Test - public void resolveAliasVendorIdShouldQueryCatalogWhenNoVendorIdsInRequest() { + public void resolveAliasVendorIdShouldReturnNullWhenVendorIdIsNotDefinedInRequest() { // given - given(bidderCatalog.vendorIdByName(anyString())).willReturn(1); - given(bidderCatalog.isActive(anyString())).willReturn(true); - - final BidderAliases aliases = BidderAliases.of(bidderCatalog); - - // when and then - assertThat(aliases.resolveAliasVendorId("alias")).isEqualTo(1); - } - - @Test - public void resolveAliasVendorIdShouldQueryCatalogWhenVendorIdIsNotDefinedInRequest() { - // given - given(bidderCatalog.vendorIdByName(eq("alias"))).willReturn(1); - final BidderAliases aliases = BidderAliases.of(null, singletonMap("anotherAlias", 2), bidderCatalog); // when and then - assertThat(aliases.resolveAliasVendorId("alias")).isEqualTo(1); + assertThat(aliases.resolveAliasVendorId("alias")).isNull(); } @Test @@ -171,19 +97,5 @@ public void resolveAliasVendorIdShouldDetectVendorIdInRequest() { // when and then assertThat(aliases.resolveAliasVendorId("alias")).isEqualTo(2); - - verifyZeroInteractions(bidderCatalog); - } - - @Test - public void resolveAliasVendorIdShouldResolveAliasWhenQueryingCatalog() { - // given - given(bidderCatalog.nameByAlias(eq("alias"))).willReturn("bidder"); - given(bidderCatalog.vendorIdByName(eq("bidder"))).willReturn(1); - - final BidderAliases aliases = BidderAliases.of(bidderCatalog); - - // when and then - assertThat(aliases.resolveAliasVendorId("alias")).isEqualTo(1); } } diff --git a/src/test/java/org/prebid/server/auction/CurrencyConversionServiceTest.java b/src/test/java/org/prebid/server/auction/CurrencyConversionServiceTest.java index f24f4d6149e..81297b77f95 100644 --- a/src/test/java/org/prebid/server/auction/CurrencyConversionServiceTest.java +++ b/src/test/java/org/prebid/server/auction/CurrencyConversionServiceTest.java @@ -270,7 +270,7 @@ public void convertCurrencyShouldFailWhenRequestRatesIsNullAndNoExternalRatesPro assertThatExceptionOfType(PreBidException.class) .isThrownBy(() -> currencyConversionService.convertCurrency(BigDecimal.ONE, givenBidRequestWithCurrencies(null, false), EUR, GBP)) - .withMessage("Unable to convert bid currency GBP to desired ad server currency EUR"); + .withMessage("Unable to convert from currency GBP to desired ad server currency EUR"); } @Test @@ -279,7 +279,7 @@ public void convertCurrencyShouldThrowPrebidExceptionIfServerAndRequestRatesAreN assertThatExceptionOfType(PreBidException.class) .isThrownBy(() -> currencyService.convertCurrency(BigDecimal.ONE, givenBidRequestWithCurrencies(null, false), USD, EUR)) - .withMessage("Unable to convert bid currency EUR to desired ad server currency USD"); + .withMessage("Unable to convert from currency EUR to desired ad server currency USD"); } @Test @@ -297,7 +297,7 @@ public void convertCurrencyShouldThrowPrebidExceptionIfMultiplierWasNotFoundFrom assertThatExceptionOfType(PreBidException.class) .isThrownBy(() -> currencyService.convertCurrency(BigDecimal.ONE, givenBidRequestWithCurrencies(requestConversionRates, false), EUR, AUD)) - .withMessage("Unable to convert bid currency AUD to desired ad server currency EUR"); + .withMessage("Unable to convert from currency AUD to desired ad server currency EUR"); } @Test @@ -312,7 +312,7 @@ public void convertCurrencyShouldThrowExceptionWhenCurrencyServerResponseStatusN assertThatExceptionOfType(PreBidException.class) .isThrownBy(() -> currencyService.convertCurrency(BigDecimal.ONE, givenBidRequestWithCurrencies(null, false), UAH, AUD)) - .withMessage("Unable to convert bid currency AUD to desired ad server currency UAH"); + .withMessage("Unable to convert from currency AUD to desired ad server currency UAH"); } @Test @@ -327,7 +327,7 @@ public void convertCurrencyShouldThrowExceptionWhenCurrencyServerResponseContain assertThatExceptionOfType(PreBidException.class) .isThrownBy(() -> currencyService.convertCurrency(BigDecimal.ONE, givenBidRequestWithCurrencies(null, false), UAH, AUD)) - .withMessage("Unable to convert bid currency AUD to desired ad server currency UAH"); + .withMessage("Unable to convert from currency AUD to desired ad server currency UAH"); } @SuppressWarnings("unchecked") diff --git a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java index 1d3198f4233..b3a8cc9ec1f 100644 --- a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java +++ b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java @@ -20,6 +20,7 @@ import com.iab.openrtb.request.Regs; import com.iab.openrtb.request.Site; import com.iab.openrtb.request.User; +import com.iab.openrtb.request.Video; import com.iab.openrtb.response.Bid; import com.iab.openrtb.response.BidResponse; import com.iab.openrtb.response.SeatBid; @@ -57,6 +58,7 @@ import org.prebid.server.metric.MetricName; import org.prebid.server.metric.Metrics; import org.prebid.server.proto.openrtb.ext.ExtPrebid; +import org.prebid.server.proto.openrtb.ext.request.BidAdjustmentMediaType; import org.prebid.server.proto.openrtb.ext.request.ExtApp; import org.prebid.server.proto.openrtb.ext.request.ExtBidderConfig; import org.prebid.server.proto.openrtb.ext.request.ExtBidderConfigOrtb; @@ -64,6 +66,7 @@ import org.prebid.server.proto.openrtb.ext.request.ExtPriceGranularity; import org.prebid.server.proto.openrtb.ext.request.ExtRegs; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestBidadjustmentfactors; import org.prebid.server.proto.openrtb.ext.request.ExtRequestCurrency; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidBidderConfig; @@ -71,8 +74,8 @@ import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidCacheBids; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidCacheVastxml; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidData; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidMultiBid; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidDataEidPermissions; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidMultiBid; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidSchain; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidSchainSchain; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidSchainSchainNode; @@ -98,6 +101,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -134,6 +138,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; import static org.prebid.server.proto.openrtb.ext.response.BidType.banner; +import static org.prebid.server.proto.openrtb.ext.response.BidType.video; public class ExchangeServiceTest extends VertxTest { @@ -143,8 +148,6 @@ public class ExchangeServiceTest extends VertxTest { @Mock private BidderCatalog bidderCatalog; @Mock - private Usersyncer usersyncer; - @Mock private StoredResponseProcessor storedResponseProcessor; @Mock private PrivacyEnforcementService privacyEnforcementService; @@ -181,7 +184,7 @@ public void setUp() { given(bidderCatalog.isValidName(anyString())).willReturn(true); given(bidderCatalog.isActive(anyString())).willReturn(true); - given(bidderCatalog.usersyncerByName(anyString())).willReturn(usersyncer); + given(bidderCatalog.usersyncerByName(anyString())).willReturn(Usersyncer.of("cookieFamily", null, null)); given(privacyEnforcementService.mask(any(), argThat(MapUtils::isNotEmpty), any(), any())) .willAnswer(inv -> @@ -204,7 +207,6 @@ public void setUp() { given(schainResolver.resolveForBidder(anyString(), any())).willReturn(null); given(responseBidValidator.validate(any(), any(), any(), any())).willReturn(ValidationResult.success()); - given(usersyncer.getCookieFamilyName()).willReturn("cookieFamily"); given(currencyService.convertCurrency(any(), any(), any(), any())) .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); @@ -395,14 +397,14 @@ public void shouldExtractMultipleRequests() { // then final ArgumentCaptor bidRequest1Captor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester).requestBids(same(bidder1), bidRequest1Captor.capture(), any(), anyBoolean()); + verify(httpBidderRequester).requestBids(same(bidder1), bidRequest1Captor.capture(), any(), any(), anyBoolean()); final BidderRequest capturedBidRequest1 = bidRequest1Captor.getValue(); assertThat(capturedBidRequest1.getBidRequest().getImp()).hasSize(2) .extracting(imp -> imp.getExt().get("bidder").asInt()) .containsOnly(1, 3); final ArgumentCaptor bidRequest2Captor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester).requestBids(same(bidder2), bidRequest2Captor.capture(), any(), anyBoolean()); + verify(httpBidderRequester).requestBids(same(bidder2), bidRequest2Captor.capture(), any(), any(), anyBoolean()); final BidderRequest capturedBidRequest2 = bidRequest2Captor.getValue(); assertThat(capturedBidRequest2.getBidRequest().getImp()).hasSize(1) .element(0).returns(2, imp -> imp.getExt().get("bidder").asInt()); @@ -437,7 +439,7 @@ public void shouldPassRequestWithExtPrebidToDefinedBidder() { // then final ArgumentCaptor bidRequest1Captor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester).requestBids(same(bidder1), bidRequest1Captor.capture(), any(), anyBoolean()); + verify(httpBidderRequester).requestBids(same(bidder1), bidRequest1Captor.capture(), any(), any(), anyBoolean()); final BidderRequest capturedBidRequest1 = bidRequest1Captor.getValue(); final ExtRequestPrebid prebid1 = capturedBidRequest1.getBidRequest().getExt().getPrebid(); @@ -448,7 +450,7 @@ public void shouldPassRequestWithExtPrebidToDefinedBidder() { .containsOnly(entry("bidder", mapper.createObjectNode().put("test1", "test1"))); final ArgumentCaptor bidRequest2Captor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester).requestBids(same(bidder2), bidRequest2Captor.capture(), any(), anyBoolean()); + verify(httpBidderRequester).requestBids(same(bidder2), bidRequest2Captor.capture(), any(), any(), anyBoolean()); final BidRequest capturedBidRequest2 = bidRequest2Captor.getValue().getBidRequest(); final ExtRequestPrebid prebid2 = capturedBidRequest2.getExt().getPrebid(); assertThat(prebid2).isNotNull(); @@ -505,7 +507,7 @@ public void shouldPassRequestWithInjectedSchainInSourceExt() { // then final ArgumentCaptor bidRequest1Captor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester).requestBids(same(bidder1), bidRequest1Captor.capture(), any(), anyBoolean()); + verify(httpBidderRequester).requestBids(same(bidder1), bidRequest1Captor.capture(), any(), any(), anyBoolean()); final BidRequest capturedBidRequest1 = bidRequest1Captor.getValue().getBidRequest(); final ExtRequestPrebidSchainSchain requestSchain1 = capturedBidRequest1.getSource().getExt().getSchain(); assertThat(requestSchain1).isNotNull(); @@ -513,7 +515,7 @@ public void shouldPassRequestWithInjectedSchainInSourceExt() { assertThat(capturedBidRequest1.getExt().getPrebid().getSchains()).isNull(); final ArgumentCaptor bidRequest2Captor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester).requestBids(same(bidder2), bidRequest2Captor.capture(), any(), anyBoolean()); + verify(httpBidderRequester).requestBids(same(bidder2), bidRequest2Captor.capture(), any(), any(), anyBoolean()); final BidRequest capturedBidRequest2 = bidRequest2Captor.getValue().getBidRequest(); final ExtRequestPrebidSchainSchain requestSchain2 = capturedBidRequest2.getSource().getExt().getSchain(); assertThat(requestSchain2).isNotNull(); @@ -521,7 +523,7 @@ public void shouldPassRequestWithInjectedSchainInSourceExt() { assertThat(capturedBidRequest2.getExt().getPrebid().getSchains()).isNull(); final ArgumentCaptor bidRequest3Captor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester).requestBids(same(bidder3), bidRequest3Captor.capture(), any(), anyBoolean()); + verify(httpBidderRequester).requestBids(same(bidder3), bidRequest3Captor.capture(), any(), any(), anyBoolean()); final BidRequest capturedBidRequest3 = bidRequest3Captor.getValue().getBidRequest(); final ExtRequestPrebidSchainSchain requestSchain3 = capturedBidRequest3.getSource().getExt().getSchain(); assertThat(requestSchain3).isNotNull(); @@ -594,7 +596,7 @@ public void shouldExtractRequestByAliasForCorrectBidder() { // then final ArgumentCaptor bidRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester).requestBids(same(bidder), bidRequestCaptor.capture(), any(), anyBoolean()); + verify(httpBidderRequester).requestBids(same(bidder), bidRequestCaptor.capture(), any(), any(), anyBoolean()); assertThat(bidRequestCaptor.getValue().getBidRequest().getImp()).hasSize(1) .extracting(imp -> imp.getExt().get("bidder").asInt()) .contains(1); @@ -618,7 +620,7 @@ public void shouldExtractMultipleRequestsForTheSameBidderIfAliasesWereUsed() { // then final ArgumentCaptor bidRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester, times(2)).requestBids(same(bidder), bidRequestCaptor.capture(), any(), + verify(httpBidderRequester, times(2)).requestBids(same(bidder), bidRequestCaptor.capture(), any(), any(), anyBoolean()); final List capturedBidderRequests = bidRequestCaptor.getAllValues(); @@ -655,7 +657,8 @@ public void shouldReturnSeparateSeatBidsForTheSameBidderIfBiddersAliasAndBidderW ExtPrebid.of(null, 1))))), builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() .auctiontimestamp(1000L) - .aliases(singletonMap("bidderAlias", "bidder")).build()))))), any(), anyBoolean())) + .aliases(singletonMap("bidderAlias", "bidder")) + .build()))))), any(), any(), anyBoolean())) .willReturn(Future.succeededFuture(givenSeatBid(singletonList( givenBid(Bid.builder().price(BigDecimal.ONE).build()))))); @@ -667,7 +670,8 @@ public void shouldReturnSeparateSeatBidsForTheSameBidderIfBiddersAliasAndBidderW ExtPrebid.of(null, 2))))), builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() .auctiontimestamp(1000L) - .aliases(singletonMap("bidderAlias", "bidder")).build()))))), any(), anyBoolean())) + .aliases(singletonMap("bidderAlias", "bidder")) + .build()))))), any(), any(), anyBoolean())) .willReturn(Future.succeededFuture(givenSeatBid(singletonList( givenBid(Bid.builder().price(BigDecimal.ONE).build()))))); @@ -688,7 +692,7 @@ public void shouldReturnSeparateSeatBidsForTheSameBidderIfBiddersAliasAndBidderW final BidResponse bidResponse = exchangeService.holdAuction(givenRequestContext(bidRequest)).result(); // then - verify(httpBidderRequester, times(2)).requestBids(any(), any(), any(), anyBoolean()); + verify(httpBidderRequester, times(2)).requestBids(any(), any(), any(), any(), anyBoolean()); assertThat(bidResponse.getSeatbid()).hasSize(2) .extracting(seatBid -> seatBid.getBid().size()) .containsOnly(1, 1); @@ -778,9 +782,16 @@ public void shouldCallBidResponseCreatorWithExpectedParamsAndUpdateDebugErrors() verify(bidResponseCreator).create(captor.capture(), eq(expectedAuctionContext), eq(expectedCacheInfo), eq(expectedMultiBidMap), eq(false)); + final ObjectNode expectedBidExt = mapper.createObjectNode().put("origbidcpm", new BigDecimal("7.89")); + final Bid expectedThirdBid = Bid.builder() + .id("bidId3") + .impid("impId1") + .price(BigDecimal.valueOf(7.89)) + .ext(expectedBidExt) + .build(); assertThat(captor.getValue()).containsOnly( BidderResponse.of("bidder2", BidderSeatBid.of(singletonList( - BidderBid.of(thirdBid, banner, null)), emptyList(), emptyList()), 0), + BidderBid.of(expectedThirdBid, banner, null)), emptyList(), emptyList()), 0), BidderResponse.of("bidder1", BidderSeatBid.of(emptyList(), emptyList(), emptyList()), 0)); } @@ -1273,7 +1284,7 @@ public void shouldDeepCopyImpExtContextToEachImpressionAndNotRemoveDataForAllWhe builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() .data(ExtRequestPrebidData.of(singletonList("someBidder"), null)) .build()))); - given(httpBidderRequester.requestBids(any(), any(), any(), anyBoolean())) + given(httpBidderRequester.requestBids(any(), any(), any(), any(), anyBoolean())) .willReturn(Future.succeededFuture(givenSeatBid(singletonList( givenBid(Bid.builder().price(TEN).build()))))); @@ -1290,7 +1301,8 @@ public void shouldDeepCopyImpExtContextToEachImpressionAndNotRemoveDataForAllWhe // then final ArgumentCaptor bidderRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester, times(2)).requestBids(any(), bidderRequestCaptor.capture(), any(), anyBoolean()); + verify(httpBidderRequester, times(2)) + .requestBids(any(), bidderRequestCaptor.capture(), any(), any(), anyBoolean()); assertThat(bidderRequestCaptor.getAllValues()) .extracting(BidderRequest::getBidRequest) .flatExtracting(BidRequest::getImp) @@ -1321,7 +1333,7 @@ public void shouldPassImpExtFieldsToEachImpression() { builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() .data(ExtRequestPrebidData.of(singletonList("someBidder"), null)) .build()))); - given(httpBidderRequester.requestBids(any(), any(), any(), anyBoolean())) + given(httpBidderRequester.requestBids(any(), any(), any(), any(), anyBoolean())) .willReturn(Future.succeededFuture(givenSeatBid(singletonList( givenBid(Bid.builder().price(TEN).build()))))); @@ -1330,7 +1342,7 @@ public void shouldPassImpExtFieldsToEachImpression() { // then final ArgumentCaptor bidderRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester).requestBids(any(), bidderRequestCaptor.capture(), any(), anyBoolean()); + verify(httpBidderRequester).requestBids(any(), bidderRequestCaptor.capture(), any(), any(), anyBoolean()); assertThat(bidderRequestCaptor.getAllValues()) .extracting(BidderRequest::getBidRequest) .flatExtracting(BidRequest::getImp) @@ -1356,7 +1368,7 @@ public void shouldPassImpExtSkadnToEachImpression() { .ext(impExt) .build()), identity()); - given(httpBidderRequester.requestBids(any(), any(), any(), anyBoolean())) + given(httpBidderRequester.requestBids(any(), any(), any(), any(), anyBoolean())) .willReturn(Future.succeededFuture(givenSeatBid(singletonList( givenBid(Bid.builder().price(TEN).build()))))); @@ -1365,7 +1377,7 @@ public void shouldPassImpExtSkadnToEachImpression() { // then final ArgumentCaptor bidRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester).requestBids(any(), bidRequestCaptor.capture(), any(), anyBoolean()); + verify(httpBidderRequester).requestBids(any(), bidRequestCaptor.capture(), any(), any(), anyBoolean()); assertThat(bidRequestCaptor.getAllValues()) .extracting(BidderRequest::getBidRequest) .flatExtracting(BidRequest::getImp) @@ -1496,7 +1508,8 @@ public void shouldPassUserDataAndExtDataOnlyForAllowedBidder() { // then final ArgumentCaptor bidderRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester, times(2)).requestBids(any(), bidderRequestCaptor.capture(), any(), anyBoolean()); + verify(httpBidderRequester, times(2)) + .requestBids(any(), bidderRequestCaptor.capture(), any(), any(), anyBoolean()); final List capturedBidRequests = bidderRequestCaptor.getAllValues(); final ExtUser maskedExtUser = ExtUser.builder().eids(eids).build(); @@ -1596,7 +1609,7 @@ public void shouldFilterUserExtEidsWhenBidderIsNotAllowedForSourceAndSetNullIfNo // then final ArgumentCaptor bidderRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester).requestBids(any(), bidderRequestCaptor.capture(), any(), anyBoolean()); + verify(httpBidderRequester).requestBids(any(), bidderRequestCaptor.capture(), any(), any(), anyBoolean()); final List capturedBidRequests = bidderRequestCaptor.getAllValues(); assertThat(capturedBidRequests) .extracting(BidderRequest::getBidRequest) @@ -1632,7 +1645,7 @@ public void shouldNotCleanRequestExtPrebidDataWhenFpdAllowedAndPrebidIsNotNull() // then final ArgumentCaptor bidderRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester).requestBids(any(), bidderRequestCaptor.capture(), any(), anyBoolean()); + verify(httpBidderRequester).requestBids(any(), bidderRequestCaptor.capture(), any(), any(), anyBoolean()); final List capturedBidRequests = bidderRequestCaptor.getAllValues(); assertThat(capturedBidRequests) .extracting(BidderRequest::getBidRequest) @@ -1670,7 +1683,8 @@ public void shouldMaskUserExtIfDataBiddersListIsEmpty() { // then final ArgumentCaptor bidderRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester, times(2)).requestBids(any(), bidderRequestCaptor.capture(), any(), anyBoolean()); + verify(httpBidderRequester, times(2)) + .requestBids(any(), bidderRequestCaptor.capture(), any(), any(), anyBoolean()); final List capturedBidRequests = bidderRequestCaptor.getAllValues(); final ExtUser expectedExtUser = ExtUser.builder().eids(eids).build(); @@ -1710,7 +1724,8 @@ public void shouldNoMaskUserExtIfDataBiddersListIsNull() { // then final ArgumentCaptor bidRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester, times(2)).requestBids(any(), bidRequestCaptor.capture(), any(), anyBoolean()); + verify(httpBidderRequester, times(2)) + .requestBids(any(), bidRequestCaptor.capture(), any(), any(), anyBoolean()); final List capturedBidRequests = bidRequestCaptor.getAllValues(); assertThat(capturedBidRequests) @@ -1754,7 +1769,8 @@ public void shouldPassSiteContentDataAndExtDataOnlyForAllowedBidder() { // then final ArgumentCaptor bidderRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester, times(2)).requestBids(any(), bidderRequestCaptor.capture(), any(), anyBoolean()); + verify(httpBidderRequester, times(2)) + .requestBids(any(), bidderRequestCaptor.capture(), any(), any(), anyBoolean()); final List capturedBidRequests = bidderRequestCaptor.getAllValues(); assertThat(capturedBidRequests) @@ -1799,7 +1815,8 @@ public void shouldNoMaskPassAppExtAndKeywordsWhenDataBiddersListIsNull() { // then final ArgumentCaptor bidderRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester, times(2)).requestBids(any(), bidderRequestCaptor.capture(), any(), anyBoolean()); + verify(httpBidderRequester, times(2)) + .requestBids(any(), bidderRequestCaptor.capture(), any(), any(), anyBoolean()); final List capturedBidRequests = bidderRequestCaptor.getAllValues(); assertThat(capturedBidRequests) @@ -1842,7 +1859,8 @@ public void shouldPassAppExtDataOnlyForAllowedBidder() { // then final ArgumentCaptor bidderRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester, times(2)).requestBids(any(), bidderRequestCaptor.capture(), any(), anyBoolean()); + verify(httpBidderRequester, times(2)) + .requestBids(any(), bidderRequestCaptor.capture(), any(), any(), anyBoolean()); final List capturedBidRequests = bidderRequestCaptor.getAllValues(); assertThat(capturedBidRequests) @@ -1916,7 +1934,7 @@ public void shouldUseConcreteOverGeneralSiteWithExtPrebidBidderConfig() { // then final ArgumentCaptor bidderRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester).requestBids(any(), bidderRequestCaptor.capture(), any(), anyBoolean()); + verify(httpBidderRequester).requestBids(any(), bidderRequestCaptor.capture(), any(), any(), anyBoolean()); final List capturedBidRequests = bidderRequestCaptor.getAllValues(); assertThat(capturedBidRequests) @@ -1964,7 +1982,7 @@ public void shouldUseConcreteOverGeneralAppWithExtPrebidBidderConfig() { // then final ArgumentCaptor bidderRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester).requestBids(any(), bidderRequestCaptor.capture(), any(), anyBoolean()); + verify(httpBidderRequester).requestBids(any(), bidderRequestCaptor.capture(), any(), any(), anyBoolean()); final List capturedBidRequests = bidderRequestCaptor.getAllValues(); assertThat(capturedBidRequests) @@ -2006,7 +2024,7 @@ public void shouldUseConcreteOverGeneralUserWithExtPrebidBidderConfig() { // then final ArgumentCaptor bidderRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester).requestBids(any(), bidderRequestCaptor.capture(), any(), anyBoolean()); + verify(httpBidderRequester).requestBids(any(), bidderRequestCaptor.capture(), any(), any(), anyBoolean()); final List capturedBidRequests = bidderRequestCaptor.getAllValues(); assertThat(capturedBidRequests) @@ -2060,7 +2078,7 @@ public void shouldPassGlobalTimeoutToConnectorUnchangedIfCachingIsNotRequested() exchangeService.holdAuction(givenRequestContext(bidRequest)); // then - verify(httpBidderRequester).requestBids(any(), any(), same(timeout), anyBoolean()); + verify(httpBidderRequester).requestBids(any(), any(), same(timeout), any(), anyBoolean()); } @Test @@ -2099,7 +2117,7 @@ public void shouldPassReducedGlobalTimeoutToConnectorAndOriginalToBidResponseCre // then final ArgumentCaptor timeoutCaptor = ArgumentCaptor.forClass(Timeout.class); - verify(httpBidderRequester).requestBids(any(), any(), timeoutCaptor.capture(), anyBoolean()); + verify(httpBidderRequester).requestBids(any(), any(), timeoutCaptor.capture(), any(), anyBoolean()); assertThat(timeoutCaptor.getValue().remaining()).isEqualTo(400L); verify(bidResponseCreator).create(anyList(), any(), any(), any(), anyBoolean()); } @@ -2189,10 +2207,13 @@ public void shouldUpdateBidPriceWithCurrencyConversionAndPriceAdjustmentFactor() givenBidder("bidder", bidder, givenSeatBid(singletonList( givenBid(Bid.builder().price(BigDecimal.valueOf(2.0)).build())))); + final ExtRequestBidadjustmentfactors givenAdjustments = ExtRequestBidadjustmentfactors.builder().build(); + givenAdjustments.addFactor("bidder", BigDecimal.valueOf(10)); + final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), identity())), builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() .aliases(emptyMap()) - .bidadjustmentfactors(singletonMap("bidder", BigDecimal.valueOf(10))) + .bidadjustmentfactors(givenAdjustments) .auctiontimestamp(1000L) .build()))); @@ -2246,7 +2267,11 @@ public void shouldUpdatePriceForOneBidAndDropAnotherIfPrebidExceptionHappensForS assertThat(argumentCaptor.getValue()).hasSize(1); - final Bid expectedBid = Bid.builder().price(updatedPrice).build(); + final ObjectNode expectedBidExt = mapper.createObjectNode(); + expectedBidExt.put("origbidcpm", new BigDecimal("2.0")); + expectedBidExt.put("origbidcur", "CUR1"); + final Bid expectedBid = Bid.builder().price(updatedPrice).ext(expectedBidExt).build(); + final BidderBid expectedBidderBid = BidderBid.of(expectedBid, banner, "CUR1"); final BidderError expectedError = BidderError.generic("Unable to convert bid currency CUR2 to desired ad server currency USD"); @@ -2287,7 +2312,10 @@ public void shouldRespondWithOneBidAndErrorWhenBidResponseContainsOneUnsupported assertThat(argumentCaptor.getValue()).hasSize(2); - final Bid expectedBid = Bid.builder().price(updatedPrice).build(); + final ObjectNode expectedBidExt = mapper.createObjectNode(); + expectedBidExt.put("origbidcpm", new BigDecimal("2.0")); + expectedBidExt.put("origbidcur", "USD"); + final Bid expectedBid = Bid.builder().price(updatedPrice).ext(expectedBidExt).build(); final BidderBid expectedBidderBid = BidderBid.of(expectedBid, banner, "USD"); assertThat(argumentCaptor.getValue()) .extracting(BidderResponse::getSeatBid) @@ -2410,7 +2438,7 @@ public void shouldNotAddExtPrebidEventsWhenEventsServiceReturnsEmptyEventsServic @Test public void shouldIncrementCommonMetrics() { // given - given(httpBidderRequester.requestBids(any(), any(), any(), anyBoolean())) + given(httpBidderRequester.requestBids(any(), any(), any(), any(), anyBoolean())) .willReturn(Future.succeededFuture(givenSeatBid(singletonList( givenBid(Bid.builder().price(TEN).build()))))); @@ -2437,11 +2465,9 @@ public void shouldIncrementCommonMetrics() { @Test public void shouldCallUpdateCookieMetricsWithExpectedValue() { // given - final BidRequest bidRequest = givenBidRequest(givenSingleImp(singletonMap("someAlias", 1)), + final BidRequest bidRequest = givenBidRequest(givenSingleImp(singletonMap("someBidder", 1)), builder -> builder.app(App.builder().build())); - given(bidderCatalog.nameByAlias("someAlias")).willReturn("someBidder"); - // when exchangeService.holdAuction(givenRequestContext(bidRequest)); @@ -2453,7 +2479,7 @@ public void shouldCallUpdateCookieMetricsWithExpectedValue() { @Test public void shouldUseEmptyStringIfPublisherIdIsEmpty() { // given - given(httpBidderRequester.requestBids(any(), any(), any(), anyBoolean())) + given(httpBidderRequester.requestBids(any(), any(), any(), any(), anyBoolean())) .willReturn(Future.succeededFuture(givenSeatBid(singletonList( givenBid(Bid.builder().price(TEN).build()))))); final BidRequest bidRequest = givenBidRequest(givenSingleImp(singletonMap("someBidder", 1))); @@ -2469,7 +2495,7 @@ public void shouldUseEmptyStringIfPublisherIdIsEmpty() { @Test public void shouldIncrementNoBidRequestsMetric() { // given - given(httpBidderRequester.requestBids(any(), any(), any(), anyBoolean())) + given(httpBidderRequester.requestBids(any(), any(), any(), any(), anyBoolean())) .willReturn(Future.succeededFuture(givenSeatBid(emptyList()))); final BidRequest bidRequest = givenBidRequest(givenSingleImp(singletonMap("someBidder", 1))); @@ -2484,7 +2510,7 @@ public void shouldIncrementNoBidRequestsMetric() { @Test public void shouldIncrementGotBidsAndErrorMetricsIfBidderReturnsBidAndDifferentErrors() { // given - given(httpBidderRequester.requestBids(any(), any(), any(), anyBoolean())) + given(httpBidderRequester.requestBids(any(), any(), any(), any(), anyBoolean())) .willReturn(Future.succeededFuture(BidderSeatBid.of( singletonList(givenBid(Bid.builder().price(TEN).build())), emptyList(), @@ -2531,25 +2557,160 @@ public void shouldReturnBidsWithAdjustedPricesWhenAdjustmentFactorPresent() { givenBidder("bidder", bidder, givenSeatBid(singletonList( givenBid(Bid.builder().price(BigDecimal.valueOf(2)).build())))); + final ExtRequestBidadjustmentfactors givenAdjustments = ExtRequestBidadjustmentfactors.builder().build(); + givenAdjustments.addFactor("bidder", BigDecimal.valueOf(2.468)); + final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), identity())), builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() .aliases(emptyMap()) - .bidadjustmentfactors(singletonMap("bidder", BigDecimal.valueOf(2.468))) + .bidadjustmentfactors(givenAdjustments) .auctiontimestamp(1000L) .build()))); - givenBidResponseCreator(singletonList(Bid.builder().price(BigDecimal.valueOf(4.936)).build())); - // when - final BidResponse bidResponse = exchangeService.holdAuction(givenRequestContext(bidRequest)).result(); + exchangeService.holdAuction(givenRequestContext(bidRequest)).result(); // then - assertThat(bidResponse.getSeatbid()) - .flatExtracting(SeatBid::getBid) + final List capturedBidResponses = captureBidResponses(); + assertThat(capturedBidResponses) + .extracting(BidderResponse::getSeatBid) + .flatExtracting(BidderSeatBid::getBids) + .extracting(BidderBid::getBid) .extracting(Bid::getPrice) .containsExactly(BigDecimal.valueOf(4.936)); } + @Test + public void shouldReturnBidsWithAdjustedPricesWithVideoInstreamMediaTypeIfVideoPlacementEqualsOne() { + // given + final Bidder bidder = mock(Bidder.class); + givenBidder("bidder", bidder, givenSeatBid(singletonList( + BidderBid.of(Bid.builder().impid("123").price(BigDecimal.valueOf(2)).build(), video, null)))); + + final ExtRequestBidadjustmentfactors givenAdjustments = ExtRequestBidadjustmentfactors.builder() + .mediatypes(new EnumMap<>(Collections.singletonMap(BidAdjustmentMediaType.video, + Collections.singletonMap("bidder", BigDecimal.valueOf(3.456))))) + .build(); + + final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), impBuilder -> + impBuilder.id("123").video(Video.builder().placement(1).build()))), + builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() + .aliases(emptyMap()) + .bidadjustmentfactors(givenAdjustments) + .auctiontimestamp(1000L) + .build()))); + + // when + exchangeService.holdAuction(givenRequestContext(bidRequest)).result(); + + // then + final List capturedBidResponses = captureBidResponses(); + assertThat(capturedBidResponses) + .extracting(BidderResponse::getSeatBid) + .flatExtracting(BidderSeatBid::getBids) + .extracting(BidderBid::getBid) + .extracting(Bid::getPrice) + .containsExactly(BigDecimal.valueOf(6.912)); + } + + @Test + public void shouldReturnBidsWithAdjustedPricesWithVideoInstreamMediaTypeIfVideoPlacementIsMissing() { + // given + final Bidder bidder = mock(Bidder.class); + givenBidder("bidder", bidder, givenSeatBid(singletonList( + BidderBid.of(Bid.builder().impid("123").price(BigDecimal.valueOf(2)).build(), video, null)))); + + final ExtRequestBidadjustmentfactors givenAdjustments = ExtRequestBidadjustmentfactors.builder() + .mediatypes(new EnumMap<>(Collections.singletonMap(BidAdjustmentMediaType.video, + Collections.singletonMap("bidder", BigDecimal.valueOf(3.456))))) + .build(); + + final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), impBuilder -> + impBuilder.id("123").video(Video.builder().build()))), + builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() + .aliases(emptyMap()) + .bidadjustmentfactors(givenAdjustments) + .auctiontimestamp(1000L) + .build()))); + + // when + exchangeService.holdAuction(givenRequestContext(bidRequest)).result(); + + // then + final List capturedBidResponses = captureBidResponses(); + assertThat(capturedBidResponses) + .extracting(BidderResponse::getSeatBid) + .flatExtracting(BidderSeatBid::getBids) + .extracting(BidderBid::getBid) + .extracting(Bid::getPrice) + .containsExactly(BigDecimal.valueOf(6.912)); + } + + @Test + public void shouldReturnBidsWithAdjustedPricesWhenAdjustmentMediaFactorPresent() { + // given + final Bidder bidder = mock(Bidder.class); + givenBidder("bidder", bidder, givenSeatBid(singletonList( + givenBid(Bid.builder().price(BigDecimal.valueOf(2)).build())))); + + final ExtRequestBidadjustmentfactors givenAdjustments = ExtRequestBidadjustmentfactors.builder() + .mediatypes(new EnumMap<>(Collections.singletonMap(BidAdjustmentMediaType.banner, + Collections.singletonMap("bidder", BigDecimal.valueOf(3.456))))) + .build(); + + final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), identity())), + builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() + .aliases(emptyMap()) + .bidadjustmentfactors(givenAdjustments) + .auctiontimestamp(1000L) + .build()))); + + // when + exchangeService.holdAuction(givenRequestContext(bidRequest)).result(); + + // then + final List capturedBidResponses = captureBidResponses(); + assertThat(capturedBidResponses) + .extracting(BidderResponse::getSeatBid) + .flatExtracting(BidderSeatBid::getBids) + .extracting(BidderBid::getBid) + .extracting(Bid::getPrice) + .containsExactly(BigDecimal.valueOf(6.912)); + } + + @Test + public void shouldAdjustPriceWithPriorityForMediaTypeAdjustment() { + // given + final Bidder bidder = mock(Bidder.class); + givenBidder("bidder", bidder, givenSeatBid(singletonList( + givenBid(Bid.builder().price(BigDecimal.valueOf(2)).build())))); + + final ExtRequestBidadjustmentfactors givenAdjustments = ExtRequestBidadjustmentfactors.builder() + .mediatypes(new EnumMap<>(Collections.singletonMap(BidAdjustmentMediaType.banner, + Collections.singletonMap("bidder", BigDecimal.valueOf(3.456))))) + .build(); + givenAdjustments.addFactor("bidder", BigDecimal.valueOf(2.468)); + + final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), identity())), + builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() + .aliases(emptyMap()) + .bidadjustmentfactors(givenAdjustments) + .auctiontimestamp(1000L) + .build()))); + + // when + exchangeService.holdAuction(givenRequestContext(bidRequest)).result(); + + // then + final List capturedBidResponses = captureBidResponses(); + assertThat(capturedBidResponses) + .extracting(BidderResponse::getSeatBid) + .flatExtracting(BidderSeatBid::getBids) + .extracting(BidderBid::getBid) + .extracting(Bid::getPrice) + .containsExactly(BigDecimal.valueOf(6.912)); + } + @Test public void shouldReturnBidsWithoutAdjustingPricesWhenAdjustmentFactorNotPresentForBidder() { // given @@ -2558,12 +2719,15 @@ public void shouldReturnBidsWithoutAdjustingPricesWhenAdjustmentFactorNotPresent givenBidder("bidder", bidder, givenSeatBid(singletonList( givenBid(Bid.builder().price(BigDecimal.ONE).build())))); + final ExtRequestBidadjustmentfactors givenAdjustments = ExtRequestBidadjustmentfactors.builder().build(); + givenAdjustments.addFactor("some-other-bidder", BigDecimal.TEN); + final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("bidder", 2), identity())), builder -> builder.ext(ExtRequest.of(ExtRequestPrebid.builder() .aliases(emptyMap()) .auctiontimestamp(1000L) .currency(ExtRequestCurrency.of(null, false)) - .bidadjustmentfactors(singletonMap("some-other-bidder", BigDecimal.TEN)) + .bidadjustmentfactors(givenAdjustments) .build()))); // when @@ -2593,10 +2757,16 @@ private AuctionContext givenRequestContext(BidRequest bidRequest, Account accoun private BidRequest captureBidRequest() { final ArgumentCaptor bidRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester).requestBids(any(), bidRequestCaptor.capture(), any(), anyBoolean()); + verify(httpBidderRequester).requestBids(any(), bidRequestCaptor.capture(), any(), any(), anyBoolean()); return bidRequestCaptor.getValue().getBidRequest(); } + private List captureBidResponses() { + final ArgumentCaptor> bidderResponseCaptor = ArgumentCaptor.forClass(List.class); + verify(bidResponseCreator).create(bidderResponseCaptor.capture(), any(), any(), any(), anyBoolean()); + return bidderResponseCaptor.getValue(); + } + private static BidRequest givenBidRequest( List imp, Function bidRequestBuilderCustomizer) { return bidRequestBuilderCustomizer.apply(BidRequest.builder().cur(singletonList("USD")).imp(imp)).build(); @@ -2618,13 +2788,13 @@ private static List givenSingleImp(T ext) { } private void givenBidder(BidderSeatBid response) { - given(httpBidderRequester.requestBids(any(), any(), any(), anyBoolean())) + given(httpBidderRequester.requestBids(any(), any(), any(), any(), anyBoolean())) .willReturn(Future.succeededFuture(response)); } private void givenBidder(String bidderName, Bidder bidder, BidderSeatBid response) { doReturn(bidder).when(bidderCatalog).bidderByName(eq(bidderName)); - given(httpBidderRequester.requestBids(same(bidder), any(), any(), anyBoolean())) + given(httpBidderRequester.requestBids(same(bidder), any(), any(), any(), anyBoolean())) .willReturn(Future.succeededFuture(response)); } @@ -2738,7 +2908,7 @@ private void testUserEidsPermissionFiltering(List givenExtUserEids, // then final ArgumentCaptor bidderRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester).requestBids(any(), bidderRequestCaptor.capture(), any(), anyBoolean()); + verify(httpBidderRequester).requestBids(any(), bidderRequestCaptor.capture(), any(), any(), anyBoolean()); final List capturedBidRequests = bidderRequestCaptor.getAllValues(); assertThat(capturedBidRequests) .extracting(BidderRequest::getBidRequest) diff --git a/src/test/java/org/prebid/server/auction/ImplicitParametersExtractorTest.java b/src/test/java/org/prebid/server/auction/ImplicitParametersExtractorTest.java index 12b57310bbc..724adda5d09 100644 --- a/src/test/java/org/prebid/server/auction/ImplicitParametersExtractorTest.java +++ b/src/test/java/org/prebid/server/auction/ImplicitParametersExtractorTest.java @@ -14,8 +14,6 @@ import org.prebid.server.exception.PreBidException; import org.prebid.server.util.HttpUtil; -import java.net.MalformedURLException; - import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; import static org.mockito.BDDMockito.given; @@ -86,38 +84,27 @@ public void refererFromShouldReturnRefererWithHttpSchemeIfRefererHeaderDoesNotCo } @Test - public void domainFromShouldFailIfUrlIsMissing() { + public void domainFromShouldFailIfHostIsNull() { assertThatCode(() -> extractor.domainFrom(null)) .isInstanceOf(PreBidException.class) - .hasMessage("Invalid URL 'null': null") - .hasCauseInstanceOf(MalformedURLException.class); - } - - @Test - public void domainFromShouldFailIfUrlCouldNotBeParsed() { - assertThatCode(() -> extractor.domainFrom("httpP://non_an_url")) - .isInstanceOf(PreBidException.class) - .hasMessage("Invalid URL 'httpP://non_an_url': unknown protocol: httpp") - .hasCauseInstanceOf(MalformedURLException.class); + .hasMessage("Host is not defined or can not be derived from request"); } @Test - public void domainFromShouldFailIfUrlDoesNotContainHost() { - assertThatCode(() -> extractor.domainFrom("http:/path")) + public void domainFromShouldFailIfDomainCouldNotBeDerivedFromHost() { + assertThatCode(() -> extractor.domainFrom("domain")) .isInstanceOf(PreBidException.class) - .hasMessage("Host not found from URL 'http:/path'"); + .hasMessage("Cannot derive eTLD+1 for host domain"); } @Test - public void domainFromShouldFailIfDomainCouldNotBeDerivedFromUrl() { - assertThatCode(() -> extractor.domainFrom("http://domain")) - .isInstanceOf(PreBidException.class) - .hasMessage("Invalid URL 'domain': cannot derive eTLD+1 for domain domain"); + public void domainFromShouldDeriveDomainFromHost() { + assertThat(extractor.domainFrom("example.com")).isEqualTo("example.com"); } @Test - public void domainFromShouldDeriveDomainFromUrl() { - assertThat(extractor.domainFrom("http://example.com")).isEqualTo("example.com"); + public void domainFromShouldDeriveDomainFromHostWithSubdomain() { + assertThat(extractor.domainFrom("subdomain.example.com")).isEqualTo("example.com"); } @Test diff --git a/src/test/java/org/prebid/server/auction/PrivacyEnforcementServiceTest.java b/src/test/java/org/prebid/server/auction/PrivacyEnforcementServiceTest.java index 45ede9551ce..69ee8a23214 100644 --- a/src/test/java/org/prebid/server/auction/PrivacyEnforcementServiceTest.java +++ b/src/test/java/org/prebid/server/auction/PrivacyEnforcementServiceTest.java @@ -8,7 +8,6 @@ import com.iab.openrtb.request.Site; import com.iab.openrtb.request.User; import io.vertx.core.Future; -import io.vertx.core.MultiMap; import io.vertx.core.http.HttpServerRequest; import org.junit.Before; import org.junit.Rule; @@ -20,6 +19,7 @@ import org.prebid.server.assertion.FutureAssertion; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.BidderPrivacyResult; +import org.prebid.server.auction.model.IpAddress; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.exception.InvalidRequestException; import org.prebid.server.execution.Timeout; @@ -94,6 +94,8 @@ public class PrivacyEnforcementServiceTest extends VertxTest { @Mock private TcfDefinerService tcfDefinerService; @Mock + private ImplicitParametersExtractor implicitParametersExtractor; + @Mock private IpAddressHelper ipAddressHelper; @Mock private Metrics metrics; @@ -119,7 +121,8 @@ public void setUp() { privacyExtractor = new PrivacyExtractor(); privacyEnforcementService = new PrivacyEnforcementService( - bidderCatalog, privacyExtractor, tcfDefinerService, ipAddressHelper, metrics, false, false); + bidderCatalog, privacyExtractor, tcfDefinerService, implicitParametersExtractor, ipAddressHelper, + metrics, false, false); } @Test @@ -137,9 +140,14 @@ public void contextFromBidRequestShouldReturnTcfContextForCoppa() { given(tcfDefinerService.resolveTcfContext(any(), any(), any(), any(), any(), any(), any())) .willReturn(Future.succeededFuture(tcfContext)); + final AuctionContext auctionContext = AuctionContext.builder() + .bidRequest(bidRequest) + .account(Account.empty("account")) + .prebidErrors(new ArrayList<>()) + .build(); + // when - final Future privacyContext = privacyEnforcementService.contextFromBidRequest( - bidRequest, Account.empty("account"), null, null, new ArrayList<>()); + final Future privacyContext = privacyEnforcementService.contextFromBidRequest(auctionContext); // then FutureAssertion.assertThat(privacyContext).succeededWith( @@ -171,9 +179,15 @@ public void contextFromBidRequestShouldReturnTcfContext() { final String accountId = "account"; final MetricName requestType = MetricName.openrtb2web; + final AuctionContext auctionContext = AuctionContext.builder() + .bidRequest(bidRequest) + .account(Account.empty(accountId)) + .requestTypeMetric(requestType) + .prebidErrors(new ArrayList<>()) + .build(); + // when - final Future privacyContext = privacyEnforcementService.contextFromBidRequest( - bidRequest, Account.empty(accountId), requestType, null, new ArrayList<>()); + final Future privacyContext = privacyEnforcementService.contextFromBidRequest(auctionContext); // then final Privacy privacy = Privacy.of("1", "consent", Ccpa.of("1YYY"), 0); @@ -213,9 +227,15 @@ public void contextFromBidRequestShouldReturnTcfContextWithIpMasked() { given(tcfDefinerService.resolveTcfContext(any(), any(), any(), any(), any(), any(), any())) .willReturn(Future.succeededFuture(tcfContext)); + final AuctionContext auctionContext = AuctionContext.builder() + .bidRequest(bidRequest) + .account(Account.empty("account")) + .requestTypeMetric(MetricName.openrtb2web) + .prebidErrors(new ArrayList<>()) + .build(); + // when - final Future privacyContext = privacyEnforcementService.contextFromBidRequest( - bidRequest, Account.empty("account"), MetricName.openrtb2web, null, new ArrayList<>()); + final Future privacyContext = privacyEnforcementService.contextFromBidRequest(auctionContext); // then final Privacy privacy = Privacy.of("1", "consent", Ccpa.of("1YYY"), 0); @@ -225,13 +245,63 @@ public void contextFromBidRequestShouldReturnTcfContextWithIpMasked() { eq(privacy), isNull(), eq("ip-masked"), isNull(), same(MetricName.openrtb2web), any(), isNull()); } + @Test + public void contextFromBidRequestShouldCallResolveTcfContextWithIpv6AnonymizedWhenIpNotPresentAndLmtIsOne() { + // given + final BidRequest bidRequest = BidRequest.builder() + .device(Device.builder() + .lmt(1) + .ipv6("ipv6") + .build()) + .build(); + given(ipAddressHelper.anonymizeIpv6(any())).willReturn("ip-masked"); + given(tcfDefinerService.resolveTcfContext(any(), any(), any(), any(), any(), any(), any())) + .willReturn(Future.succeededFuture(TcfContext.builder().build())); + final AuctionContext auctionContext = AuctionContext.builder() + .bidRequest(bidRequest) + .account(Account.empty("account")) + .prebidErrors(new ArrayList<>()) + .build(); + + // when + privacyEnforcementService.contextFromBidRequest(auctionContext); + + // then + verify(tcfDefinerService).resolveTcfContext(any(), any(), eq("ip-masked"), any(), any(), any(), any()); + } + + @Test + public void contextFromBidRequestShouldCallResolveTcfContextWithIpv6WhenIpv4NotPresent() { + // given + final BidRequest bidRequest = BidRequest.builder() + .device(Device.builder() + .ipv6("ipv6") + .build()) + .build(); + given(tcfDefinerService.resolveTcfContext(any(), any(), any(), any(), any(), any(), any())) + .willReturn(Future.succeededFuture(TcfContext.builder().build())); + final AuctionContext auctionContext = AuctionContext.builder() + .bidRequest(bidRequest) + .account(Account.empty("account")) + .prebidErrors(new ArrayList<>()) + .build(); + + // when + privacyEnforcementService.contextFromBidRequest(auctionContext); + + // then + verify(tcfDefinerService).resolveTcfContext(any(), any(), eq("ipv6"), any(), any(), any(), any()); + } + @Test public void contextFromSetuidRequestShouldReturnContext() { // given - final HttpServerRequest request = mock(HttpServerRequest.class); - given(request.getParam("gdpr")).willReturn("1"); - given(request.getParam("gdpr_consent")).willReturn("consent"); - given(request.headers()).willReturn(MultiMap.caseInsensitiveMultiMap().add("X-Forwarded-For", "ip")); + final HttpServerRequest httpRequest = mock(HttpServerRequest.class); + given(httpRequest.getParam("gdpr")).willReturn("1"); + given(httpRequest.getParam("gdpr_consent")).willReturn("consent"); + + given(implicitParametersExtractor.ipFrom(httpRequest)).willReturn(singletonList("ip")); + given(ipAddressHelper.toIpAddress(anyString())).willReturn(IpAddress.of("ip", IpAddress.IP.v4)); final TcfContext tcfContext = TcfContext.builder() .gdpr("1") @@ -245,7 +315,7 @@ public void contextFromSetuidRequestShouldReturnContext() { // when final Future privacyContext = privacyEnforcementService.contextFromSetuidRequest( - request, Account.empty(accountId), null); + httpRequest, Account.empty(accountId), null); // then final Privacy privacy = Privacy.of("1", "consent", Ccpa.EMPTY, 0); @@ -259,9 +329,9 @@ public void contextFromSetuidRequestShouldReturnContext() { @Test public void contextFromCookieSyncRequestShouldReturnContext() { // given - final HttpServerRequest httpServerRequest = mock(HttpServerRequest.class); - given(httpServerRequest.headers()) - .willReturn(MultiMap.caseInsensitiveMultiMap().add("X-Forwarded-For", "ip")); + final HttpServerRequest httpRequest = mock(HttpServerRequest.class); + given(implicitParametersExtractor.ipFrom(httpRequest)).willReturn(singletonList("ip")); + given(ipAddressHelper.toIpAddress(anyString())).willReturn(IpAddress.of("ip", IpAddress.IP.v4)); final CookieSyncRequest cookieSyncRequest = CookieSyncRequest.builder() .gdpr(1) @@ -281,7 +351,7 @@ public void contextFromCookieSyncRequestShouldReturnContext() { // when final Future privacyContext = privacyEnforcementService.contextFromCookieSyncRequest( - cookieSyncRequest, httpServerRequest, Account.empty(accountId), null); + cookieSyncRequest, httpRequest, Account.empty(accountId), null); // then final Privacy privacy = Privacy.of("1", "consent", Ccpa.of("1YYY"), 0); @@ -328,7 +398,8 @@ public void shouldMaskForCoppaWhenDeviceLmtIsEnforceAndOneAndRegsCoppaIsOneAndDo public void shouldMaskForCcpaWhenUsPolicyIsValidAndCoppaIsZero() { // given privacyEnforcementService = new PrivacyEnforcementService( - bidderCatalog, privacyExtractor, tcfDefinerService, ipAddressHelper, metrics, true, false); + bidderCatalog, privacyExtractor, tcfDefinerService, implicitParametersExtractor, ipAddressHelper, + metrics, true, false); given(tcfDefinerService.resultForBidderNames(anySet(), any(), any(), any())) .willReturn(Future.succeededFuture(TcfResponse.of(true, emptyMap(), null))); @@ -465,7 +536,8 @@ public void shouldNotMaskWhenDeviceLmtIsZeroAndCoppaIsZeroAndGdprIsZeroAndTcfDef public void shouldMaskForTcfWhenTcfServiceAllowAllAndDeviceLmtIsOneAndLmtIsEnforced() { // given privacyEnforcementService = new PrivacyEnforcementService( - bidderCatalog, privacyExtractor, tcfDefinerService, ipAddressHelper, metrics, false, true); + bidderCatalog, privacyExtractor, tcfDefinerService, implicitParametersExtractor, ipAddressHelper, + metrics, false, true); given(tcfDefinerService.resultForBidderNames(any(), any(), any(), any())) .willReturn(Future.succeededFuture( @@ -1095,7 +1167,8 @@ public void shouldReturnFailedFutureWhenTcfServiceIsReturnFailedFuture() { public void shouldMaskForCcpaAndTcfWhenUsPolicyIsValidAndGdprIsEnforcedAndCOPPAIsZero() { // given privacyEnforcementService = new PrivacyEnforcementService( - bidderCatalog, privacyExtractor, tcfDefinerService, ipAddressHelper, metrics, true, false); + bidderCatalog, privacyExtractor, tcfDefinerService, implicitParametersExtractor, ipAddressHelper, + metrics, true, false); final String bidder1Name = "bidder1Name"; final String bidder2Name = "bidder2Name"; @@ -1137,7 +1210,7 @@ public void shouldMaskForCcpaAndTcfWhenUsPolicyIsValidAndGdprIsEnforcedAndCOPPAI context, bidderToUser, asList(bidder1Name, bidder2Name, bidder3Name), - BidderAliases.of(bidderCatalog)) + BidderAliases.of(null, null, bidderCatalog)) .result(); // then @@ -1165,7 +1238,8 @@ public void shouldMaskForCcpaAndTcfWhenUsPolicyIsValidAndGdprIsEnforcedAndCOPPAI public void shouldNotMaskForCcpaWhenCatchAllWildcardIsPresentInNosaleList() { // given privacyEnforcementService = new PrivacyEnforcementService( - bidderCatalog, privacyExtractor, tcfDefinerService, ipAddressHelper, metrics, true, false); + bidderCatalog, privacyExtractor, tcfDefinerService, implicitParametersExtractor, ipAddressHelper, + metrics, true, false); given(tcfDefinerService.resultForBidderNames(anySet(), any(), any(), any())) .willReturn(Future.succeededFuture( @@ -1191,7 +1265,7 @@ public void shouldNotMaskForCcpaWhenCatchAllWildcardIsPresentInNosaleList() { // when final List result = privacyEnforcementService - .mask(context, bidderToUser, singletonList(BIDDER_NAME), BidderAliases.of(bidderCatalog)) + .mask(context, bidderToUser, singletonList(BIDDER_NAME), BidderAliases.of(null, null, bidderCatalog)) .result(); // then @@ -1219,7 +1293,8 @@ public void isCcpaEnforcedShouldReturnFalseWhenEnforcedPropertyIsFalseInConfigur public void isCcpaEnforcedShouldReturnFalseWhenEnforcedPropertyIsTrueInConfigurationAndFalseInAccount() { // given privacyEnforcementService = new PrivacyEnforcementService( - bidderCatalog, privacyExtractor, tcfDefinerService, ipAddressHelper, metrics, true, false); + bidderCatalog, privacyExtractor, tcfDefinerService, implicitParametersExtractor, ipAddressHelper, + metrics, true, false); final Ccpa ccpa = Ccpa.of("1YYY"); final Account account = Account.builder().enforceCcpa(false).build(); @@ -1232,7 +1307,8 @@ public void isCcpaEnforcedShouldReturnFalseWhenEnforcedPropertyIsTrueInConfigura public void isCcpaEnforcedShouldReturnFalseWhenEnforcedPropertyIsTrue() { // given privacyEnforcementService = new PrivacyEnforcementService( - bidderCatalog, privacyExtractor, tcfDefinerService, ipAddressHelper, metrics, true, false); + bidderCatalog, privacyExtractor, tcfDefinerService, implicitParametersExtractor, ipAddressHelper, + metrics, true, false); final Ccpa ccpa = Ccpa.of("1YNY"); final Account account = Account.builder().build(); @@ -1245,7 +1321,8 @@ public void isCcpaEnforcedShouldReturnFalseWhenEnforcedPropertyIsTrue() { public void isCcpaEnforcedShouldReturnTrueWhenEnforcedPropertyIsTrueAndCcpaReturnsTrue() { // given privacyEnforcementService = new PrivacyEnforcementService( - bidderCatalog, privacyExtractor, tcfDefinerService, ipAddressHelper, metrics, true, false); + bidderCatalog, privacyExtractor, tcfDefinerService, implicitParametersExtractor, ipAddressHelper, + metrics, true, false); final Ccpa ccpa = Ccpa.of("1YYY"); final Account account = Account.builder().build(); @@ -1490,7 +1567,14 @@ private static PrivacyEnforcementAction restrictDeviceAndUser() { } private static BidderInfo givenBidderInfo(int gdprVendorId, boolean enforceCcpa) { - return new BidderInfo(true, null, null, null, - new BidderInfo.GdprInfo(gdprVendorId, true), enforceCcpa, false); + return BidderInfo.of( + true, + null, + null, + null, + null, + new BidderInfo.GdprInfo(gdprVendorId, true), + enforceCcpa, + false); } } diff --git a/src/test/java/org/prebid/server/auction/AmpRequestFactoryTest.java b/src/test/java/org/prebid/server/auction/requestfactory/AmpRequestFactoryTest.java similarity index 84% rename from src/test/java/org/prebid/server/auction/AmpRequestFactoryTest.java rename to src/test/java/org/prebid/server/auction/requestfactory/AmpRequestFactoryTest.java index 0adc684d253..0d8213d785b 100644 --- a/src/test/java/org/prebid/server/auction/AmpRequestFactoryTest.java +++ b/src/test/java/org/prebid/server/auction/requestfactory/AmpRequestFactoryTest.java @@ -1,4 +1,4 @@ -package org.prebid.server.auction; +package org.prebid.server.auction.requestfactory; import com.fasterxml.jackson.core.JsonProcessingException; import com.iab.openrtb.request.App; @@ -23,9 +23,20 @@ import org.mockito.junit.MockitoRule; import org.mockito.stubbing.Answer; import org.prebid.server.VertxTest; +import org.prebid.server.auction.FpdResolver; +import org.prebid.server.auction.ImplicitParametersExtractor; +import org.prebid.server.auction.OrtbTypesResolver; +import org.prebid.server.auction.PrivacyEnforcementService; +import org.prebid.server.auction.StoredRequestProcessor; +import org.prebid.server.auction.TimeoutResolver; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.exception.InvalidRequestException; +import org.prebid.server.geolocation.model.GeoInfo; import org.prebid.server.metric.MetricName; +import org.prebid.server.privacy.ccpa.Ccpa; +import org.prebid.server.privacy.gdpr.model.TcfContext; +import org.prebid.server.privacy.model.Privacy; +import org.prebid.server.privacy.model.PrivacyContext; import org.prebid.server.proto.openrtb.ext.ExtIncludeBrandCategory; import org.prebid.server.proto.openrtb.ext.request.ExtGranularityRange; import org.prebid.server.proto.openrtb.ext.request.ExtPriceGranularity; @@ -53,9 +64,11 @@ import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static java.util.function.Function.identity; +import static org.apache.commons.lang3.StringUtils.EMPTY; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; @@ -66,30 +79,41 @@ public class AmpRequestFactoryTest extends VertxTest { + private static final String ACCOUNT_ID = "acc_id"; + @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private StoredRequestProcessor storedRequestProcessor; @Mock - private AuctionRequestFactory auctionRequestFactory; + private Ortb2RequestFactory ortb2RequestFactory; + @Mock + private OrtbTypesResolver ortbTypesResolver; + @Mock + private ImplicitParametersExtractor implicitParametersExtractor; + @Mock + private Ortb2ImplicitParametersResolver ortb2ImplicitParametersResolver; + @Mock + private FpdResolver fpdResolver; + @Mock + private PrivacyEnforcementService privacyEnforcementService; @Mock private TimeoutResolver timeoutResolver; - private AmpRequestFactory factory; + private AmpRequestFactory target; + @Mock private HttpServerRequest httpRequest; @Mock private RoutingContext routingContext; - @Mock - private OrtbTypesResolver ortbTypesResolver; - @Mock - private ImplicitParametersExtractor implicitParametersExtractor; - @Mock - private FpdResolver fpdResolver; + + private BidRequest defaultBidRequest; @Before public void setUp() { + defaultBidRequest = BidRequest.builder().build(); + given(timeoutResolver.resolve(any())).willReturn(2000L); given(timeoutResolver.adjustTimeout(anyLong())).willReturn(1900L); @@ -106,8 +130,22 @@ public void setUp() { given(fpdResolver.resolveBidRequestExt(any(), any())).willAnswer(invocationOnMock -> invocationOnMock .getArgument(0)); - factory = new AmpRequestFactory(storedRequestProcessor, auctionRequestFactory, ortbTypesResolver, - implicitParametersExtractor, fpdResolver, timeoutResolver, jacksonMapper); + final PrivacyContext defaultPrivacyContext = PrivacyContext.of( + Privacy.of("0", EMPTY, Ccpa.EMPTY, 0), + TcfContext.empty()); + given(privacyEnforcementService.contextFromBidRequest(any())) + .willReturn(Future.succeededFuture(defaultPrivacyContext)); + + target = new AmpRequestFactory( + storedRequestProcessor, + ortb2RequestFactory, + ortbTypesResolver, + implicitParametersExtractor, + ortb2ImplicitParametersResolver, + fpdResolver, + privacyEnforcementService, + timeoutResolver, + jacksonMapper); } @Test @@ -116,7 +154,7 @@ public void shouldReturnFailedFutureIfRequestHasNoTagId() { given(httpRequest.getParam("tag_id")).willReturn(null); // when - final Future future = factory.fromRequest(routingContext, 0L); + final Future future = target.fromRequest(routingContext, 0L); // then verifyZeroInteractions(storedRequestProcessor); @@ -132,7 +170,7 @@ public void shouldReturnFailedFutureIfStoredBidRequestHasNoImp() { givenBidRequest(identity()); // when - final Future future = factory.fromRequest(routingContext, 0L); + final Future future = target.fromRequest(routingContext, 0L); // then assertThat(future.failed()).isTrue(); @@ -148,7 +186,7 @@ public void shouldReturnFailedFutureIfStoredBidRequestHasMoreThenOneImp() { givenBidRequest(identity(), imp, imp); // when - final Future future = factory.fromRequest(routingContext, 0L); + final Future future = target.fromRequest(routingContext, 0L); // then assertThat(future.failed()).isTrue(); @@ -168,7 +206,7 @@ public void shouldReturnFailedFutureIfStoredBidRequestHasApp() { .willReturn(Future.succeededFuture(bidRequest)); // when - final Future future = factory.fromRequest(routingContext, 0L); + final Future future = target.fromRequest(routingContext, 0L); // then assertThat(future.failed()).isTrue(); @@ -183,7 +221,7 @@ public void shouldReturnFailedFutureIfStoredBidRequestHasNoExt() { givenBidRequest(identity(), Imp.builder().build()); // when - final Future future = factory.fromRequest(routingContext, 0L); + final Future future = target.fromRequest(routingContext, 0L); // then assertThat(future.failed()).isTrue(); @@ -198,7 +236,7 @@ public void shouldReturnBidRequestWithDefaultPrebidValuesIfPrebidIsNull() { givenBidRequest(builder -> builder.ext(ExtRequest.empty()), Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then // result was wrapped to list because extracting method works different on iterable and not iterable objects, @@ -229,7 +267,7 @@ public void shouldCallOrtbTypeResolver() { Imp.builder().build()); // when - factory.fromRequest(routingContext, 0L).result(); + target.fromRequest(routingContext, 0L).result(); // then verify(ortbTypesResolver).normalizeTargeting(any(), anyList(), any()); @@ -244,7 +282,7 @@ public void shouldReturnBidRequestWithDefaultTargetingIfStoredBidRequestExtHasNo Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -272,7 +310,7 @@ public void shouldReturnBidRequestWithDefaultIncludeWinnersIfStoredBidRequestExt Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -296,7 +334,7 @@ public void shouldReturnBidRequestWithIncludeWinnersFromStoredBidRequest() { Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -320,7 +358,7 @@ public void shouldReturnBidRequestWithIncludeFormatFromStoredBidRequest() { Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -340,7 +378,7 @@ public void shouldReturnBidRequestWithDefaultIncludeBidderKeysIfStoredRequestExt Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -365,7 +403,7 @@ public void shouldReturnBidRequestWithIncludeBidderKeysFromStoredBidRequest() { Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -385,7 +423,7 @@ public void shouldReturnBidRequestWithDefaultPriceGranularityIfStoredBidRequestE Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -411,7 +449,7 @@ public void shouldReturnBidRequestWithNotChangedExtRequestPrebidTargetingFields( Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -422,10 +460,6 @@ public void shouldReturnBidRequestWithNotChangedExtRequestPrebidTargetingFields( .containsOnly(tuple(ExtIncludeBrandCategory.of(1, "publisher", true), 10)); } - private Answer answerWithFirstArgument() { - return invocationOnMock -> invocationOnMock.getArguments()[0]; - } - @Test public void shouldReturnBidRequestWithDefaultCachingIfStoredBidRequestExtHasNoCaching() { // given @@ -435,7 +469,7 @@ public void shouldReturnBidRequestWithDefaultCachingIfStoredBidRequestExtHasNoCa Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -453,7 +487,7 @@ public void shouldReturnBidRequestWithChannelIfStoredBidRequestExtHasNoChannel() Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -473,7 +507,7 @@ public void shouldReturnBidRequestWithChannelFromStoredBidRequest() { Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -491,7 +525,7 @@ public void shouldReturnBidRequestWithImpSecureEqualsToOneIfInitiallyItWasNotSec Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -512,11 +546,11 @@ public void shouldRespondWithBidRequestWithTestFlagOn() { Imp.builder().build()); // when - factory.fromRequest(routingContext, 0L); + target.fromRequest(routingContext, 0L); // then final ArgumentCaptor captor = ArgumentCaptor.forClass(BidRequest.class); - verify(auctionRequestFactory).fillImplicitParameters(captor.capture(), any(), any()); + verify(ortb2ImplicitParametersResolver).resolve(captor.capture(), any(), any()); assertThat(captor.getValue().getTest()).isEqualTo(1); } @@ -532,11 +566,11 @@ public void shouldRespondWithBidRequestWithDebugFlagOn() { Imp.builder().build()); // when - factory.fromRequest(routingContext, 0L); + target.fromRequest(routingContext, 0L); // then final ArgumentCaptor captor = ArgumentCaptor.forClass(BidRequest.class); - verify(auctionRequestFactory).fillImplicitParameters(captor.capture(), any(), any()); + verify(ortb2ImplicitParametersResolver).resolve(captor.capture(), any(), any()); final ExtRequest extRequest = captor.getValue().getExt(); assertThat(extRequest.getPrebid().getDebug()).isEqualTo(1); @@ -553,7 +587,7 @@ public void shouldReturnBidRequestWithOverriddenTagIdBySlotParamValue() { Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -573,7 +607,7 @@ public void shouldSetBidRequestSiteExt() { Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -594,7 +628,7 @@ public void shouldReturnBidRequestWithOverriddenSitePageAndDomainByCurlParamValu Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -616,7 +650,7 @@ public void shouldReturnBidRequestWithSitePageAndDomainContainingCurlParamValueW Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -638,7 +672,7 @@ public void shouldReturnBidRequestWithSitePublisherIdOverriddenWithAccountParamV Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -661,7 +695,7 @@ public void shouldReturnBidRequestWithSitePublisherIdFromAccountParamWhenSiteDoe Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -684,7 +718,7 @@ public void shouldReturnBidRequestWithSitePublisherIdFromAccountParamWhenSitePub Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -716,7 +750,7 @@ public void shouldReturnRequestWithOverriddenBannerFormatByOverwriteWHParamsResp .build()).build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -747,7 +781,7 @@ public void shouldReturnBidRequestWithOverriddenBannerFromOWAndHParamAndMultiLis .build()).build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -778,7 +812,7 @@ public void shouldReturnBidRequestWithOverriddenBannerFromWAndOHParamAndMultiLis .build()).build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -808,7 +842,7 @@ public void shouldReturnBidRequestWithBannerFromHWParamsAndMultiList() { .build()).build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -837,7 +871,7 @@ public void shouldReturnBidRequestWithOverriddenBannerFromWAndHParamsIfOwOhAndMu .build()).build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -863,7 +897,7 @@ public void shouldReturnBidRequestWithUpdatedWidthForAllBannerFormatsWhenOnlyWIs .build()).build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -889,7 +923,7 @@ public void shouldReturnBidRequestWithUpdatedHeightForAllBannerFormatsWhenOnlyHI .build()).build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -917,7 +951,7 @@ public void shouldReturnBidRequestWithOverriddenBannerFormatsByMultiSizeParams() .build()).build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -945,7 +979,7 @@ public void shouldReturnBidRequestWithOriginalBannerFormatsWhenMultiSizeParamCon .build()).build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -973,7 +1007,7 @@ public void shouldReturnBidRequestWithOriginBannerFormatsWhenMultiSizeParamConta .build()).build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -1001,7 +1035,7 @@ public void shouldReturnBidRequestOverriddenBannerFormatsWhenMsParamSizePairHasO .build()).build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -1029,7 +1063,7 @@ public void shouldReturnBidRequestWithOriginBannerFormatsWhenMultiSizeParamConta .build()).build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -1057,7 +1091,7 @@ public void shouldReturnBidRequestWithOverriddenBannerFormatsWhenMultiSizeParamC .build()).build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -1089,7 +1123,7 @@ public void shouldReturnBidRequestWithOriginBannerFormatsWhenAllParametersAreZer .build()).build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -1119,7 +1153,7 @@ public void shouldReturnBidRequestWithOverriddenBannerWhenInvalidParamTreatedAsZ .build()).build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -1141,7 +1175,7 @@ public void shouldReturnBidRequestWithOverriddenTmaxWhenTimeoutParamIsAvailable( Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(request.getTmax()).isEqualTo(1000L); @@ -1161,8 +1195,8 @@ public void shouldReturnBidRequestWithUnmodifiedUserWhenGdprConsentParamIsNullOr Imp.builder().build()); // when - final BidRequest firstResult = factory.fromRequest(routingContext, 0L).result().getBidRequest(); - final BidRequest secondResult = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest firstResult = target.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest secondResult = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then final User expectedUser = User.builder() @@ -1188,7 +1222,7 @@ public void shouldReturnBidRequestWithOverriddenUserExtConsentWhenGdprConsentPar Imp.builder().build()); // when - final BidRequest result = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest result = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(result.getUser()) @@ -1209,7 +1243,7 @@ public void shouldReturnBidRequestWithNewUserThatContainsUserExtConsentWhenIniti Imp.builder().build()); // when - final BidRequest result = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest result = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(result.getUser()) @@ -1230,7 +1264,7 @@ public void shouldKeepEmptyUserWhenGdprConsentIsInvalid() { Imp.builder().build()); // when - final BidRequest result = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest result = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(result.getUser()) @@ -1249,12 +1283,13 @@ public void shouldReturnAddErrorToAuctionContextWhenPrivacyIsNotValid() { Imp.builder().build()); // when - factory.fromRequest(routingContext, 0L).result(); + target.fromRequest(routingContext, 0L).result(); // then @SuppressWarnings("unchecked") final ArgumentCaptor> errorsCaptor = ArgumentCaptor.forClass( List.class); - verify(auctionRequestFactory).toAuctionContext(any(), any(), any(), errorsCaptor.capture(), anyLong(), any()); + verify(ortb2RequestFactory).fetchAccountAndCreateAuctionContext(any(), any(), any(), anyBoolean(), anyLong(), + errorsCaptor.capture()); assertThat(errorsCaptor.getValue()).contains("Amp request parameter consent_string or gdpr_consent have" + " invalid format: consent-value"); } @@ -1275,7 +1310,7 @@ public void shouldReturnBidRequestWithExtPrebidDataBiddersUpdatedByFpdResolver() Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then verify(fpdResolver).resolveBidRequestExt(any(), any()); @@ -1301,7 +1336,7 @@ public void shouldReturnBidRequestImpExtContextDataWithTargetingAttributes() thr Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then verify(fpdResolver).resolveBidRequestExt(any(), any()); @@ -1323,7 +1358,7 @@ public void shouldThrowInvalidRequestExceptionWhenTargetingHasTypeOtherToObject( Imp.builder().build()); // when - final Future result = factory.fromRequest(routingContext, 0L); + final Future result = target.fromRequest(routingContext, 0L); // then assertThat(result.failed()).isTrue(); @@ -1340,7 +1375,7 @@ public void shouldReturnBidRequestWithoutRegsExtWhenNoPrivacyPolicyIsExist() { Imp.builder().build()); // when - final BidRequest result = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest result = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(result.getRegs()).isNull(); @@ -1356,7 +1391,7 @@ public void shouldReturnBidRequestWithRegsExtUsPrivacyWhenUsPrivacyParamIsValid( Imp.builder().build()); // when - final BidRequest result = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest result = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(result.getRegs()) @@ -1376,7 +1411,7 @@ public void shouldReturnBidRequestWithRegsExtUsPrivacyWhenConsentStringIsValid() Imp.builder().build()); // when - final BidRequest result = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest result = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(result.getUser()) @@ -1394,7 +1429,7 @@ public void shouldPassExtPrebidDebugFlagIfPresent() { Imp.builder().build()); // when - final BidRequest request = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest request = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then assertThat(singletonList(request)) @@ -1417,7 +1452,7 @@ public void shouldReturnBidRequestWithCreatedExtPrebidAmpData() { Imp.builder().build()); // when - final BidRequest result = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest result = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then final Map expectedAmpData = new HashMap<>(); @@ -1449,7 +1484,7 @@ public void shouldReturnBidRequestWithUpdatedExtPrebidAmpData() { Imp.builder().build()); // when - final BidRequest result = factory.fromRequest(routingContext, 0L).result().getBidRequest(); + final BidRequest result = target.fromRequest(routingContext, 0L).result().getBidRequest(); // then final Map expectedAmpData = new HashMap<>(); @@ -1464,23 +1499,75 @@ public void shouldReturnBidRequestWithUpdatedExtPrebidAmpData() { .containsOnly(expectedAmpData); } + @Test + public void shouldReturnModifiedBidRequestWhenRequestWasPopulatedWithImplicitParams() { + // given + givenBidRequest( + builder -> builder.ext(ExtRequest.empty()), + Imp.builder().build()); + + final BidRequest updatedBidRequest = defaultBidRequest.toBuilder().id("updated").build(); + given(ortb2ImplicitParametersResolver.resolve(any(), any(), any())) + .willReturn(updatedBidRequest); + + // when + final AuctionContext result = target.fromRequest(routingContext, 0L).result(); + + // then + assertThat(result.getBidRequest()).isEqualTo(updatedBidRequest); + } + + @Test + public void shouldReturnPopulatedPrivacyContextAndGetWhenPrivacyEnforcementReturnContext() { + // given + givenBidRequest( + builder -> builder.ext(ExtRequest.empty()), + Imp.builder().build()); + + final GeoInfo geoInfo = GeoInfo.builder().vendor("vendor").city("found").build(); + final PrivacyContext privacyContext = PrivacyContext.of( + Privacy.of("1", "consent", Ccpa.EMPTY, 0), + TcfContext.builder().geoInfo(geoInfo).build()); + given(privacyEnforcementService.contextFromBidRequest(any())) + .willReturn(Future.succeededFuture(privacyContext)); + + // when + final AuctionContext result = target.fromRequest(routingContext, 0L).result(); + + // then + assertThat(result.getPrivacyContext()).isEqualTo(privacyContext); + assertThat(result.getGeoInfo()).isEqualTo(geoInfo); + } + private void givenBidRequest( Function bidRequestBuilderCustomizer, Imp... imps) { final List impList = imps.length > 0 ? asList(imps) : null; - final BidRequest bidRequest = bidRequestBuilderCustomizer.apply(BidRequest.builder().imp(impList)).build(); + final BidRequest bidRequest = bidRequestBuilderCustomizer.apply(defaultBidRequest.toBuilder().imp(impList)) + .build(); given(storedRequestProcessor.processAmpRequest(any(), anyString())) .willReturn(Future.succeededFuture(bidRequest)); - given(auctionRequestFactory.fillImplicitParameters(any(), any(), any())).willAnswer(answerWithFirstArgument()); - given(auctionRequestFactory.validateRequest(any())).willAnswer(answerWithFirstArgument()); - given(auctionRequestFactory.toAuctionContext(any(), any(), eq(MetricName.amp), anyList(), anyLong(), any())) + final MetricName metricName = MetricName.amp; + given(ortb2RequestFactory.fetchAccountAndCreateAuctionContext(any(), any(), eq(metricName), anyBoolean(), + anyLong(), any())) .willAnswer(invocationOnMock -> Future.succeededFuture( AuctionContext.builder() .bidRequest((BidRequest) invocationOnMock.getArguments()[1]) .build())); + + given(ortb2ImplicitParametersResolver.resolve(any(), any(), any())).willAnswer( + answerWithFirstArgument()); + given(ortb2RequestFactory.validateRequest(any())).willAnswer(answerWithFirstArgument()); + + given(ortb2RequestFactory.enrichBidRequestWithAccountAndPrivacyData(any(), any(), any())) + .willAnswer(answerWithFirstArgument()); + } + + private Answer answerWithFirstArgument() { + return invocationOnMock -> invocationOnMock.getArguments()[0]; } private static ExtRequest givenRequestExt(ExtRequestTargeting extRequestTargeting) { diff --git a/src/test/java/org/prebid/server/auction/requestfactory/AuctionRequestFactoryTest.java b/src/test/java/org/prebid/server/auction/requestfactory/AuctionRequestFactoryTest.java new file mode 100644 index 00000000000..530e5b43dd2 --- /dev/null +++ b/src/test/java/org/prebid/server/auction/requestfactory/AuctionRequestFactoryTest.java @@ -0,0 +1,455 @@ +package org.prebid.server.auction.requestfactory; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.iab.openrtb.request.App; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Site; +import io.vertx.core.Future; +import io.vertx.core.http.CaseInsensitiveHeaders; +import io.vertx.core.http.HttpServerRequest; +import io.vertx.ext.web.RoutingContext; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.prebid.server.VertxTest; +import org.prebid.server.auction.ImplicitParametersExtractor; +import org.prebid.server.auction.InterstitialProcessor; +import org.prebid.server.auction.OrtbTypesResolver; +import org.prebid.server.auction.PrivacyEnforcementService; +import org.prebid.server.auction.StoredRequestProcessor; +import org.prebid.server.auction.TimeoutResolver; +import org.prebid.server.auction.model.AuctionContext; +import org.prebid.server.exception.InvalidRequestException; +import org.prebid.server.geolocation.model.GeoInfo; +import org.prebid.server.metric.MetricName; +import org.prebid.server.privacy.ccpa.Ccpa; +import org.prebid.server.privacy.gdpr.model.TcfContext; +import org.prebid.server.privacy.model.Privacy; +import org.prebid.server.privacy.model.PrivacyContext; +import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidData; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidDataEidPermissions; +import org.prebid.server.settings.model.Account; + +import java.util.ArrayList; + +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; +import static org.apache.commons.lang3.StringUtils.EMPTY; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.verify; + +public class AuctionRequestFactoryTest extends VertxTest { + + private static final String ACCOUNT_ID = "acc_id"; + + @Rule + public final MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Mock + private Ortb2RequestFactory ortb2RequestFactory; + @Mock + private StoredRequestProcessor storedRequestProcessor; + @Mock + private ImplicitParametersExtractor paramsExtractor; + @Mock + private Ortb2ImplicitParametersResolver paramsResolver; + @Mock + private InterstitialProcessor interstitialProcessor; + @Mock + private OrtbTypesResolver ortbTypesResolver; + @Mock + private PrivacyEnforcementService privacyEnforcementService; + @Mock + private TimeoutResolver timeoutResolver; + + @Mock + private AuctionRequestFactory target; + + @Mock + private RoutingContext routingContext; + @Mock + private HttpServerRequest httpRequest; + + private Account defaultAccount; + private BidRequest defaultBidRequest; + private AuctionContext defaultActionContext; + + @Before + public void setUp() { + defaultBidRequest = BidRequest.builder().build(); + defaultAccount = Account.empty(ACCOUNT_ID); + + final PrivacyContext defaultPrivacyContext = PrivacyContext.of( + Privacy.of("0", EMPTY, Ccpa.EMPTY, 0), + TcfContext.empty()); + defaultActionContext = AuctionContext.builder() + .bidRequest(defaultBidRequest) + .account(defaultAccount) + .prebidErrors(new ArrayList<>()) + .privacyContext(defaultPrivacyContext) + .build(); + + given(routingContext.request()).willReturn(httpRequest); + given(httpRequest.headers()).willReturn(new CaseInsensitiveHeaders()); + + given(timeoutResolver.resolve(any())).willReturn(2000L); + given(timeoutResolver.adjustTimeout(anyLong())).willReturn(1900L); + + given(paramsResolver.resolve(any(), any(), any())) + .will(invocationOnMock -> invocationOnMock.getArgument(0)); + given(ortb2RequestFactory.validateRequest(any())) + .will(invocationOnMock -> invocationOnMock.getArgument(0)); + given(interstitialProcessor.process(any())) + .will(invocationOnMock -> invocationOnMock.getArgument(0)); + + given(privacyEnforcementService.contextFromBidRequest(any())) + .willReturn(Future.succeededFuture(defaultPrivacyContext)); + + given(ortb2RequestFactory.enrichBidRequestWithAccountAndPrivacyData(any(), any(), any())) + .will(invocationOnMock -> invocationOnMock.getArgument(0)); + + target = new AuctionRequestFactory( + Integer.MAX_VALUE, + ortb2RequestFactory, + storedRequestProcessor, + paramsExtractor, + paramsResolver, + interstitialProcessor, + ortbTypesResolver, + privacyEnforcementService, + timeoutResolver, + jacksonMapper); + } + + @Test + public void shouldReturnFailedFutureIfRequestBodyIsMissing() { + // given + given(routingContext.getBody()).willReturn(null); + + // when + final Future future = target.fromRequest(routingContext, 0L); + + // then + assertThat(future.failed()).isTrue(); + assertThat(future.cause()) + .isInstanceOf(InvalidRequestException.class) + .hasMessage("Incoming request has no body"); + } + + @Test + public void shouldReturnFailedFutureIfRequestBodyExceedsMaxRequestSize() { + // given + target = new AuctionRequestFactory( + 1, + ortb2RequestFactory, + storedRequestProcessor, + paramsExtractor, + paramsResolver, + interstitialProcessor, + ortbTypesResolver, + privacyEnforcementService, + timeoutResolver, + jacksonMapper); + + given(routingContext.getBodyAsString()).willReturn("body"); + + // when + final Future future = target.fromRequest(routingContext, 0L); + + // then + assertThat(future.failed()).isTrue(); + assertThat(future.cause()) + .isInstanceOf(InvalidRequestException.class) + .hasMessage("Request size exceeded max size of 1 bytes."); + } + + @Test + public void shouldReturnFailedFutureIfRequestBodyCouldNotBeParsed() { + // given + given(routingContext.getBodyAsString()).willReturn("body"); + + // when + final Future future = target.fromRequest(routingContext, 0L); + + // then + assertThat(future.failed()).isTrue(); + assertThat(future.cause()).isInstanceOf(InvalidRequestException.class); + assertThat(((InvalidRequestException) future.cause()).getMessages()).hasSize(1) + .element(0).asString().startsWith("Error decoding bidRequest: Unrecognized token 'body'"); + } + + @Test + public void shouldReturnFailedFutureIfEidsPermissionsContainsWrongDataType() { + // given + final BidRequest bidRequest = BidRequest.builder() + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .data(ExtRequestPrebidData.of(emptyList(), null)) + .build())) + .build(); + + final ObjectNode requestNode = mapper.convertValue(bidRequest, ObjectNode.class); + final JsonNode eidPermissionNode = mapper.convertValue( + ExtRequestPrebidDataEidPermissions.of("source", emptyList()), JsonNode.class); + + requestNode.with("ext").with("prebid").with("data").set("eidpermissions", eidPermissionNode); + + given(routingContext.getBodyAsString()).willReturn(requestNode.toString()); + + // when + final Future result = target.fromRequest(routingContext, 0L); + + // then + assertThat(result.failed()).isTrue(); + assertThat(result.cause()).isInstanceOf(InvalidRequestException.class); + assertThat(((InvalidRequestException) result.cause()).getMessages()).hasSize(1) + .allSatisfy(message -> + assertThat(message).startsWith("Error decoding bidRequest: Cannot deserialize instance")); + } + + @Test + public void shouldReturnFailedFutureIfEidsPermissionsBiddersContainsWrongDataType() { + // given + final BidRequest bidRequest = BidRequest.builder() + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .data(ExtRequestPrebidData.of(emptyList(), null)) + .build())) + .build(); + + final ObjectNode requestNode = mapper.convertValue(bidRequest, ObjectNode.class); + + final ObjectNode eidPermissionNode = mapper.convertValue( + ExtRequestPrebidDataEidPermissions.of("source", emptyList()), ObjectNode.class); + + eidPermissionNode.put("bidders", "notArrayValue"); + + final ArrayNode arrayNode = requestNode + .with("ext") + .with("prebid") + .with("data") + .putArray("eidpermissions"); + arrayNode.add(eidPermissionNode); + + given(routingContext.getBodyAsString()).willReturn(requestNode.toString()); + + // when + final Future result = target.fromRequest(routingContext, 0L); + + // then + assertThat(result.failed()).isTrue(); + assertThat(result.cause()).isInstanceOf(InvalidRequestException.class); + assertThat(((InvalidRequestException) result.cause()).getMessages()).hasSize(1) + .allSatisfy(message -> + assertThat(message).startsWith("Error decoding bidRequest: Cannot deserialize instance")); + } + + @Test + public void shouldTolerateMissingImpExtWhenProcessingAliases() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().ext(null).build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .aliases(singletonMap("alias", "bidder")) + .build())) + .build(); + givenBidRequest(bidRequest); + givenAuctionContext(bidRequest, defaultAccount); + givenProcessStoredRequest(bidRequest); + + // when + final Future result = target.fromRequest(routingContext, 0L); + + // then + assertThat(result.succeeded()).isTrue(); + } + + @Test + public void shouldCallOrtbFieldsResolver() { + // given + givenValidBidRequest(); + + // when + target.fromRequest(routingContext, 0L).result(); + + // then + verify(ortbTypesResolver).normalizeBidRequest(any(), any(), any()); + } + + @Test + public void shouldReturnFailedFutureIfOrtb2RequestFactoryReturnedFailedFuture() { + // given + givenBidRequest(BidRequest.builder().build()); + given(ortb2RequestFactory.fetchAccountAndCreateAuctionContext(any(), any(), any(), anyBoolean(), anyLong(), + any())).willReturn(Future.failedFuture("error")); + + // when + final Future future = target.fromRequest(routingContext, 0L); + + // then + assertThat(future.failed()).isTrue(); + assertThat(future.cause()).hasMessage("error"); + } + + @Test + public void shouldPassWebRequestTypeMetricToFetchAccountWhenSiteIsPresent() { + // given + final BidRequest bidRequest = BidRequest.builder().site(Site.builder().build()).build(); + givenBidRequest(bidRequest); + givenAuctionContext(bidRequest, Account.empty(ACCOUNT_ID)); + + // when + target.fromRequest(routingContext, 0L); + + // then + verify(ortb2RequestFactory).fetchAccountAndCreateAuctionContext(eq(routingContext), eq(bidRequest), + eq(MetricName.openrtb2web), eq(true), anyLong(), any()); + } + + @Test + public void shouldPassAppRequestTypeMetricToFetchAccountWhenAppIsPresent() { + // given + final BidRequest bidRequest = BidRequest.builder().app(App.builder().build()).build(); + givenBidRequest(bidRequest); + givenAuctionContext(bidRequest, Account.empty(ACCOUNT_ID)); + + // when + target.fromRequest(routingContext, 0L); + + // then + verify(ortb2RequestFactory).fetchAccountAndCreateAuctionContext(eq(routingContext), eq(bidRequest), + eq(MetricName.openrtb2app), eq(true), anyLong(), any()); + } + + @Test + public void storedRequestProcessorShouldUseAccountIdFetchedByOrtb2RequestFactory() { + // given + givenValidBidRequest(); + + // when + target.fromRequest(routingContext, 0L); + + // then + verify(storedRequestProcessor).processStoredRequests(eq(ACCOUNT_ID), any()); + } + + @Test + public void shouldReturnFailedFutureIfProcessStoredRequestsFailed() { + // given + givenValidBidRequest(); + given(storedRequestProcessor.processStoredRequests(any(), any())) + .willReturn(Future.failedFuture("error")); + + // when + final Future future = target.fromRequest(routingContext, 0L); + + // then + assertThat(future.failed()).isTrue(); + assertThat(future.cause()).hasMessage("error"); + } + + @Test + public void shouldReturnFailedFutureIfRequestValidationFailed() { + // given + givenValidBidRequest(); + + given(ortb2RequestFactory.validateRequest(any())) + .willThrow(new InvalidRequestException("errors")); + + // when + final Future future = target.fromRequest(routingContext, 0L); + + // then + assertThat(future.failed()).isTrue(); + assertThat(future.cause()).isInstanceOf(InvalidRequestException.class); + assertThat(((InvalidRequestException) future.cause()).getMessages()).containsOnly("errors"); + } + + @Test + public void shouldReturnAuctionContextWithExpectedParameters() { + // given + givenValidBidRequest(); + + // when + final AuctionContext result = target.fromRequest(routingContext, 0L).result(); + + // then + assertThat(result).isEqualTo(defaultActionContext); + } + + @Test + public void shouldReturnModifiedBidRequestInAuctionContextWhenRequestWasPopulatedWithImplicitParams() { + // given + givenValidBidRequest(); + + final BidRequest updatedBidRequest = defaultBidRequest.toBuilder().id("updated").build(); + given(paramsResolver.resolve(any(), any(), any())).willReturn(updatedBidRequest); + + // when + final AuctionContext result = target.fromRequest(routingContext, 0L).result(); + + // then + assertThat(result.getBidRequest()).isEqualTo(updatedBidRequest); + } + + @Test + public void shouldReturnPopulatedPrivacyContextAndGetWhenPrivacyEnforcementReturnContext() { + // given + givenValidBidRequest(); + + final GeoInfo geoInfo = GeoInfo.builder().vendor("vendor").city("found").build(); + final PrivacyContext privacyContext = PrivacyContext.of( + Privacy.of("1", "consent", Ccpa.EMPTY, 0), + TcfContext.builder().geoInfo(geoInfo).build()); + given(privacyEnforcementService.contextFromBidRequest(any())) + .willReturn(Future.succeededFuture(privacyContext)); + + // when + final AuctionContext result = target.fromRequest(routingContext, 0L).result(); + + // then + assertThat(result.getPrivacyContext()).isEqualTo(privacyContext); + assertThat(result.getGeoInfo()).isEqualTo(geoInfo); + } + + private void givenBidRequest(BidRequest bidRequest) { + try { + given(routingContext.getBodyAsString()).willReturn(mapper.writeValueAsString(bidRequest)); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + private void givenAuctionContext(BidRequest bidRequest, Account account) { + given(ortb2RequestFactory.fetchAccountAndCreateAuctionContext(any(), any(), any(), anyBoolean(), anyLong(), + any())) + .willReturn(Future.succeededFuture(defaultActionContext.toBuilder() + .bidRequest(bidRequest) + .account(account) + .build())); + } + + private void givenProcessStoredRequest(BidRequest bidRequest) { + given(storedRequestProcessor.processStoredRequests(any(), any())) + .willReturn(Future.succeededFuture(bidRequest)); + } + + private void givenValidBidRequest() { + givenBidRequest(defaultBidRequest); + givenAuctionContext(defaultBidRequest, defaultAccount); + givenProcessStoredRequest(defaultBidRequest); + } +} diff --git a/src/test/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolverTest.java b/src/test/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolverTest.java new file mode 100644 index 00000000000..120ab0169a2 --- /dev/null +++ b/src/test/java/org/prebid/server/auction/requestfactory/Ortb2ImplicitParametersResolverTest.java @@ -0,0 +1,1762 @@ +package org.prebid.server.auction.requestfactory; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.TextNode; +import com.iab.openrtb.request.App; +import com.iab.openrtb.request.Banner; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Device; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Publisher; +import com.iab.openrtb.request.Site; +import com.iab.openrtb.request.Source; +import com.iab.openrtb.request.User; +import com.iab.openrtb.request.Video; +import io.vertx.core.http.CaseInsensitiveHeaders; +import io.vertx.core.http.HttpServerRequest; +import io.vertx.ext.web.RoutingContext; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.prebid.server.VertxTest; +import org.prebid.server.auction.ImplicitParametersExtractor; +import org.prebid.server.auction.IpAddressHelper; +import org.prebid.server.auction.TimeoutResolver; +import org.prebid.server.auction.model.IpAddress; +import org.prebid.server.exception.BlacklistedAppException; +import org.prebid.server.exception.InvalidRequestException; +import org.prebid.server.exception.PreBidException; +import org.prebid.server.identity.IdGenerator; +import org.prebid.server.proto.openrtb.ext.ExtIncludeBrandCategory; +import org.prebid.server.proto.openrtb.ext.request.ExtDevice; +import org.prebid.server.proto.openrtb.ext.request.ExtGranularityRange; +import org.prebid.server.proto.openrtb.ext.request.ExtMediaTypePriceGranularity; +import org.prebid.server.proto.openrtb.ext.request.ExtPriceGranularity; +import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidCache; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidCacheBids; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidCacheVastxml; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidChannel; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestTargeting; +import org.prebid.server.proto.openrtb.ext.request.ExtSite; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.List; + +import static java.util.Collections.singleton; +import static java.util.Collections.singletonList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.groups.Tuple.tuple; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +public class Ortb2ImplicitParametersResolverTest extends VertxTest { + + private static final List BLACKLISTED_APPS = singletonList("bad_app"); + + @Rule + public final MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Mock + private ImplicitParametersExtractor paramsExtractor; + @Mock + private IpAddressHelper ipAddressHelper; + @Mock + private IdGenerator idGenerator; + + private Ortb2ImplicitParametersResolver target; + + @Mock + private RoutingContext routingContext; + @Mock + private HttpServerRequest httpRequest; + @Mock + private TimeoutResolver timeoutResolver; + + private BidRequest defaultBidRequest; + + @Before + public void setUp() { + defaultBidRequest = BidRequest.builder().build(); + + given(idGenerator.generateId()).willReturn(null); + given(timeoutResolver.resolve(any())).willReturn(2000L); + + given(routingContext.request()).willReturn(httpRequest); + given(httpRequest.headers()).willReturn(new CaseInsensitiveHeaders()); + + target = new Ortb2ImplicitParametersResolver( + false, + "USD", + BLACKLISTED_APPS, + paramsExtractor, + ipAddressHelper, + idGenerator, + jacksonMapper); + } + + @Test + public void shouldSetFieldsFromHeadersIfBodyFieldsEmptyForIpv4() { + // given + givenImplicitParams("http://example.com", "example.com", "192.168.244.1", IpAddress.IP.v4, "UnitTest"); + + // when + final BidRequest result = target.resolve(defaultBidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getSite()).isEqualTo(Site.builder() + .page("http://example.com") + .domain("example.com") + .publisher(Publisher.builder().domain("example.com").build()) + .ext(ExtSite.of(0, null)) + .build()); + assertThat(result.getDevice()) + .isEqualTo(Device.builder().ip("192.168.244.1").ua("UnitTest").build()); + } + + @Test + public void shouldSetFieldsFromHeadersIfBodyFieldsInvalidForIpv4() { + // given + final BidRequest bidRequest = BidRequest.builder() + .device(Device.builder().ip("127.0.0.1").build()) + .build(); + + given(ipAddressHelper.toIpAddress(eq("127.0.0.1"))).willReturn(null); + + givenImplicitParams("http://example.com", "example.com", "192.168.244.1", IpAddress.IP.v4, "UnitTest"); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getSite()).isEqualTo(Site.builder() + .page("http://example.com") + .domain("example.com") + .publisher(Publisher.builder().domain("example.com").build()) + .ext(ExtSite.of(0, null)) + .build()); + assertThat(result.getDevice()) + .isEqualTo(Device.builder().ip("192.168.244.1").ua("UnitTest").build()); + } + + @Test + public void shouldSetFieldsFromHeadersIfBodyFieldsEmptyForIpv6() { + // given + givenImplicitParams( + "http://example.com", + "example.com", + "2001:0db8:85a3:0000:0000:8a2e:0370:7334", + IpAddress.IP.v6, + "UnitTest"); + + // when + final BidRequest result = target.resolve(defaultBidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getSite()).isEqualTo(Site.builder() + .page("http://example.com") + .domain("example.com") + .publisher(Publisher.builder().domain("example.com").build()) + .ext(ExtSite.of(0, null)) + .build()); + assertThat(result.getDevice()) + .isEqualTo(Device.builder().ipv6("2001:0db8:85a3:0000:0000:8a2e:0370:7334").ua("UnitTest").build()); + } + + @Test + public void shouldSetFieldsFromHeadersIfBodyFieldsInvalidForIpv6() { + // given + final BidRequest bidRequest = BidRequest.builder() + .device(Device.builder().ipv6("::1").build()) + .build(); + + given(ipAddressHelper.toIpAddress(eq("::1"))).willReturn(null); + + givenImplicitParams( + "http://example.com", + "example.com", + "2001:0db8:85a3:0000:0000:8a2e:0370:7334", + IpAddress.IP.v6, + "UnitTest"); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getSite()).isEqualTo(Site.builder() + .page("http://example.com") + .domain("example.com") + .publisher(Publisher.builder().domain("example.com").build()) + .ext(ExtSite.of(0, null)) + .build()); + assertThat(result.getDevice()) + .isEqualTo(Device.builder().ipv6("2001:0db8:85a3:0000:0000:8a2e:0370:7334").ua("UnitTest").build()); + } + + @Test + public void shouldSetAnonymizedIpv6FromField() { + // given + final BidRequest bidRequest = BidRequest.builder() + .device(Device.builder().ipv6("2001:0db8:85a3:0000:0000:8a2e:0370:7334").build()) + .build(); + + given(ipAddressHelper.toIpAddress(eq("2001:0db8:85a3:0000:0000:8a2e:0370:7334"))) + .willReturn(IpAddress.of("2001:0db8:85a3:0000::", IpAddress.IP.v6)); + + givenImplicitParams( + "http://example.com", + "example.com", + "1111:2222:3333:4444:5555:6666:7777:8888", + IpAddress.IP.v6, + "UnitTest"); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getSite()).isEqualTo(Site.builder() + .page("http://example.com") + .domain("example.com") + .publisher(Publisher.builder().domain("example.com").build()) + .ext(ExtSite.of(0, null)) + .build()); + assertThat(result.getDevice()) + .isEqualTo(Device.builder().ipv6("2001:0db8:85a3:0000::").ua("UnitTest").build()); + } + + @Test + public void shouldNotImplicitlyResolveIpIfIpv6IsPassed() { + // given + final BidRequest bidRequest = BidRequest.builder() + .device(Device.builder().ipv6("2001:0db8:85a3:0000:0000:8a2e:0370:7334").build()) + .build(); + + given(ipAddressHelper.toIpAddress(eq("2001:0db8:85a3:0000:0000:8a2e:0370:7334"))) + .willReturn(IpAddress.of("2001:0db8:85a3:0000::", IpAddress.IP.v6)); + + // when + target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + verify(paramsExtractor, never()).ipFrom(any()); + } + + @Test + public void shouldNotSetDeviceDntIfHeaderHasInvalidValue() { + // given + given(httpRequest.getHeader("DNT")).willReturn("invalid"); + + // when + final BidRequest result = target.resolve(defaultBidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getDnt()).isNull(); + } + + @Test + public void shouldSetDeviceDntIfHeaderExists() { + // given + given(httpRequest.getHeader("DNT")).willReturn("1"); + + // when + final BidRequest result = target.resolve(defaultBidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getDnt()).isOne(); + } + + @Test + public void shouldOverrideDeviceDntIfHeaderExists() { + // given + given(httpRequest.getHeader("DNT")).willReturn("0"); + + final BidRequest bidRequest = BidRequest.builder() + .device(Device.builder().dnt(1).build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getDnt()).isZero(); + } + + @Test + public void shouldNotSetDeviceLmtForIos14IfNoApp() { + // given + final BidRequest bidRequest = BidRequest.builder() + .device(Device.builder() + .os("iOS") + .osv("14.0") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isNull(); + } + + @Test + public void shouldNotSetDeviceLmtForNonIos() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("plan9") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isNull(); + } + + @Test + public void shouldNotSetDeviceLmtForIosInvalidVersion() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("invalid-version") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isNull(); + } + + @Test + public void shouldNotSetDeviceLmtForIosInvalidVersionMajor() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("invalid-major.0") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isNull(); + } + + @Test + public void shouldNotSetDeviceLmtForIosInvalidVersionMinor() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("14.invalid-minor") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isNull(); + } + + @Test + public void shouldNotSetDeviceLmtForIosMissingVersionMinor() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("14") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isNull(); + } + + @Test + public void shouldNotSetDeviceLmtForIosLowerThan14() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("13.4") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isNull(); + } + + @Test + public void shouldSetDeviceLmtOneForIos14WithPatchVersion() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("14.0.patch-version") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isOne(); + } + + @Test + public void shouldSetDeviceLmtOneForIos14Minor0() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("14.0") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isOne(); + } + + @Test + public void shouldSetDeviceLmtOneForIos14Minor0AndEmptyIfa() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("14.0") + .ifa("") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isOne(); + } + + @Test + public void shouldOverrideDeviceLmtForIos14Minor0AndEmptyIfa() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .lmt(0) + .os("iOS") + .osv("14.0") + .ifa("") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isOne(); + } + + @Test + public void shouldSetDeviceLmtOneForIos14Minor0AndZerosIfa() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("14.0") + .ifa("00000000-0000-0000-0000-000000000000") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isOne(); + } + + @Test + public void shouldSetDeviceLmtZeroForIos14Minor0AndNonZerosIfa() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("14.1") + .ifa("12345") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isZero(); + } + + @Test + public void shouldNotOverrideDeviceLmtForIos14Minor0AndNonZerosIfaWhenLmtAlreadySet() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .lmt(1) + .os("iOS") + .osv("14.0") + .ifa("12345") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isOne(); + } + + @Test + public void shouldSetDeviceLmtOneForIos14Minor1() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("14.1") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isOne(); + } + + @Test + public void shouldSetDeviceLmtOneForIos14Minor1AndEmptyIfa() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("14.1") + .ifa("") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isOne(); + } + + @Test + public void shouldOverrideDeviceLmtForIos14Minor1AndEmptyIfa() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .lmt(0) + .os("iOS") + .osv("14.1") + .ifa("") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isOne(); + } + + @Test + public void shouldSetDeviceLmtOneForIos14Minor1AndZerosIfa() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("14.1") + .ifa("00000000-0000-0000-0000-000000000000") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isOne(); + } + + @Test + public void shouldSetDeviceLmtZeroForIos14Minor1AndNonZerosIfa() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("14.1") + .ifa("12345") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isZero(); + } + + @Test + public void shouldNotOverrideDeviceLmtForIos14Minor1AndNonZerosIfaWhenLmtAlreadySet() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .lmt(1) + .os("iOS") + .osv("14.1") + .ifa("12345") + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isOne(); + } + + @Test + public void shouldSetDeviceLmtZeroForIos14Minor2AndAtts0() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("14.2") + .ext(ExtDevice.of(0, null)) + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isZero(); + } + + @Test + public void shouldNotOverrideDeviceLmtForIos14Minor2AndAtts0() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .lmt(1) + .os("iOS") + .osv("14.2") + .ext(ExtDevice.of(0, null)) + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isOne(); + } + + @Test + public void shouldSetDeviceLmtOneForIos14Minor2AndAtts1() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("14.2") + .ext(ExtDevice.of(1, null)) + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isOne(); + } + + @Test + public void shouldNotOverrideDeviceLmtForIos14Minor2AndAtts1() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .lmt(0) + .os("iOS") + .osv("14.2") + .ext(ExtDevice.of(1, null)) + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isZero(); + } + + @Test + public void shouldSetDeviceLmtOneForIos15Minor0AndAtts1() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("15.0") + .ext(ExtDevice.of(1, null)) + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isOne(); + } + + @Test + public void shouldSetDeviceLmtOneForIos15Minor0AndAtts2() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("15.0") + .ext(ExtDevice.of(2, null)) + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isOne(); + } + + @Test + public void shouldNotOverrideDeviceLmtForIos14Minor2AndAtts2() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .lmt(0) + .os("iOS") + .osv("14.2") + .ext(ExtDevice.of(2, null)) + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isZero(); + } + + @Test + public void shouldSetDeviceLmtZeroForIos14Minor2AndAtts3() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("14.2") + .ext(ExtDevice.of(3, null)) + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isZero(); + } + + @Test + public void shouldNotOverrideDeviceLmtForIos14Minor2AndAtts3() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .lmt(1) + .os("iOS") + .osv("14.2") + .ext(ExtDevice.of(3, null)) + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isOne(); + } + + @Test + public void shouldNotSetDeviceLmtForIos14Minor3AndAtts4() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("14.3") + .ext(ExtDevice.of(4, null)) + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isNull(); + } + + @Test + public void shouldNotSetDeviceLmtForIos14Minor3AndAttsNull() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .device(Device.builder() + .os("iOS") + .osv("14.3") + .ext(ExtDevice.of(null, null)) + .build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getDevice().getLmt()).isNull(); + } + + @Test + public void shouldUpdateImpsWithSecurityOneIfRequestIsSecuredAndImpSecurityNotDefined() { + // given + final BidRequest bidRequest = BidRequest.builder().imp(singletonList(Imp.builder().build())).build(); + given(paramsExtractor.secureFrom(any())).willReturn(1); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getImp()).flatExtracting(Imp::getSecure).containsOnly(1); + } + + @Test + public void shouldNotUpdateImpsWithSecurityOneIfRequestIsSecureAndImpSecurityIsZero() { + // given + final List imps = singletonList(Imp.builder().secure(0).build()); + + final BidRequest bidRequest = BidRequest.builder().imp(imps).build(); + + given(paramsExtractor.secureFrom(any())).willReturn(1); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getImp()).isSameAs(imps); + } + + @Test + public void shouldUpdateImpsOnlyWithNotDefinedSecurityWithSecurityOneIfRequestIsSecure() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(Arrays.asList(Imp.builder().build(), Imp.builder().secure(0).build())) + .build(); + given(paramsExtractor.secureFrom(any())).willReturn(1); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getImp()).extracting(Imp::getSecure).containsOnly(1, 0); + } + + @Test + public void shouldNotUpdateImpsWithSecurityOneIfRequestIsNotSecureAndImpSecurityIsNotDefined() { + // given + final List imps = singletonList(Imp.builder().build()); + + final BidRequest bidRequest = BidRequest.builder().imp(imps).build(); + + given(paramsExtractor.secureFrom(any())).willReturn(0); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getImp()).isSameAs(imps); + } + + @Test + public void shouldMoveBidderParametersToImpExtPrebidBidderAndMergeWithExisting() { + // given + final List imps = singletonList( + Imp.builder() + .ext(mapper.createObjectNode() + .set("bidder1", mapper.createObjectNode().put("param1", "value1")) + .set("bidder2", mapper.createObjectNode().put("param2", "value2")) + .set("context", mapper.createObjectNode().put("data", "datavalue")) + .set("all", mapper.createObjectNode().put("all-data", "all-value")) + .set("general", mapper.createObjectNode() + .put("general-data", "general-value")) + .set("skadn", mapper.createObjectNode() + .put("skadn-data", "skadn-value")) + .set("data", mapper.createObjectNode() + .put("data-data", "data-value")) + .set("prebid", mapper.createObjectNode() + .set("bidder", mapper.createObjectNode() + .set("bidder2", mapper.createObjectNode().put("param22", "value22"))) + .set("storedresult", mapper.createObjectNode().put("id", "storedreq1")))) + .build()); + + final BidRequest bidRequest = BidRequest.builder().imp(imps).build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + final Imp expectedImp = Imp.builder() + .ext(mapper.createObjectNode() + .set("context", mapper.createObjectNode().put("data", "datavalue")) + .set("all", mapper.createObjectNode().put("all-data", "all-value")) + .set("general", mapper.createObjectNode() + .put("general-data", "general-value")) + .set("skadn", mapper.createObjectNode() + .put("skadn-data", "skadn-value")) + .set("data", mapper.createObjectNode() + .put("data-data", "data-value")) + .set("prebid", mapper.createObjectNode() + .set("bidder", mapper.createObjectNode() + .set( + "bidder1", mapper.createObjectNode().put("param1", "value1")) + .set( + "bidder2", mapper.createObjectNode() + .put("param2", "value2") + .put("param22", "value22"))) + .set("storedresult", mapper.createObjectNode().put("id", "storedreq1")))) + .build(); + + assertThat(result.getImp()).isEqualTo(singletonList(expectedImp)); + } + + @Test + public void shouldMoveBidderParametersToImpExtPrebidBidderWhenImpExtPrebidAbsent() { + // given + final List imps = singletonList( + Imp.builder() + .ext(mapper.createObjectNode() + .set("bidder1", mapper.createObjectNode().put("param1", "value1")) + .set("bidder2", mapper.createObjectNode().put("param2", "value2"))) + .build()); + + final BidRequest bidRequest = BidRequest.builder().imp(imps).build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + final Imp expectedImp = Imp.builder() + .ext(mapper.createObjectNode() + .set("prebid", mapper.createObjectNode() + .set("bidder", mapper.createObjectNode() + .set( + "bidder1", mapper.createObjectNode().put("param1", "value1")) + .set( + "bidder2", mapper.createObjectNode().put("param2", "value2"))))) + .build(); + assertThat(result.getImp()).isEqualTo(singletonList(expectedImp)); + } + + @Test + public void shouldNotChangeImpExtWhenBidderParametersAreAtImpExtPrebidBidderOnly() { + // given + final List imps = singletonList( + Imp.builder() + .ext(mapper.createObjectNode() + .set("prebid", mapper.createObjectNode() + .set("bidder", mapper.createObjectNode() + .set( + "bidder1", mapper.createObjectNode().put("param1", "value1")) + .set( + "bidder2", mapper.createObjectNode().put("param2", "value2"))))) + .build()); + + final BidRequest bidRequest = BidRequest.builder().imp(imps).build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getImp()).isSameAs(imps); + } + + @Test + public void shouldNotSetFieldsFromHeadersIfRequestFieldsNotEmpty() { + // given + final BidRequest bidRequest = BidRequest.builder() + .site(Site.builder() + .page("http://test.com") + .domain("test.com") + .publisher(Publisher.builder().domain("test.com").build()) + .ext(ExtSite.of(0, null)) + .build()) + .device(Device.builder().ua("UnitTestUA").ip("56.76.12.3").build()) + .user(User.builder().id("userId").build()) + .cur(singletonList("USD")) + .tmax(2000L) + .at(1) + .build(); + + given(ipAddressHelper.toIpAddress(eq("56.76.12.3"))) + .willReturn(IpAddress.of("56.76.12.3", IpAddress.IP.v4)); + + givenImplicitParams( + "http://anotherexample.com", "anotherexample.com", "192.168.244.2", IpAddress.IP.v4, "UnitTest2"); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result).isSameAs(bidRequest); + } + + @Test + public void shouldSetSiteExtIfNoReferer() { + // when + final BidRequest result = target.resolve(defaultBidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getSite()) + .extracting(Site::getExt) + .containsOnly(ExtSite.of(0, null)); + } + + @Test + public void shouldNotSetSitePageIfNoReferer() { + // given + final BidRequest bidRequest = BidRequest.builder() + .site(Site.builder().domain("home.com").build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getSite()).isEqualTo( + Site.builder().domain("home.com").ext(ExtSite.of(0, null)).build()); + } + + @Test + public void shouldNotSetSitePageIfDomainCouldNotBeDerived() { + // given + given(paramsExtractor.refererFrom(any())).willReturn("http://not-valid-site"); + given(paramsExtractor.domainFrom(anyString())).willThrow(new PreBidException("Couldn't derive domain")); + + // when + final BidRequest result = target.resolve(defaultBidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getSite().getPage()).isNull(); + } + + @Test + public void shouldSetDomainFromPageInsteadOfReferer() { + // given + final BidRequest bidRequest = BidRequest.builder() + .site(Site.builder().page("http://page.site.com/page1.html").build()) + .build(); + + given(paramsExtractor.refererFrom(any())).willReturn("http://any-site/referer.html"); + given(paramsExtractor.domainFrom(anyString())).willReturn("site.com"); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + verify(paramsExtractor).domainFrom(eq("page.site.com")); + + assertThat(singleton(result.getSite())) + .extracting(Site::getPage, Site::getDomain, site -> site.getPublisher().getDomain()) + .containsOnly(tuple("http://page.site.com/page1.html", "page.site.com", "site.com")); + } + + @Test + public void shouldSetSiteExtAmpIfSiteHasNoExt() { + // given + final BidRequest bidRequest = BidRequest.builder() + .site(Site.builder() + .page("http://test.com") + .domain("test.com") + .publisher(Publisher.builder().domain("test.com").build()) + .build()) + .build(); + givenImplicitParams( + "http://anotherexample.com", "anotherexample.com", "192.168.244.2", IpAddress.IP.v4, "UnitTest2"); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getSite()).isEqualTo( + Site.builder() + .page("http://test.com") + .domain("test.com") + .publisher(Publisher.builder().domain("test.com").build()) + .ext(ExtSite.of(0, null)) + .build()); + } + + @Test + public void shouldSetSiteExtAmpIfSiteExtHasNoAmp() { + // given + final BidRequest bidRequest = BidRequest.builder() + .site(Site.builder() + .page("http://test.com") + .domain("test.com") + .publisher(Publisher.builder().domain("test.com").build()) + .ext(ExtSite.of(null, null)) + .build()) + .build(); + givenImplicitParams( + "http://anotherexample.com", "anotherexample.com", "192.168.244.2", IpAddress.IP.v4, "UnitTest2"); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getSite()).isEqualTo(Site.builder() + .page("http://test.com") + .domain("test.com") + .publisher(Publisher.builder().domain("test.com").build()) + .ext(ExtSite.of(0, null)) + .build()); + } + + @Test + public void shouldSetSiteExtAmpIfNoReferer() { + // given + final BidRequest bidRequest = BidRequest.builder() + .site(Site.builder().domain("test.com").page("http://test.com").build()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getSite()).isEqualTo( + Site.builder().domain("test.com").page("http://test.com") + .ext(ExtSite.of(0, null)).build()); + } + + @Test + public void shouldSetSourceTidIfNotDefined() { + // given + given(idGenerator.generateId()).willReturn("f6965ea7-f281-4eb9-9de2-560a52d954a3"); + + final BidRequest bidRequest = BidRequest.builder().build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getSource()) + .isEqualTo(Source.builder().tid("f6965ea7-f281-4eb9-9de2-560a52d954a3").build()); + } + + @Test + public void shouldSetDefaultAtIfInitialValueIsEqualsToZero() { + // given + final BidRequest bidRequest = BidRequest.builder().at(0).build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getAt()).isEqualTo(1); + } + + @Test + public void shouldSetDefaultAtIfInitialValueIsEqualsToNull() { + // given + final BidRequest bidRequest = BidRequest.builder().at(null).build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getAt()).isEqualTo(1); + } + + @Test + public void shouldSetCurrencyIfMissedInRequestAndPresentInAdServerCurrencyConfig() { + // given + final BidRequest bidRequest = BidRequest.builder().cur(null).build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getCur()).isEqualTo(singletonList("USD")); + } + + @Test + public void shouldSetTimeoutFromTimeoutResolver() { + // given + final BidRequest bidRequest = BidRequest.builder().build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getTmax()).isEqualTo(2000L); + } + + @Test + public void shouldConvertStringPriceGranularityViewToCustom() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .targeting(ExtRequestTargeting.builder().pricegranularity(new TextNode("low")).build()) + .build())) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + // result was wrapped to list because extracting method works different on iterable and not iterable objects, + // which force to make type casting or exception handling in lambdas + assertThat(singletonList(result)) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getTargeting) + .extracting(ExtRequestTargeting::getPricegranularity) + .containsOnly(mapper.valueToTree(ExtPriceGranularity.of(2, singletonList(ExtGranularityRange.of( + BigDecimal.valueOf(5), BigDecimal.valueOf(0.5)))))); + } + + @Test + public void shouldReturnFailedFutureWithInvalidRequestExceptionWhenStringPriceGranularityInvalid() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .targeting(ExtRequestTargeting.builder().pricegranularity(new TextNode("invalid")).build()) + .build())) + .build(); + + // when and then + assertThatThrownBy(() -> target.resolve(bidRequest, routingContext, timeoutResolver)) + .isInstanceOf(InvalidRequestException.class) + .hasMessage("Invalid string price granularity with value: invalid"); + } + + @Test + public void shouldSetDefaultPriceGranularityIfPriceGranularityAndMediaTypePriceGranularityIsMissing() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().video(Video.builder().build()).ext(mapper.createObjectNode()).build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .targeting(ExtRequestTargeting.builder().build()) + .build())) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(singletonList(result)) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getTargeting) + .extracting(ExtRequestTargeting::getPricegranularity) + .containsOnly(mapper.valueToTree(ExtPriceGranularity.of(2, singletonList(ExtGranularityRange.of( + BigDecimal.valueOf(20), BigDecimal.valueOf(0.1)))))); + } + + @Test + public void shouldNotSetDefaultPriceGranularityIfThereIsAMediaTypePriceGranularityForImpType() { + // given + final ExtMediaTypePriceGranularity mediaTypePriceGranularity = ExtMediaTypePriceGranularity.of( + mapper.valueToTree(ExtPriceGranularity.of(2, singletonList(ExtGranularityRange.of( + BigDecimal.valueOf(20), BigDecimal.valueOf(0.1))))), null, null); + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().banner(Banner.builder().build()) + .ext(mapper.createObjectNode()).build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .targeting(ExtRequestTargeting.builder() + .mediatypepricegranularity(mediaTypePriceGranularity) + .build()) + .build())) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(singletonList(result)) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getTargeting) + .extracting(ExtRequestTargeting::getPricegranularity) + .containsOnly((JsonNode) null); + } + + @Test + public void shouldSetDefaultIncludeWinnersIfIncludeWinnersIsMissed() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .targeting(ExtRequestTargeting.builder().build()) + .build())) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(singletonList(result)) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getTargeting) + .extracting(ExtRequestTargeting::getIncludewinners) + .containsOnly(true); + } + + @Test + public void shouldSetDefaultIncludeBidderKeysIfIncludeBidderKeysIsMissed() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .targeting(ExtRequestTargeting.builder().build()) + .build())) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(singletonList(result)) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getTargeting) + .extracting(ExtRequestTargeting::getIncludebidderkeys) + .containsOnly(true); + } + + @Test + public void shouldSetDefaultIncludeBidderKeysToFalseIfIncludeBidderKeysIsMissedAndWinningonlyIsTrue() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .targeting(ExtRequestTargeting.builder().build()) + .cache(ExtRequestPrebidCache.of(null, null, true)) + .build())) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(singletonList(result)) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getTargeting) + .extracting(ExtRequestTargeting::getIncludebidderkeys) + .containsOnly(false); + } + + @Test + public void shouldSetDefaultIncludeBidderKeysToFalseIfIncludeBidderKeysIsMissedAndWinningonlyIsTrueInConfig() { + // given + target = new Ortb2ImplicitParametersResolver( + true, + "USD", + BLACKLISTED_APPS, + paramsExtractor, + ipAddressHelper, + idGenerator, + jacksonMapper); + + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .targeting(ExtRequestTargeting.builder().build()) + .build())) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getExt()) + .extracting(extBidRequest -> extBidRequest.getPrebid().getTargeting().getIncludebidderkeys()) + .containsOnly(false); + } + + @Test + public void shouldSetCacheWinningonlyFromConfigWhenExtRequestPrebidIsNull() { + // given + target = new Ortb2ImplicitParametersResolver( + true, + "USD", + BLACKLISTED_APPS, + paramsExtractor, + ipAddressHelper, + idGenerator, + jacksonMapper); + + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) + .ext(ExtRequest.empty()) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(singletonList(result)) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getCache) + .extracting(ExtRequestPrebidCache::getWinningonly) + .containsOnly(true); + } + + @Test + public void shouldSetCacheWinningonlyFromConfigWhenExtRequestPrebidCacheIsNull() { + // given + target = new Ortb2ImplicitParametersResolver( + true, + "USD", + BLACKLISTED_APPS, + paramsExtractor, + ipAddressHelper, + idGenerator, + jacksonMapper); + + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder().build())) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(singletonList(result)) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getCache) + .extracting(ExtRequestPrebidCache::getWinningonly) + .containsOnly(true); + } + + @Test + public void shouldSetCacheWinningonlyFromConfigWhenCacheWinningonlyIsNull() { + // given + target = new Ortb2ImplicitParametersResolver( + true, + "USD", + BLACKLISTED_APPS, + paramsExtractor, + ipAddressHelper, + idGenerator, + jacksonMapper); + + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .cache(ExtRequestPrebidCache.of(null, null, null)) + .build())) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(singletonList(result)) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getCache) + .extracting(ExtRequestPrebidCache::getWinningonly) + .containsOnly(true); + } + + @Test + public void shouldNotChangeAnyOtherExtRequestPrebidCacheFields() { + // given + final ExtRequestPrebidCacheBids cacheBids = ExtRequestPrebidCacheBids.of(100, true); + final ExtRequestPrebidCacheVastxml cacheVastxml = ExtRequestPrebidCacheVastxml.of(100, true); + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .cache(ExtRequestPrebidCache.of(cacheBids, cacheVastxml, null)) + .build())) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(singletonList(result)) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getCache) + .extracting(ExtRequestPrebidCache::getBids, ExtRequestPrebidCache::getVastxml) + .containsOnly(tuple(cacheBids, cacheVastxml)); + } + + @Test + public void shouldNotChangeAnyOtherExtRequestPrebidTargetingFields() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .targeting(ExtRequestTargeting.builder() + .includebrandcategory(ExtIncludeBrandCategory.of(1, "publisher", true)) + .truncateattrchars(10) + .build()) + .build())) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(singletonList(result)) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getTargeting) + .extracting(ExtRequestTargeting::getIncludebrandcategory, ExtRequestTargeting::getTruncateattrchars) + .containsOnly(tuple(ExtIncludeBrandCategory.of(1, "publisher", true), 10)); + } + + @Test + public void shouldSetCacheWinningonlyFromRequestWhenCacheWinningonlyIsPresent() { + // given + target = new Ortb2ImplicitParametersResolver( + true, + "USD", + BLACKLISTED_APPS, + paramsExtractor, + ipAddressHelper, + idGenerator, + jacksonMapper); + + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .cache(ExtRequestPrebidCache.of(null, null, false)) + .build())) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(singletonList(result)) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getCache) + .extracting(ExtRequestPrebidCache::getWinningonly) + .containsOnly(false); + } + + @Test + public void shouldNotSetCacheWinningonlyFromConfigWhenCacheWinningonlyIsNullAndConfigValueIsFalse() { + // given + final ExtRequest extBidRequest = ExtRequest.of(ExtRequestPrebid.builder() + .cache(ExtRequestPrebidCache.of(null, null, null)) + .build()); + + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) + .ext(extBidRequest) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(result.getExt()).isSameAs(extBidRequest); + } + + @Test + public void shouldSetRequestPrebidChannelWhenMissingInRequestAndSite() { + // given + final BidRequest bidRequest = BidRequest.builder() + .site(Site.builder().build()) + .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder().build())) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(singletonList(result)) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getChannel) + .containsOnly(ExtRequestPrebidChannel.of("web")); + } + + @Test + public void shouldSetRequestPrebidChannelWhenMissingInRequestAndApp() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder().build())) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(singletonList(result)) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getChannel) + .containsOnly(ExtRequestPrebidChannel.of("app")); + } + + @Test + public void shouldNotSetRequestPrebidChannelWhenMissingInRequestAndNotSiteOrApp() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder().build())) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(singletonList(result)) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getChannel) + .containsOnly((ExtRequestPrebidChannel) null); + } + + @Test + public void shouldNotSetRequestPrebidChannelWhenPresentInRequestAndApp() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().build()) + .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .channel(ExtRequestPrebidChannel.of("custom")) + .build())) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(singletonList(result)) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getChannel) + .containsOnly(ExtRequestPrebidChannel.of("custom")); + } + + @Test + public void shouldPassExtPrebidDebugFlagIfPresent() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) + .ext(ExtRequest.of(ExtRequestPrebid.builder() + .debug(1) + .build())) + .build(); + + // when + final BidRequest result = target.resolve(bidRequest, routingContext, timeoutResolver); + + // then + assertThat(singletonList(result)) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getDebug) + .containsOnly(1); + } + + @Test + public void shouldReturnFailedFutureWhenAppIdIsBlacklisted() { + // given + final BidRequest bidRequest = BidRequest.builder() + .app(App.builder().id("bad_app").build()) + .build(); + + // when and then + assertThatExceptionOfType(BlacklistedAppException.class) + .isThrownBy(() -> target.resolve(bidRequest, routingContext, timeoutResolver)) + .withMessage("Prebid-server does not process requests from App ID: bad_app"); + } + + private void givenImplicitParams(String referer, String domain, String ip, IpAddress.IP ipVersion, String ua) { + given(paramsExtractor.refererFrom(any())).willReturn(referer); + given(paramsExtractor.domainFrom(anyString())).willReturn(domain); + given(paramsExtractor.ipFrom(any())).willReturn(singletonList(ip)); + given(ipAddressHelper.toIpAddress(eq(ip))).willReturn(IpAddress.of(ip, ipVersion)); + given(paramsExtractor.uaFrom(any())).willReturn(ua); + } +} diff --git a/src/test/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactoryTest.java b/src/test/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactoryTest.java new file mode 100644 index 00000000000..62d51923380 --- /dev/null +++ b/src/test/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactoryTest.java @@ -0,0 +1,688 @@ +package org.prebid.server.auction.requestfactory; + +import com.iab.openrtb.request.App; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Device; +import com.iab.openrtb.request.Geo; +import com.iab.openrtb.request.Publisher; +import com.iab.openrtb.request.Site; +import io.vertx.core.Future; +import io.vertx.core.http.CaseInsensitiveHeaders; +import io.vertx.core.http.HttpServerRequest; +import io.vertx.ext.web.RoutingContext; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.prebid.server.VertxTest; +import org.prebid.server.auction.IpAddressHelper; +import org.prebid.server.auction.StoredRequestProcessor; +import org.prebid.server.auction.TimeoutResolver; +import org.prebid.server.auction.model.AuctionContext; +import org.prebid.server.auction.model.IpAddress; +import org.prebid.server.cookie.UidsCookie; +import org.prebid.server.cookie.UidsCookieService; +import org.prebid.server.cookie.proto.Uids; +import org.prebid.server.exception.BlacklistedAccountException; +import org.prebid.server.exception.InvalidRequestException; +import org.prebid.server.exception.PreBidException; +import org.prebid.server.exception.UnauthorizedAccountException; +import org.prebid.server.execution.Timeout; +import org.prebid.server.execution.TimeoutFactory; +import org.prebid.server.geolocation.model.GeoInfo; +import org.prebid.server.metric.MetricName; +import org.prebid.server.privacy.ccpa.Ccpa; +import org.prebid.server.privacy.gdpr.model.TcfContext; +import org.prebid.server.privacy.model.Privacy; +import org.prebid.server.privacy.model.PrivacyContext; +import org.prebid.server.proto.openrtb.ext.request.ExtPublisher; +import org.prebid.server.proto.openrtb.ext.request.ExtPublisherPrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; +import org.prebid.server.settings.ApplicationSettings; +import org.prebid.server.settings.model.Account; +import org.prebid.server.settings.model.AccountStatus; +import org.prebid.server.validation.RequestValidator; +import org.prebid.server.validation.model.ValidationResult; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.UnaryOperator; + +import static java.util.Collections.emptyMap; +import static java.util.Collections.singleton; +import static java.util.Collections.singletonList; +import static java.util.function.UnaryOperator.identity; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.tuple; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; + +public class Ortb2RequestFactoryTest extends VertxTest { + + private static final List BLACKLISTED_ACCOUNTS = singletonList("321"); + + @Rule + public final MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Mock + private UidsCookieService uidsCookieService; + @Mock + private RequestValidator requestValidator; + @Mock + private TimeoutResolver timeoutResolver; + @Mock + private TimeoutFactory timeoutFactory; + @Mock + private StoredRequestProcessor storedRequestProcessor; + @Mock + private ApplicationSettings applicationSettings; + @Mock + private IpAddressHelper ipAddressHelper; + + private Ortb2RequestFactory target; + + @Mock + private RoutingContext routingContext; + @Mock + private HttpServerRequest httpRequest; + @Mock + private Timeout timeout; + + private BidRequest defaultBidRequest; + + @Before + public void setUp() { + defaultBidRequest = BidRequest.builder().build(); + + given(routingContext.request()).willReturn(httpRequest); + given(httpRequest.headers()).willReturn(new CaseInsensitiveHeaders()); + + given(timeoutResolver.resolve(any())).willReturn(2000L); + given(timeoutResolver.adjustTimeout(anyLong())).willReturn(1900L); + + target = new Ortb2RequestFactory( + false, + BLACKLISTED_ACCOUNTS, + uidsCookieService, + requestValidator, + timeoutResolver, + timeoutFactory, + storedRequestProcessor, + applicationSettings, + ipAddressHelper); + } + + @Test + public void shouldReturnFailedFutureIfAccountIsEnforcedAndIdIsNotProvided() { + // given + target = new Ortb2RequestFactory( + true, + BLACKLISTED_ACCOUNTS, + uidsCookieService, + requestValidator, + timeoutResolver, + timeoutFactory, + storedRequestProcessor, + applicationSettings, + ipAddressHelper); + + // when + final Future result = target.fetchAccountAndCreateAuctionContext(routingContext, defaultBidRequest, null, + false, 2000, new ArrayList<>()); + + // then + verify(applicationSettings, never()).getAccountById(any(), any()); + + assertThat(result.failed()).isTrue(); + assertThat(result.cause()) + .isInstanceOf(UnauthorizedAccountException.class) + .hasMessage("Unauthorized account id: "); + } + + @Test + public void shouldReturnFailedFutureIfAccountIsEnforcedAndFailedGetAccountById() { + // given + target = new Ortb2RequestFactory( + true, + BLACKLISTED_ACCOUNTS, + uidsCookieService, + requestValidator, + timeoutResolver, + timeoutFactory, + storedRequestProcessor, + applicationSettings, + ipAddressHelper); + + given(applicationSettings.getAccountById(any(), any())) + .willReturn(Future.failedFuture(new PreBidException("Not found"))); + + final String accountId = "absentId"; + final BidRequest bidRequest = givenBidRequest(builder -> builder + .app(App.builder() + .publisher(Publisher.builder().id(accountId).build()) + .build())); + + // when + final Future result = target.fetchAccountAndCreateAuctionContext(routingContext, bidRequest, null, + false, 2000, new ArrayList<>()); + + // then + verify(applicationSettings).getAccountById(eq(accountId), any()); + + assertThat(result.failed()).isTrue(); + assertThat(result.cause()) + .isInstanceOf(UnauthorizedAccountException.class) + .hasMessage("Unauthorized account id: absentId"); + } + + @Test + public void shouldReturnFailedFutureIfAccountIsInactive() { + // given + final String accountId = "accountId"; + final BidRequest bidRequest = givenBidRequest(builder -> builder + .app(App.builder() + .publisher(Publisher.builder().id(accountId).build()) + .build())); + + given(applicationSettings.getAccountById(any(), any())) + .willReturn(Future.succeededFuture(Account.builder() + .id(accountId) + .status(AccountStatus.inactive) + .build())); + + // when + final Future result = target.fetchAccountAndCreateAuctionContext(routingContext, bidRequest, + null, false, 2000, new ArrayList<>()); + + // then + assertThat(result.failed()).isTrue(); + assertThat(result.cause()) + .isInstanceOf(UnauthorizedAccountException.class) + .hasMessage("Account accountId is inactive"); + } + + @Test + public void shouldReturnFailedFutureWhenAccountIdIsBlacklisted() { + // given + final BidRequest bidRequest = givenBidRequest(builder -> builder + .site(Site.builder() + .publisher(Publisher.builder().id("321").build()) + .build())); + + // when + final Future result = target.fetchAccountAndCreateAuctionContext(routingContext, bidRequest, + null, + false, 2000, new ArrayList<>()); + + // then + assertThat(result.failed()).isTrue(); + assertThat(result.cause()) + .isInstanceOf(BlacklistedAccountException.class) + .hasMessage("Prebid-server has blacklisted Account ID: 321, please reach out to the prebid " + + "server host."); + } + + @Test + public void shouldReturnAuctionContextWithAccountIdTakenFromPublisherExt() { + // given + final String parentAccount = "parentAccount"; + final BidRequest bidRequest = givenBidRequest(builder -> builder + .site(Site.builder() + .publisher(Publisher.builder().id("accountId") + .ext(ExtPublisher.of(ExtPublisherPrebid.of(parentAccount))) + .build()) + .build())); + + final Account account = Account.builder().id(parentAccount).build(); + given(applicationSettings.getAccountById(any(), any())) + .willReturn(Future.succeededFuture(account)); + + // when + final Future result = target.fetchAccountAndCreateAuctionContext(routingContext, bidRequest, + null, false, 2000, new ArrayList<>()); + + // then + verify(applicationSettings).getAccountById(eq(parentAccount), any()); + + assertThat(result.result().getAccount()).isSameAs(account); + } + + @Test + public void shouldReturnAuctionContextWithAccountIdTakenFromPublisherIdWhenExtIsNull() { + // given + final String accountId = "accountId"; + final BidRequest bidRequest = givenBidRequest(builder -> builder + .site(Site.builder() + .publisher(Publisher.builder().id(accountId).ext(null).build()) + .build())); + + final Account account = Account.builder().id(accountId).build(); + given(applicationSettings.getAccountById(any(), any())).willReturn(Future.succeededFuture(account)); + + // when + final Future result = target.fetchAccountAndCreateAuctionContext(routingContext, bidRequest, + null, false, 2000, new ArrayList<>()); + + // then + verify(applicationSettings).getAccountById(eq(accountId), any()); + + assertThat(result.result().getAccount()).isSameAs(account); + } + + @Test + public void shouldReturnAuctionContextWithAccountIdTakenFromPublisherIdWhenExtPublisherPrebidIsNull() { + // given + final String accountId = "accountId"; + final BidRequest bidRequest = givenBidRequest(builder -> builder + .site(Site.builder() + .publisher(Publisher.builder().id(accountId) + .ext(ExtPublisher.empty()) + .build()) + .build())); + + final Account account = Account.builder().id(accountId).build(); + given(applicationSettings.getAccountById(any(), any())).willReturn(Future.succeededFuture(account)); + + // when + final Future result = target.fetchAccountAndCreateAuctionContext(routingContext, bidRequest, + null, false, 2000, new ArrayList<>()); + + // then + verify(applicationSettings).getAccountById(eq(accountId), any()); + + assertThat(result.result().getAccount()).isSameAs(account); + } + + @Test + public void shouldReturnAuctionContextWithAccountIdTakenFromPublisherIdWhenExtParentIsEmpty() { + // given + final BidRequest bidRequest = givenBidRequest(builder -> builder + .site(Site.builder() + .publisher(Publisher.builder().id("accountId") + .ext(ExtPublisher.of(ExtPublisherPrebid.of(""))) + .build()) + .build())); + + final Account account = Account.builder().id("accountId").build(); + given(applicationSettings.getAccountById(any(), any())) + .willReturn(Future.succeededFuture(account)); + + // when + final Future result = target.fetchAccountAndCreateAuctionContext(routingContext, bidRequest, + null, false, 2000, new ArrayList<>()); + + // then + verify(applicationSettings).getAccountById(eq("accountId"), any()); + + assertThat(result.result().getAccount()).isSameAs(account); + } + + @Test + public void shouldReturnAuctionContextWithEmptyAccountIfNotFound() { + // given + final String parentAccount = "parentAccount"; + final BidRequest bidRequest = givenBidRequest(builder -> builder + .site(Site.builder() + .publisher(Publisher.builder().id("accountId") + .ext(ExtPublisher.of(ExtPublisherPrebid.of(parentAccount))) + .build()) + .build())); + + given(applicationSettings.getAccountById(any(), any())) + .willReturn(Future.failedFuture(new PreBidException("not found"))); + + // when + final Future result = target.fetchAccountAndCreateAuctionContext(routingContext, bidRequest, + null, false, 2000, new ArrayList<>()); + + // then + verify(applicationSettings).getAccountById(eq(parentAccount), any()); + + assertThat(result.result().getAccount()).isEqualTo(Account.empty(parentAccount)); + } + + @Test + public void shouldReturnAuctionContextWithEmptyAccountIfExceptionOccurred() { + // given + final String accountId = "accountId"; + final BidRequest bidRequest = givenBidRequest(builder -> builder + .site(Site.builder() + .publisher(Publisher.builder().id(accountId).build()) + .build())); + + given(applicationSettings.getAccountById(any(), any())) + .willReturn(Future.failedFuture(new RuntimeException("error"))); + + // when + final Future result = target.fetchAccountAndCreateAuctionContext(routingContext, bidRequest, + null, false, 2000, new ArrayList<>()); + + // then + verify(applicationSettings).getAccountById(eq(accountId), any()); + + assertThat(result.result().getAccount()).isEqualTo(Account.empty(accountId)); + } + + @Test + public void shouldReturnAuctionContextWithEmptyAccountIfItIsMissingInRequest() { + // given + final BidRequest bidRequest = givenBidRequest(identity()); + + given(applicationSettings.getAccountById(any(), any())) + .willReturn(Future.failedFuture(new RuntimeException("error"))); + + // when + final Future result = target.fetchAccountAndCreateAuctionContext(routingContext, bidRequest, + null, false, 2000, new ArrayList<>()); + + // then + verifyZeroInteractions(applicationSettings); + + assertThat(result.result().getAccount()).isEqualTo(Account.empty("")); + } + + @Test + public void shouldFetchAccountFromStoredIfStoredLookupIsTrueAndAccountIsNotFoundPreviously() { + // given + final BidRequest receivedBidRequest = givenBidRequest(identity()); + + final String accountId = "accountId"; + final BidRequest mergedBidRequest = givenBidRequest(builder -> builder + .site(Site.builder() + .publisher(Publisher.builder().id(accountId).build()) + .build())); + + given(storedRequestProcessor.processStoredRequests(any(), any())) + .willReturn(Future.succeededFuture(mergedBidRequest)); + + final Account fetchedAccount = Account.builder().id(accountId).status(AccountStatus.active).build(); + given(applicationSettings.getAccountById(any(), any())) + .willReturn(Future.succeededFuture(fetchedAccount)); + + // when + final Future result = target.fetchAccountAndCreateAuctionContext(routingContext, + receivedBidRequest, null, true, 2000, new ArrayList<>()); + + // then + verify(storedRequestProcessor).processStoredRequests("", receivedBidRequest); + verify(applicationSettings).getAccountById(eq(accountId), any()); + + assertThat(result.result().getAccount()).isEqualTo(fetchedAccount); + } + + @Test + public void shouldFetchAccountFromStoredAndReturnFailedFutureWhenAccountIdIsBlacklisted() { + // given + final BidRequest receivedBidRequest = givenBidRequest(identity()); + + final BidRequest mergedBidRequest = givenBidRequest(builder -> builder + .site(Site.builder() + .publisher(Publisher.builder().id("321").build()).build())); + + given(storedRequestProcessor.processStoredRequests(any(), any())) + .willReturn(Future.succeededFuture(mergedBidRequest)); + + // when + final Future result = target.fetchAccountAndCreateAuctionContext(routingContext, + receivedBidRequest, null, true, 2000, new ArrayList<>()); + + // then + verify(storedRequestProcessor).processStoredRequests("", receivedBidRequest); + verifyZeroInteractions(applicationSettings); + + assertThat(result.failed()).isTrue(); + assertThat(result.cause()) + .isInstanceOf(BlacklistedAccountException.class) + .hasMessage("Prebid-server has blacklisted Account ID: 321, please reach out to the prebid " + + "server host."); + } + + @Test + public void shouldFetchAccountFromStoredAndReturnFailedFutureIfValidIsEnforcedAndStoredLookupIsFailed() { + // given + target = new Ortb2RequestFactory( + true, + BLACKLISTED_ACCOUNTS, + uidsCookieService, + requestValidator, + timeoutResolver, + timeoutFactory, + storedRequestProcessor, + applicationSettings, + ipAddressHelper); + + final BidRequest receivedBidRequest = givenBidRequest(identity()); + given(storedRequestProcessor.processStoredRequests(any(), any())) + .willReturn(Future.failedFuture(new RuntimeException("error"))); + + // when + final Future result = target.fetchAccountAndCreateAuctionContext(routingContext, + receivedBidRequest, null, true, 2000, new ArrayList<>()); + + // then + verify(storedRequestProcessor).processStoredRequests("", receivedBidRequest); + verifyZeroInteractions(applicationSettings); + + assertThat(result.failed()).isTrue(); + assertThat(result.cause()).hasMessage("error"); + } + + @Test + public void shouldFetchAccountFromStoredAndReturnEmptyAccountIfStoredLookupIsFailed() { + // given + final BidRequest receivedBidRequest = givenBidRequest(identity()); + given(storedRequestProcessor.processStoredRequests(any(), any())) + .willReturn(Future.failedFuture(new RuntimeException("error"))); + + // when + final Future result = target.fetchAccountAndCreateAuctionContext(routingContext, + receivedBidRequest, null, true, 2000, new ArrayList<>()); + + // then + verify(storedRequestProcessor).processStoredRequests("", receivedBidRequest); + verifyZeroInteractions(applicationSettings); + + assertThat(result.failed()).isTrue(); + assertThat(result.cause()).hasMessage("error"); + } + + @Test + public void shouldReturnExpectedAuctionContext() { + // given + final String accountId = "123"; + final long tmax = 1000L; + final BidRequest bidRequest = givenBidRequest(builder -> builder + .app(App.builder() + .publisher(Publisher.builder().id(accountId).build()) + .build()) + .tmax(tmax)); + + final Account account = Account.builder() + .id(accountId) + .status(AccountStatus.active) + .build(); + given(applicationSettings.getAccountById(any(), any())).willReturn(Future.succeededFuture(account)); + + final long resolvedTimeout = 200L; + final long adjustedTimeout = 250L; + given(timeoutResolver.resolve(anyLong())).willReturn(resolvedTimeout); + given(timeoutResolver.adjustTimeout(anyLong())).willReturn(adjustedTimeout); + given(timeoutFactory.create(anyLong(), anyLong())).willReturn(timeout); + + final UidsCookie uidsCookie = new UidsCookie(Uids.builder().uids(emptyMap()).build(), jacksonMapper); + given(uidsCookieService.parseFromRequest(any())).willReturn(uidsCookie); + + final int startTime = 100; + final MetricName metricName = MetricName.openrtb2app; + final ArrayList errors = new ArrayList<>(); + + // when + final Future future = target.fetchAccountAndCreateAuctionContext(routingContext, bidRequest, + metricName, false, startTime, errors); + + // then + verify(timeoutResolver).resolve(tmax); + verify(timeoutResolver).adjustTimeout(resolvedTimeout); + verify(timeoutFactory).create(startTime, adjustedTimeout); + + verify(applicationSettings).getAccountById(accountId, timeout); + verify(uidsCookieService).parseFromRequest(routingContext); + + final AuctionContext expectedAuctionContext = AuctionContext.builder() + .routingContext(routingContext) + .uidsCookie(uidsCookie) + .bidRequest(bidRequest) + .requestTypeMetric(metricName) + .timeout(timeout) + .account(account) + .prebidErrors(errors) + .debugWarnings(new ArrayList<>()) + .build(); + assertThat(future.succeeded()).isTrue(); + assertThat(future.result()).isEqualTo(expectedAuctionContext); + } + + @Test + public void validateRequestShouldThrowInvalidRequestExceptionIfRequestIsInvalid() { + // given + given(requestValidator.validate(any())).willReturn(ValidationResult.error("error")); + + final BidRequest bidRequest = givenBidRequest(identity()); + + // when and then + assertThatExceptionOfType(InvalidRequestException.class) + .isThrownBy(() -> target.validateRequest(bidRequest)) + .withMessage("error"); + + verify(requestValidator).validate(bidRequest); + } + + @Test + public void validateRequestShouldReturnSameBidRequest() { + // given + given(requestValidator.validate(any())).willReturn(ValidationResult.success()); + + final BidRequest bidRequest = givenBidRequest(identity()); + + // when + final BidRequest result = target.validateRequest(bidRequest); + + // then + verify(requestValidator).validate(bidRequest); + + assertThat(result).isSameAs(bidRequest); + } + + @Test + public void enrichBidRequestWithAccountAndPrivacyDataShouldReturnIntegrationFromAccount() { + // given + final String accountId = "accId"; + final BidRequest bidRequest = givenBidRequest(builder -> builder + .imp(new ArrayList<>()) + .site(Site.builder() + .publisher(Publisher.builder().id(accountId).build()) + .build()) + .ext(ExtRequest.of(ExtRequestPrebid.builder().build()))); + + final PrivacyContext privacyContext = PrivacyContext.of( + Privacy.of("", "", Ccpa.EMPTY, 0), + TcfContext.empty(), + "ip"); + + final String integration = "integration"; + final Account account = Account.builder().id(accountId).defaultIntegration(integration).build(); + given(applicationSettings.getAccountById(any(), any())).willReturn(Future.succeededFuture(account)); + + // when + final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(bidRequest, account, privacyContext); + + // then + assertThat(result) + .extracting(auctionBidRequest -> auctionBidRequest.getExt().getPrebid().getIntegration()) + .containsOnly(integration); + } + + @Test + public void enrichBidRequestWithAccountAndPrivacyDataShouldAddCountryFromPrivacy() { + // given + final BidRequest bidRequest = givenBidRequest(identity()); + final PrivacyContext privacyContext = PrivacyContext.of( + Privacy.of("", "", Ccpa.EMPTY, 0), + TcfContext.builder() + .geoInfo(GeoInfo.builder().vendor("v").country("ua").build()) + .build(), + null); + + final Account account = Account.empty("id"); + + // when + final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(bidRequest, account, privacyContext); + + // then + assertThat(singleton(result)) + .extracting(BidRequest::getDevice) + .extracting(Device::getGeo) + .extracting(Geo::getCountry) + .containsOnly("ua"); + } + + @Test + public void enrichBidRequestWithAccountAndPrivacyDataShouldAddIpAddressV4FromPrivacy() { + // given + given(ipAddressHelper.toIpAddress(anyString())).willReturn(IpAddress.of("ignored", IpAddress.IP.v4)); + + final BidRequest bidRequest = givenBidRequest(identity()); + final PrivacyContext privacyContext = PrivacyContext.of( + Privacy.of("", "", Ccpa.EMPTY, 0), + TcfContext.builder().build(), + "ipv4"); + + final Account account = Account.empty("id"); + + // when + final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(bidRequest, account, privacyContext); + + // then + assertThat(singleton(result)) + .extracting(BidRequest::getDevice) + .extracting(Device::getIp, Device::getIpv6) + .containsOnly(tuple("ipv4", null)); + } + + @Test + public void enrichBidRequestWithAccountAndPrivacyDataShouldAddIpAddressV6FromPrivacy() { + // given + given(ipAddressHelper.toIpAddress(anyString())).willReturn(IpAddress.of("ignored", IpAddress.IP.v6)); + + final BidRequest bidRequest = givenBidRequest(identity()); + final PrivacyContext privacyContext = PrivacyContext.of( + Privacy.of("", "", Ccpa.EMPTY, 0), + TcfContext.builder().build(), + "ipv6"); + + final Account account = Account.empty("id"); + + // when + final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(bidRequest, account, privacyContext); + + // then + assertThat(singleton(result)) + .extracting(BidRequest::getDevice) + .extracting(Device::getIp, Device::getIpv6) + .containsOnly(tuple(null, "ipv6")); + } + + private static BidRequest givenBidRequest(UnaryOperator requestCustomizer) { + return requestCustomizer.apply(BidRequest.builder()).build(); + } +} diff --git a/src/test/java/org/prebid/server/auction/VideoRequestFactoryTest.java b/src/test/java/org/prebid/server/auction/requestfactory/VideoRequestFactoryTest.java similarity index 64% rename from src/test/java/org/prebid/server/auction/VideoRequestFactoryTest.java rename to src/test/java/org/prebid/server/auction/requestfactory/VideoRequestFactoryTest.java index 12e9c997341..2139b9a6320 100644 --- a/src/test/java/org/prebid/server/auction/VideoRequestFactoryTest.java +++ b/src/test/java/org/prebid/server/auction/requestfactory/VideoRequestFactoryTest.java @@ -1,4 +1,4 @@ -package org.prebid.server.auction; +package org.prebid.server.auction.requestfactory; import com.fasterxml.jackson.core.JsonProcessingException; import com.iab.openrtb.request.BidRequest; @@ -11,7 +11,6 @@ import com.iab.openrtb.request.video.BidRequestVideo; import com.iab.openrtb.request.video.PodError; import io.vertx.core.Future; -import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpServerRequest; import io.vertx.ext.web.RoutingContext; import org.junit.Before; @@ -20,11 +19,20 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; +import org.mockito.stubbing.Answer; import org.prebid.server.VertxTest; +import org.prebid.server.auction.PriceGranularity; +import org.prebid.server.auction.PrivacyEnforcementService; +import org.prebid.server.auction.TimeoutResolver; +import org.prebid.server.auction.VideoStoredRequestProcessor; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.WithPodErrors; import org.prebid.server.exception.InvalidRequestException; import org.prebid.server.metric.MetricName; +import org.prebid.server.privacy.ccpa.Ccpa; +import org.prebid.server.privacy.gdpr.model.TcfContext; +import org.prebid.server.privacy.model.Privacy; +import org.prebid.server.privacy.model.PrivacyContext; import org.prebid.server.proto.openrtb.ext.ExtIncludeBrandCategory; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; @@ -35,12 +43,14 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import static java.util.Collections.emptySet; import static java.util.Collections.singletonList; +import static org.apache.commons.lang3.StringUtils.EMPTY; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -52,13 +62,16 @@ public class VideoRequestFactoryTest extends VertxTest { @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock + private Ortb2RequestFactory ortb2RequestFactory; + @Mock + private Ortb2ImplicitParametersResolver paramsResolver; @Mock private VideoStoredRequestProcessor videoStoredRequestProcessor; - @Mock - private AuctionRequestFactory auctionRequestFactory; + private PrivacyEnforcementService privacyEnforcementService; - private VideoRequestFactory factory; + private VideoRequestFactory target; @Mock private RoutingContext routingContext; @@ -72,11 +85,19 @@ public void setUp() { given(routingContext.request()).willReturn(httpServerRequest); given(httpServerRequest.getParam(anyString())).willReturn("test"); - factory = new VideoRequestFactory( + final PrivacyContext defaultPrivacyContext = PrivacyContext.of( + Privacy.of("0", EMPTY, Ccpa.EMPTY, 0), + TcfContext.empty()); + given(privacyEnforcementService.contextFromBidRequest(any())) + .willReturn(Future.succeededFuture(defaultPrivacyContext)); + + target = new VideoRequestFactory( Integer.MAX_VALUE, false, + ortb2RequestFactory, + paramsResolver, videoStoredRequestProcessor, - auctionRequestFactory, + privacyEnforcementService, timeoutResolver, jacksonMapper); } @@ -87,7 +108,7 @@ public void shouldReturnFailedFutureIfRequestBodyIsMissing() { given(routingContext.getBody()).willReturn(null); // when - final Future future = factory.fromRequest(routingContext, 0L); + final Future future = target.fromRequest(routingContext, 0L); // then assertThat(future.failed()).isTrue(); @@ -99,19 +120,21 @@ public void shouldReturnFailedFutureIfRequestBodyIsMissing() { @Test public void shouldReturnFailedFutureIfStoredRequestIsEnforcedAndIdIsNotProvided() throws JsonProcessingException { // given - given(routingContext.getBody()) - .willReturn(Buffer.buffer(mapper.writeValueAsBytes(BidRequestVideo.builder().build()))); + given(routingContext.getBodyAsString()) + .willReturn(mapper.writeValueAsString(BidRequestVideo.builder().build())); given(routingContext.request().getHeader(HttpUtil.USER_AGENT_HEADER)).willReturn("123"); - factory = new VideoRequestFactory( + target = new VideoRequestFactory( Integer.MAX_VALUE, true, + ortb2RequestFactory, + paramsResolver, videoStoredRequestProcessor, - auctionRequestFactory, + privacyEnforcementService, timeoutResolver, jacksonMapper); // when - final Future future = factory.fromRequest(routingContext, 0L); + final Future future = target.fromRequest(routingContext, 0L); // then assertThat(future.failed()).isTrue(); @@ -123,18 +146,20 @@ public void shouldReturnFailedFutureIfStoredRequestIsEnforcedAndIdIsNotProvided( @Test public void shouldReturnFailedFutureIfRequestBodyExceedsMaxRequestSize() { // given - factory = new VideoRequestFactory( + target = new VideoRequestFactory( 2, true, + ortb2RequestFactory, + paramsResolver, videoStoredRequestProcessor, - auctionRequestFactory, + privacyEnforcementService, timeoutResolver, jacksonMapper); - given(routingContext.getBody()).willReturn(Buffer.buffer("body")); + given(routingContext.getBodyAsString()).willReturn("body"); // when - final Future future = factory.fromRequest(routingContext, 0L); + final Future future = target.fromRequest(routingContext, 0L); // then assertThat(future.failed()).isTrue(); @@ -146,10 +171,10 @@ public void shouldReturnFailedFutureIfRequestBodyExceedsMaxRequestSize() { @Test public void shouldReturnFailedFutureIfRequestBodyCouldNotBeParsed() { // given - given(routingContext.getBody()).willReturn(Buffer.buffer("body")); + given(routingContext.getBodyAsString()).willReturn("body"); // when - final Future future = factory.fromRequest(routingContext, 0L); + final Future future = target.fromRequest(routingContext, 0L); // then assertThat(future.failed()).isTrue(); @@ -201,39 +226,34 @@ public void shouldReturnExpectedResultAndReturnErrors() throws JsonProcessingExc .ext(ExtRequest.of(ext)) .build(); - final WithPodErrors mergedBidRequest = WithPodErrors.of( - bidRequest, singletonList(PodError.of(1, 1, singletonList("TEST")))); - final BidRequestVideo requestVideo = BidRequestVideo.builder().device( Device.builder().ua("123").build()).build(); - given(routingContext.getBody()).willReturn(Buffer.buffer(mapper.writeValueAsBytes(requestVideo))); - given(videoStoredRequestProcessor.processVideoRequest(any(), any(), any(), any())) - .willReturn(Future.succeededFuture(mergedBidRequest)); - given(auctionRequestFactory.validateRequest(any())).willAnswer(invocation -> invocation.getArgument(0)); - given(auctionRequestFactory.fillImplicitParameters(any(), any(), any())) - .willAnswer(invocation -> invocation.getArgument(0)); - given(auctionRequestFactory.toAuctionContext(any(), any(), any(), anyList(), anyLong(), any())) - .willReturn(Future.succeededFuture()); + given(routingContext.getBodyAsString()).willReturn(mapper.writeValueAsString(requestVideo)); + + final List podErrors = singletonList(PodError.of(1, 1, singletonList("TEST"))); + givenBidRequest(bidRequest, podErrors); // when - final Future> result = factory.fromRequest(routingContext, 0L); + final Future> result = target.fromRequest(routingContext, 0L); // then - verify(routingContext).getBody(); + verify(routingContext).getBodyAsString(); verify(videoStoredRequestProcessor).processVideoRequest("", null, emptySet(), requestVideo); - verify(auctionRequestFactory).validateRequest(bidRequest); - verify(auctionRequestFactory).fillImplicitParameters(bidRequest, routingContext, timeoutResolver); - verify(auctionRequestFactory).toAuctionContext( - routingContext, bidRequest, MetricName.video, new ArrayList<>(), 0, timeoutResolver); - - assertThat(result.result().getPodErrors()).isEqualTo(mergedBidRequest.getPodErrors()); + verify(ortb2RequestFactory).fetchAccountAndCreateAuctionContext( + routingContext, bidRequest, MetricName.video, false, 0, new ArrayList<>()); + verify(ortb2RequestFactory).validateRequest(bidRequest); + verify(paramsResolver).resolve(bidRequest, routingContext, timeoutResolver); + verify(ortb2RequestFactory).enrichBidRequestWithAccountAndPrivacyData(eq(bidRequest), any(), any()); + + assertThat(result.result().getData().getBidRequest()).isEqualTo(bidRequest); + assertThat(result.result().getPodErrors()).isEqualTo(podErrors); } @Test public void shouldReplaceDeviceUaWithUserAgentHeaderIfPresented() throws JsonProcessingException { // given final BidRequestVideo requestVideo = BidRequestVideo.builder().build(); - given(routingContext.getBody()).willReturn(Buffer.buffer(mapper.writeValueAsBytes(requestVideo))); + given(routingContext.getBodyAsString()).willReturn(mapper.writeValueAsString(requestVideo)); given(routingContext.request().getHeader(HttpUtil.USER_AGENT_HEADER)).willReturn("user-agent-123"); final WithPodErrors emptyMergeObject = WithPodErrors.of(null, null); @@ -241,7 +261,7 @@ public void shouldReplaceDeviceUaWithUserAgentHeaderIfPresented() throws JsonPro .willReturn(Future.succeededFuture(emptyMergeObject)); // when - factory.fromRequest(routingContext, 0L); + target.fromRequest(routingContext, 0L); // then verify(videoStoredRequestProcessor).processVideoRequest(any(), any(), any(), eq(BidRequestVideo.builder() @@ -255,10 +275,10 @@ public void shouldReplaceDeviceUaWithUserAgentHeaderIfPresented() throws JsonPro public void shouldReturnErrorIfDeviceUaAndUserAgentHeaderIsEmpty() throws JsonProcessingException { // given final BidRequestVideo requestVideo = BidRequestVideo.builder().build(); - given(routingContext.getBody()).willReturn(Buffer.buffer(mapper.writeValueAsBytes(requestVideo))); + given(routingContext.getBodyAsString()).willReturn(mapper.writeValueAsString(requestVideo)); // when - Future> future = factory.fromRequest(routingContext, 0L); + Future> future = target.fromRequest(routingContext, 0L); // then assertThat(future.failed()).isTrue(); @@ -266,4 +286,27 @@ public void shouldReturnErrorIfDeviceUaAndUserAgentHeaderIsEmpty() throws JsonPr .isInstanceOf(InvalidRequestException.class) .hasMessage("Device.UA and User-Agent Header is not presented"); } + + private void givenBidRequest(BidRequest bidRequest, List podErrors) { + given(videoStoredRequestProcessor.processVideoRequest(any(), any(), any(), any())) + .willReturn(Future.succeededFuture(WithPodErrors.of(bidRequest, podErrors))); + given(ortb2RequestFactory.fetchAccountAndCreateAuctionContext(any(), any(), any(), anyBoolean(), anyLong(), + any())) + .willAnswer(invocationOnMock -> Future.succeededFuture( + AuctionContext.builder() + .bidRequest((BidRequest) invocationOnMock.getArguments()[1]) + .build())); + + given(ortb2RequestFactory.validateRequest(any())).willAnswer(answerWithFirstArgument()); + given(paramsResolver.resolve(any(), any(), any())) + .willAnswer(answerWithFirstArgument()); + + given(ortb2RequestFactory.enrichBidRequestWithAccountAndPrivacyData(any(), any(), any())) + .willAnswer(answerWithFirstArgument()); + } + + private Answer answerWithFirstArgument() { + return invocationOnMock -> invocationOnMock.getArguments()[0]; + } + } diff --git a/src/test/java/org/prebid/server/bidder/BidderCatalogTest.java b/src/test/java/org/prebid/server/bidder/BidderCatalogTest.java index 79cd7b2577d..c4a4e5e1154 100644 --- a/src/test/java/org/prebid/server/bidder/BidderCatalogTest.java +++ b/src/test/java/org/prebid/server/bidder/BidderCatalogTest.java @@ -18,22 +18,18 @@ public class BidderCatalogTest { @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); - @Mock - private Usersyncer usersyncer; @Mock private Bidder bidder; - private BidderDeps bidderDeps; private BidderCatalog bidderCatalog; @Test public void isValidNameShouldReturnTrueForKnownBidder() { // given - bidderDeps = BidderDeps.builder() + final BidderDeps bidderDeps = BidderDeps.of(singletonList(BidderInstanceDeps.builder() .name(BIDDER) .deprecatedNames(emptyList()) - .aliases(emptyList()) - .build(); + .build())); bidderCatalog = new BidderCatalog(singletonList(bidderDeps)); // when and then @@ -52,11 +48,10 @@ public void isValidNameShouldReturnFalseForUnknownBidder() { @Test public void isDeprecatedNameShouldReturnTrueForDeprecatedBidder() { // given - bidderDeps = BidderDeps.builder() + final BidderDeps bidderDeps = BidderDeps.of(singletonList(BidderInstanceDeps.builder() .name(BIDDER) .deprecatedNames(singletonList("deprecated")) - .aliases(emptyList()) - .build(); + .build())); bidderCatalog = new BidderCatalog(singletonList(bidderDeps)); // when and then @@ -75,11 +70,10 @@ public void isDeprecatedNameShouldReturnFalseForUnknownBidder() { @Test public void errorForDeprecatedNameShouldReturnErrorForDeprecatedBidder() { // given - bidderDeps = BidderDeps.builder() + final BidderDeps bidderDeps = BidderDeps.of(singletonList(BidderInstanceDeps.builder() .name(BIDDER) .deprecatedNames(singletonList("deprecated")) - .aliases(emptyList()) - .build(); + .build())); bidderCatalog = new BidderCatalog(singletonList(bidderDeps)); // when and then @@ -87,69 +81,27 @@ public void errorForDeprecatedNameShouldReturnErrorForDeprecatedBidder() { .isEqualTo("deprecated has been deprecated and is no longer available. Use rubicon instead."); } - @Test - public void aliasesShouldReturnConfiguredAliases() { - // given - bidderDeps = BidderDeps.builder() - .name(BIDDER) - .deprecatedNames(emptyList()) - .aliases(singletonList("alias")) - .build(); - bidderCatalog = new BidderCatalog(singletonList(bidderDeps)); - - // when and then - assertThat(bidderCatalog.aliases()).containsOnly("alias"); - } - - @Test - public void isAliasShouldReturnTrueForBidderAlias() { - // given - bidderDeps = BidderDeps.builder() - .name(BIDDER) - .deprecatedNames(emptyList()) - .aliases(singletonList("alias")) - .build(); - bidderCatalog = new BidderCatalog(singletonList(bidderDeps)); - - // when and then - assertThat(bidderCatalog.isAlias("alias")).isTrue(); - } - - @Test - public void isAliasShouldReturnFalseForUnknownBidderAlias() { - // given - bidderCatalog = new BidderCatalog(emptyList()); - - // when and then - assertThat(bidderCatalog.isAlias("alias")).isFalse(); - } - - @Test - public void nameByAliasShouldReturnBidderName() { - // given - bidderDeps = BidderDeps.builder() - .name(BIDDER) - .deprecatedNames(emptyList()) - .aliases(singletonList("alias")) - .build(); - bidderCatalog = new BidderCatalog(singletonList(bidderDeps)); - - // when and then - assertThat(bidderCatalog.nameByAlias("alias")).isEqualTo(BIDDER); - } - @Test public void metaInfoByNameShouldReturnMetaInfoForKnownBidder() { // given - final BidderInfo bidderInfo = BidderInfo.create(true, "test@email.com", - singletonList("banner"), singletonList("video"), null, 99, true, true, false); - - bidderDeps = BidderDeps.builder() + final BidderInfo bidderInfo = BidderInfo.create( + true, + null, + "test@email.com", + singletonList("banner"), + singletonList("video"), + null, + 99, + true, + true, + false); + + final BidderDeps bidderDeps = BidderDeps.of(singletonList(BidderInstanceDeps.builder() .name(BIDDER) .deprecatedNames(emptyList()) - .aliases(emptyList()) .bidderInfo(bidderInfo) - .build(); + .build())); + bidderCatalog = new BidderCatalog(singletonList(bidderDeps)); // when and then @@ -168,12 +120,12 @@ public void metaInfoByNameShouldReturnNullForUnknownBidder() { @Test public void usersyncerByNameShouldReturnUsersyncerForKnownBidder() { // given - bidderDeps = BidderDeps.builder() + final Usersyncer usersyncer = Usersyncer.of(null, null, null); + final BidderDeps bidderDeps = BidderDeps.of(singletonList(BidderInstanceDeps.builder() .name(BIDDER) .deprecatedNames(emptyList()) - .aliases(emptyList()) .usersyncer(usersyncer) - .build(); + .build())); bidderCatalog = new BidderCatalog(singletonList(bidderDeps)); // when and then @@ -192,12 +144,11 @@ public void usersyncerByNameShouldReturnNullForUnknownBidder() { @Test public void bidderByNameShouldReturnBidderForKnownBidder() { // given - bidderDeps = BidderDeps.builder() + final BidderDeps bidderDeps = BidderDeps.of(singletonList(BidderInstanceDeps.builder() .name(BIDDER) .deprecatedNames(emptyList()) - .aliases(emptyList()) .bidder(bidder) - .build(); + .build())); bidderCatalog = new BidderCatalog(singletonList(bidderDeps)); // when and then @@ -207,17 +158,24 @@ public void bidderByNameShouldReturnBidderForKnownBidder() { @Test public void nameByVendorIdShouldReturnBidderNameForVendorId() { // given - final BidderInfo bidderInfo = BidderInfo.create(true, "test@email.com", - singletonList("banner"), singletonList("video"), null, 99, true, true, false); - - bidderDeps = BidderDeps.builder() + final BidderInfo bidderInfo = BidderInfo.create( + true, + null, + "test@email.com", + singletonList("banner"), + singletonList("video"), + null, + 99, + true, + true, + false); + + final BidderDeps bidderDeps = BidderDeps.of(singletonList(BidderInstanceDeps.builder() .name(BIDDER) .deprecatedNames(emptyList()) - .aliases(emptyList()) .bidder(bidder) .bidderInfo(bidderInfo) - .build(); - + .build())); bidderCatalog = new BidderCatalog(singletonList(bidderDeps)); // when and then diff --git a/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java b/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java index 9967ff73517..cd02ff01229 100644 --- a/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java +++ b/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java @@ -5,11 +5,16 @@ import io.vertx.core.MultiMap; import io.vertx.core.http.CaseInsensitiveHeaders; import io.vertx.core.http.HttpMethod; +import io.vertx.core.http.HttpServerRequest; +import io.vertx.ext.web.RoutingContext; +import lombok.AllArgsConstructor; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatcher; import org.mockito.BDDMockito; +import org.mockito.Captor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -40,6 +45,7 @@ import static org.apache.commons.lang3.StringUtils.EMPTY; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.same; import static org.mockito.BDDMockito.given; @@ -62,6 +68,12 @@ public class HttpBidderRequesterTest extends VertxTest { private HttpClient httpClient; @Mock private BidderErrorNotifier bidderErrorNotifier; + @Mock + private RoutingContext routingContext; + @Mock + private HttpServerRequest httpServerRequest; + @Captor + private ArgumentCaptor headerCaptor; private HttpBidderRequester httpBidderRequester; @@ -71,6 +83,8 @@ public class HttpBidderRequesterTest extends VertxTest { @Before public void setUp() { given(bidderErrorNotifier.processTimeout(any(), any())).will(invocation -> invocation.getArgument(0)); + given(routingContext.request()).willReturn(httpServerRequest); + given(httpServerRequest.headers()).willReturn(new CaseInsensitiveHeaders()); final Clock clock = Clock.fixed(Instant.now(), ZoneId.systemDefault()); final TimeoutFactory timeoutFactory = new TimeoutFactory(clock); @@ -88,7 +102,7 @@ public void shouldReturnFailedToRequestBidsErrorWhenBidderReturnsEmptyHttpReques // when final BidderSeatBid bidderSeatBid = - httpBidderRequester.requestBids(bidder, bidderRequest, timeout, false).result(); + httpBidderRequester.requestBids(bidder, bidderRequest, timeout, routingContext, false).result(); // then assertThat(bidderSeatBid.getBids()).isEmpty(); @@ -107,7 +121,7 @@ public void shouldTolerateBidderReturningErrorsAndNoHttpRequests() { // when final BidderSeatBid bidderSeatBid = - httpBidderRequester.requestBids(bidder, bidderRequest, timeout, false).result(); + httpBidderRequester.requestBids(bidder, bidderRequest, timeout, routingContext, false).result(); // then assertThat(bidderSeatBid.getBids()).isEmpty(); @@ -122,6 +136,9 @@ public void shouldSendPopulatedPostRequest() { givenHttpClientReturnsResponse(200, null); final MultiMap headers = new CaseInsensitiveHeaders(); + headers.add("header1", "value1"); + headers.add("header2", "value2"); + given(bidder.makeHttpRequests(any())).willReturn(Result.of(singletonList( HttpRequest.builder() .method(HttpMethod.POST) @@ -130,15 +147,15 @@ public void shouldSendPopulatedPostRequest() { .headers(headers) .build()), emptyList())); - headers.add("header1", "value1"); - headers.add("header2", "value2"); final BidderRequest bidderRequest = BidderRequest.of("bidder", null, BidRequest.builder().build()); + // when - httpBidderRequester.requestBids(bidder, bidderRequest, timeout, false); + httpBidderRequester.requestBids(bidder, bidderRequest, timeout, routingContext, false); // then - verify(httpClient).request(eq(HttpMethod.POST), eq("uri"), eq(headers), eq("requestBody"), eq(500L)); + verify(httpClient).request(eq(HttpMethod.POST), eq("uri"), argThat(new MultiMapMatcher(headers)), + eq("requestBody"), eq(500L)); } @Test @@ -162,7 +179,8 @@ public void shouldPassStoredResponseToBidderMakeBidsMethodAndReturnSeatBids() { final BidderRequest bidderRequest = BidderRequest.of("bidder", "storedResponse", BidRequest.builder().build()); // when - final BidderSeatBid bidderSeatBid = httpBidderRequester.requestBids(bidder, bidderRequest, timeout, false) + final BidderSeatBid bidderSeatBid = httpBidderRequester + .requestBids(bidder, bidderRequest, timeout, routingContext, false) .result(); // then @@ -200,7 +218,7 @@ public void shouldMakeRequestToBidderWhenStoredResponseDefinedButBidderCreatesMo final BidderRequest bidderRequest = BidderRequest.of("bidder", "storedResponse", BidRequest.builder().build()); // when - httpBidderRequester.requestBids(bidder, bidderRequest, timeout, false).result(); + httpBidderRequester.requestBids(bidder, bidderRequest, timeout, routingContext, false).result(); // then verify(httpClient, times(2)).request(any(), anyString(), any(), any(), anyLong()); @@ -221,7 +239,7 @@ public void shouldSendPopulatedGetRequestWithoutBody() { final BidderRequest bidderRequest = BidderRequest.of("bidder", null, BidRequest.builder().build()); // when - httpBidderRequester.requestBids(bidder, bidderRequest, timeout, false); + httpBidderRequester.requestBids(bidder, bidderRequest, timeout, routingContext, false); // then verify(httpClient).request(any(), anyString(), any(), isNull(), anyLong()); @@ -249,7 +267,7 @@ public void shouldSendMultipleRequests() { final BidderRequest bidderRequest = BidderRequest.of("bidder", null, BidRequest.builder().build()); // when - httpBidderRequester.requestBids(bidder, bidderRequest, timeout, false); + httpBidderRequester.requestBids(bidder, bidderRequest, timeout, routingContext, false); // then verify(httpClient, times(2)).request(any(), anyString(), any(), any(), anyLong()); @@ -276,7 +294,7 @@ public void shouldReturnBidsCreatedByBidder() { // when final BidderSeatBid bidderSeatBid = - httpBidderRequester.requestBids(bidder, bidderRequest, timeout, false).result(); + httpBidderRequester.requestBids(bidder, bidderRequest, timeout, routingContext, false).result(); // then assertThat(bidderSeatBid.getBids()).containsOnlyElementsOf(bids); @@ -310,7 +328,7 @@ public void shouldReturnFullDebugInfoIfDebugEnabled() { // when final BidderSeatBid bidderSeatBid = - httpBidderRequester.requestBids(bidder, bidderRequest, timeout, true).result(); + httpBidderRequester.requestBids(bidder, bidderRequest, timeout, routingContext, true).result(); // then assertThat(bidderSeatBid.getHttpCalls()).hasSize(2).containsOnly( @@ -336,7 +354,7 @@ public void shouldReturnPartialDebugInfoIfDebugEnabledAndGlobalTimeoutAlreadyExp // when final BidderSeatBid bidderSeatBid = - httpBidderRequester.requestBids(bidder, bidderRequest, expiredTimeout, true).result(); + httpBidderRequester.requestBids(bidder, bidderRequest, expiredTimeout, routingContext, true).result(); // then assertThat(bidderSeatBid.getHttpCalls()).hasSize(1).containsOnly( @@ -361,13 +379,64 @@ public void shouldReturnPartialDebugInfoIfDebugEnabledAndHttpErrorOccurs() { // when final BidderSeatBid bidderSeatBid = - httpBidderRequester.requestBids(bidder, bidderRequest, timeout, true).result(); + httpBidderRequester.requestBids(bidder, bidderRequest, timeout, routingContext, true).result(); // then assertThat(bidderSeatBid.getHttpCalls()).hasSize(1).containsOnly( ExtHttpCall.builder().uri("uri1").requestbody("requestBody1").build()); } + @Test + public void shouldAddSecGpcHeaderFromOriginalRequest() { + // given + givenHttpClientReturnsResponse(200, null); + given(httpServerRequest.headers()).willReturn(new CaseInsensitiveHeaders().add("Sec-GPC", "1")); + + given(bidder.makeHttpRequests(any())).willReturn(Result.of(singletonList( + HttpRequest.builder() + .method(HttpMethod.POST) + .uri("uri") + .body("requestBody") + .headers(new CaseInsensitiveHeaders()) + .build()), + emptyList())); + + final BidderRequest bidderRequest = BidderRequest.of("bidder", null, BidRequest.builder().build()); + // when + httpBidderRequester.requestBids(bidder, bidderRequest, timeout, routingContext, false); + + // then + verify(httpClient).request(eq(HttpMethod.POST), eq("uri"), headerCaptor.capture(), eq("requestBody"), eq(500L)); + assertThat(headerCaptor.getValue().contains("Sec-GPC")).isTrue(); + assertThat(headerCaptor.getValue().get("Sec-GPC")).isEqualTo("1"); + } + + @Test + public void shouldNotOverrideHeadersFromBidRequest() { + // given + givenHttpClientReturnsResponse(200, null); + given(httpServerRequest.headers()).willReturn(new CaseInsensitiveHeaders().add("Sec-GPC", "1")); + + given(bidder.makeHttpRequests(any())).willReturn(Result.of(singletonList( + HttpRequest.builder() + .method(HttpMethod.POST) + .uri("uri") + .body("requestBody") + .headers(new CaseInsensitiveHeaders().add("Sec-GPC", "0")) + .build()), + emptyList())); + + final BidderRequest bidderRequest = BidderRequest.of("bidder", null, BidRequest.builder().build()); + // when + httpBidderRequester.requestBids(bidder, bidderRequest, timeout, routingContext, false); + + // then + verify(httpClient).request(eq(HttpMethod.POST), eq("uri"), headerCaptor.capture(), eq("requestBody"), eq(500L)); + assertThat(headerCaptor.getValue().contains("Sec-GPC")).isTrue(); + assertThat(headerCaptor.getValue().getAll("Sec-GPC")).hasSize(1); + assertThat(headerCaptor.getValue().get("Sec-GPC")).isEqualTo("0"); + } + @Test public void shouldReturnFullDebugInfoIfDebugEnabledAndErrorStatus() { // given @@ -386,7 +455,7 @@ public void shouldReturnFullDebugInfoIfDebugEnabledAndErrorStatus() { // when final BidderSeatBid bidderSeatBid = - httpBidderRequester.requestBids(bidder, bidderRequest, timeout, true).result(); + httpBidderRequester.requestBids(bidder, bidderRequest, timeout, routingContext, true).result(); // then assertThat(bidderSeatBid.getHttpCalls()).hasSize(1).containsOnly( @@ -413,7 +482,7 @@ public void shouldTolerateAlreadyExpiredGlobalTimeout() { // when final BidderSeatBid bidderSeatBid = - httpBidderRequester.requestBids(bidder, bidderRequest, expiredTimeout, false).result(); + httpBidderRequester.requestBids(bidder, bidderRequest, expiredTimeout, routingContext, false).result(); // then assertThat(bidderSeatBid.getErrors()).hasSize(1) @@ -440,7 +509,7 @@ public void shouldNotifyBidderOfTimeout() { final BidderRequest bidderRequest = BidderRequest.of("bidder", null, BidRequest.builder().build()); // when - httpBidderRequester.requestBids(bidder, bidderRequest, timeout, false); + httpBidderRequester.requestBids(bidder, bidderRequest, timeout, routingContext, false); // then verify(bidderErrorNotifier).processTimeout(any(), same(bidder)); @@ -516,7 +585,7 @@ public void shouldTolerateMultipleErrors() { // when final BidderSeatBid bidderSeatBid = httpBidderRequester - .requestBids(bidder, bidderRequest, timeout, false) + .requestBids(bidder, bidderRequest, timeout, routingContext, false) .result(); // then @@ -549,7 +618,7 @@ public void shouldNotMakeBidsIfResponseStatusIs204() { final BidderRequest bidderRequest = BidderRequest.of("bidder", null, BidRequest.builder().test(1).build()); // when - httpBidderRequester.requestBids(bidder, bidderRequest, timeout, false); + httpBidderRequester.requestBids(bidder, bidderRequest, timeout, routingContext, false); // then verify(bidder, never()).makeBids(any(), any()); @@ -574,4 +643,16 @@ private void givenHttpClientReturnsResponses(HttpClientResponse... httpClientRes stubbing = stubbing.willReturn(Future.succeededFuture(httpClientResponse)); } } + + @AllArgsConstructor + public static class MultiMapMatcher implements ArgumentMatcher { + + private final MultiMap left; + + @Override + public boolean matches(MultiMap right) { + return left.size() == right.size() && left.entries().stream() + .allMatch(entry -> right.contains(entry.getKey(), entry.getValue(), true)); + } + } } diff --git a/src/test/java/org/prebid/server/bidder/UsersyncInfoAssemblerTest.java b/src/test/java/org/prebid/server/bidder/UsersyncInfoAssemblerTest.java index 6b29fc60b55..ea90a395d58 100644 --- a/src/test/java/org/prebid/server/bidder/UsersyncInfoAssemblerTest.java +++ b/src/test/java/org/prebid/server/bidder/UsersyncInfoAssemblerTest.java @@ -13,8 +13,8 @@ public class UsersyncInfoAssemblerTest { public void assembleUsersyncInfoShouldAppendRedirectUrlToUsersyncUrl() { // given and when final UsersyncInfo result = UsersyncInfoAssembler - .from(new Usersyncer(null, "http://url/redirect=", "redirectUrl", - "http://localhost:8000", null, false)).assemble(); + .from(createUsersyncMethod("http://url/redirect=", "http://localhost:8000redirectUrl")) + .assemble(); // then assertThat(result.getUrl()).isEqualTo("http://url/redirect=http%3A%2F%2Flocalhost%3A8000redirectUrl"); @@ -24,8 +24,10 @@ public void assembleUsersyncInfoShouldAppendRedirectUrlToUsersyncUrl() { public void assembleUsersyncInfoShouldAppendEncodedRedirectUrlAndNotEncodedQueryParamsToUsersyncUrl() { // given and when final UsersyncInfo result = UsersyncInfoAssembler - .from(new Usersyncer(null, "http://url/redirect=", "/setuid?gdpr={{gdpr}}?gdpr={{gdpr}}", - "http://localhost:8000", null, false)).assemble(); + .from(createUsersyncMethod( + "http://url/redirect=", + "http://localhost:8000/setuid?gdpr={{gdpr}}?gdpr={{gdpr}}")) + .assemble(); // then assertThat(result.getUrl()).isEqualTo( @@ -36,7 +38,8 @@ public void assembleUsersyncInfoShouldAppendEncodedRedirectUrlAndNotEncodedQuery public void assembleUsersyncInfoShouldIgnoreRedirectUrlIfNotDefined() { // given and when final UsersyncInfo result = UsersyncInfoAssembler - .from(new Usersyncer(null, "http://url/redirect=", null, null, null, false)).assemble(); + .from(createUsersyncMethod("http://url/redirect=", null)) + .assemble(); // then assertThat(result.getUrl()).isEqualTo("http://url/redirect="); @@ -46,11 +49,12 @@ public void assembleUsersyncInfoShouldIgnoreRedirectUrlIfNotDefined() { public void assembleWithPrivacyShouldCreatePrivacyAwareUsersyncInfo() { // given and when final UsersyncInfo result = UsersyncInfoAssembler - .from(new Usersyncer(null, "http://url?redir=%26gdpr%3D{{gdpr}}" - + "%26gdpr_consent%3D{{gdpr_consent}}" - + "%26us_privacy={{us_privacy}}", - null, null, null, false)) - .withPrivacy(Privacy.of("1", "consent$1", Ccpa.of("1YNN"), null)).assemble(); + .from(createUsersyncMethod( + "http://url?redir=%26gdpr%3D{{gdpr}}%26gdpr_consent%3D{{gdpr_consent}}" + + "%26us_privacy={{us_privacy}}", + null)) + .withPrivacy(Privacy.of("1", "consent$1", Ccpa.of("1YNN"), null)) + .assemble(); // then assertThat(result.getUrl()).isEqualTo( @@ -61,11 +65,12 @@ public void assembleWithPrivacyShouldCreatePrivacyAwareUsersyncInfo() { public void assembleWithPrivacyShouldTolerateMissingPrivacyParamsUsersyncInfo() { // given and when final UsersyncInfo result = UsersyncInfoAssembler - .from(new Usersyncer(null, "http://url?redir=%26gdpr%3D{{gdpr}}" - + "%26gdpr_consent%3D{{gdpr_consent}}" - + "%26us_privacy%3D{{us_privacy}}", - null, null, null, false)) - .withPrivacy(Privacy.of(null, null, Ccpa.EMPTY, null)).assemble(); + .from(createUsersyncMethod( + "http://url?redir=%26gdpr%3D{{gdpr}}%26gdpr_consent%3D{{gdpr_consent}}" + + "%26us_privacy%3D{{us_privacy}}", + null)) + .withPrivacy(Privacy.of(null, null, Ccpa.EMPTY, null)) + .assemble(); // then assertThat(result.getUrl()).isEqualTo("http://url?redir=%26gdpr%3D%26gdpr_consent%3D%26us_privacy%3D"); @@ -75,8 +80,9 @@ public void assembleWithPrivacyShouldTolerateMissingPrivacyParamsUsersyncInfo() public void assembleWithPrivacyShouldIgnorePrivacyParamsIfTheyAreMissingInUrl() { // given and when final UsersyncInfo result = UsersyncInfoAssembler - .from(new Usersyncer(null, "http://url?redir=a%3Db", null, null, null, false)) - .withPrivacy(Privacy.of("1", "consent", Ccpa.of("YNN"), null)).assemble(); + .from(createUsersyncMethod("http://url?redir=a%3Db", null)) + .withPrivacy(Privacy.of("1", "consent", Ccpa.of("YNN"), null)) + .assemble(); // then assertThat(result.getUrl()).isEqualTo("http://url?redir=a%3Db"); @@ -86,12 +92,12 @@ public void assembleWithPrivacyShouldIgnorePrivacyParamsIfTheyAreMissingInUrl() public void assembleWithPrivacyUsersyncInfoShouldPopulateWithPrivacyRedirectAndUsersyncUrl() { // given and when final UsersyncInfo result = UsersyncInfoAssembler - .from(new Usersyncer(null, "http://url/{{gdpr}}/{{gdpr_consent}}?redir=", - "/setuid?bidder=adnxs&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}" - + "&us_privacy={{us_privacy}}" - + "&uid=$UID", - "http://localhost:8000", null, false)) - .withPrivacy(Privacy.of("1", "consent$1", Ccpa.of("1YNN"), null)).assemble(); + .from(createUsersyncMethod( + "http://url/{{gdpr}}/{{gdpr_consent}}?redir=", + "http://localhost:8000/setuid?bidder=adnxs&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}" + + "&us_privacy={{us_privacy}}&uid=$UID")) + .withPrivacy(Privacy.of("1", "consent$1", Ccpa.of("1YNN"), null)) + .assemble(); // then assertThat(result.getUrl()).isEqualTo( @@ -103,10 +109,15 @@ public void assembleWithPrivacyUsersyncInfoShouldPopulateWithPrivacyRedirectAndU public void assembleWithUrlUsersyncInfoShouldUpdateUsersyncUrl() { // given and when final UsersyncInfo result = UsersyncInfoAssembler - .from(new Usersyncer(null, "http://url", null, null, null, false)) - .withUrl("http://updated-url").assemble(); + .from(createUsersyncMethod("http://url", null)) + .withUrl("http://updated-url") + .assemble(); // then assertThat(result.getUrl()).isEqualTo("http://updated-url"); } + + private static Usersyncer.UsersyncMethod createUsersyncMethod(String usersyncUrl, String redirectUrl) { + return Usersyncer.UsersyncMethod.of(null, usersyncUrl, redirectUrl, false); + } } diff --git a/src/test/java/org/prebid/server/bidder/UsersyncMethodChooserTest.java b/src/test/java/org/prebid/server/bidder/UsersyncMethodChooserTest.java new file mode 100644 index 00000000000..f4dfdf21c65 --- /dev/null +++ b/src/test/java/org/prebid/server/bidder/UsersyncMethodChooserTest.java @@ -0,0 +1,367 @@ +package org.prebid.server.bidder; + +import com.fasterxml.jackson.databind.node.IntNode; +import com.fasterxml.jackson.databind.node.TextNode; +import org.junit.Test; +import org.prebid.server.VertxTest; +import org.prebid.server.proto.request.CookieSyncRequest; + +import static org.assertj.core.api.Assertions.assertThat; + +public class UsersyncMethodChooserTest extends VertxTest { + + private static final String BIDDER = "bidder"; + + @Test + public void shouldReturnPrimaryMethodWhenFilterIsNull() { + // given + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", "url"); + final Usersyncer usersyncer = createUsersyncer(primaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(null).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isSameAs(primaryMethod); + } + + @Test + public void shouldReturnPrimaryMethodWhenFilterIsEmpty() { + // given + final CookieSyncRequest.FilterSettings filter = CookieSyncRequest.FilterSettings.of(null, null); + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", "url"); + final Usersyncer usersyncer = createUsersyncer(primaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(filter).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isSameAs(primaryMethod); + } + + @Test + public void shouldReturnPrimaryMethodWhenMethodFilterTypeIsNull() { + // given + final CookieSyncRequest.FilterSettings filter = CookieSyncRequest.FilterSettings.of( + CookieSyncRequest.MethodFilter.of(null, null), + null); + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", "url"); + final Usersyncer usersyncer = createUsersyncer(primaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(filter).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isSameAs(primaryMethod); + } + + @Test + public void shouldReturnSecondaryMethodWhenMethodFilterExcludeAndNullBidders() { + // given + final CookieSyncRequest.FilterSettings filter = CookieSyncRequest.FilterSettings.of( + CookieSyncRequest.MethodFilter.of( + null, + CookieSyncRequest.FilterType.exclude), + null); + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", "url"); + final Usersyncer.UsersyncMethod secondaryMethod = createMethod("redirect", "url"); + final Usersyncer usersyncer = createUsersyncer(primaryMethod, secondaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(filter).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isSameAs(secondaryMethod); + } + + @Test + public void shouldReturnPrimaryMethodWhenNotInMethodFilterExcludeList() { + // given + final CookieSyncRequest.FilterSettings filter = CookieSyncRequest.FilterSettings.of( + CookieSyncRequest.MethodFilter.of( + mapper.createArrayNode().add("anotherbidder"), + CookieSyncRequest.FilterType.exclude), + null); + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", "url"); + final Usersyncer usersyncer = createUsersyncer(primaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(filter).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isSameAs(primaryMethod); + } + + @Test + public void shouldReturnSecondaryMethodWhenInMethodFilterExcludeList() { + // given + final CookieSyncRequest.FilterSettings filter = CookieSyncRequest.FilterSettings.of( + CookieSyncRequest.MethodFilter.of( + mapper.createArrayNode().add(BIDDER), + CookieSyncRequest.FilterType.exclude), + null); + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", "url"); + final Usersyncer.UsersyncMethod secondaryMethod = createMethod("redirect", "url"); + final Usersyncer usersyncer = createUsersyncer(primaryMethod, secondaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(filter).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isSameAs(secondaryMethod); + } + + @Test + public void shouldReturnSecondaryMethodWhenMethodFilterExcludesAll() { + // given + final CookieSyncRequest.FilterSettings filter = CookieSyncRequest.FilterSettings.of( + CookieSyncRequest.MethodFilter.of( + new TextNode("*"), + CookieSyncRequest.FilterType.exclude), + null); + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", "url"); + final Usersyncer.UsersyncMethod secondaryMethod = createMethod("redirect", "url"); + final Usersyncer usersyncer = createUsersyncer(primaryMethod, secondaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(filter).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isSameAs(secondaryMethod); + } + + @Test + public void shouldReturnPrimaryMethodWhenMethodFilterExcludeListIsNotArray() { + // given + final CookieSyncRequest.FilterSettings filter = CookieSyncRequest.FilterSettings.of( + CookieSyncRequest.MethodFilter.of( + new IntNode(1), + CookieSyncRequest.FilterType.exclude), + null); + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", "url"); + final Usersyncer usersyncer = createUsersyncer(primaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(filter).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isSameAs(primaryMethod); + } + + @Test + public void shouldReturnPrimaryMethodWhenMethodFilterExcludeListIsNotStringArray() { + // given + final CookieSyncRequest.FilterSettings filter = CookieSyncRequest.FilterSettings.of( + CookieSyncRequest.MethodFilter.of( + mapper.createArrayNode().add(1), + CookieSyncRequest.FilterType.exclude), + null); + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", "url"); + final Usersyncer usersyncer = createUsersyncer(primaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(filter).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isSameAs(primaryMethod); + } + + @Test + public void shouldReturnPrimaryMethodWhenMethodFilterIncludeAndNullBidders() { + // given + final CookieSyncRequest.FilterSettings filter = CookieSyncRequest.FilterSettings.of( + CookieSyncRequest.MethodFilter.of( + null, + CookieSyncRequest.FilterType.include), + null); + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", "url"); + final Usersyncer usersyncer = createUsersyncer(primaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(filter).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isSameAs(primaryMethod); + } + + @Test + public void shouldReturnSecondaryMethodWhenNotInMethodFilterIncludeList() { + // given + final CookieSyncRequest.FilterSettings filter = CookieSyncRequest.FilterSettings.of( + CookieSyncRequest.MethodFilter.of( + mapper.createArrayNode().add("anotherbidder"), + CookieSyncRequest.FilterType.include), + null); + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", "url"); + final Usersyncer.UsersyncMethod secondaryMethod = createMethod("redirect", "url"); + final Usersyncer usersyncer = createUsersyncer(primaryMethod, secondaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(filter).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isSameAs(secondaryMethod); + } + + @Test + public void shouldReturnPrimaryMethodWhenInMethodFilterIncludeList() { + // given + final CookieSyncRequest.FilterSettings filter = CookieSyncRequest.FilterSettings.of( + CookieSyncRequest.MethodFilter.of( + mapper.createArrayNode().add(BIDDER), + CookieSyncRequest.FilterType.include), + null); + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", "url"); + final Usersyncer usersyncer = createUsersyncer(primaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(filter).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isSameAs(primaryMethod); + } + + @Test + public void shouldReturnPrimaryMethodWhenMethodFilterIncludesAll() { + // given + final CookieSyncRequest.FilterSettings filter = CookieSyncRequest.FilterSettings.of( + CookieSyncRequest.MethodFilter.of( + new TextNode("*"), + CookieSyncRequest.FilterType.include), + null); + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", "url"); + final Usersyncer usersyncer = createUsersyncer(primaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(filter).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isSameAs(primaryMethod); + } + + @Test + public void shouldReturnSecondaryMethodWhenMethodFilterIncludeListIsNotArray() { + // given + final CookieSyncRequest.FilterSettings filter = CookieSyncRequest.FilterSettings.of( + CookieSyncRequest.MethodFilter.of( + new IntNode(1), + CookieSyncRequest.FilterType.include), + null); + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", "url"); + final Usersyncer.UsersyncMethod secondaryMethod = createMethod("redirect", "url"); + final Usersyncer usersyncer = createUsersyncer(primaryMethod, secondaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(filter).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isSameAs(secondaryMethod); + } + + @Test + public void shouldReturnSecondaryMethodWhenMethodFilterIncludeListIsNotStringArray() { + // given + final CookieSyncRequest.FilterSettings filter = CookieSyncRequest.FilterSettings.of( + CookieSyncRequest.MethodFilter.of( + mapper.createArrayNode().add(1), + CookieSyncRequest.FilterType.include), + null); + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", "url"); + final Usersyncer.UsersyncMethod secondaryMethod = createMethod("redirect", "url"); + final Usersyncer usersyncer = createUsersyncer(primaryMethod, secondaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(filter).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isSameAs(secondaryMethod); + } + + @Test + public void shouldReturnSecondaryMethodWhenPrimaryIsFilteredOutAndSecondIsNot() { + // given + final CookieSyncRequest.FilterSettings filter = CookieSyncRequest.FilterSettings.of( + CookieSyncRequest.MethodFilter.of( + new TextNode("*"), + CookieSyncRequest.FilterType.exclude), + CookieSyncRequest.MethodFilter.of( + new TextNode("*"), + CookieSyncRequest.FilterType.include)); + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", "url"); + final Usersyncer.UsersyncMethod secondaryMethod = createMethod("redirect", "url"); + final Usersyncer usersyncer = createUsersyncer(primaryMethod, secondaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(filter).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isSameAs(secondaryMethod); + } + + @Test + public void shouldReturnNullWhenPrimaryAndSecondaryAreFilteredOut() { + // given + final CookieSyncRequest.FilterSettings filter = CookieSyncRequest.FilterSettings.of( + CookieSyncRequest.MethodFilter.of( + new TextNode("*"), + CookieSyncRequest.FilterType.exclude), + CookieSyncRequest.MethodFilter.of( + new TextNode("*"), + CookieSyncRequest.FilterType.exclude)); + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", "url"); + final Usersyncer.UsersyncMethod secondaryMethod = createMethod("redirect", "url"); + final Usersyncer usersyncer = createUsersyncer(primaryMethod, secondaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(filter).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isNull(); + } + + @Test + public void shouldReturnNullWhenPrimaryHasNoUrl() { + // given + final CookieSyncRequest.FilterSettings filter = CookieSyncRequest.FilterSettings.of(null, null); + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", null); + final Usersyncer usersyncer = createUsersyncer(primaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(filter).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isNull(); + } + + @Test + public void shouldReturnNullWhenPrimaryIsFilteredOutAndNoSecondary() { + // given + final CookieSyncRequest.FilterSettings filter = CookieSyncRequest.FilterSettings.of( + CookieSyncRequest.MethodFilter.of( + new TextNode("*"), + CookieSyncRequest.FilterType.exclude), + null); + final Usersyncer.UsersyncMethod primaryMethod = createMethod("iframe", "url"); + final Usersyncer usersyncer = createUsersyncer(primaryMethod); + + // when + final Usersyncer.UsersyncMethod chosenMethod = UsersyncMethodChooser.from(filter).choose(usersyncer, BIDDER); + + // then + assertThat(chosenMethod).isNull(); + } + + private Usersyncer createUsersyncer(Usersyncer.UsersyncMethod primaryMethod) { + return createUsersyncer(primaryMethod, null); + } + + private Usersyncer createUsersyncer(Usersyncer.UsersyncMethod primaryMethod, + Usersyncer.UsersyncMethod secondaryMethod) { + + return Usersyncer.of(null, primaryMethod, secondaryMethod); + } + + private Usersyncer.UsersyncMethod createMethod(String type, String url) { + return Usersyncer.UsersyncMethod.of(type, url, null, false); + } +} diff --git a/src/test/java/org/prebid/server/bidder/UsersyncUtilTest.java b/src/test/java/org/prebid/server/bidder/UsersyncUtilTest.java new file mode 100644 index 00000000000..814d7d751ca --- /dev/null +++ b/src/test/java/org/prebid/server/bidder/UsersyncUtilTest.java @@ -0,0 +1,72 @@ +package org.prebid.server.bidder; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class UsersyncUtilTest { + + @Test + public void enrichUsersyncUrlWithFormatShouldNotChangeUrlIfMissing() { + // given and when + final String url = UsersyncUtil.enrichUsersyncUrlWithFormat(null, "iframe"); + + // then + assertThat(url).isNull(); + } + + @Test + public void enrichUsersyncUrlWithFormatShouldNotChangeUrlIfEmpty() { + // given and when + final String url = UsersyncUtil.enrichUsersyncUrlWithFormat("", "iframe"); + + // then + assertThat(url).isEmpty(); + } + + @Test + public void enrichUsersyncUrlWithFormatShouldNotChangeUrlIfTypeMissing() { + // given and when + final String url = UsersyncUtil.enrichUsersyncUrlWithFormat("", null); + + // then + assertThat(url).isEmpty(); + } + + @Test + public void enrichUsersyncUrlWithFormatShouldNotChangeUrlIfTypeEmpty() { + // given and when + final String url = UsersyncUtil.enrichUsersyncUrlWithFormat("", ""); + + // then + assertThat(url).isEmpty(); + } + + @Test + public void enrichUsersyncUrlWithFormatShouldAddFormat() { + // given and when + final String url = UsersyncUtil.enrichUsersyncUrlWithFormat("//url", "iframe"); + + // then + assertThat(url).isEqualTo("//url?f=b"); + } + + @Test + public void enrichUsersyncUrlWithFormatShouldAppendFormat() { + // given and when + final String url = UsersyncUtil.enrichUsersyncUrlWithFormat("http://url?param1=value1", "redirect"); + + // then + assertThat(url).isEqualTo("http://url?param1=value1&f=i"); + } + + @Test + public void enrichUsersyncUrlWithFormatShouldInsertFormat() { + // given and when + final String url = UsersyncUtil.enrichUsersyncUrlWithFormat("http://url?param1=value1¶m2=value2", + "redirect"); + + // then + assertThat(url).isEqualTo("http://url?param1=value1&f=i¶m2=value2"); + } +} diff --git a/src/test/java/org/prebid/server/bidder/UsersyncerTest.java b/src/test/java/org/prebid/server/bidder/UsersyncerTest.java deleted file mode 100644 index 85d02862836..00000000000 --- a/src/test/java/org/prebid/server/bidder/UsersyncerTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.prebid.server.bidder; - -import org.junit.Test; - -import java.net.MalformedURLException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -public class UsersyncerTest { - - @Test - public void newUsersyncerShouldReturnUsersyncerWithConcatenatedExternalAndRedirectUrl() { - // given, when and then - assertThat( - new Usersyncer("rubicon", "//usersync-url", "/redicret-url", "http://localhost:8000", "redirect", true)) - .extracting(Usersyncer::getRedirectUrl) - .containsOnly("http://localhost:8000/redicret-url"); - } - - @Test - public void newUsersyncerShouldReturnUsersyncerWithEmptyRedirectUrlWhenItWasNotDefined() { - // given, when and then - assertThat(new Usersyncer("rubicon", "//usersync-url", null, null, "redirect", true)) - .extracting(Usersyncer::getRedirectUrl) - .containsOnly(""); - } - - @Test - public void newUsersyncerShouldValidateExtenalUrl() { - // given, when and then - assertThatThrownBy(() -> new Usersyncer(null, "//usersync-url", "not-valid-url", null, "redirect", true)) - .hasCauseExactlyInstanceOf(MalformedURLException.class) - .hasMessage("URL supplied is not valid: null"); - } -} diff --git a/src/test/java/org/prebid/server/bidder/adform/AdformBidderTest.java b/src/test/java/org/prebid/server/bidder/adform/AdformBidderTest.java index ed8909ec01f..cf86cb8aa5d 100644 --- a/src/test/java/org/prebid/server/bidder/adform/AdformBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/adform/AdformBidderTest.java @@ -31,6 +31,7 @@ import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.util.HttpUtil; +import java.util.Arrays; import java.util.Base64; import java.util.List; import java.util.Map; @@ -259,6 +260,35 @@ public void makeBidsShouldReturnBidderBidIfResponseIsBannerAndBannerIsPresent() Bid.builder().id("id").impid("id").adm("admBanner").build(), BidType.banner, "currency")); } + @Test + public void makeBidsShouldReturnBidderBidsWithCurrencyFromEveryAdformResponse() throws JsonProcessingException { + // given + final AdformBid firstAdformResponse = AdformBid.builder().banner("admBanner") + .response("banner").winCur("EUR").build(); + final AdformBid secondAdformResponse = AdformBid.builder().banner("admBanner") + .response("banner").winCur("USD").build(); + final String adformBidResponse = + mapper.writeValueAsString(Arrays.asList(firstAdformResponse, secondAdformResponse)); + + final HttpCall httpCall = givenHttpCall(adformBidResponse); + final BidRequest bidRequest = BidRequest.builder() + .imp(asList(Imp.builder().id("firstId").build(), Imp.builder().id("secondId").build())) + .build(); + + // when + final Result> result = adformBidder.makeBids(httpCall, bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(2).containsExactly( + BidderBid.of(Bid.builder().id("firstId").impid("firstId").adm("admBanner").build(), + BidType.banner, + "EUR"), + BidderBid.of(Bid.builder().id("secondId").impid("secondId").adm("admBanner").build(), + BidType.banner, + "USD")); + } + @Test public void makeBidsShouldReturnVideoBidIfResponseEqualsVastContent() throws JsonProcessingException { // given diff --git a/src/test/java/org/prebid/server/bidder/adhese/AdheseBidderTest.java b/src/test/java/org/prebid/server/bidder/adhese/AdheseBidderTest.java index 67b32cada5c..7cb67c1739b 100644 --- a/src/test/java/org/prebid/server/bidder/adhese/AdheseBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/adhese/AdheseBidderTest.java @@ -17,6 +17,7 @@ import org.prebid.server.VertxTest; import org.prebid.server.bidder.adhese.model.AdheseBid; import org.prebid.server.bidder.adhese.model.AdheseOriginData; +import org.prebid.server.bidder.adhese.model.AdheseRequestBody; import org.prebid.server.bidder.adhese.model.AdheseResponseExt; import org.prebid.server.bidder.adhese.model.Cpm; import org.prebid.server.bidder.adhese.model.CpmValues; @@ -33,9 +34,12 @@ import org.prebid.server.proto.openrtb.ext.response.BidType; import java.math.BigDecimal; +import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.TreeMap; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; @@ -94,7 +98,8 @@ public void makeHttpRequestsShouldReturnErrorWhenImpExtCouldNotBeParsed() { } @Test - public void makeHttpRequestsShouldModifyIncomingRequestAndSetExpectedHttpRequestUri() { + public void makeHttpRequestsShouldModifyIncomingRequestAndSetExpectedHttpRequestUri() + throws JsonProcessingException { // given Map> targets = new HashMap<>(); targets.put("ci", asList("gent", "brussels")); @@ -105,8 +110,11 @@ public void makeHttpRequestsShouldModifyIncomingRequestAndSetExpectedHttpRequest .ext(ExtUser.builder().consent("dummy").build()) .build()) .imp(singletonList(Imp.builder() - .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpAdhese.of("demo", - "_adhese_prebid_demo_", "leaderboard", mapper.convertValue(targets, JsonNode.class))))) + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpAdhese.of( + "demo", + "_adhese_prebid_demo_", + "leaderboard", + mapper.convertValue(targets, JsonNode.class))))) .build())) .device(Device.builder().ifa("dum-my").build()) .build(); @@ -117,12 +125,27 @@ public void makeHttpRequestsShouldModifyIncomingRequestAndSetExpectedHttpRequest // then assertThat(result.getValue()) .extracting(HttpRequest::getUri) - .containsOnly("https://ads-demo.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/ag55/cigent;brussels" - + "/tlall/xtdummy/xzdum-my"); + .containsOnly("https://ads-demo.adhese.com/json"); + assertThat(result.getValue()) + .extracting(HttpRequest::getBody) + .containsOnly(jacksonMapper.mapper().writeValueAsString( + AdheseRequestBody + .builder() + .slots(Collections.singletonList( + AdheseRequestBody.Slot.builder() + .slotname("_adhese_prebid_demo_-leaderboard") + .build())) + .parameters(new TreeMap>() {{ + put("ag", Arrays.asList("55")); + put("ci", Arrays.asList("gent", "brussels")); + put("tl", Arrays.asList("all")); + put("xt", Arrays.asList("dummy")); + put("xz", Arrays.asList("dum-my")); }}) + .build())); } @Test - public void makeHttpRequestsShouldModifyIncomingRequestWithIfaParameter() { + public void makeHttpRequestsShouldModifyIncomingRequestWithIfaParameter() throws JsonProcessingException { // given final BidRequest bidRequest = BidRequest.builder() .device(Device.builder().ifa("ifaValue").build()) @@ -139,11 +162,23 @@ public void makeHttpRequestsShouldModifyIncomingRequestWithIfaParameter() { // then assertThat(result.getValue()) .extracting(HttpRequest::getUri) - .containsOnly("https://ads-demo.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/xzifaValue"); + .containsOnly("https://ads-demo.adhese.com/json"); + assertThat(result.getValue()) + .extracting(HttpRequest::getBody) + .containsOnly(jacksonMapper.mapper().writeValueAsString( + AdheseRequestBody + .builder() + .slots(Collections.singletonList( + AdheseRequestBody.Slot.builder() + .slotname("_adhese_prebid_demo_-leaderboard") + .build())) + .parameters(new TreeMap<>(Collections.singletonMap( + "xz", Arrays.asList("ifaValue")))) + .build())); } @Test - public void makeHttpRequestsShouldModifyIncomingRequestWithRefererParameter() { + public void makeHttpRequestsShouldModifyIncomingRequestWithRefererParameter() throws JsonProcessingException { // given final BidRequest bidRequest = BidRequest.builder() .site(Site.builder().page("pageValue").build()) @@ -160,19 +195,34 @@ public void makeHttpRequestsShouldModifyIncomingRequestWithRefererParameter() { // then assertThat(result.getValue()) .extracting(HttpRequest::getUri) - .containsOnly("https://ads-demo.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/xfpageValue"); + .containsOnly("https://ads-demo.adhese.com/json"); + assertThat(result.getValue()) + .extracting(HttpRequest::getBody) + .containsOnly(jacksonMapper.mapper().writeValueAsString( + AdheseRequestBody + .builder() + .slots(Collections.singletonList( + AdheseRequestBody.Slot.builder() + .slotname("_adhese_prebid_demo_-leaderboard") + .build())) + .parameters(new TreeMap<>(Collections.singletonMap( + "xf", Arrays.asList("pageValue")))) + .build())); } @Test - public void makeHttpRequestsShouldNotModifyIncomingRequestIfTargetsNotPresent() { + public void makeHttpRequestsShouldNotModifyIncomingRequestIfTargetsNotPresent() throws JsonProcessingException { // given final BidRequest bidRequest = BidRequest.builder() .user(User.builder() .ext(ExtUser.builder().consent("dummy").build()) .build()) .imp(singletonList(Imp.builder() - .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpAdhese.of("demo", - "_adhese_prebid_demo_", "leaderboard", mapper.convertValue(null, JsonNode.class))))) + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpAdhese.of( + "demo", + "_adhese_prebid_demo_", + "leaderboard", + mapper.convertValue(null, JsonNode.class))))) .build())) .build(); @@ -182,7 +232,19 @@ public void makeHttpRequestsShouldNotModifyIncomingRequestIfTargetsNotPresent() // then assertThat(result.getValue()) .extracting(HttpRequest::getUri) - .containsOnly("https://ads-demo.adhese.com/json/sl_adhese_prebid_demo_-leaderboard/xtdummy"); + .containsOnly("https://ads-demo.adhese.com/json"); + assertThat(result.getValue()) + .extracting(HttpRequest::getBody) + .containsOnly(jacksonMapper.mapper().writeValueAsString( + AdheseRequestBody + .builder() + .slots(Collections.singletonList( + AdheseRequestBody.Slot.builder() + .slotname("_adhese_prebid_demo_-leaderboard") + .build())) + .parameters(new TreeMap<>(Collections.singletonMap( + "xt", Arrays.asList("dummy")))) + .build())); } @Test diff --git a/src/test/java/org/prebid/server/bidder/adoppler/AdopplerBidderTest.java b/src/test/java/org/prebid/server/bidder/adoppler/AdopplerBidderTest.java index 9fbc71e9990..607d308944a 100644 --- a/src/test/java/org/prebid/server/bidder/adoppler/AdopplerBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/adoppler/AdopplerBidderTest.java @@ -13,6 +13,7 @@ import org.junit.Before; import org.junit.Test; import org.prebid.server.VertxTest; +import org.prebid.server.bidder.adoppler.model.AdopplerResponseAdsExt; import org.prebid.server.bidder.adoppler.model.AdopplerResponseExt; import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderError; @@ -24,7 +25,6 @@ import org.prebid.server.proto.openrtb.ext.request.adoppler.ExtImpAdoppler; import org.prebid.server.util.HttpUtil; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -113,53 +113,6 @@ public void makeHttpRequestsShouldSetExpectedHeaders() { tuple(HttpUtil.ACCEPT_HEADER.toString(), HttpHeaderValues.APPLICATION_JSON.toString())); } - @Test - public void makeBidsShouldReturnErrorIfDuplicateId() throws JsonProcessingException { - // given - final Imp imp1 = Imp.builder().id("impId").banner(Banner.builder().build()).build(); - final Imp imp2 = Imp.builder().id("impId").video(Video.builder().build()).build(); - - final BidRequest bidRequest = BidRequest.builder() - .imp(Arrays.asList(imp1, imp2)) - .build(); - final HttpCall httpCall = givenHttpCall( - bidRequest, mapper.writeValueAsString( - givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); - - // when - final Result> result = adopplerBidder.makeBids(httpCall, bidRequest); - - // then - assertThat(result.getErrors()) - .containsExactly(BidderError.badInput("duplicate $.imp.id impId")); - assertThat(result.getValue()).isEmpty(); - } - - @Test - public void makeBidsShouldReturnErrorIfEmptyImp() throws JsonProcessingException { - // given - final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(Imp.builder().id("123") - .banner(null) - .video(null) - .audio(null) - .xNative(null) - .build())) - .build(); - final HttpCall httpCall = givenHttpCall( - bidRequest, mapper.writeValueAsString( - givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); - - // when - final Result> result = adopplerBidder.makeBids(httpCall, bidRequest); - - // then - assertThat(result.getErrors()) - .containsExactly(BidderError.badInput("one of $.imp.banner, $.imp.video, " - + "$.imp.audio and $.imp.native field required")); - assertThat(result.getValue()).isEmpty(); - } - @Test public void makeBidsShouldReturnErrorIfBidIdEmpty() throws JsonProcessingException { // given @@ -186,7 +139,7 @@ public void makeBidsShouldReturnErrorIfExtEmpty() throws JsonProcessingException // given final Imp imp = Imp.builder().id("impId").video(Video.builder().build()).build(); final BidRequest bidRequest = BidRequest.builder().imp(Collections.singletonList(imp)).build(); - final ObjectNode ext = mapper.valueToTree(AdopplerResponseExt.of(null)); + final ObjectNode ext = mapper.valueToTree(AdopplerResponseExt.of(AdopplerResponseAdsExt.of(null))); final HttpCall httpCall = givenHttpCall(bidRequest, mapper.writeValueAsString( givenBidResponse(bidBuilder -> bidBuilder .id("321") @@ -226,7 +179,8 @@ private static Imp givenImp(Function impCustomiz private static BidResponse givenBidResponse(Function bidCustomizer) { return BidResponse.builder() .cur("USD") - .seatbid(singletonList(SeatBid.builder().bid(singletonList(bidCustomizer.apply(Bid.builder()).build())) + .seatbid(singletonList(SeatBid.builder() + .bid(singletonList(bidCustomizer.apply(Bid.builder()).build())) .build())) .build(); } diff --git a/src/test/java/org/prebid/server/bidder/adyoulike/AdyoulikeBidderTest.java b/src/test/java/org/prebid/server/bidder/adyoulike/AdyoulikeBidderTest.java new file mode 100644 index 00000000000..914df222948 --- /dev/null +++ b/src/test/java/org/prebid/server/bidder/adyoulike/AdyoulikeBidderTest.java @@ -0,0 +1,303 @@ +package org.prebid.server.bidder.adyoulike; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.iab.openrtb.request.Banner; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Native; +import com.iab.openrtb.request.Video; +import com.iab.openrtb.response.Bid; +import com.iab.openrtb.response.BidResponse; +import com.iab.openrtb.response.SeatBid; +import org.junit.Before; +import org.junit.Test; +import org.prebid.server.VertxTest; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.HttpCall; +import org.prebid.server.bidder.model.HttpRequest; +import org.prebid.server.bidder.model.HttpResponse; +import org.prebid.server.bidder.model.Result; +import org.prebid.server.proto.openrtb.ext.ExtPrebid; +import org.prebid.server.proto.openrtb.ext.request.adyoulike.ExtImpAdyoulike; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; +import static java.util.function.Function.identity; +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.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 AdyoulikeBidderTest extends VertxTest { + + public static final String ENDPOINT_URL = "https://test.endpoint.com"; + + private AdyoulikeBidder adyoulikeBidder; + + @Before + public void setUp() { + adyoulikeBidder = new AdyoulikeBidder(ENDPOINT_URL, jacksonMapper); + } + + @Test + public void creationShouldFailOnInvalidEndpointUrl() { + assertThatIllegalArgumentException().isThrownBy(() -> new AdyoulikeBidder("invalid_url", jacksonMapper)); + } + + @Test + public void makeHttpRequestsShouldMakeOneRequestWithAllImps() { + // given + final BidRequest bidRequest = givenBidRequest( + identity(), + requestBuilder -> requestBuilder.imp(Arrays.asList( + givenImp(identity()), + givenImp(identity())))); + + // when + final Result>> result = adyoulikeBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .hasSize(2); + } + + @Test + public void makeHttpRequestsShouldReturnErrorIfImpExtCanNotBeParsed() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(asList(Imp.builder() + .ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createArrayNode()))) + .build(), + givenImp(identity()))) + .build(); + + // when + final Result>> result = adyoulikeBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).hasSize(1) + .allSatisfy(error -> { + assertThat(error.getType()).isEqualTo(BidderError.Type.bad_input); + assertThat(error.getMessage()).startsWith("Cannot deserialize instance"); + }); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeHttpRequestsShouldReturnEveryOccurredErrorWithNoValue() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(asList(Imp.builder() + .ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createArrayNode()))) + .build(), + Imp.builder() + .ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createArrayNode()))) + .build())) + .build(); + + // when + final Result>> result = adyoulikeBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).hasSize(2); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeHttpRequestsShouldUpdateImpTagId() { + // given + final BidRequest bidRequest = givenBidRequest(identity()); + + // when + final Result>> result = adyoulikeBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getTagid) + .containsExactly("placementId"); + } + + @Test + public void makeBidsShouldReturnEmptyListIfBidResponseIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall(null, mapper.writeValueAsString(null)); + + // when + final Result> result = adyoulikeBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnEmptyListIfBidResponseSeatBidIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall(null, + mapper.writeValueAsString(BidResponse.builder().build())); + + // when + final Result> result = adyoulikeBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { + // given + final HttpCall httpCall = givenHttpCall(null, "invalid"); + + // when + final Result> result = adyoulikeBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).hasSize(1) + .allSatisfy(error -> { + assertThat(error.getType()).isEqualTo(BidderError.Type.bad_server_response); + assertThat(error.getMessage()).startsWith("Failed to decode: Unrecognized token"); + }); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnBannerBidByDefault() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().id("123").build())) + .build(), + mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = adyoulikeBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), banner, "EUR")); + } + + @Test + public void makeBidsShouldReturnBannerBidIfBannerIsPresent() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().banner(Banner.builder().build()).id("123").build())) + .build(), + mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = adyoulikeBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), banner, "EUR")); + } + + @Test + public void makeBidsShouldReturnVideoBidIfNoBannerAndHasVideo() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().video(Video.builder().build()).id("123").build())) + .build(), + mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = adyoulikeBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), video, "EUR")); + } + + @Test + public void makeBidsShouldReturnNativeBidIfNoBannerAndHasNative() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().xNative(Native.builder().build()).id("123").build())) + .build(), + mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = adyoulikeBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), xNative, "EUR")); + } + + @Test + public void makeBidsShouldReturnNativeBidIfNativeIsPresentInRequestImp() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().id("123").xNative(Native.builder().build()).build())) + .build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = adyoulikeBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), xNative, "EUR")); + } + + private static BidRequest givenBidRequest( + Function impCustomizer, + Function requestCustomizer) { + return requestCustomizer.apply(BidRequest.builder() + .imp(singletonList(givenImp(impCustomizer)))) + .build(); + } + + private static BidRequest givenBidRequest( + Function impCustomizer) { + return givenBidRequest(impCustomizer, identity()); + } + + private static Imp givenImp(Function impCustomizer) { + return impCustomizer.apply(Imp.builder() + .id("123")) + .banner(Banner.builder().build()) + .ext(mapper.valueToTree(ExtPrebid.of(null, + ExtImpAdyoulike.of("placementId", "campaign", "track", + "creative", "source", "debug")))) + .build(); + } + + private static BidResponse givenBidResponse(Function bidCustomizer) { + return BidResponse.builder() + .cur("EUR") + .seatbid(singletonList(SeatBid.builder() + .bid(singletonList(bidCustomizer.apply(Bid.builder()).build())) + .build())) + .build(); + } + + private static HttpCall givenHttpCall(BidRequest bidRequest, String body) { + return HttpCall.success(HttpRequest.builder().payload(bidRequest).build(), + HttpResponse.of(200, null, body), null); + } +} diff --git a/src/test/java/org/prebid/server/bidder/appnexus/AppnexusBidderTest.java b/src/test/java/org/prebid/server/bidder/appnexus/AppnexusBidderTest.java index e3a6e5f8745..8e397eab9ff 100644 --- a/src/test/java/org/prebid/server/bidder/appnexus/AppnexusBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/appnexus/AppnexusBidderTest.java @@ -482,6 +482,69 @@ public void makeHttpRequestsShouldSetImpTagidAndImpBidFloorIfExtImpAppnexusHasIn .build())); } + @Test + public void makeHttpRequestsShouldSetReserveIfImpBidFloorIsNotSet() { + // given + final BidRequest bidRequest = givenBidRequest( + identity(), + identity(), + extImpAppnexusBuilder -> extImpAppnexusBuilder + .placementId(20) + .reserve(BigDecimal.valueOf(123))); + + // when + final Result>> result = appnexusBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getBidfloor) + .containsExactly(BigDecimal.valueOf(123)); + } + + @Test + public void makeHttpRequestsShouldSetReserveIfImpBidFloorIsZero() { + // given + final BidRequest bidRequest = givenBidRequest( + identity(), + impBuilder -> impBuilder.bidfloor(BigDecimal.ZERO), + extImpAppnexusBuilder -> extImpAppnexusBuilder + .placementId(20) + .reserve(BigDecimal.valueOf(123))); + + // when + final Result>> result = appnexusBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getBidfloor) + .containsExactly(BigDecimal.valueOf(123)); + } + + @Test + public void makeHttpRequestsShouldSetReserveIfImpBidFloorIsNegative() { + // given + final BidRequest bidRequest = givenBidRequest( + identity(), + impBuilder -> impBuilder.bidfloor(BigDecimal.ZERO.subtract(BigDecimal.ONE)), + extImpAppnexusBuilder -> extImpAppnexusBuilder + .placementId(20) + .reserve(BigDecimal.valueOf(123))); + + // when + final Result>> result = appnexusBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getBidfloor) + .containsExactly(BigDecimal.valueOf(123)); + } + @Test public void makeHttpRequestsShouldSetNativeIfRequestImpIsNative() { // given diff --git a/src/test/java/org/prebid/server/bidder/beachfront/BeachfrontBidderTest.java b/src/test/java/org/prebid/server/bidder/beachfront/BeachfrontBidderTest.java index 9049df3f9a8..89c93b38c4f 100644 --- a/src/test/java/org/prebid/server/bidder/beachfront/BeachfrontBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/beachfront/BeachfrontBidderTest.java @@ -268,10 +268,10 @@ public void makeHttpRequestsShouldReturnExpectedBannerRequest() { .deviceOs("nokia") .isMobile(1) .user(User.builder().id("userId").buyeruid("buid").build()) - .adapterVersion("0.9.1") + .adapterVersion("0.9.2") .adapterName("BF_PREBID_S2S") - .ip("192.168.255.255") .requestId("153") + .real204(true) .build()); } @@ -280,7 +280,7 @@ public void makeHttpRequestsShouldReturnExpectedAdmAndNurlVideoRequests() { // given final BidRequest bidRequest = BidRequest.builder() .app(App.builder().bundle("prefix_test1.test2.test3_suffix").build()) - .device(Device.builder().ip("127.0.0.1").build()) + .device(Device.builder().build()) .imp(asList( givenImp(impBuilder -> impBuilder.ext(mapper.valueToTree(ExtPrebid.of(null, mapper.valueToTree(ExtImpBeachfront.of("appId2", null, BigDecimal.TEN, "nurl")))))), @@ -293,10 +293,6 @@ public void makeHttpRequestsShouldReturnExpectedAdmAndNurlVideoRequests() { // then assertThat(result.getErrors()).isEmpty(); - final BidRequest.BidRequestBuilder expectedRequestBuilder = BidRequest.builder() - .device(Device.builder().ip("192.168.255.255").devicetype(1).build()) - .cur(singletonList("USD")); - final Imp.ImpBuilder expectedImpBuilder = Imp.builder() .video(Video.builder().w(300).h(250).build()) .secure(0); @@ -307,25 +303,50 @@ public void makeHttpRequestsShouldReturnExpectedAdmAndNurlVideoRequests() { .isPrebid(true) .appId("appId2") .videoResponseType("nurl") - .request(expectedRequestBuilder + .request(BidRequest.builder() + .device(Device.builder().devicetype(1).build()) .app(App.builder().bundle("prefix_test1.test2.test3_suffix") .domain("test2.prefix_test1").build()) .imp(singletonList(expectedImpBuilder.id("123") .bidfloor(BigDecimal.TEN).build())) + .cur(singletonList("USD")) .build()) .build(), BeachfrontVideoRequest.builder() .appId("appId") .videoResponseType("adm") - .request(expectedRequestBuilder + .request(BidRequest.builder() + .device(Device.builder().ip("255.255.255.255").devicetype(1).build()) .app(App.builder().bundle("prefix_test1.test2.test3_suffix") .domain("test2.prefix_test1").build()) .imp(singletonList(expectedImpBuilder.id("234") .bidfloor(BigDecimal.ONE).build())) + .cur(singletonList("USD")) .build()) .build()); } + @Test + public void makeHttpRequestsShouldCreateAdmRequestForEveryUnknownResponseType() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList( + givenImp(impBuilder -> impBuilder.ext(mapper.valueToTree(ExtPrebid.of(null, + mapper.valueToTree(ExtImpBeachfront.of("appId2", null, null, "unknownType")))))) + )) + .build(); + + // when + final Result>> result = beachfrontBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BeachfrontVideoRequest.class)) + .extracting(BeachfrontVideoRequest::getVideoResponseType) + .containsExactly("adm"); + } + @Test public void makeBidsShouldReturnEmptyResultWhenResponseBodyHasEmptyArray() { // given @@ -350,7 +371,9 @@ public void makeBidsShouldReturnErrorWhenResponseBodyIsInvalid() { // then assertThat(result.getValue()).isEmpty(); assertThat(result.getErrors()).hasSize(1); - assertThat(result.getErrors().get(0).getMessage()).startsWith("Unrecognized token"); + assertThat(result.getErrors().get(0).getMessage()) + .isEqualTo("server response failed to unmarshal as valid rtb. " + + "Run with request.debug = 1 for more info"); } @Test diff --git a/src/test/java/org/prebid/server/bidder/decenterads/DecenteradsBidderTest.java b/src/test/java/org/prebid/server/bidder/decenterads/DecenteradsBidderTest.java new file mode 100644 index 00000000000..79ff3cdc87a --- /dev/null +++ b/src/test/java/org/prebid/server/bidder/decenterads/DecenteradsBidderTest.java @@ -0,0 +1,232 @@ +package org.prebid.server.bidder.decenterads; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.iab.openrtb.request.Audio; +import com.iab.openrtb.request.Banner; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Native; +import com.iab.openrtb.request.Video; +import com.iab.openrtb.response.Bid; +import com.iab.openrtb.response.BidResponse; +import com.iab.openrtb.response.SeatBid; +import org.junit.Before; +import org.junit.Test; +import org.prebid.server.VertxTest; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.HttpCall; +import org.prebid.server.bidder.model.HttpRequest; +import org.prebid.server.bidder.model.HttpResponse; +import org.prebid.server.bidder.model.Result; +import org.prebid.server.proto.openrtb.ext.ExtPrebid; +import org.prebid.server.proto.openrtb.ext.request.decenterads.ExtImpDecenterads; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; +import static java.util.function.Function.identity; +import static org.assertj.core.api.Assertions.assertThat; +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 DecenteradsBidderTest extends VertxTest { + + public static final String ENDPOINT_URL = "https://test.endpoint.com"; + + private DecenteradsBidder decenteradsBidder; + + @Before + public void setUp() { + decenteradsBidder = new DecenteradsBidder(ENDPOINT_URL, jacksonMapper); + } + + @Test + public void makeHttpRequestsShouldMakeOneRequestPerImp() { + // given + final BidRequest bidRequest = givenBidRequest( + identity(), + requestBuilder -> requestBuilder.imp(Arrays.asList( + givenImp(identity()), + Imp.builder() + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpDecenterads.of("somePubId")))) + .build()))); + + // when + final Result>> result = decenteradsBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(2) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .hasSize(2); + } + + @Test + public void makeHttpRequestsShouldReturnErrorOfEveryNotValidImp() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(asList(Imp.builder() + .id("123") + .banner(Banner.builder().build()) + .ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createArrayNode()))) + .build(), + givenImp(identity()))) + .build(); + + // when + final Result>> result = decenteradsBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).containsExactly(BidderError.badInput("bidder parameters required")); + } + + @Test + public void makeHttpRequestsShouldUpdateImpExt() { + // given + final BidRequest bidRequest = givenBidRequest(identity()); + + // when + final Result>> result = decenteradsBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getExt) + .containsExactly(mapper.valueToTree(ExtImpDecenterads.of("somePubId"))); + } + + @Test + public void makeBidsShouldReturnBannerBidByDefault() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder().imp(singletonList(Imp.builder().id("123").build())).build(), + mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = decenteradsBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), banner, "USD")); + } + + @Test + public void makeBidsShouldReturnVideoBidIfNoBannerAndHasVideo() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().video(Video.builder().build()).id("123").build())) + .build(), + mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = decenteradsBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), video, "USD")); + } + + @Test + public void makeBidsShouldReturnBannerBidIfHasBothBannerAndVideo() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(givenImp(identity()))) + .build(), + mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = decenteradsBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), banner, "USD")); + } + + @Test + public void makeBidsShouldReturnNativeBidIfNativeIsPresentInRequestImp() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().id("123").xNative(Native.builder().build()).build())) + .build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = decenteradsBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), xNative, "USD")); + } + + @Test + public void makeBidsShouldReturnAudioBidIfAudioIsPresentInRequestImp() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().id("123").audio(Audio.builder().build()).build())) + .build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = decenteradsBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), audio, "USD")); + } + + private static BidRequest givenBidRequest( + Function impCustomizer, + Function requestCustomizer) { + return requestCustomizer.apply(BidRequest.builder() + .imp(singletonList(givenImp(impCustomizer)))) + .build(); + } + + private static BidRequest givenBidRequest( + Function impCustomizer) { + return givenBidRequest(impCustomizer, identity()); + } + + private static Imp givenImp(Function impCustomizer) { + return impCustomizer.apply(Imp.builder() + .id("123")) + .banner(Banner.builder().build()) + .video(Video.builder().build()) + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpDecenterads.of("somePubId")))) + .build(); + } + + private static BidResponse givenBidResponse(Function bidCustomizer) { + return BidResponse.builder() + .cur("USD") + .seatbid(singletonList(SeatBid.builder() + .bid(singletonList(bidCustomizer.apply(Bid.builder()).build())) + .build())) + .build(); + } + + private static HttpCall givenHttpCall(BidRequest bidRequest, String body) { + return HttpCall.success(HttpRequest.builder().payload(bidRequest).build(), + HttpResponse.of(200, null, body), null); + } +} diff --git a/src/test/java/org/prebid/server/bidder/dmx/DmxBidderTest.java b/src/test/java/org/prebid/server/bidder/dmx/DmxBidderTest.java index 445178e3eb3..a8c9992dd9e 100644 --- a/src/test/java/org/prebid/server/bidder/dmx/DmxBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/dmx/DmxBidderTest.java @@ -5,6 +5,7 @@ import com.iab.openrtb.request.App; import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Device; import com.iab.openrtb.request.Format; import com.iab.openrtb.request.Imp; import com.iab.openrtb.request.Publisher; @@ -30,6 +31,7 @@ import org.prebid.server.proto.openrtb.ext.request.dmx.ExtImpDmx; import java.math.BigDecimal; +import java.util.Arrays; import java.util.List; import java.util.function.Function; @@ -77,6 +79,7 @@ public void makeHttpRequestsShouldReturnErrorWhenRequestContainsNoIdentifierIdIs final BidRequest bidRequest = givenBidRequest( builder -> builder .app(App.builder().id(null).build()) + .device(Device.builder().ifa(null).build()) .user(User.builder().id(null).ext(ExtUser.builder().eids(emptyList()).build()).build()), identity()); @@ -88,6 +91,23 @@ public void makeHttpRequestsShouldReturnErrorWhenRequestContainsNoIdentifierIdIs .containsExactly(BidderError.badInput("This request contained no identifier")); } + @Test + public void makeHttpRequestsShouldNotReturnErrorWhenRequestContainsNoAppIdentifierButHaveUser() { + // given + final BidRequest bidRequest = givenBidRequest( + builder -> builder + .app(App.builder().id(null).build()) + .device(Device.builder().ifa(null).build()) + .user(User.builder().id("uid").ext(ExtUser.builder().eids(emptyList()).build()).build()), + identity()); + + // when + final Result>> result = dmxBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + } + @Test public void makeHttpRequestsShouldReturnErrorIfImpExtCouldNotBeParsed() { // given @@ -137,6 +157,24 @@ public void makeHttpRequestsShouldModifyImpWhenBannerFormatIsNotEmpty() { .containsOnly(tuple("dmxId", 1, BigDecimal.ONE)); } + @Test + public void makeHttpRequestsShouldGetSizeForBannerFromFirstFormatIfAnyOfBannerSizesAreMissed() { + // given + final BidRequest bidRequest = givenBidRequest(identity()); + + // when + final Result>> result = dmxBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getBanner) + .extracting(Banner::getH, Banner::getW) + .containsOnly(tuple(500, 300)); + } + @Test public void makeHttpRequestsShouldModifyImpWhenVideoIsNotEmpty() { // given @@ -225,6 +263,25 @@ public void makeHttpRequestsShouldUpdateImpTagIdFromDmxIdWhenExtTagIdAndDmxIdIsP .containsExactly("dmxId"); } + @Test + public void makeHttpRequestsShouldEnrichVideoWithNeededProtocolsIfProtocolsAreMissed() { + // given + final BidRequest bidRequest = givenBidRequest( + builder -> builder.video(Video.builder().protocols(null).build())); + + // when + final Result>> result = dmxBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getVideo) + .flatExtracting(Video::getProtocols) + .containsAll(Arrays.asList(2, 3, 5, 6, 7, 8)); + } + @Test public void makeHttpRequestsShouldUpdateAppPublisherWhenAppAndExtImpPublisherIdIsPresent() { // given @@ -264,6 +321,27 @@ public void makeHttpRequestsShouldUpdateAppPublisherWhenAppAndMemberIdPresentAnd .containsExactly(expectedPublisher("memberId", true)); } + @Test + public void makeHttpRequestsShouldReplaceAppIdWithDeviceIfa() { + // given + final BidRequest bidRequest = givenBidRequest( + builder -> builder + .app(App.builder().id(null).build()) + .device(Device.builder().ifa("ifa").build()), + identity()); + + // when + final Result>> result = dmxBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .extracting(BidRequest::getApp) + .flatExtracting(App::getId) + .containsExactly("ifa"); + } + @Test public void makeHttpRequestsShouldUpdateSitePublisherWhenSiteAndExtImpPublisherIdIsPresent() { // given diff --git a/src/test/java/org/prebid/server/bidder/epom/EpomBidderTest.java b/src/test/java/org/prebid/server/bidder/epom/EpomBidderTest.java new file mode 100644 index 00000000000..f2b2d777405 --- /dev/null +++ b/src/test/java/org/prebid/server/bidder/epom/EpomBidderTest.java @@ -0,0 +1,291 @@ +package org.prebid.server.bidder.epom; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.iab.openrtb.request.Banner; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Device; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Native; +import com.iab.openrtb.request.Video; +import com.iab.openrtb.response.Bid; +import com.iab.openrtb.response.BidResponse; +import com.iab.openrtb.response.SeatBid; +import org.junit.Before; +import org.junit.Test; +import org.prebid.server.VertxTest; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.HttpCall; +import org.prebid.server.bidder.model.HttpRequest; +import org.prebid.server.bidder.model.HttpResponse; +import org.prebid.server.bidder.model.Result; +import org.prebid.server.proto.openrtb.ext.ExtPrebid; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +import static java.util.Collections.singletonList; +import static java.util.function.Function.identity; +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.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 EpomBidderTest extends VertxTest { + + public static final String ENDPOINT_URL = "https://test.endpoint.com"; + + private EpomBidder epomBidder; + + @Before + public void setUp() { + epomBidder = new EpomBidder(ENDPOINT_URL, jacksonMapper); + } + + @Test + public void creationShouldFailOnInvalidEndpointUrl() { + assertThatIllegalArgumentException().isThrownBy(() -> new EpomBidder("invalid_url", jacksonMapper)); + } + + @Test + public void makeHttpRequestsShouldMakeOneRequestWithAllImps() { + // given + final BidRequest bidRequest = givenBidRequest( + identity(), + requestBuilder -> requestBuilder.imp(Arrays.asList( + givenImp(identity()), + givenImp(identity())))); + + // when + final Result>> result = epomBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .hasSize(2); + } + + @Test + public void makeHttpRequestsShouldReturnErrorIfDeviceNotPresent() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createObjectNode()))) + .build())) + .build(); + + // when + final Result>> result = epomBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).containsExactly(BidderError.badInput("ipv4 address is required field")); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeHttpRequestsShouldReturnErrorIfDeviceIpNotPresent() { + // given + final BidRequest bidRequest = BidRequest.builder() + .device(Device.builder().build()) + .imp(singletonList(Imp.builder() + .ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createObjectNode()))) + .build())) + .build(); + + // when + final Result>> result = epomBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).containsExactly(BidderError.badInput("ipv4 address is required field")); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnEmptyListIfBidResponseIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall(null, mapper.writeValueAsString(null)); + + // when + final Result> result = epomBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnEmptyListIfBidResponseSeatBidIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall(null, + mapper.writeValueAsString(BidResponse.builder().build())); + + // when + final Result> result = epomBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { + // given + final HttpCall httpCall = givenHttpCall(null, "invalid"); + + // when + final Result> result = epomBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).hasSize(1) + .allSatisfy(error -> { + assertThat(error.getType()).isEqualTo(BidderError.Type.bad_server_response); + assertThat(error.getMessage()).startsWith("Failed to decode: Unrecognized token"); + }); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnBannerBidByDefault() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().id("123").xNative(Native.builder().build()).build())) + .build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.impid("125")))); + + // when + final Result> result = epomBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("125").build(), banner, "USD")); + } + + @Test + public void makeBidsShouldReturnBannerBidIfBannerIsPresent() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().banner(Banner.builder().build()).id("123").build())) + .build(), + mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = epomBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), banner, "USD")); + } + + @Test + public void makeBidsShouldReturnVideoBidIfNoBannerAndHasVideo() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().video(Video.builder().build()).id("123").build())) + .build(), + mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = epomBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), video, "USD")); + } + + @Test + public void makeBidsShouldReturnNativeBidIfNoBannerAndVideoButNativeIsPresent() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().xNative(Native.builder().build()).id("123").build())) + .build(), + mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = epomBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), xNative, "USD")); + } + + @Test + public void makeBidsShouldReturnBannerBidIfHasBothBannerAndVideo() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(givenImp(identity()))) + .build(), + mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = epomBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), banner, "USD")); + } + + @Test + public void makeBidsShouldReturnNativeBidIfNativeIsPresentInRequestImp() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().id("123").xNative(Native.builder().build()).build())) + .build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = epomBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), xNative, "USD")); + } + + private static BidRequest givenBidRequest( + Function impCustomizer, + Function requestCustomizer) { + return requestCustomizer.apply(BidRequest.builder() + .device(Device.builder().ip("123.123.123.123").build()) + .imp(singletonList(givenImp(impCustomizer)))) + .build(); + } + + private static Imp givenImp(Function impCustomizer) { + return impCustomizer.apply(Imp.builder() + .id("123")) + .banner(Banner.builder().build()) + .ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createObjectNode()))) + .build(); + } + + private static BidResponse givenBidResponse(Function bidCustomizer) { + return BidResponse.builder() + .cur("USD") + .seatbid(singletonList(SeatBid.builder() + .bid(singletonList(bidCustomizer.apply(Bid.builder()).build())) + .build())) + .build(); + } + + private static HttpCall givenHttpCall(BidRequest bidRequest, String body) { + return HttpCall.success(HttpRequest.builder().payload(bidRequest).build(), + HttpResponse.of(200, null, body), null); + } +} diff --git a/src/test/java/org/prebid/server/bidder/gamma/GammaBidderTest.java b/src/test/java/org/prebid/server/bidder/gamma/GammaBidderTest.java index 62169af095c..d6069fcd6fe 100644 --- a/src/test/java/org/prebid/server/bidder/gamma/GammaBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/gamma/GammaBidderTest.java @@ -16,6 +16,8 @@ import org.junit.Test; import org.prebid.server.VertxTest; import org.prebid.server.bidder.gamma.model.GammaBid; +import org.prebid.server.bidder.gamma.model.GammaBidResponse; +import org.prebid.server.bidder.gamma.model.GammaSeatBid; import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderError; import org.prebid.server.bidder.model.HttpCall; @@ -238,13 +240,14 @@ public void makeBidsShouldSetAdmFromVastXmlIsPresentAndVideoType() throws JsonPr final BidRequest bidRequest = BidRequest.builder().imp(singletonList(imp)).build(); final String adm = "ADM"; - final GammaBid bid = GammaBid.builder().id("impId").vastXml(adm).build(); + final Bid bid = Bid.builder().id("impId").build(); + final GammaBid gammaBid = GammaBid.builder().bid(bid).vastXml(adm).build(); final HttpCall httpCall = givenHttpCall(mapper.writeValueAsString( - BidResponse.builder() + GammaBidResponse.builder() .id("impId") .cur("USD") - .seatbid(singletonList(SeatBid.builder() - .bid(singletonList(bid)) + .seatbid(singletonList(GammaSeatBid.builder() + .bid(singletonList(gammaBid)) .build())) .build())); @@ -266,13 +269,14 @@ public void makeBidsShouldSetAdmFromVastXmlAndNurlFromVastUrlAndVideoType() thro final String adm = "ADM"; final String nurl = "NURL"; - final GammaBid bid = GammaBid.builder().id("impId").vastXml(adm).vastUrl(nurl).build(); + final Bid bid = Bid.builder().id("impId").build(); + final GammaBid gammaBid = GammaBid.builder().bid(bid).vastXml(adm).vastUrl(nurl).build(); final HttpCall httpCall = givenHttpCall(mapper.writeValueAsString( - BidResponse.builder() + GammaBidResponse.builder() .id("impId") .cur("USD") - .seatbid(singletonList(SeatBid.builder() - .bid(singletonList(bid)) + .seatbid(singletonList(GammaSeatBid.builder() + .bid(singletonList(gammaBid)) .build())) .build())); @@ -350,7 +354,7 @@ public void makeBidsShouldReturnBannerWhenNoProvided() throws JsonProcessingExce // then assertThat(result.getErrors()).isEmpty(); - final GammaBid expectedBid = GammaBid.builder().adm("ADM").build(); + final Bid expectedBid = Bid.builder().adm("ADM").build(); assertThat(result.getValue()) .containsOnly(BidderBid.of(expectedBid, banner, "USD")); } diff --git a/src/test/java/org/prebid/server/bidder/gumgum/GumgumBidderTest.java b/src/test/java/org/prebid/server/bidder/gumgum/GumgumBidderTest.java index 30eba2a7588..831ac28a777 100644 --- a/src/test/java/org/prebid/server/bidder/gumgum/GumgumBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/gumgum/GumgumBidderTest.java @@ -1,12 +1,12 @@ package org.prebid.server.bidder.gumgum; import com.fasterxml.jackson.core.JsonProcessingException; -import com.iab.openrtb.request.Audio; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Format; import com.iab.openrtb.request.Imp; -import com.iab.openrtb.request.Native; +import com.iab.openrtb.request.Publisher; import com.iab.openrtb.request.Site; import com.iab.openrtb.request.Video; import com.iab.openrtb.response.Bid; @@ -23,8 +23,10 @@ import org.prebid.server.bidder.model.Result; import org.prebid.server.proto.openrtb.ext.ExtPrebid; import org.prebid.server.proto.openrtb.ext.request.gumgum.ExtImpGumgum; +import org.prebid.server.proto.openrtb.ext.request.gumgum.ExtImpGumgumVideo; import java.math.BigDecimal; +import java.math.BigInteger; import java.util.List; import java.util.function.Function; @@ -80,17 +82,16 @@ public void makeHttpRequestsShouldReturnErrorsIfImpExtCouldNotBeParsed() { public void makeHttpRequestsShouldReturnErrorIfNoValidImpressions() { // given final BidRequest bidRequest = BidRequest.builder() - .imp(asList( - givenImp(impBuilder -> impBuilder.banner(null).audio(Audio.builder().build())), - givenImp(impBuilder -> impBuilder.banner(null).xNative(Native.builder().build())))) + .imp(singletonList( + givenImp(impBuilder -> impBuilder.video(Video.builder().build())))) .build(); // when final Result>> result = gumgumBidder.makeHttpRequests(bidRequest); // then - assertThat(result.getErrors()) - .containsExactly(BidderError.badInput("No valid impressions")); + assertThat(result.getErrors()).hasSize(2) + .contains(BidderError.badInput("No valid impressions")); assertThat(result.getValue()).isEmpty(); } @@ -100,7 +101,7 @@ public void makeHttpRequestsShouldReturnErrorIfVideoFieldsAreNotValid() { final BidRequest bidRequest = BidRequest.builder() .imp(singletonList(Imp.builder() .video(Video.builder().w(0).build()) - .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpGumgum.of("zone")))) + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpGumgum.of("zone", BigInteger.TEN, "irisId")))) .build())) .build(); @@ -115,39 +116,45 @@ public void makeHttpRequestsShouldReturnErrorIfVideoFieldsAreNotValid() { } @Test - public void makeHttpRequestsShouldSkipImpressionsWithoutBannerOrVideo() { + public void makeHttpRequestsShouldModifyVideoExtOfIrisIdIsPresent() { // given final BidRequest bidRequest = BidRequest.builder() - .imp(asList( - givenImp(impBuilder -> impBuilder.banner(null).video(null).audio(Audio.builder().build())), - givenImp(identity()))) + .imp(singletonList(Imp.builder() + .video(Video.builder() + .w(20) + .h(30) + .maxduration(12) + .minduration(34) + .placement(33) + .linearity(233) + .build()) + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpGumgum.of("zone", BigInteger.TEN, "irisId")))) + .build())) .build(); // when final Result>> result = gumgumBidder.makeHttpRequests(bidRequest); // then + final ObjectNode expectedVideoExt = mapper.valueToTree(ExtImpGumgumVideo.of("irisId")); assertThat(result.getErrors()).isEmpty(); assertThat(result.getValue()) .extracting(HttpRequest::getPayload) .flatExtracting(BidRequest::getImp) - .extracting(Imp::getBanner) - .extracting(Banner::getId) - .containsExactly("banner_id"); + .extracting(Imp::getVideo) + .extracting(Video::getExt) + .containsExactly(expectedVideoExt); } @Test - public void makeHttpRequestsShouldSetEmtyStringIfZoneIsNull() { + public void makeHttpRequestsShouldNotChangeBannerWidthAndHeightIfPresent() { // given - final BidRequest bidRequest = givenBidRequest(bidRequestBuilder -> - bidRequestBuilder.site(Site.builder().build()), - impBuilder -> impBuilder.ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpGumgum.of(null))))); - BidRequest.builder() - .site(Site.builder().build()) - .imp(asList( - givenImp(impBuilder -> impBuilder.banner(null).video(null).audio(Audio.builder().build())), - givenImp(identity()))) - .build(); + final BidRequest bidRequest = givenBidRequest( + impBuilder -> impBuilder + .banner(Banner.builder() + .format(singletonList(Format.builder().w(300).h(450).build())) + .w(600).h(900) + .build())); // when final Result>> result = gumgumBidder.makeHttpRequests(bidRequest); @@ -155,33 +162,32 @@ public void makeHttpRequestsShouldSetEmtyStringIfZoneIsNull() { // then assertThat(result.getErrors()).isEmpty(); assertThat(result.getValue()) - .extracting(HttpRequest::getPayload) - .extracting(BidRequest::getSite) - .extracting(Site::getId) - .containsExactly(""); + .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getBanner) + .extracting(Banner::getW, Banner::getH) + .containsExactly(tuple(600, 900)); } @Test - public void makeHttpRequestsShouldNotChangeBannerWidthAndHeightIfPresent() { + public void makeHttpRequestsShouldUpdatePublisherIfPubIdIsPresent() { // given + final Publisher sitePublisher = Publisher.builder().name("testPublisher").build(); final BidRequest bidRequest = givenBidRequest( - impBuilder -> impBuilder - .banner(Banner.builder() - .format(singletonList(Format.builder().w(300).h(450).build())) - .w(600).h(900) - .build())); + bidRequestBuilder -> bidRequestBuilder.site(Site.builder().publisher(sitePublisher).build()), + impBuilder -> impBuilder.banner(Banner.builder().w(600).h(900).build())); // when final Result>> result = gumgumBidder.makeHttpRequests(bidRequest); // then + final Publisher expectedPublisher = sitePublisher.toBuilder().id("10").build(); assertThat(result.getErrors()).isEmpty(); assertThat(result.getValue()) .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) - .flatExtracting(BidRequest::getImp) - .extracting(Imp::getBanner) - .extracting(Banner::getW, Banner::getH) - .containsExactly(tuple(600, 900)); + .extracting(BidRequest::getSite) + .extracting(Site::getPublisher) + .containsExactly(expectedPublisher); } @Test @@ -189,8 +195,8 @@ public void makeHttpRequestsShouldSetBannerWidthAndHeightFromfirstFormatIfAbsent // given final BidRequest bidRequest = givenBidRequest( impBuilder -> impBuilder.banner(Banner.builder() - .format(singletonList(Format.builder().w(300).h(450).build())) - .build())); + .format(singletonList(Format.builder().w(300).h(450).build())) + .build())); // when final Result>> result = gumgumBidder.makeHttpRequests(bidRequest); @@ -229,12 +235,9 @@ public void makeHttpRequestsShouldSetSiteIdFromLastValidImpExtZone() { .imp(asList( givenImp(impBuilder -> impBuilder .banner(Banner.builder().build()) - .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpGumgum.of("ignored zone"))))), - givenImp(identity()), - givenImp(impBuilder -> impBuilder - .banner(null) - .audio(Audio.builder().build()) - .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpGumgum.of("invalid imp"))))))) + .ext(mapper.valueToTree(ExtPrebid.of(null, + ExtImpGumgum.of("ignored zone", BigInteger.TEN, "irisId"))))), + givenImp(identity()))) .build(); // when @@ -379,7 +382,7 @@ private static Imp givenImp(Function impCustomiz return impCustomizer.apply(Imp.builder() .id("123") .banner(Banner.builder().id("banner_id").build()) - .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpGumgum.of("zone"))))) + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpGumgum.of("zone", BigInteger.TEN, "irisId"))))) .build(); } diff --git a/src/test/java/org/prebid/server/bidder/improvedigital/ImprovedigitalBidderTest.java b/src/test/java/org/prebid/server/bidder/improvedigital/ImprovedigitalBidderTest.java index b8e41ba5496..97358df6662 100644 --- a/src/test/java/org/prebid/server/bidder/improvedigital/ImprovedigitalBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/improvedigital/ImprovedigitalBidderTest.java @@ -1,8 +1,11 @@ package org.prebid.server.bidder.improvedigital; import com.fasterxml.jackson.core.JsonProcessingException; +import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Native; +import com.iab.openrtb.request.Video; import com.iab.openrtb.response.Bid; import com.iab.openrtb.response.BidResponse; import com.iab.openrtb.response.SeatBid; @@ -20,10 +23,13 @@ import java.util.List; import java.util.function.Function; +import static java.util.Arrays.asList; 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.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 ImprovedigitalBidderTest extends VertxTest { @@ -57,8 +63,8 @@ public void makeHttpRequestsShouldNotModifyIncomingRequest() { // then assertThat(result.getErrors()).isEmpty(); assertThat(result.getValue()).hasSize(1) - .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) - .containsOnly(bidRequest); + .extracting(HttpRequest::getPayload) + .containsExactly(bidRequest); } @Test @@ -105,7 +111,28 @@ public void makeBidsShouldReturnEmptyListIfBidResponseSeatBidIsNull() throws Jso } @Test - public void makeBidsShouldReturnBannerBidIfBannerIsPresent() throws JsonProcessingException { + public void makeBidsShouldReturnErrorWhenSeatBidsCountIsMoreThanOne() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall(null, + mapper.writeValueAsString(BidResponse.builder().seatbid(asList(SeatBid.builder() + .bid(singletonList(Bid.builder().build())) + .build(), + SeatBid.builder() + .bid(singletonList(Bid.builder().build())) + .build() + )).build())); + + // when + final Result> result = improvedigitalBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).hasSize(1) + .containsExactly(BidderError.badServerResponse("Unexpected SeatBid! Must be only one but have: 2")); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnErrorIfBannerOrVideoNotPresent() throws JsonProcessingException { // given final HttpCall httpCall = givenHttpCall( BidRequest.builder() @@ -117,10 +144,86 @@ public void makeBidsShouldReturnBannerBidIfBannerIsPresent() throws JsonProcessi // when final Result> result = improvedigitalBidder.makeBids(httpCall, null); + // then + assertThat(result.getErrors()) + .containsExactly(BidderError.badServerResponse("Unknown impression type for ID: \"123\"")); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnBannerBidIfBannerIsPresent() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().banner(Banner.builder().build()).id("123").build())) + .build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = improvedigitalBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), banner, "USD")); + } + + @Test + public void makeBidsShouldReturnVideoBidIfVideoIsPresent() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().video(Video.builder().build()).id("123").build())) + .build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = improvedigitalBidder.makeBids(httpCall, null); + // then assertThat(result.getErrors()).isEmpty(); assertThat(result.getValue()) - .containsOnly(BidderBid.of(Bid.builder().impid("123").build(), banner, "USD")); + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), video, "USD")); + } + + @Test + public void makeBidsShouldReturnNativeBidIfNativeIsPresent() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().xNative(Native.builder().build()).id("123").build())) + .build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = improvedigitalBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), xNative, "USD")); + } + + @Test + public void makeBidsShouldReturnErrorIfImpNotFoundForId() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().video(Video.builder().build()).id("123").build())) + .build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.impid("456")))); + + // when + final Result> result = improvedigitalBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()) + .containsExactly(BidderError.badServerResponse("Failed to find impression for ID: \"456\"")); + assertThat(result.getValue()).isEmpty(); } private static BidResponse givenBidResponse(Function bidCustomizer) { diff --git a/src/test/java/org/prebid/server/bidder/jixie/JixieBidderTest.java b/src/test/java/org/prebid/server/bidder/jixie/JixieBidderTest.java new file mode 100644 index 00000000000..de5d1312872 --- /dev/null +++ b/src/test/java/org/prebid/server/bidder/jixie/JixieBidderTest.java @@ -0,0 +1,233 @@ +package org.prebid.server.bidder.jixie; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.iab.openrtb.request.Banner; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Device; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Native; +import com.iab.openrtb.request.Site; +import com.iab.openrtb.response.Bid; +import com.iab.openrtb.response.BidResponse; +import com.iab.openrtb.response.SeatBid; +import io.netty.handler.codec.http.HttpHeaderValues; +import org.junit.Before; +import org.junit.Test; +import org.prebid.server.VertxTest; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.HttpCall; +import org.prebid.server.bidder.model.HttpRequest; +import org.prebid.server.bidder.model.HttpResponse; +import org.prebid.server.bidder.model.Result; +import org.prebid.server.proto.openrtb.ext.ExtPrebid; +import org.prebid.server.proto.openrtb.ext.request.jixie.ExtImpJixie; +import org.prebid.server.util.HttpUtil; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +import static java.util.Collections.singletonList; +import static java.util.function.Function.identity; +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.proto.openrtb.ext.response.BidType.banner; +import static org.prebid.server.proto.openrtb.ext.response.BidType.video; + +public class JixieBidderTest extends VertxTest { + + public static final String ENDPOINT_URL = "https://test.endpoint.com"; + + private JixieBidder jixieBidder; + + @Before + public void setUp() { + jixieBidder = new JixieBidder(ENDPOINT_URL, jacksonMapper); + } + + @Test + public void creationShouldFailOnInvalidEndpointUrl() { + assertThatIllegalArgumentException().isThrownBy(() -> new JixieBidder("invalid_url", jacksonMapper)); + } + + @Test + public void makeHttpRequestsShouldMakeOneRequestWithAllImps() { + // given + final BidRequest bidRequest = givenBidRequest( + identity(), + requestBuilder -> requestBuilder.imp(Arrays.asList( + givenImp(identity()), + givenImp(identity())))); + + // when + final Result>> result = jixieBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .hasSize(2); + } + + @Test + public void makeHttpRequestsShouldCorrectlyAddHeaders() { + // given + final Imp firstImp = givenImp(identity()); + + final BidRequest bidRequest = BidRequest.builder() + .device(Device.builder().ua("someUa").ip("someIp").build()) + .site(Site.builder().page("somePage").build()) + .imp(singletonList(firstImp)) + .build(); + + // when + final Result>> result = jixieBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getValue()) + .flatExtracting(res -> res.getHeaders().entries()) + .extracting(Map.Entry::getKey, Map.Entry::getValue) + .containsExactlyInAnyOrder( + tuple(HttpUtil.CONTENT_TYPE_HEADER.toString(), HttpUtil.APPLICATION_JSON_CONTENT_TYPE), + tuple(HttpUtil.ACCEPT_HEADER.toString(), HttpHeaderValues.APPLICATION_JSON.toString()), + tuple(HttpUtil.USER_AGENT_HEADER.toString(), "someUa"), + tuple(HttpUtil.X_FORWARDED_FOR_HEADER.toString(), "someIp"), + tuple(HttpUtil.REFERER_HEADER.toString(), "somePage")); + } + + @Test + public void makeBidsShouldReturnEmptyListIfBidResponseIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall(null, mapper.writeValueAsString(null)); + + // when + final Result> result = jixieBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnEmptyListIfBidResponseSeatBidIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall(null, + mapper.writeValueAsString(BidResponse.builder().build())); + + // when + final Result> result = jixieBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { + // given + final HttpCall httpCall = givenHttpCall(null, "invalid"); + + // when + final Result> result = jixieBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).hasSize(1) + .allSatisfy(error -> { + assertThat(error.getType()).isEqualTo(BidderError.Type.bad_server_response); + assertThat(error.getMessage()).startsWith("Failed to decode: Unrecognized token"); + }); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnVideoBidIfAdmContainsVast() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().id("123").xNative(Native.builder().build()).build())) + .build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.adm("contains > result = jixieBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().adm("contains httpCall = givenHttpCall( + givenBidRequest(identity()), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.adm("contains > result = jixieBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().adm("contains httpCall = givenHttpCall( + givenBidRequest(identity()), + mapper.writeValueAsString(givenBidResponse(identity()))); + + // when + final Result> result = jixieBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().build(), banner, "EUR")); + } + + private static BidRequest givenBidRequest( + Function impCustomizer, + Function requestCustomizer) { + return requestCustomizer.apply(BidRequest.builder() + .imp(singletonList(givenImp(impCustomizer)))) + .build(); + } + + private static BidRequest givenBidRequest( + Function impCustomizer) { + return givenBidRequest(impCustomizer, identity()); + } + + private static Imp givenImp(Function impCustomizer) { + return impCustomizer.apply(Imp.builder() + .id("123")) + .banner(Banner.builder().build()) + .ext(mapper.valueToTree(ExtPrebid.of(null, + ExtImpJixie.of("unit", "accountId", "jxProp1", "jxProp2")))) + .build(); + } + + private static BidResponse givenBidResponse(Function bidCustomizer) { + return BidResponse.builder() + .cur("EUR") + .seatbid(singletonList(SeatBid.builder() + .bid(singletonList(bidCustomizer.apply(Bid.builder()).build())) + .build())) + .build(); + } + + private static HttpCall givenHttpCall(BidRequest bidRequest, String body) { + return HttpCall.success(HttpRequest.builder().payload(bidRequest).build(), + HttpResponse.of(200, null, body), null); + } +} diff --git a/src/test/java/org/prebid/server/bidder/mobfoxpb/MobfoxpbBidderTest.java b/src/test/java/org/prebid/server/bidder/mobfoxpb/MobfoxpbBidderTest.java index 62a1b44d49e..afafb34c6a1 100644 --- a/src/test/java/org/prebid/server/bidder/mobfoxpb/MobfoxpbBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/mobfoxpb/MobfoxpbBidderTest.java @@ -23,9 +23,11 @@ import java.util.Arrays; import java.util.List; +import java.util.function.Function; import java.util.function.UnaryOperator; import static java.util.Collections.singletonList; +import static java.util.function.Function.identity; 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.banner; @@ -34,7 +36,7 @@ public class MobfoxpbBidderTest extends VertxTest { - private static final String ENDPOINT_URL = "https://test.endpoint.com"; + private static final String ENDPOINT_URL = "https://test.endpoint.com?c=__route__&m=__method__&key=__key__"; private MobfoxpbBidder mobfoxpbBidder; @@ -51,69 +53,90 @@ public void creationShouldFailOnInvalidEndpointUrl() { @Test public void makeHttpRequestsShouldReturnErrorIfImpExtCouldNotBeParsed() { // given - final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(Imp.builder() - .ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createArrayNode()))) - .build())) - .build(); + final BidRequest bidRequest = givenBidRequest(impBuilder -> impBuilder + .ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createArrayNode())))); // when final Result>> result = mobfoxpbBidder.makeHttpRequests(bidRequest); // then - assertThat(result.getErrors()).hasSize(1); - assertThat(result.getErrors().get(0).getMessage()).startsWith("Cannot deserialize instance"); + assertThat(result.getErrors()).allSatisfy(error -> { + assertThat(error.getType()).isEqualTo(BidderError.Type.bad_input); + assertThat(error.getMessage()).startsWith("Cannot deserialize instance"); + }); assertThat(result.getValue()).isEmpty(); } @Test - public void makeHttpRequestsShouldModifyImpTagId() { + public void makeHttpRequestsShouldReturnErrorIfImpExtDoesNotContainRequiredAttributes() { // given - final String extTagId = "extTagId"; - final BidRequest bidRequest = BidRequest.builder() - .imp(singletonList(Imp.builder() - .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpMobfoxpb.of(extTagId)))) - .build())) - .build(); + final BidRequest bidRequest = givenBidRequest(impBuilder -> impBuilder + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpMobfoxpb.of("", null))))); + + // when + final Result>> result = mobfoxpbBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()) + .containsExactly( + BidderError.badInput("Invalid or non existing key and tagId, atleast one should be present")); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeHttpRequestsShouldSetKeyRtbRouteAndMethodToUrlIfKeyParamIsPresent() { + // given + final BidRequest bidRequest = givenBidRequest(identity()); // when final Result>> result = mobfoxpbBidder.makeHttpRequests(bidRequest); // then assertThat(result.getErrors()).isEmpty(); - assertThat(result.getValue()).hasSize(1) - .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) - .flatExtracting(BidRequest::getImp) - .extracting(Imp::getTagid) - .containsExactly(extTagId); + assertThat(result.getValue()).hasSize(1); + assertThat(result.getValue()) + .extracting(HttpRequest::getUri) + .containsExactly("https://test.endpoint.com?c=rtb&m=req&key=key"); + } + + @Test + public void makeHttpRequestsShouldSetNativeRouteAndMethodToUrlIfKeyParamIsPresent() { + // given + final BidRequest bidRequest = givenBidRequest(impBuilder -> + impBuilder.ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpMobfoxpb.of("tagId", null)))) + ); + + // when + final Result>> result = mobfoxpbBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1); + assertThat(result.getValue()) + .extracting(HttpRequest::getUri) + .containsExactly("https://test.endpoint.com?c=o&m=ortb&key=__key__"); } @Test public void makeHttpRequestsShouldSendOnlyOneImp() { // given - final String extTagId = "extTagId"; - final Imp firstImp = Imp.builder() - .tagid("tag") - .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpMobfoxpb.of(extTagId)))) - .build(); - final List imps = Arrays.asList(firstImp, Imp.builder().build(), Imp.builder().build()); - final BidRequest bidRequest = BidRequest.builder() - .imp(imps) - .build(); + final Imp firstImp = givenImp(impBuilder -> impBuilder.id("firstImpId")); + final List imps = Arrays.asList(firstImp, givenImp(identity()), givenImp(identity())); + final BidRequest bidRequest = + BidRequest.builder() + .imp(imps) + .build(); // when final Result>> result = mobfoxpbBidder.makeHttpRequests(bidRequest); // then - final Imp expectedImp = Imp.builder() - .tagid(extTagId) - .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpMobfoxpb.of(extTagId)))) - .build(); assertThat(result.getErrors()).isEmpty(); assertThat(result.getValue()).hasSize(1) .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) .flatExtracting(BidRequest::getImp) - .containsExactly(expectedImp); + .extracting(Imp::getId) + .containsExactly("firstImpId"); } @Test @@ -125,9 +148,38 @@ public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { final Result> result = mobfoxpbBidder.makeBids(httpCall, null); // then - assertThat(result.getErrors()).hasSize(1); - assertThat(result.getErrors().get(0).getMessage()).startsWith("Failed to decode: Unrecognized token"); - assertThat(result.getErrors().get(0).getType()).isEqualTo(BidderError.Type.bad_server_response); + assertThat(result.getErrors()).allSatisfy(error -> { + assertThat(error.getType()).isEqualTo(BidderError.Type.bad_server_response); + assertThat(error.getMessage()).startsWith("Failed to decode: Unrecognized token"); + }); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnEmptyListIfBidResponseIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall(givenBidRequest(identity()), + mapper.writeValueAsString(null)); + + // when + final Result> result = mobfoxpbBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnEmptyListIfBidResponseSeatBidIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall(givenBidRequest(identity()), + mapper.writeValueAsString(BidResponse.builder().build())); + + // when + final Result> result = mobfoxpbBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); assertThat(result.getValue()).isEmpty(); } @@ -135,9 +187,7 @@ public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { public void makeBidsShouldReturnBannerBidIfBannerIsPresent() throws JsonProcessingException { // given final HttpCall httpCall = givenHttpCall( - BidRequest.builder() - .imp(singletonList(Imp.builder().id("123").banner(Banner.builder().build()).build())) - .build(), + givenBidRequest(impBuilder -> impBuilder.banner(Banner.builder().build())), mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); // when @@ -153,9 +203,7 @@ public void makeBidsShouldReturnBannerBidIfBannerIsPresent() throws JsonProcessi public void makeBidsShouldReturnVideoBidIfVideoIsPresent() throws JsonProcessingException { // given final HttpCall httpCall = givenHttpCall( - BidRequest.builder() - .imp(singletonList(Imp.builder().id("123").video(Video.builder().build()).build())) - .build(), + givenBidRequest(impBuilder -> impBuilder.video(Video.builder().build())), mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); // when @@ -171,9 +219,7 @@ public void makeBidsShouldReturnVideoBidIfVideoIsPresent() throws JsonProcessing public void makeBidsShouldReturnNativeBidIfNativeIsPresent() throws JsonProcessingException { // given final HttpCall httpCall = givenHttpCall( - BidRequest.builder() - .imp(singletonList(Imp.builder().id("123").xNative(Native.builder().build()).build())) - .build(), + givenBidRequest(impBuilder -> impBuilder.xNative(Native.builder().build())), mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); // when @@ -189,19 +235,37 @@ public void makeBidsShouldReturnNativeBidIfNativeIsPresent() throws JsonProcessi public void makeBidsShouldReturnResponseWithErrorWhenIdIsNotFound() throws JsonProcessingException { // given final HttpCall httpCall = givenHttpCall( - BidRequest.builder() - .imp(singletonList(Imp.builder().id("123").build())) - .build(), + givenBidRequest(identity()), mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("no")))); // when final Result> result = mobfoxpbBidder.makeBids(httpCall, null); // then - assertThat(result.getErrors()).containsOnly(BidderError.badInput("Failed to find impression no")); + assertThat(result.getErrors()).containsOnly(BidderError.badInput("Failed to find impression \"no\"")); assertThat(result.getValue()).isEmpty(); } + private static BidRequest givenBidRequest( + Function bidRequestCustomizer, + Function impCustomizer) { + + return bidRequestCustomizer.apply(BidRequest.builder() + .imp(singletonList(givenImp(impCustomizer)))) + .build(); + } + + private static BidRequest givenBidRequest(Function impCustomizer) { + return givenBidRequest(identity(), impCustomizer); + } + + private static Imp givenImp(Function impCustomizer) { + return impCustomizer.apply(Imp.builder() + .id("123") + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpMobfoxpb.of("tagId", "key"))))) + .build(); + } + private static BidResponse givenBidResponse(UnaryOperator bidCustomizer) { return BidResponse.builder() .cur("USD") @@ -216,5 +280,4 @@ private static HttpCall givenHttpCall(BidRequest bidRequest, String HttpRequest.builder().payload(bidRequest).build(), HttpResponse.of(200, null, body), null); } - } diff --git a/src/test/java/org/prebid/server/bidder/onetag/OnetagBidderTest.java b/src/test/java/org/prebid/server/bidder/onetag/OnetagBidderTest.java new file mode 100644 index 00000000000..1ad6bceec87 --- /dev/null +++ b/src/test/java/org/prebid/server/bidder/onetag/OnetagBidderTest.java @@ -0,0 +1,362 @@ +package org.prebid.server.bidder.onetag; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.iab.openrtb.request.Banner; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Native; +import com.iab.openrtb.request.Video; +import com.iab.openrtb.response.Bid; +import com.iab.openrtb.response.BidResponse; +import com.iab.openrtb.response.SeatBid; +import org.junit.Before; +import org.junit.Test; +import org.prebid.server.VertxTest; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.HttpCall; +import org.prebid.server.bidder.model.HttpRequest; +import org.prebid.server.bidder.model.HttpResponse; +import org.prebid.server.bidder.model.Result; +import org.prebid.server.proto.openrtb.ext.ExtPrebid; +import org.prebid.server.proto.openrtb.ext.request.onetag.ExtImpOnetag; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; +import static java.util.function.Function.identity; +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.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 OnetagBidderTest extends VertxTest { + + public static final String ENDPOINT_URL = "https://test.endpoint.com/{{publisherId}}"; + + private OnetagBidder onetagBidder; + + @Before + public void setUp() { + onetagBidder = new OnetagBidder(ENDPOINT_URL, jacksonMapper); + } + + @Test + public void creationShouldFailOnInvalidEndpointUrl() { + assertThatIllegalArgumentException().isThrownBy(() -> new OnetagBidder("invalid_url", jacksonMapper)); + } + + @Test + public void makeHttpRequestsShouldCreateCorrectURL() { + // given + final BidRequest bidRequest = givenBidRequest(identity()); + + // when + final Result>> result = onetagBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1); + assertThat(result.getValue()) + .extracting(HttpRequest::getUri) + .containsExactly("https://test.endpoint.com/somePubId"); + } + + @Test + public void makeHttpRequestsShouldMakeOneRequestWithAllImps() { + // given + final BidRequest bidRequest = givenBidRequest( + identity(), + requestBuilder -> requestBuilder.imp(Arrays.asList( + givenImp(identity()), + givenImp(identity())))); + + // when + final Result>> result = onetagBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .hasSize(2); + } + + @Test + public void makeHttpRequestsShouldReturnErrorIfImpExtCanNotBeParsed() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(asList(Imp.builder() + .ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createArrayNode()))) + .build(), + givenImp(identity()))) + .build(); + + // when + final Result>> result = onetagBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).hasSize(1) + .allSatisfy(error -> { + assertThat(error.getType()).isEqualTo(BidderError.Type.bad_input); + assertThat(error.getMessage()).startsWith("Cannot deserialize instance"); + }); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeHttpRequestsShouldUpdateImpExt() { + // given + final ObjectNode oneTagExt = mapper.createObjectNode(); + oneTagExt.put("someField", "someName"); + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpOnetag.of("somePubId", oneTagExt)))) + .build())) + .build(); + + // when + final Result>> result = onetagBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getExt) + .containsExactly(oneTagExt); + } + + @Test + public void makeHttpRequestsShouldReturnErrorIfPubIdNotPresent() { + // given + final ObjectNode oneTagExt = mapper.createObjectNode(); + oneTagExt.put("someField", "someName"); + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpOnetag.of("", oneTagExt)))) + .build())) + .build(); + + // when + final Result>> result = onetagBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).containsExactly(BidderError.badInput("The publisher ID must not be empty")); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeHttpRequestsShouldReturnErrorIfPubIdAreDifferentInImpExts() { + // given + final BidRequest bidRequest = givenBidRequest( + identity(), + requestBuilder -> requestBuilder.imp(Arrays.asList( + givenImp(identity()), + Imp.builder() + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpOnetag.of("anotherPubId", + mapper.createObjectNode())))) + .build()))); + + // when + final Result>> result = onetagBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).containsExactly(BidderError.badInput("There must be only one publisher ID")); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnEmptyListIfBidResponseIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall(null, mapper.writeValueAsString(null)); + + // when + final Result> result = onetagBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnEmptyListIfBidResponseSeatBidIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall(null, + mapper.writeValueAsString(BidResponse.builder().build())); + + // when + final Result> result = onetagBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { + // given + final HttpCall httpCall = givenHttpCall(null, "invalid"); + + // when + final Result> result = onetagBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).hasSize(1) + .allSatisfy(error -> { + assertThat(error.getType()).isEqualTo(BidderError.Type.bad_server_response); + assertThat(error.getMessage()).startsWith("Failed to decode: Unrecognized token"); + }); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnErrorIfImpWasNotFound() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().id("123").xNative(Native.builder().build()).build())) + .build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.impid("125")))); + + // when + final Result> result = onetagBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()) + .containsExactly( + BidderError.badServerResponse("The impression with ID 125 is not present into the request")); + } + + @Test + public void makeBidsShouldReturnBannerBidIfBannerIsPresent() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().banner(Banner.builder().build()).id("123").build())) + .build(), + mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = onetagBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), banner, "USD")); + } + + @Test + public void makeBidsShouldReturnVideoBidIfNoBannerAndHasVideo() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().video(Video.builder().build()).id("123").build())) + .build(), + mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = onetagBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), video, "USD")); + } + + @Test + public void makeBidsShouldReturnNativeBidIfNoBannerAndVideoButNativeIsPresent() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().xNative(Native.builder().build()).id("123").build())) + .build(), + mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = onetagBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), xNative, "USD")); + } + + @Test + public void makeBidsShouldReturnBannerBidIfHasBothBannerAndVideo() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(givenImp(identity()))) + .build(), + mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = onetagBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), banner, "USD")); + } + + @Test + public void makeBidsShouldReturnNativeBidIfNativeIsPresentInRequestImp() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().id("123").xNative(Native.builder().build()).build())) + .build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = onetagBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), xNative, "USD")); + } + + private static BidRequest givenBidRequest( + Function impCustomizer, + Function requestCustomizer) { + return requestCustomizer.apply(BidRequest.builder() + .imp(singletonList(givenImp(impCustomizer)))) + .build(); + } + + private static BidRequest givenBidRequest( + Function impCustomizer) { + return givenBidRequest(impCustomizer, identity()); + } + + private static Imp givenImp(Function impCustomizer) { + return impCustomizer.apply(Imp.builder() + .id("123")) + .banner(Banner.builder().build()) + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpOnetag.of("somePubId", mapper.createObjectNode())))) + .build(); + } + + private static BidResponse givenBidResponse(Function bidCustomizer) { + return BidResponse.builder() + .cur("USD") + .seatbid(singletonList(SeatBid.builder() + .bid(singletonList(bidCustomizer.apply(Bid.builder()).build())) + .build())) + .build(); + } + + private static HttpCall givenHttpCall(BidRequest bidRequest, String body) { + return HttpCall.success(HttpRequest.builder().payload(bidRequest).build(), + HttpResponse.of(200, null, body), null); + } +} diff --git a/src/test/java/org/prebid/server/bidder/openx/OpenxBidderTest.java b/src/test/java/org/prebid/server/bidder/openx/OpenxBidderTest.java index 6713dcc6d2b..7e94f1f7475 100644 --- a/src/test/java/org/prebid/server/bidder/openx/OpenxBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/openx/OpenxBidderTest.java @@ -201,16 +201,17 @@ public void makeHttpRequestsShouldReturnResultWithExpectedFieldsSet() { .imp(asList( Imp.builder() .id("impId1") + .bidfloor(BigDecimal.valueOf(0.5)) .banner(Banner.builder().build()) .ext(mapper.valueToTree( ExtPrebid.of(null, ExtImpOpenx.builder() - .customFloor(BigDecimal.valueOf(0.1)) .customParams(givenCustomParams("foo1", singletonList("bar1"))) .delDomain("se-demo-d.openx.net") .unit("unitId").build()))).build(), Imp.builder() .id("impId2") + .bidfloor(BigDecimal.valueOf(0.5)) .banner(Banner.builder().build()) .ext(mapper.valueToTree( ExtPrebid.of(null, @@ -237,7 +238,6 @@ public void makeHttpRequestsShouldReturnResultWithExpectedFieldsSet() { .ext(mapper.valueToTree( ExtPrebid.of(null, ExtImpOpenx.builder() - .customFloor(BigDecimal.valueOf(0.1)) .customParams(givenCustomParams("foo4", "bar4")) .platform("PLATFORM") .unit("unitId").build()))).build(), @@ -266,7 +266,7 @@ public void makeHttpRequestsShouldReturnResultWithExpectedFieldsSet() { .id("impId1") .banner(Banner.builder().build()) .tagid("unitId") - .bidfloor(BigDecimal.valueOf(0.1)) + .bidfloor(BigDecimal.valueOf(0.5)) .ext(mapper.valueToTree( ExtImpOpenx.builder() .customParams( @@ -278,7 +278,7 @@ public void makeHttpRequestsShouldReturnResultWithExpectedFieldsSet() { .id("impId2") .banner(Banner.builder().build()) .tagid("unitId") - .bidfloor(BigDecimal.valueOf(0.1)) + .bidfloor(BigDecimal.valueOf(0.5)) .ext(mapper.valueToTree( ExtImpOpenx.builder() .customParams( @@ -328,7 +328,6 @@ public void makeHttpRequestsShouldReturnResultWithExpectedFieldsSet() { .id("impId4") .video(Video.builder().build()) .tagid("unitId") - .bidfloor(BigDecimal.valueOf(0.1)) .ext(mapper.valueToTree( ExtImpOpenx.builder() .customParams( @@ -344,6 +343,52 @@ public void makeHttpRequestsShouldReturnResultWithExpectedFieldsSet() { .build()); } + @Test + public void makeHttpRequestShouldReturnResultWithCustomBidFloorIfImpBidFloorIsZero() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .bidfloor(BigDecimal.ZERO) + .video(Video.builder().build()) + .ext(mapper.valueToTree( + ExtPrebid.of(null, ExtImpOpenx.builder().customFloor(BigDecimal.valueOf(123)).build())) + ).build())) + .build(); + + // when + final Result>> result = openxBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getBidfloor) + .containsExactly(BigDecimal.valueOf(123)); + } + + @Test + public void makeHttpRequestShouldReturnResultWithCustomBidFloorIfImpBidFloorIsNegative() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .bidfloor(BigDecimal.ZERO.subtract(BigDecimal.ONE)) + .video(Video.builder().build()) + .ext(mapper.valueToTree( + ExtPrebid.of(null, ExtImpOpenx.builder().customFloor(BigDecimal.valueOf(123)).build())) + ).build())) + .build(); + + // when + final Result>> result = openxBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getBidfloor) + .containsExactly(BigDecimal.valueOf(123)); + } + @Test public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { // given diff --git a/src/test/java/org/prebid/server/bidder/outbrain/OutbrainBidderTest.java b/src/test/java/org/prebid/server/bidder/outbrain/OutbrainBidderTest.java new file mode 100644 index 00000000000..b3a0121b0b5 --- /dev/null +++ b/src/test/java/org/prebid/server/bidder/outbrain/OutbrainBidderTest.java @@ -0,0 +1,265 @@ +package org.prebid.server.bidder.outbrain; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.iab.openrtb.request.App; +import com.iab.openrtb.request.Banner; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Native; +import com.iab.openrtb.request.Publisher; +import com.iab.openrtb.request.Site; +import com.iab.openrtb.response.Bid; +import com.iab.openrtb.response.BidResponse; +import com.iab.openrtb.response.SeatBid; +import org.junit.Before; +import org.junit.Test; +import org.prebid.server.VertxTest; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.HttpCall; +import org.prebid.server.bidder.model.HttpRequest; +import org.prebid.server.bidder.model.HttpResponse; +import org.prebid.server.bidder.model.Result; +import org.prebid.server.proto.openrtb.ext.ExtPrebid; +import org.prebid.server.proto.openrtb.ext.request.outbrains.ExtImpOutbrain; +import org.prebid.server.proto.openrtb.ext.request.outbrains.ExtImpOutbrainPublisher; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +import static java.util.Collections.singletonList; +import static java.util.function.Function.identity; +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.banner; +import static org.prebid.server.proto.openrtb.ext.response.BidType.xNative; + +public class OutbrainBidderTest extends VertxTest { + + private static final String ENDPOINT_URL = "https://test.endpoint.com"; + + private OutbrainBidder outbrainBidder; + + @Before + public void setUp() { + outbrainBidder = new OutbrainBidder(ENDPOINT_URL, jacksonMapper); + } + + @Test + public void creationShouldFailOnInvalidEndpointUrl() { + assertThatIllegalArgumentException().isThrownBy(() -> new OutbrainBidder("invalid_url", jacksonMapper)); + } + + @Test + public void makeHttpRequestsShouldCreateOneSingleRequestWithAllImps() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(Arrays.asList(givenImp(identity()), givenImp(identity()))) + .build(); + + // when + final Result>> result = outbrainBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .hasSize(2); + } + + @Test + public void makeHttpRequestsShouldUpdatePresentedAppWithPublisherParamsFromExt() { + // given + final BidRequest bidRequest = givenBidRequest( + bidRequestBuilder -> bidRequestBuilder.app(App.builder().build()), + identity()); + + // when + final Result>> result = outbrainBidder.makeHttpRequests(bidRequest); + + // then + final App expectedApp = App.builder() + .publisher(Publisher.builder().id("testId").name("testName").domain("testDomain").build()) + .build(); + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getApp) + .containsExactly(expectedApp); + } + + @Test + public void makeHttpRequestsShouldUpdatePresentedSiteWithPublisherParamsFromExt() { + // given + final BidRequest bidRequest = givenBidRequest( + bidRequestBuilder -> bidRequestBuilder.site(Site.builder().build()), + identity()); + + // when + final Result>> result = outbrainBidder.makeHttpRequests(bidRequest); + + // then + final Site expectedSite = Site.builder() + .publisher(Publisher.builder().id("testId").name("testName").domain("testDomain").build()) + .build(); + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getSite) + .containsExactly(expectedSite); + } + + @Test + public void makeHttpRequestsShouldReturnErrorsOfNotValidImps() { + // given + final BidRequest bidRequest = givenBidRequest( + impBuilder -> impBuilder + .ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createArrayNode())))); + // when + final Result>> result = outbrainBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).hasSize(1); + assertThat(result.getErrors()) + .containsExactly(BidderError.badInput("Impression id=123, has invalid Ext")); + } + + @Test + public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { + // given + final HttpCall httpCall = givenHttpCall(null, "invalid"); + + // when + final Result> result = outbrainBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).hasSize(1); + assertThat(result.getErrors().get(0).getMessage()).startsWith("Failed to decode: Unrecognized token"); + assertThat(result.getErrors().get(0).getType()).isEqualTo(BidderError.Type.bad_server_response); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnEmptyListIfBidResponseIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall(null, + mapper.writeValueAsString(null)); + + // when + final Result> result = outbrainBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnEmptyListIfBidResponseSeatBidIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall(null, + mapper.writeValueAsString(BidResponse.builder().build())); + + // when + final Result> result = outbrainBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnBannerBidIfBannerIsPresent() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().banner(Banner.builder().build()).id("123").build())) + .build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = outbrainBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), banner, "USD")); + } + + @Test + public void makeBidsShouldReturnNativeBidIfNativeIsPresent() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().xNative(Native.builder().build()).id("123").build())) + .build(), + mapper.writeValueAsString( + givenBidResponse(bidBuilder -> bidBuilder.impid("123")))); + + // when + final Result> result = outbrainBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder().impid("123").build(), xNative, "USD")); + } + + @Test + public void makeBidsShouldReturnResponseWithErrorWhenIdIsNotFound() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + BidRequest.builder() + .imp(singletonList(Imp.builder().id("123").build())) + .build(), + mapper.writeValueAsString(givenBidResponse(bidBuilder -> bidBuilder.impid("12")))); + + // when + final Result> result = outbrainBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()) + .containsExactly(BidderError.badServerResponse("Failed to find native/banner impression \"12\"")); + assertThat(result.getValue()).isEmpty(); + } + + private static BidRequest givenBidRequest( + Function bidRequestCustomizer, + Function impCustomizer) { + + return bidRequestCustomizer.apply(BidRequest.builder() + .imp(singletonList(givenImp(impCustomizer)))) + .build(); + } + + private static BidRequest givenBidRequest(Function impCustomizer) { + return givenBidRequest(identity(), impCustomizer); + } + + private static Imp givenImp(Function impCustomizer) { + return impCustomizer.apply(Imp.builder() + .id("123") + .banner(Banner.builder().w(23).h(25).build()) + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpOutbrain.of( + ExtImpOutbrainPublisher.of("testId", "testName", "testDomain"), + "tagId", singletonList("testBcat"), singletonList("testBadv")))))) + .build(); + } + + private static BidResponse givenBidResponse(Function bidCustomizer) { + return BidResponse.builder() + .cur("USD") + .seatbid(singletonList(SeatBid.builder().bid(singletonList(bidCustomizer.apply(Bid.builder()).build())) + .build())) + .build(); + } + + private static HttpCall givenHttpCall(BidRequest bidRequest, String body) { + return HttpCall.success( + HttpRequest.builder().payload(bidRequest).build(), + HttpResponse.of(200, null, body), + null); + } +} diff --git a/src/test/java/org/prebid/server/bidder/pangle/PangleBidderTest.java b/src/test/java/org/prebid/server/bidder/pangle/PangleBidderTest.java new file mode 100644 index 00000000000..cbe95a016e5 --- /dev/null +++ b/src/test/java/org/prebid/server/bidder/pangle/PangleBidderTest.java @@ -0,0 +1,508 @@ +package org.prebid.server.bidder.pangle; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.iab.openrtb.request.Audio; +import com.iab.openrtb.request.Banner; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Native; +import com.iab.openrtb.request.Video; +import com.iab.openrtb.response.Bid; +import com.iab.openrtb.response.BidResponse; +import com.iab.openrtb.response.SeatBid; +import io.netty.handler.codec.http.HttpHeaderValues; +import org.junit.Before; +import org.junit.Test; +import org.prebid.server.VertxTest; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.HttpCall; +import org.prebid.server.bidder.model.HttpRequest; +import org.prebid.server.bidder.model.HttpResponse; +import org.prebid.server.bidder.model.Result; +import org.prebid.server.bidder.pangle.model.BidExt; +import org.prebid.server.bidder.pangle.model.PangleBidExt; +import org.prebid.server.bidder.pangle.model.WrappedImpExtBidder; +import org.prebid.server.proto.openrtb.ext.ExtPrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebid; +import org.prebid.server.proto.openrtb.ext.request.pangle.ExtImpPangle; +import org.prebid.server.util.HttpUtil; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +import static java.util.Collections.singletonList; +import static java.util.function.Function.identity; +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.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 PangleBidderTest extends VertxTest { + + public static final String ENDPOINT_URL = "https://test.endpoint.com"; + + private PangleBidder pangleBidder; + + @Before + public void setUp() { + pangleBidder = new PangleBidder(ENDPOINT_URL, jacksonMapper); + } + + @Test + public void creationShouldFailOnInvalidEndpointUrl() { + assertThatIllegalArgumentException().isThrownBy(() -> new PangleBidder("invalid_url", jacksonMapper)); + } + + @Test + public void makeHttpRequestsShouldMakeOneRequestPerImp() { + // given + final BidRequest bidRequest = givenBidRequest( + identity(), + requestBuilder -> requestBuilder.imp(Arrays.asList( + givenImp(identity()), + givenImp(identity())))); + + // when + final Result>> result = pangleBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(2) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .hasSize(2); + } + + @Test + public void makeHttpRequestsShouldUpdateImpExtWithAdTypeSevenIfVideoIsPresentAndIsRewardedIsOne() { + // given + final ExtImpPrebid extPrebid = ExtImpPrebid.builder().isRewardedInventory(1).build(); + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .video(Video.builder().build()) + .ext(mapper.valueToTree(WrappedImpExtBidder.of(extPrebid, ExtImpPangle.of("token"), null))) + .build())) + .build(); + + // when + final Result>> result = pangleBidder.makeHttpRequests(bidRequest); + + // then + final ObjectNode expectedExt = mapper + .valueToTree(WrappedImpExtBidder.of(extPrebid, ExtImpPangle.of("token"), 7)); + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getExt) + .containsExactly(expectedExt); + } + + @Test + public void makeHttpRequestsShouldUpdateImpExtWithAdTypeEightIfVideoIsPresentAndInstlIsOne() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .instl(1) + .video(Video.builder().build()) + .ext(mapper.valueToTree(WrappedImpExtBidder.of(null, ExtImpPangle.of("token"), null))) + .build())) + .build(); + + // when + final Result>> result = pangleBidder.makeHttpRequests(bidRequest); + + // then + final ObjectNode expectedExt = mapper + .valueToTree(WrappedImpExtBidder.of(null, ExtImpPangle.of("token"), 8)); + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getExt) + .containsExactly(expectedExt); + } + + @Test + public void makeHttpRequestsShouldUpdateImpExtWithAdTypeTwoIfBannerIsPresentAndInstlIsOne() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .instl(1) + .banner(Banner.builder().build()) + .ext(mapper.valueToTree(WrappedImpExtBidder.of(null, ExtImpPangle.of("token"), null))) + .build())) + .build(); + + // when + final Result>> result = pangleBidder.makeHttpRequests(bidRequest); + + // then + final ObjectNode expectedExt = mapper + .valueToTree(WrappedImpExtBidder.of(null, ExtImpPangle.of("token"), 2)); + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getExt) + .containsExactly(expectedExt); + } + + @Test + public void makeHttpRequestsShouldUpdateImpExtWithAdTypeOneIfBannerIsPresent() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .banner(Banner.builder().build()) + .ext(mapper.valueToTree(WrappedImpExtBidder.of(null, ExtImpPangle.of("token"), null))) + .build())) + .build(); + + // when + final Result>> result = pangleBidder.makeHttpRequests(bidRequest); + + // then + final ObjectNode expectedExt = mapper + .valueToTree(WrappedImpExtBidder.of(null, ExtImpPangle.of("token"), 1)); + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getExt) + .containsExactly(expectedExt); + } + + @Test + public void makeHttpRequestsShouldUpdateImpExtWithAdTypeFiveIfNativeRequestIsPresent() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .xNative(Native.builder().request("someRequest").build()) + .ext(mapper.valueToTree(WrappedImpExtBidder.of(null, ExtImpPangle.of("token"), null))) + .build())) + .build(); + + // when + final Result>> result = pangleBidder.makeHttpRequests(bidRequest); + + // then + final ObjectNode expectedExt = mapper + .valueToTree(WrappedImpExtBidder.of(null, ExtImpPangle.of("token"), 5)); + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getExt) + .containsExactly(expectedExt); + } + + @Test + public void makeHttpRequestsShouldReturnErrorForNotSupportedAdType() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .audio(Audio.builder().build()) + .ext(mapper.valueToTree(WrappedImpExtBidder.of(null, ExtImpPangle.of("token"), null))) + .build())) + .build(); + + // when + final Result>> result = pangleBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).containsExactly(BidderError.badInput("not a supported adtype")); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeHttpRequestsShouldCorrectlyAddHeaders() { + // given + final BidRequest bidRequest = givenBidRequest(identity()); + + // when + final Result>> result = pangleBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getValue()) + .flatExtracting(res -> res.getHeaders().entries()) + .extracting(Map.Entry::getKey, Map.Entry::getValue) + .containsExactlyInAnyOrder( + tuple(HttpUtil.CONTENT_TYPE_HEADER.toString(), HttpUtil.APPLICATION_JSON_CONTENT_TYPE), + tuple(HttpUtil.ACCEPT_HEADER.toString(), HttpHeaderValues.APPLICATION_JSON.toString()), + tuple("TOKEN", "token")); + } + + @Test + public void makeBidsShouldReturnEmptyListIfBidResponseIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall(null, mapper.writeValueAsString(null)); + + // when + final Result> result = pangleBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnEmptyListIfBidResponseSeatBidIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall(null, + mapper.writeValueAsString(BidResponse.builder().build())); + + // when + final Result> result = pangleBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { + // given + final HttpCall httpCall = givenHttpCall(null, "invalid"); + + // when + final Result> result = pangleBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).hasSize(1) + .allSatisfy(error -> { + assertThat(error.getType()).isEqualTo(BidderError.Type.bad_server_response); + assertThat(error.getMessage()).startsWith("Failed to decode: Unrecognized token"); + }); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnErrorIfBidIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + givenBidRequest(identity()), + mapper.writeValueAsString(BidResponse.builder() + .seatbid(singletonList(SeatBid.builder() + .bid(singletonList(null)) + .build())) + .build())); + + // when + final Result> result = pangleBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()) + .containsExactly( + BidderError.badServerResponse("the bid request object is not present")); + } + + @Test + public void makeBidsShouldReturnErrorIfBidExtIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + givenBidRequest(identity()), + mapper.writeValueAsString(givenBidResponse(identity()))); + + // when + final Result> result = pangleBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()) + .containsExactly( + BidderError.badServerResponse("missing pangleExt/adtype in bid ext")); + } + + @Test + public void makeBidsShouldReturnErrorIfBidExtAdTypeIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + givenBidRequest(identity()), + mapper.writeValueAsString( + givenBidResponse(bid -> bid.ext(mapper.valueToTree(PangleBidExt.of(BidExt.of(null))))))); + + // when + final Result> result = pangleBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()) + .containsExactly( + BidderError.badServerResponse("missing pangleExt/adtype in bid ext")); + } + + @Test + public void makeBidsShouldReturnBannerBidIfAdTypeIsOne() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + givenBidRequest(identity()), + mapper.writeValueAsString(givenBidResponse(bid -> + bid.ext(mapper.valueToTree(PangleBidExt.of(BidExt.of(1))))))); + + // when + final Result> result = pangleBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder() + .ext(mapper.valueToTree(PangleBidExt.of(BidExt.of(1)))) + .build(), banner, "USD")); + } + + @Test + public void makeBidsShouldReturnBannerBidIfAdTypeIsTwo() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + givenBidRequest(identity()), + mapper.writeValueAsString(givenBidResponse(bid -> + bid.ext(mapper.valueToTree(PangleBidExt.of(BidExt.of(2))))))); + + // when + final Result> result = pangleBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder() + .ext(mapper.valueToTree(PangleBidExt.of(BidExt.of(2)))) + .build(), banner, "USD")); + } + + @Test + public void makeBidsShouldReturnNativeBidIfAdTypeIsFive() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + givenBidRequest(identity()), + mapper.writeValueAsString(givenBidResponse(bid -> + bid.ext(mapper.valueToTree(PangleBidExt.of(BidExt.of(5))))))); + + // when + final Result> result = pangleBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder() + .ext(mapper.valueToTree(PangleBidExt.of(BidExt.of(5)))) + .build(), xNative, "USD")); + } + + @Test + public void makeBidsShouldReturnVide0BidIfAdTypeIsSeven() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + givenBidRequest(identity()), + mapper.writeValueAsString(givenBidResponse(bid -> + bid.ext(mapper.valueToTree(PangleBidExt.of(BidExt.of(7))))))); + + // when + final Result> result = pangleBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder() + .ext(mapper.valueToTree(PangleBidExt.of(BidExt.of(7)))) + .build(), video, "USD")); + } + + @Test + public void makeBidsShouldReturnVide0BidIfAdTypeIsEight() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + givenBidRequest(identity()), + mapper.writeValueAsString(givenBidResponse(bid -> + bid.ext(mapper.valueToTree(PangleBidExt.of(BidExt.of(8))))))); + + // when + final Result> result = pangleBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsExactly(BidderBid.of(Bid.builder() + .ext(mapper.valueToTree(PangleBidExt.of(BidExt.of(8)))) + .build(), video, "USD")); + } + + @Test + public void makeBidsShouldReturnErrorForUnrecognizedAdType() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + givenBidRequest(identity()), + mapper.writeValueAsString(givenBidResponse(bid -> + bid.ext(mapper.valueToTree(PangleBidExt.of(BidExt.of(777))))))); + + // when + final Result> result = pangleBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()) + .containsExactly( + BidderError.badServerResponse("unrecognized adtype in response")); + } + + @Test + public void makeBidsShouldReturnErrorsAndResult() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + givenBidRequest(identity()), + mapper.writeValueAsString(BidResponse.builder() + .cur("USD") + .seatbid(singletonList(SeatBid.builder() + .bid(Arrays.asList(Bid.builder().build(), + Bid.builder() + .ext(mapper.valueToTree(PangleBidExt.of(BidExt.of(8)))) + .build())) + .build())) + .build())); + + // when + final Result> result = pangleBidder.makeBids(httpCall, null); + + // then + assertThat(result.getValue()).hasSize(1); + assertThat(result.getErrors()).hasSize(1); + } + + private static BidRequest givenBidRequest( + Function impCustomizer, + Function requestCustomizer) { + return requestCustomizer.apply(BidRequest.builder() + .imp(singletonList(givenImp(impCustomizer)))) + .build(); + } + + private static BidRequest givenBidRequest( + Function impCustomizer) { + return givenBidRequest(impCustomizer, identity()); + } + + private static Imp givenImp(Function impCustomizer) { + return impCustomizer.apply(Imp.builder() + .id("123")) + .banner(Banner.builder().build()) + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpPangle.of("token")))) + .build(); + } + + private static BidResponse givenBidResponse(Function bidCustomizer) { + return BidResponse.builder() + .cur("USD") + .seatbid(singletonList(SeatBid.builder() + .bid(singletonList(bidCustomizer.apply(Bid.builder()).build())) + .build())) + .build(); + } + + private static HttpCall givenHttpCall(BidRequest bidRequest, String body) { + return HttpCall.success(HttpRequest.builder().payload(bidRequest).build(), + HttpResponse.of(200, null, body), null); + } +} + diff --git a/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java b/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java index e4b8572b547..84e3b3f19dd 100644 --- a/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java @@ -32,7 +32,11 @@ import lombok.AllArgsConstructor; import lombok.Value; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.prebid.server.VertxTest; import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderError; @@ -57,6 +61,8 @@ import org.prebid.server.bidder.rubicon.proto.RubiconUserExtRp; import org.prebid.server.bidder.rubicon.proto.RubiconVideoExt; import org.prebid.server.bidder.rubicon.proto.RubiconVideoExtRp; +import org.prebid.server.currency.CurrencyConversionService; +import org.prebid.server.exception.PreBidException; import org.prebid.server.proto.openrtb.ext.ExtPrebid; import org.prebid.server.proto.openrtb.ext.ExtPrebidBidders; import org.prebid.server.proto.openrtb.ext.request.ExtApp; @@ -97,6 +103,12 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.entry; import static org.assertj.core.api.Assertions.tuple; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; import static org.prebid.server.proto.openrtb.ext.response.BidType.banner; import static org.prebid.server.proto.openrtb.ext.response.BidType.video; @@ -108,17 +120,25 @@ public class RubiconBidderTest extends VertxTest { private static final List SUPPORTED_VENDORS = Arrays.asList("activeview", "adform", "comscore", "doubleverify", "integralads", "moat", "sizmek", "whiteops"); + @Rule + public final MockitoRule mockitoRule = MockitoJUnit.rule(); + private RubiconBidder rubiconBidder; + @Mock + private CurrencyConversionService currencyConversionService; + @Before public void setUp() { - rubiconBidder = new RubiconBidder(ENDPOINT_URL, USERNAME, PASSWORD, SUPPORTED_VENDORS, false, jacksonMapper); + rubiconBidder = new RubiconBidder(ENDPOINT_URL, USERNAME, PASSWORD, SUPPORTED_VENDORS, false, + currencyConversionService, jacksonMapper); } @Test public void creationShouldFailOnInvalidEndpointUrl() { assertThatIllegalArgumentException().isThrownBy( - () -> new RubiconBidder("invalid_url", USERNAME, PASSWORD, SUPPORTED_VENDORS, false, jacksonMapper)); + () -> new RubiconBidder("invalid_url", USERNAME, PASSWORD, SUPPORTED_VENDORS, false, + currencyConversionService, jacksonMapper)); } @Test @@ -189,11 +209,11 @@ public void makeHttpRequestsShouldFilterAllImpressionsAndReturnErrorMeessagesWit @Test public void makeHttpRequestsShouldReplaceDefaultParametersWithExtPrebidBiddersBidder() { // given - final ExtRequest prebidExt = ExtRequest.of(ExtRequestPrebid.builder() + final ExtRequest extRequest = ExtRequest.of(ExtRequestPrebid.builder() .integration("test") .build()); - final BidRequest bidRequest = givenBidRequest(bidRequestBuilder -> bidRequestBuilder.ext(prebidExt), + final BidRequest bidRequest = givenBidRequest(bidRequestBuilder -> bidRequestBuilder.ext(extRequest), builder -> builder.banner(Banner.builder().format(singletonList(Format.builder().w(300).h(250).build())) .build()), identity()); @@ -414,8 +434,7 @@ public void makeHttpRequestsShouldSetMobileLandscape101SizeIdFotInterstitialNotV .flatExtracting(BidRequest::getImp).doesNotContainNull() .extracting(Imp::getBanner).doesNotContainNull() .containsOnly(Banner.builder() - .format(singletonList( - Format.builder().w(616).h(360).build())) + .format(singletonList(Format.builder().w(616).h(360).build())) .ext(mapper.valueToTree(RubiconBannerExt.of(RubiconBannerExtRp.of(101, null, "text/html")))) .build()); } @@ -472,6 +491,81 @@ public void makeHttpRequestsShouldCreateVideoRequestIfImpHasBannerAndVideoButAll .maxduration(60).linearity(2).api(singletonList(3)).build())); } + @Test + public void makeHttpRequestsShouldResolveImpBidFloorCurrencyIfNotUSDAndCallCurrencyService() { + // given + final BidRequest bidRequest = givenBidRequest( + builder -> builder + .banner(Banner.builder().format(singletonList(Format.builder().w(300).h(250).build())).build()) + .bidfloor(BigDecimal.ONE).bidfloorcur("EUR"), + identity()); + + given(currencyConversionService.convertCurrency(any(), any(), anyString(), anyString())) + .willReturn(BigDecimal.TEN); + + // when + final Result>> result = rubiconBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + verify(currencyConversionService).convertCurrency(eq(BigDecimal.ONE), any(), eq("EUR"), eq("USD")); + assertThat(result.getValue()).hasSize(1).doesNotContainNull() + .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) + .flatExtracting(BidRequest::getImp).doesNotContainNull() + .extracting(Imp::getBidfloor, Imp::getBidfloorcur) + .containsOnly(tuple(BigDecimal.TEN, "USD")); + } + + @Test + public void makeHttpRequestsShouldNotSetBidFloorCurrencyToUSDIfNull() { + // given + final BidRequest bidRequest = givenBidRequest( + builder -> builder + .ext(ExtRequest.of(ExtRequestPrebid.builder().debug(1).build())), + builder -> builder + .id("impId") + .banner(Banner.builder().format(singletonList(Format.builder().w(300).h(250).build())).build()) + .bidfloor(BigDecimal.ONE).bidfloorcur(null), + identity()); + + // when + final Result>> result = rubiconBidder.makeHttpRequests(bidRequest); + + // then + verifyZeroInteractions(currencyConversionService); + assertThat(result.getErrors()).hasSize(1) + .containsOnly(BidderError.of("Imp `impId` floor provided with no currency, assuming USD", + BidderError.Type.bad_input)); + assertThat(result.getValue()).hasSize(1).doesNotContainNull() + .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) + .flatExtracting(BidRequest::getImp).doesNotContainNull() + .extracting(Imp::getBidfloor, Imp::getBidfloorcur) + .containsOnly(tuple(BigDecimal.ONE, null)); + } + + @Test + public void makeHttpRequestsShouldIgnoreBidRequestIfCurrencyServiceThrowsAnException() { + // given + final BidRequest bidRequest = givenBidRequest( + builder -> builder + .id("impId") + .banner(Banner.builder().format(singletonList(Format.builder().w(300).h(250).build())).build()) + .bidfloor(BigDecimal.ONE).bidfloorcur("EUR"), + identity()); + + given(currencyConversionService.convertCurrency(any(), any(), anyString(), anyString())) + .willThrow(new PreBidException("failed")); + + // when + final Result>> result = rubiconBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getValue()).isEmpty(); + assertThat(result.getErrors()).hasSize(1) + .containsOnly(BidderError.of("Unable to convert provided bid floor currency from EUR to USD" + + " for imp `impId` with a reason: failed", BidderError.Type.bad_input)); + } + @Test public void shouldSetSizeIdTo201IfPlacementIs1AndSizeIdIsNotPresent() { // given @@ -720,15 +814,13 @@ public void makeHttpRequestsShouldFillUserExtIfUserAndVisitorPresent() { } @Test - public void makeHttpRequestsShouldFillUserExtRpWithIabAttributeIfTaxonomynameContainsIab() { + public void makeHttpRequestsShouldFillUserExtRpWithIabAttributeIfSegtaxEqualsThree() { // given - final ObjectNode userNode = mapper.createObjectNode(); - userNode.put("taxonomyname", "contains IaB"); final BidRequest bidRequest = givenBidRequest( - builder -> builder.user(User.builder().data(singletonList(Data.builder() - .segment(singletonList(Segment.builder().id("segmentId") - .build())) - .ext(userNode).build())).build()), + builder -> builder.user(User.builder() + .data(singletonList( + givenDataWithSegmentEntry(3, "segmentId") + )).build()), builder -> builder.video(Video.builder().build()), identity()); @@ -753,21 +845,14 @@ public void makeHttpRequestsShouldFillUserExtRpWithIabAttributeIfTaxonomynameCon } @Test - public void makeHttpRequestsShouldFillWithIabAttributeOnlyIfContainsIabInTaxonomynameAttribute() { + public void makeHttpRequestsShouldFillUserExtRpWithIabAttributeOnlyIfSegtaxIsEqualThree() { // given - final ObjectNode firstUserDataNode = mapper.createObjectNode(); - firstUserDataNode.put("taxonomyname", "contains IaB"); - final ObjectNode secondUserDataNode = mapper.createObjectNode(); - secondUserDataNode.put("taxonomyname", "not contain"); final BidRequest bidRequest = givenBidRequest( - builder -> builder.user(User.builder().data(asList(Data.builder() - .segment(singletonList(Segment.builder().id("segmentId") - .build())) - .ext(firstUserDataNode).build(), - Data.builder() - .segment(singletonList(Segment.builder().id("secondSegmentId") - .build())) - .ext(secondUserDataNode).build())).build()), + builder -> builder.user(User.builder() + .data(asList( + givenDataWithSegmentEntry(3, "segmentId"), + givenDataWithSegmentEntry(2, "secondSegmentId"))) + .build()), builder -> builder.video(Video.builder().build()), identity()); @@ -792,12 +877,44 @@ public void makeHttpRequestsShouldFillWithIabAttributeOnlyIfContainsIabInTaxonom } @Test - public void makeHttpRequestsShouldIgnoreNotTextualTaxonomynameProperty() { + public void makeHttpRequestsShouldFillSiteExtRpWithIabAttributeIfSegtaxEqualsOneOrTwo() { // given - final ObjectNode userNode = mapper.createObjectNode(); - final ArrayNode wrongTaxonomyAttributeType = userNode.putArray("taxonomyname"); - wrongTaxonomyAttributeType.add("contains IaB value"); + final BidRequest bidRequest = givenBidRequest( + builder -> builder.site(Site.builder() + .content(Content.builder() + .data(asList( + givenDataWithSegmentEntry(1, "firstSegmentId"), + givenDataWithSegmentEntry(2, "secondSegmentId"), + givenDataWithSegmentEntry(3, "thirdSegmentId"))) + .build()) + .build()), + builder -> builder.video(Video.builder().build()), + identity()); + + // when + final Result>> result = rubiconBidder.makeHttpRequests(bidRequest); + + // then + final ObjectNode expectedTarget = mapper.createObjectNode(); + final ArrayNode expectedIabAttribute = expectedTarget.putArray("iab"); + expectedIabAttribute.add("firstSegmentId"); + expectedIabAttribute.add("secondSegmentId"); + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1).doesNotContainNull() + .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) + .extracting(BidRequest::getSite).doesNotContainNull() + .extracting(Site::getExt) + .extracting(ext -> ext.getProperty("rp")) + .extracting(rp -> rp.get("target")) + .containsExactly(expectedTarget); + } + + @Test + public void makeHttpRequestsShouldIgnoreNotIntSegtaxProperty() { + // given + final ObjectNode userNode = mapper.createObjectNode(); + userNode.put("segtax", "3"); final BidRequest bidRequest = givenBidRequest( builder -> builder.user(User.builder().data(singletonList(Data.builder() .segment(singletonList(Segment.builder().id("segmentId") @@ -815,7 +932,6 @@ public void makeHttpRequestsShouldIgnoreNotTextualTaxonomynameProperty() { .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) .extracting(BidRequest::getUser).doesNotContainNull() .extracting(User::getExt) - .hasSize(1) .containsNull(); } @@ -1470,7 +1586,7 @@ public void makeHttpRequestsShouldFillSiteExtIfSitePresent() { RubiconPubExt.of(RubiconPubExtRp.of(2001)))) .build()) .ext(jacksonMapper.fillExtension( - ExtSite.of(null, null), RubiconSiteExt.of(RubiconSiteExtRp.of(3001)))) + ExtSite.of(null, null), RubiconSiteExt.of(RubiconSiteExtRp.of(3001, null)))) .build()); } @@ -1497,7 +1613,7 @@ public void makeHttpRequestsShouldPassSiteExtAmpIfPresent() { RubiconPubExt.of(RubiconPubExtRp.of(2001)))) .build()) .ext(jacksonMapper.fillExtension( - ExtSite.of(1, null), RubiconSiteExt.of(RubiconSiteExtRp.of(3001)))) + ExtSite.of(1, null), RubiconSiteExt.of(RubiconSiteExtRp.of(3001, null)))) .build()); } @@ -1519,7 +1635,7 @@ public void makeHttpRequestsShouldRemoveSiteExtData() { .extracting(Site::getExt) .containsOnly(jacksonMapper.fillExtension( ExtSite.of(null, null), - RubiconSiteExt.of(RubiconSiteExtRp.of(3001)))); + RubiconSiteExt.of(RubiconSiteExtRp.of(3001, null)))); } @Test @@ -1546,7 +1662,7 @@ public void makeHttpRequestsShouldFillAppExtIfAppPresent() { .build()) .ext(jacksonMapper.fillExtension( ExtApp.of(null, null), - RubiconAppExt.of(RubiconSiteExtRp.of(3001)))) + RubiconAppExt.of(RubiconSiteExtRp.of(3001, null)))) .build()); } @@ -1568,7 +1684,7 @@ public void makeHttpRequestsShouldRemoveAppExtData() { .extracting(App::getExt) .containsOnly(jacksonMapper.fillExtension( ExtApp.of(null, null), - RubiconAppExt.of(RubiconSiteExtRp.of(3001)))); + RubiconAppExt.of(RubiconSiteExtRp.of(3001, null)))); } @Test @@ -2079,7 +2195,7 @@ public void makeHttpRequestsShouldCopyImpExtVideoLanguageToSiteContentLanguage() @Test public void makeHttpRequestsShouldMergeImpExtContextSearchAndSiteSearchAndCopyToRubiconImpExtRpTarget() - throws IOException { + throws JsonProcessingException { // given final BidRequest bidRequest = givenBidRequest( requestBuilder -> requestBuilder.site(Site.builder().search("site search").build()), @@ -2345,13 +2461,13 @@ public void makeHttpRequestsShouldProcessMetricsAndFillViewabilityVendor() { Metric.builder().type("unsupported").value(0.5f).vendor("comscore").build(), Metric.builder().type("viewability").value(0.6f).vendor("seller-declared").build(), Metric.builder().type("unsupported").value(0.7f).vendor("somebody").build()); + assertThat(result.getValue()).hasSize(1).doesNotContainNull() .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) .flatExtracting(BidRequest::getImp).doesNotContainNull() .extracting(Imp::getExt).doesNotContainNull() .extracting(ext -> mapper.treeToValue(ext, RubiconImpExt.class)) - .containsOnly(RubiconImpExt.of(RubiconImpExtRp.of(null, - null, + .containsOnly(RubiconImpExt.of(RubiconImpExtRp.of(null, null, RubiconImpExtRpTrack.of("", "")), asList("moat.com", "doubleclickbygoogle.com"), 1)); } @@ -2394,6 +2510,21 @@ public void makeHttpRequestsShouldUpdateSourceWithPchainIfDefinedInImpExt() { .containsOnly("pchain"); } + @Test + public void makeBidsShouldTolerateMismatchedBidImpId() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + givenBidRequest(impBuilder -> impBuilder.id("impId")), + givenBidResponse(bidBuilder -> bidBuilder.price(ONE).impid("mismatched_impId"))); + + // when + final Result> result = rubiconBidder.makeBids(httpCall, givenBidRequest(identity())); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1); + } + @Test public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { // given @@ -2412,8 +2543,7 @@ public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { @Test public void makeBidsShouldReturnBannerBidIfRequestImpHasNoVideo() throws JsonProcessingException { // given - final HttpCall httpCall = givenHttpCall(givenBidRequest(identity()), - givenBidResponse(ONE)); + final HttpCall httpCall = givenHttpCall(givenBidRequest(identity()), givenBidResponse(ONE)); // when final Result> result = rubiconBidder.makeBids(httpCall, givenBidRequest(identity())); @@ -2662,7 +2792,7 @@ public void makeBidsShouldReturnBidWithOriginalBidIdFieldFromBidResponseIfNotZer public void makeBidsShouldReturnBidWithRandomlyGeneratedId() throws JsonProcessingException { // given rubiconBidder = new RubiconBidder( - ENDPOINT_URL, USERNAME, PASSWORD, SUPPORTED_VENDORS, true, jacksonMapper); + ENDPOINT_URL, USERNAME, PASSWORD, SUPPORTED_VENDORS, true, currencyConversionService, jacksonMapper); final HttpCall httpCall = givenHttpCall(givenBidRequest(identity()), mapper.writeValueAsString(BidResponse.builder() @@ -2687,7 +2817,7 @@ public void makeBidsShouldReturnBidWithRandomlyGeneratedId() throws JsonProcessi public void makeBidsShouldReturnBidWithCurrencyFromBidResponse() throws JsonProcessingException { // given rubiconBidder = new RubiconBidder( - ENDPOINT_URL, USERNAME, PASSWORD, SUPPORTED_VENDORS, true, jacksonMapper); + ENDPOINT_URL, USERNAME, PASSWORD, SUPPORTED_VENDORS, true, currencyConversionService, jacksonMapper); final HttpCall httpCall = givenHttpCall(givenBidRequest(identity()), mapper.writeValueAsString(BidResponse.builder() @@ -2709,11 +2839,13 @@ public void makeBidsShouldReturnBidWithCurrencyFromBidResponse() throws JsonProc @Test public void extractTargetingShouldReturnEmptyMapForEmptyExtension() { + // when and then assertThat(rubiconBidder.extractTargeting(mapper.createObjectNode())).isEmpty(); } @Test public void extractTargetingShouldReturnEmptyMapForInvalidExtension() { + // when and then assertThat(rubiconBidder.extractTargeting(mapper.createObjectNode().put("rp", 1))).isEmpty(); assertThat(rubiconBidder.extractTargeting(mapper.createObjectNode().putObject("rp").put("targeting", 1))) .isEmpty(); @@ -2721,11 +2853,13 @@ public void extractTargetingShouldReturnEmptyMapForInvalidExtension() { @Test public void extractTargetingShouldReturnEmptyMapForNullRp() { + // when and then assertThat(rubiconBidder.extractTargeting(mapper.createObjectNode().putObject("rp"))).isEmpty(); } @Test public void extractTargetingShouldReturnEmptyMapForNullTargeting() { + // when and then assertThat(rubiconBidder.extractTargeting(mapper.createObjectNode().putObject("rp").putObject("targeting"))) .isEmpty(); } @@ -2779,6 +2913,13 @@ private static Imp givenImp(Function impCustomizer) { return givenImp(impCustomizer, identity()); } + private static Data givenDataWithSegmentEntry(Integer segtax, String segmentId) { + return Data.builder() + .segment(singletonList(Segment.builder().id(segmentId).build())) + .ext(mapper.createObjectNode().put("segtax", segtax)) + .build(); + } + private static HttpCall givenHttpCall(BidRequest bidRequest, String body) { return HttpCall.success( HttpRequest.builder().payload(bidRequest).build(), @@ -2786,17 +2927,24 @@ private static HttpCall givenHttpCall(BidRequest bidRequest, String null); } - private static String givenBidResponse(BigDecimal price) throws JsonProcessingException { + private static String givenBidResponse(Function bidCustomizer) + throws JsonProcessingException { return mapper.writeValueAsString(BidResponse.builder() .cur("USD") .seatbid(singletonList(SeatBid.builder() - .bid(singletonList(Bid.builder() - .price(price) - .build())) + .bid(singletonList(givenBid(bidCustomizer))) .build())) .build()); } + private static String givenBidResponse(BigDecimal price) throws JsonProcessingException { + return givenBidResponse(bidBuilder -> bidBuilder.price(price)); + } + + private static Bid givenBid(Function bidCustomizer) { + return bidCustomizer.apply(Bid.builder()).build(); + } + @AllArgsConstructor(staticName = "of") @Value private static class Inventory { diff --git a/src/test/java/org/prebid/server/bidder/smaato/SmaatoBidderTest.java b/src/test/java/org/prebid/server/bidder/smaato/SmaatoBidderTest.java index d23ebbcf1ef..69dbf69cd7f 100644 --- a/src/test/java/org/prebid/server/bidder/smaato/SmaatoBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/smaato/SmaatoBidderTest.java @@ -1,6 +1,7 @@ package org.prebid.server.bidder.smaato; import com.fasterxml.jackson.core.JsonProcessingException; +import com.iab.openrtb.request.App; import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Format; @@ -184,6 +185,25 @@ public void makeHttpRequestsShouldModifyRequestSite() { .containsOnly("keywords"); } + @Test + public void makeHttpRequestsShouldModifyRequestAppPublisherId() { + // given + final BidRequest bidRequest = givenBidRequest(bidRequestBuilder -> + bidRequestBuilder.app(App.builder().build()), identity()); + + // when + final Result>> result = smaatoBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .extracting(BidRequest::getApp) + .extracting(App::getPublisher) + .extracting(Publisher::getId) + .containsOnly("publisherId"); + } + @Test public void makeHttpRequestsShouldModifyRequestUser() { // given @@ -476,8 +496,12 @@ private static BidRequest givenBidRequest(Function impCustomizer) { return impCustomizer.apply(Imp.builder() .id("123") - .banner(Banner.builder().id("banner_id").build()).ext(mapper.valueToTree(ExtPrebid.of(null, - ExtImpSmaato.of("publisherId", "adspaceId"))))) + .banner(Banner.builder() + .id("banner_id") + .w(300) + .h(500) + .build()) + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpSmaato.of("publisherId", "adspaceId"))))) .build(); } diff --git a/src/test/java/org/prebid/server/bidder/smartadserver/SmartadserverBidderTest.java b/src/test/java/org/prebid/server/bidder/smartadserver/SmartadserverBidderTest.java index fe54c02a0fc..2f280cc67f6 100644 --- a/src/test/java/org/prebid/server/bidder/smartadserver/SmartadserverBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/smartadserver/SmartadserverBidderTest.java @@ -4,6 +4,8 @@ import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Publisher; +import com.iab.openrtb.request.Site; import com.iab.openrtb.request.Video; import com.iab.openrtb.response.Bid; import com.iab.openrtb.response.BidResponse; @@ -81,6 +83,33 @@ public void makeHttpRequestsShouldCreateCorrectURL() { .isEqualTo("https://test.endpoint.com/path/api/bid?testParam=testVal&callerId=5"); } + @Test + public void makeHttpRequestsShouldUpdateSiteObjectIfPresent() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(givenImp(Function.identity()))) + .site(Site.builder() + .domain("www.foo.com") + .publisher(Publisher.builder().domain("foo.com").build()) + .build()) + .build(); + + // when + final Result>> result = smartadserverBidder.makeHttpRequests(bidRequest); + + // then + final Site expectedSite = Site.builder() + .domain("www.foo.com") + .publisher(Publisher.builder().domain("foo.com").id("4").build()) + .build(); + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1); + assertThat(result.getValue()) + .extracting(HttpRequest::getPayload) + .extracting(BidRequest::getSite) + .containsExactly(expectedSite); + } + @Test public void makeHttpRequestsShouldCreateRequestForEveryValidImp() { // given diff --git a/src/test/java/org/prebid/server/bidder/tappx/TappxBidderTest.java b/src/test/java/org/prebid/server/bidder/tappx/TappxBidderTest.java index 123efcc7e02..d240c6cdbde 100644 --- a/src/test/java/org/prebid/server/bidder/tappx/TappxBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/tappx/TappxBidderTest.java @@ -114,7 +114,122 @@ public void makeHttpRequestsShouldMakeRequestWithUrl() { // then assertThat(result.getErrors()).isEmpty(); - final String expectedUri = "https://host/endpoint?tappxkey=tappxkey&v=1.1&type_cnn=prebid"; + final String expectedUri = "https://host/endpoint?tappxkey=tappxkey&v=1.2&type_cnn=prebid"; + assertThat(result.getValue()).hasSize(1) + .allSatisfy(httpRequest -> { + assertThat(httpRequest.getUri()).isEqualTo(expectedUri); + assertThat(httpRequest.getMethod()).isEqualTo(HttpMethod.POST); + }); + } + + @Test + public void makeHttpRequestShouldBuildCorrectUriWithPathInHostParameter() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .ext(mapper.valueToTree(ExtPrebid.of(null, + ExtImpTappx.of("host/rtb/v2/", "tappxkey", "endpoint", BigDecimal.ONE)))) + .build())) + .build(); + + // when + final Result>> result = tappxBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + final String expectedUri = "https://host/rtb/v2/endpoint?tappxkey=tappxkey&v=1.2&type_cnn=prebid"; + assertThat(result.getValue()).hasSize(1) + .allSatisfy(httpRequest -> { + assertThat(httpRequest.getUri()).isEqualTo(expectedUri); + assertThat(httpRequest.getMethod()).isEqualTo(HttpMethod.POST); + }); + } + + @Test + public void makeHttpRequestShouldBuildCorrectUriWithPathInHostParameterButWithoutTrailingForwardSlash() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .ext(mapper.valueToTree(ExtPrebid.of(null, + ExtImpTappx.of("host/rtb/v2", "tappxkey", "endpoint", BigDecimal.ONE)))) + .build())) + .build(); + + // when + final Result>> result = tappxBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + final String expectedUri = "https://host/rtb/v2/endpoint?tappxkey=tappxkey&v=1.2&type_cnn=prebid"; + assertThat(result.getValue()).hasSize(1) + .allSatisfy(httpRequest -> { + assertThat(httpRequest.getUri()).isEqualTo(expectedUri); + assertThat(httpRequest.getMethod()).isEqualTo(HttpMethod.POST); + }); + } + + @Test + public void makeHttpRequestShouldBuildCorrectUriWithPathInHostParameterAndSlashBeforeEndpoint() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .ext(mapper.valueToTree(ExtPrebid.of(null, + ExtImpTappx.of("host/rtb/v2", "tappxkey", "/endpoint", BigDecimal.ONE)))) + .build())) + .build(); + + // when + final Result>> result = tappxBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + final String expectedUri = "https://host/rtb/v2/endpoint?tappxkey=tappxkey&v=1.2&type_cnn=prebid"; + assertThat(result.getValue()).hasSize(1) + .allSatisfy(httpRequest -> { + assertThat(httpRequest.getUri()).isEqualTo(expectedUri); + assertThat(httpRequest.getMethod()).isEqualTo(HttpMethod.POST); + }); + } + + @Test + public void makeHttpRequestShouldBuildCorrectUriWithWeirdCaseHttpsSchemeInHostParam() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .ext(mapper.valueToTree(ExtPrebid.of(null, + ExtImpTappx.of("htTpS://host-host.com/rtb/v2", "tappxkey", "/endpoint", BigDecimal.ONE)))) + .build())) + .build(); + + // when + final Result>> result = tappxBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + final String expectedUri = "htTpS://host-host.com/rtb/v2/endpoint?tappxkey=tappxkey&v=1.2&type_cnn=prebid"; + assertThat(result.getValue()).hasSize(1) + .allSatisfy(httpRequest -> { + assertThat(httpRequest.getUri()).isEqualTo(expectedUri); + assertThat(httpRequest.getMethod()).isEqualTo(HttpMethod.POST); + }); + } + + @Test + public void makeHttpRequestsShouldModifyUrl() { + // given + final BidRequest bidRequest = BidRequest.builder() + .imp(singletonList(Imp.builder() + .ext(mapper.valueToTree(ExtPrebid.of(null, + ExtImpTappx.of("endpoint.host", "tappxkey", "endpoint", BigDecimal.ONE)))) + .build())) + .build(); + + // when + final Result>> result = tappxBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + final String expectedUri = "https://endpoint.host?tappxkey=tappxkey&v=1.2&type_cnn=prebid"; assertThat(result.getValue()).hasSize(1) .allSatisfy(httpRequest -> { assertThat(httpRequest.getUri()).isEqualTo(expectedUri); diff --git a/src/test/java/org/prebid/server/bidder/unicorn/UnicornBidderTest.java b/src/test/java/org/prebid/server/bidder/unicorn/UnicornBidderTest.java new file mode 100644 index 00000000000..0483d32c8de --- /dev/null +++ b/src/test/java/org/prebid/server/bidder/unicorn/UnicornBidderTest.java @@ -0,0 +1,341 @@ +package org.prebid.server.bidder.unicorn; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.node.TextNode; +import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Device; +import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.Regs; +import com.iab.openrtb.request.Source; +import com.iab.openrtb.response.Bid; +import com.iab.openrtb.response.BidResponse; +import com.iab.openrtb.response.SeatBid; +import io.netty.handler.codec.http.HttpHeaderValues; +import org.junit.Before; +import org.junit.Test; +import org.prebid.server.VertxTest; +import org.prebid.server.bidder.model.BidderBid; +import org.prebid.server.bidder.model.BidderError; +import org.prebid.server.bidder.model.HttpCall; +import org.prebid.server.bidder.model.HttpRequest; +import org.prebid.server.bidder.model.HttpResponse; +import org.prebid.server.bidder.model.Result; +import org.prebid.server.proto.openrtb.ext.ExtPrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebid; +import org.prebid.server.proto.openrtb.ext.request.ExtRegs; +import org.prebid.server.proto.openrtb.ext.request.ExtSource; +import org.prebid.server.proto.openrtb.ext.request.ExtStoredRequest; +import org.prebid.server.proto.openrtb.ext.request.unicorn.ExtImpUnicorn; +import org.prebid.server.util.HttpUtil; + +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +import static java.util.Collections.singletonList; +import static java.util.function.Function.identity; +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.proto.openrtb.ext.response.BidType.banner; + +public class UnicornBidderTest extends VertxTest { + + private static final String ENDPOINT_URL = "https://127.0.0.1/test"; + + private UnicornBidder unicornBidder; + + @Before + public void setUp() { + unicornBidder = new UnicornBidder(ENDPOINT_URL, jacksonMapper); + } + + @Test + public void creationShouldFailOnInvalidEndpointUrl() { + assertThatIllegalArgumentException().isThrownBy(() -> new UnicornBidder("invalid_url", jacksonMapper)); + } + + @Test + public void makeHttpRequestsShouldCorrectlyAddHeaders() { + // given + final BidRequest bidRequest = givenBidRequest(bidRequestBuilder -> + bidRequestBuilder.device(Device.builder().ua("someUa").ip("someIp").build()), + identity()); + + // when + final Result>> result = unicornBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getValue()) + .flatExtracting(res -> res.getHeaders().entries()) + .extracting(Map.Entry::getKey, Map.Entry::getValue) + .containsExactlyInAnyOrder( + tuple(HttpUtil.CONTENT_TYPE_HEADER.toString(), HttpUtil.APPLICATION_JSON_CONTENT_TYPE), + tuple(HttpUtil.ACCEPT_HEADER.toString(), HttpHeaderValues.APPLICATION_JSON.toString()), + tuple(HttpUtil.USER_AGENT_HEADER.toString(), "someUa"), + tuple(HttpUtil.X_FORWARDED_FOR_HEADER.toString(), "someIp"), + tuple(HttpUtil.X_OPENRTB_VERSION_HEADER.toString(), "2.5")); + } + + @Test + public void makeHttpRequestsShouldReturnErrorForNotValidImpExt() { + // given + final BidRequest bidRequest = givenBidRequest( + impBuilder -> impBuilder.ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createArrayNode())))); + // when + final Result>> result = unicornBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).hasSize(1); + assertThat(result.getErrors()) + .allSatisfy(error -> { + assertThat(error.getType()).isEqualTo(BidderError.Type.bad_input); + assertThat(error.getMessage()) + .startsWith("Error while decoding ext of imp with id: 123, error: Cannot deserialize"); + }); + } + + @Test + public void makeHttpRequestsShouldReturnErrorIfCoppaIsOne() { + // given + final BidRequest bidRequest = givenBidRequest( + bidRequestBuilder -> bidRequestBuilder.regs(Regs.of(1, null)), identity()); + // when + final Result>> result = unicornBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).containsExactly(BidderError.badInput("COPPA is not supported")); + } + + @Test + public void makeHttpRequestsShouldReturnErrorIfGdprIsOne() { + // given + final BidRequest bidRequest = givenBidRequest( + bidRequestBuilder -> bidRequestBuilder.regs(Regs.of(0, ExtRegs.of(1, null))), identity()); + // when + final Result>> result = unicornBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).containsExactly(BidderError.badInput("GDPR is not supported")); + } + + @Test + public void makeHttpRequestsShouldReturnErrorIfUsPrivacyIsPresent() { + // given + final BidRequest bidRequest = givenBidRequest( + bidRequestBuilder -> bidRequestBuilder.regs(Regs.of(0, ExtRegs.of(0, "privacy"))), identity()); + // when + final Result>> result = unicornBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).containsExactly(BidderError.badInput("CCPA is not supported")); + } + + @Test + public void makeHttpRequestsShouldNotModifyEndpointURL() { + // given + final BidRequest bidRequest = givenBidRequest(identity()); + + // when + final Result>> result = unicornBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1); + assertThat(result.getValue()) + .extracting(HttpRequest::getUri) + .containsExactly("https://127.0.0.1/test"); + } + + @Test + public void makeHttpRequestsShouldEnrichEveryImpWithSecureAndTagIdParams() { + // given + final BidRequest bidRequest = givenBidRequest(identity()); + + // when + final Result>> result = unicornBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getSecure, Imp::getTagid) + .containsExactly(tuple(1, "placementId")); + } + + @Test + public void makeHttpRequestsShouldSetTagIdAndUpdateBidderPlacementIdPropertyWithStoredRequestProperty() { + // given + final BidRequest bidRequest = givenBidRequest(impBuilder -> + impBuilder.ext(mapper.valueToTree(ExtPrebid.of(ExtImpPrebid.builder() + .storedrequest(ExtStoredRequest.of("storedRequestId")) + .build(), ExtImpUnicorn.of("", 123, "mediaId", 456))))); + + // when + final Result>> result = unicornBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getTagid) + .containsExactly("storedRequestId"); + assertThat(result.getValue()) + .extracting(HttpRequest::getPayload) + .flatExtracting(BidRequest::getImp) + .extracting(Imp::getExt) + .extracting(node -> node.get("bidder")) + .extracting(bidder -> mapper.convertValue(bidder, ExtImpUnicorn.class)) + .extracting(ExtImpUnicorn::getPlacementId) + .containsExactly("storedRequestId"); + } + + @Test + public void makeHttpRequestsShouldSetAddAccountIdPropertyToRequestExt() { + // given + final BidRequest bidRequest = givenBidRequest(identity()); + + // when + final Result>> result = unicornBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .extracting(HttpRequest::getPayload) + .extracting(BidRequest::getExt) + .extracting(requestExt -> requestExt.getProperty("accountId").intValue()) + .containsExactly(456); + } + + @Test + public void makeHttpRequestsShouldUpdateSourceValue() { + // given + final BidRequest bidRequest = givenBidRequest(bidRequestBuilder -> + bidRequestBuilder.source(Source.builder().tid("someTid").build()), + identity()); + + // when + final Result>> result = unicornBidder.makeHttpRequests(bidRequest); + + // then + final ExtSource extSource = ExtSource.of(null); + extSource.addProperty("stype", new TextNode("prebid_server_uncn")); + extSource.addProperty("bidder", new TextNode("unicorn")); + final Source expectedSource = Source.builder().tid("someTid").ext(extSource).build(); + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .extracting(HttpRequest::getPayload) + .extracting(BidRequest::getSource) + .containsExactly(expectedSource); + } + + @Test + public void makeHttpRequestsShouldReturnErrorForNotFoundStoredRequestId() { + // given + final BidRequest bidRequest = givenBidRequest(impBuilder -> + impBuilder.ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpUnicorn.of("", 123, "mediaId", 456))))); + + // when + final Result>> result = unicornBidder.makeHttpRequests(bidRequest); + + // then + assertThat(result.getErrors()).containsExactly(BidderError.badInput("stored request id not found in imp: 123")); + } + + @Test + public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { + // given + final HttpCall httpCall = givenHttpCall(null, "invalid"); + + // when + final Result> result = unicornBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).hasSize(1) + .allSatisfy(error -> { + assertThat(error.getType()).isEqualTo(BidderError.Type.bad_server_response); + assertThat(error.getMessage()).startsWith("Failed to decode: Unrecognized token"); + }); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnEmptyListIfBidResponseIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall(null, mapper.writeValueAsString(null)); + + // when + final Result> result = unicornBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnEmptyListIfBidResponseSeatBidIsNull() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall(null, + mapper.writeValueAsString(BidResponse.builder().build())); + + // when + final Result> result = unicornBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).isEmpty(); + } + + @Test + public void makeBidsShouldReturnBannerBidByDefault() throws JsonProcessingException { + // given + final HttpCall httpCall = givenHttpCall( + givenBidRequest(identity()), + mapper.writeValueAsString( + givenBidResponse(identity()))); + + // when + final Result> result = unicornBidder.makeBids(httpCall, null); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()) + .containsOnly(BidderBid.of(Bid.builder().build(), banner, null)); + } + + private static BidRequest givenBidRequest( + Function bidRequestCustomizer, + Function impCustomizer) { + + return bidRequestCustomizer.apply(BidRequest.builder() + .imp(singletonList(givenImp(impCustomizer)))) + .build(); + } + + private static BidRequest givenBidRequest(Function impCustomizer) { + return givenBidRequest(identity(), impCustomizer); + } + + private static Imp givenImp(Function impCustomizer) { + return impCustomizer.apply(Imp.builder() + .id("123") + .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpUnicorn.of("placementId", 123, "mediaId", 456))))) + .build(); + } + + private static BidResponse givenBidResponse(Function bidCustomizer) { + return BidResponse.builder() + .seatbid(singletonList(SeatBid.builder().bid(singletonList(bidCustomizer.apply(Bid.builder()).build())) + .build())) + .build(); + } + + private static HttpCall givenHttpCall(BidRequest bidRequest, String body) { + return HttpCall.success( + HttpRequest.builder().payload(bidRequest).build(), + HttpResponse.of(200, null, body), + null); + } +} diff --git a/src/test/java/org/prebid/server/cache/CacheServiceTest.java b/src/test/java/org/prebid/server/cache/CacheServiceTest.java index 9ea10cffaf2..a59e14e11ee 100644 --- a/src/test/java/org/prebid/server/cache/CacheServiceTest.java +++ b/src/test/java/org/prebid/server/cache/CacheServiceTest.java @@ -1,6 +1,7 @@ package org.prebid.server.cache; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Imp; @@ -32,7 +33,9 @@ import org.prebid.server.execution.Timeout; import org.prebid.server.execution.TimeoutFactory; import org.prebid.server.metric.Metrics; +import org.prebid.server.proto.openrtb.ext.ExtPrebid; import org.prebid.server.proto.openrtb.ext.response.BidType; +import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; import org.prebid.server.settings.model.Account; import org.prebid.server.vast.VastModifier; import org.prebid.server.vertx.http.HttpClient; @@ -50,6 +53,7 @@ import static java.util.Arrays.asList; import static java.util.Collections.emptyList; +import static java.util.Collections.emptyMap; import static java.util.Collections.emptySet; import static java.util.Collections.singleton; import static java.util.Collections.singletonList; @@ -402,18 +406,16 @@ public void cacheBidsOpenrtbShouldReturnExpectedCacheBids() { @Test public void cacheBidsOpenrtbShouldPerformHttpRequestWithExpectedBody() throws IOException { // given + final ObjectNode bidExt2 = mapper.valueToTree( + ExtPrebid.of(ExtBidPrebid.builder().bidid("generatedId").build(), + emptyMap())); final String receivedBid2Adm = "adm2"; - final String generatedId = "generatedId"; - final String bidder = "bidder2"; - final BidInfo bidInfo1 = givenBidInfo(builder -> builder.id("bidId1"), null, BidType.banner, "bidder1"); - final BidInfo bidInfo2 = givenBidInfo(builder -> builder.id("bidId2").adm(receivedBid2Adm), generatedId, - BidType.video, - bidder); + final BidInfo bidInfo1 = givenBidInfo(builder -> builder.id("bidId1"), BidType.banner, "bidder1"); + final BidInfo bidInfo2 = givenBidInfo(builder -> builder.id("bidId2").adm(receivedBid2Adm).ext(bidExt2), + BidType.video, "bidder2"); final EventsContext eventsContext = EventsContext.builder().auctionTimestamp(1000L).build(); - given(vastModifier.createBidVastXml(any(), any(), any(), any(), any(), any())).willReturn(receivedBid2Adm); - // when cacheService.cacheBidsOpenrtb( asList(bidInfo1, bidInfo2), @@ -431,14 +433,13 @@ public void cacheBidsOpenrtbShouldPerformHttpRequestWithExpectedBody() throws IO final Bid bid1 = bidInfo1.getBid(); final Bid bid2 = bidInfo2.getBid(); - verify(vastModifier).createBidVastXml(bidder, receivedBid2Adm, null, generatedId, ACCOUNT_ID, eventsContext); final BidCacheRequest bidCacheRequest = captureBidCacheRequest(); assertThat(bidCacheRequest.getPuts()).hasSize(3) .containsOnly( PutObject.builder().type("json").value(mapper.valueToTree(bid1)).build(), PutObject.builder().type("json").value(mapper.valueToTree(bid2)).build(), - PutObject.builder().type("xml").value(new TextNode(bid2.getAdm())).build()); + PutObject.builder().type("xml").value(new TextNode(receivedBid2Adm)).build()); } @Test @@ -674,14 +675,8 @@ public void cacheBidsOpenrtbShouldReturnExpectedResultForBids() { @Test public void cacheBidsOpenrtbShouldReturnExpectedResultForVideoBids() { // given - final String receivedAdm = "adm1"; - final String bidId = "bidId1"; - final String bidder = "bidder"; - final BidInfo bidInfo = givenBidInfo(bidBuilder -> bidBuilder.id(bidId).adm(receivedAdm), null, - BidType.video, bidder); - - given(vastModifier.createBidVastXml(anyString(), anyString(), anyString(), anyString(), anyString(), any())) - .willReturn(receivedAdm); + final BidInfo bidInfo = givenBidInfo(bidBuilder -> bidBuilder.id("bidId1").adm("adm1"), BidType.video, + "bidder"); // when final Future future = cacheService.cacheBidsOpenrtb( @@ -693,8 +688,6 @@ public void cacheBidsOpenrtbShouldReturnExpectedResultForVideoBids() { eventsContext); // then - verify(vastModifier).createBidVastXml(bidder, receivedAdm, null, bidId, ACCOUNT_ID, eventsContext); - assertThat(future.result().getCacheBids()).hasSize(1) .containsEntry(bidInfo.getBid(), CacheInfo.of(null, "uuid1", null, null)); } @@ -708,12 +701,8 @@ public void cacheBidsOpenrtbShouldReturnExpectedResultForBidsAndVideoBids() thro CacheObject.of("uuid2"), CacheObject.of("videoUuid1"))))); - final String bidder1 = "bidder1"; - final String bidId1 = "bidId1"; - final BidInfo bidInfo1 = givenBidInfo(builder -> builder.id(bidId1), null, BidType.video, bidder1); - final BidInfo bidInfo2 = givenBidInfo(builder -> builder.id("bidId2"), null, BidType.banner, "bidder2"); - - given(vastModifier.createBidVastXml(any(), any(), any(), any(), any(), any())).willReturn("modifiedAdm"); + final BidInfo bidInfo1 = givenBidInfo(builder -> builder.id("bidId1"), BidType.video, "bidder1"); + final BidInfo bidInfo2 = givenBidInfo(builder -> builder.id("bidId2"), BidType.banner, "bidder2"); // when final Future future = cacheService.cacheBidsOpenrtb( @@ -726,45 +715,12 @@ public void cacheBidsOpenrtbShouldReturnExpectedResultForBidsAndVideoBids() thro eventsContext); // then - verify(vastModifier).createBidVastXml(bidder1, null, null, bidId1, ACCOUNT_ID, eventsContext); - assertThat(future.result().getCacheBids()).hasSize(2) .containsOnly( entry(bidInfo1.getBid(), CacheInfo.of("uuid1", "videoUuid1", null, null)), entry(bidInfo2.getBid(), CacheInfo.of("uuid2", null, null, null))); } - @Test - public void cacheBidsOpenrtbShouldModifyVastXmlWhenVastModifierReturnAdm() throws IOException { - // given - final String generatedId = "generatedId"; - final String bidder = "bidder1"; - final String adm = "adm1"; - final BidInfo bidInfo = givenBidInfo(builder -> builder.id("bidId1").adm(adm), generatedId, BidType.video, - bidder); - - given(vastModifier.createBidVastXml(any(), any(), any(), any(), any(), any())).willReturn("modifiedAdm"); - - // when - cacheService.cacheBidsOpenrtb( - singletonList(bidInfo), - givenAuctionContext(), - CacheContext.builder() - .shouldCacheBids(true) - .shouldCacheVideoBids(true) - .build(), - eventsContext); - - // then - verify(vastModifier).createBidVastXml(bidder, adm, null, generatedId, ACCOUNT_ID, eventsContext); - - final BidCacheRequest bidCacheRequest = captureBidCacheRequest(); - assertThat(bidCacheRequest.getPuts()).hasSize(2) - .containsOnly( - PutObject.builder().type("json").value(mapper.valueToTree(bidInfo.getBid())).build(), - PutObject.builder().type("xml").value(new TextNode("modifiedAdm")).build()); - } - @Test public void cachePutObjectsShouldTolerateGlobalTimeoutAlreadyExpired() { // when @@ -883,12 +839,10 @@ private static BidInfo givenBidInfo(UnaryOperator bidCustomizer, } private static BidInfo givenBidInfo(UnaryOperator bidCustomizer, - String generatedBidId, BidType bidType, String bidder) { return BidInfo.builder() .bid(bidCustomizer.apply(Bid.builder()).build()) - .generatedBidId(generatedBidId) .correspondingImp(givenImp(UnaryOperator.identity())) .bidder(bidder) .bidType(bidType) diff --git a/src/test/java/org/prebid/server/handler/CookieSyncHandlerTest.java b/src/test/java/org/prebid/server/handler/CookieSyncHandlerTest.java index 6ebc7a31c0c..b01db3a7cd2 100644 --- a/src/test/java/org/prebid/server/handler/CookieSyncHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/CookieSyncHandlerTest.java @@ -1,6 +1,7 @@ package org.prebid.server.handler; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.node.TextNode; import io.netty.util.AsciiString; import io.vertx.core.Future; import io.vertx.core.buffer.Buffer; @@ -239,6 +240,29 @@ public void shouldRespondWithErrorIfGdprConsentIsMissing() { .isEqualTo(CookieSyncEvent.error(400, "Invalid request format: gdpr_consent is required if gdpr is 1")); } + @Test + public void shouldRespondWithBadRequestStatusIfGdprConsentIsInvalid() { + // given + given(routingContext.getBody()) + .willReturn(givenRequestBody(CookieSyncRequest.builder() + .bidders(singletonList(RUBICON)) + .gdpr(1) + .gdprConsent("invalid") + .build())); + + given(privacyEnforcementService.contextFromCookieSyncRequest(any(), any(), any(), any())) + .willReturn(Future.succeededFuture(PrivacyContext.of(null, + TcfContext.builder().gdpr("1").isConsentValid(false).build()))); + + // when + cookieSyncHandler.handle(routingContext); + + // then + verify(metrics).updateUserSyncTcfInvalidMetric(); + verify(httpResponse).setStatusCode(eq(400)); + verify(httpResponse).end(eq("Invalid request format: Consent string is invalid")); + } + @Test public void shouldNotSendResponseIfClientClosedConnection() { // given @@ -330,8 +354,8 @@ public void shouldRespondWithSomeBidderStatusesIfSomeUidsMissingInCookies() thro given(bidderCatalog.isActive(anyString())).willReturn(true); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "http://adnxsexample.com", null, null, "redirect", false); - rubiconUsersyncer = new Usersyncer(RUBICON, "url", null, null, "redirect", false); + appnexusUsersyncer = createUsersyncer(APPNEXUS_COOKIE, "http://adnxsexample.com", "redirect"); + rubiconUsersyncer = createUsersyncer(RUBICON, "url", "redirect"); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -365,8 +389,8 @@ public void shouldRespondWithAllActiveBiddersWhenRequestCoopSyncTrueAndNoPriorit given(routingContext.getBody()).willReturn(givenRequestBody( CookieSyncRequest.builder().bidders(singletonList(APPNEXUS)).coopSync(true).build())); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "http://adnxsexample.com", null, null, "redirect", false); - rubiconUsersyncer = new Usersyncer(RUBICON, "http://rubiconexample.com", null, null, "redirect", false); + appnexusUsersyncer = createUsersyncer(APPNEXUS_COOKIE, "http://adnxsexample.com", "redirect"); + rubiconUsersyncer = createUsersyncer(RUBICON, "http://rubiconexample.com", "redirect"); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -401,8 +425,8 @@ public void shouldRespondWithCoopBiddersWhenRequestCoopSyncTrue() throws IOExcep given(routingContext.getBody()).willReturn(givenRequestBody( CookieSyncRequest.builder().bidders(singletonList(APPNEXUS)).coopSync(true).build())); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "http://adnxsexample.com", null, null, "redirect", false); - rubiconUsersyncer = new Usersyncer(RUBICON, "http://rubiconexample.com", null, null, "redirect", false); + appnexusUsersyncer = createUsersyncer(APPNEXUS_COOKIE, "http://adnxsexample.com", "redirect"); + rubiconUsersyncer = createUsersyncer(RUBICON, "http://rubiconexample.com", "redirect"); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -443,8 +467,10 @@ public void shouldRespondWithCoopBiddersWhenAccountCoopSyncTrue() throws IOExcep .cookieSync(AccountCookieSyncConfig.of(null, null, true)) .build())); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "http://adnxsexample.com", null, null, "redirect", false); - rubiconUsersyncer = new Usersyncer(RUBICON, "http://rubiconexample.com", null, null, "redirect", false); + appnexusUsersyncer = Usersyncer.of(APPNEXUS_COOKIE, + Usersyncer.UsersyncMethod.of("redirect", "http://adnxsexample.com", null, false), null); + rubiconUsersyncer = Usersyncer.of(RUBICON, + Usersyncer.UsersyncMethod.of("redirect", "http://rubiconexample.com", null, false), null); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -478,8 +504,8 @@ public void shouldRespondWithPrioritisedCoopBidderWhenRequestCoopDefaultTrueAndL given(routingContext.getBody()).willReturn(givenRequestBody( CookieSyncRequest.builder().bidders(singletonList(APPNEXUS)).limit(2).build())); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "http://adnxsexample.com", null, null, "redirect", false); - rubiconUsersyncer = new Usersyncer(RUBICON, "http://rubiconexample.com", null, null, "redirect", false); + appnexusUsersyncer = createUsersyncer(APPNEXUS_COOKIE, "http://adnxsexample.com", "redirect"); + rubiconUsersyncer = createUsersyncer(RUBICON, "http://rubiconexample.com", "redirect"); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -514,8 +540,8 @@ public void shouldRespondWithBidderStatusForAllBiddersIfBiddersListOmittedInRequ bidderCatalog, tcfDefinerService, privacyEnforcementService, 1, false, emptyList(), analyticsReporterDelegator, metrics, timeoutFactory, jacksonMapper); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "http://adnxsexample.com", null, null, "redirect", false); - rubiconUsersyncer = new Usersyncer(RUBICON, "http://rubiconexample.com", null, null, "redirect", false); + appnexusUsersyncer = createUsersyncer(APPNEXUS_COOKIE, "http://adnxsexample.com", "redirect"); + rubiconUsersyncer = createUsersyncer(RUBICON, "http://rubiconexample.com", "redirect"); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -547,8 +573,8 @@ public void shouldRespondWithNoBidderStatusesIfAllUidsPresentInCookies() throws given(routingContext.getBody()) .willReturn(givenRequestBody(CookieSyncRequest.builder().bidders(asList(RUBICON, APPNEXUS)).build())); - rubiconUsersyncer = new Usersyncer(RUBICON, "", null, null, null, false); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "", null, null, null, false); + rubiconUsersyncer = createUsersyncer(RUBICON, "", null); + appnexusUsersyncer = createUsersyncer(APPNEXUS_COOKIE, "", null); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -572,7 +598,7 @@ public void shouldTolerateUnsupportedBidder() throws IOException { given(routingContext.getBody()).willReturn(givenRequestBody( CookieSyncRequest.builder().bidders(asList(RUBICON, "unsupported")).build())); - rubiconUsersyncer = new Usersyncer(RUBICON, "", null, null, null, false); + rubiconUsersyncer = createUsersyncer(RUBICON, "", null); givenUsersyncersReturningFamilyName(); given(bidderCatalog.isActive(RUBICON)).willReturn(true); @@ -602,7 +628,7 @@ public void shouldTolerateDisabledBidder() throws IOException { given(routingContext.getBody()) .willReturn(givenRequestBody(CookieSyncRequest.builder().bidders(asList(RUBICON, "disabled")).build())); - rubiconUsersyncer = new Usersyncer(RUBICON, "", null, null, null, false); + rubiconUsersyncer = createUsersyncer(RUBICON, "", null); givenUsersyncersReturningFamilyName(); given(bidderCatalog.isValidName(RUBICON)).willReturn(true); @@ -638,16 +664,15 @@ public void shouldTolerateRejectedBidderByTcf() throws IOException { given(routingContext.getBody()) .willReturn(givenRequestBody(CookieSyncRequest.builder().bidders(asList(RUBICON, APPNEXUS)).build())); - rubiconUsersyncer = new Usersyncer(RUBICON, "", null, null, null, false); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "", null, null, null, false); + rubiconUsersyncer = createUsersyncer(RUBICON, "", null); + appnexusUsersyncer = createUsersyncer(APPNEXUS_COOKIE, "", null); givenUsersyncersReturningFamilyName(); given(bidderCatalog.isActive(RUBICON)).willReturn(true); given(bidderCatalog.isActive(APPNEXUS)).willReturn(true); given(bidderCatalog.bidderInfoByName(APPNEXUS)) - .willReturn(BidderInfo.create(true, null, null, - null, null, 2, true, true, false)); + .willReturn(BidderInfo.create(true, null, null, null, null, null, 2, true, true, false)); givenTcfServiceReturningVendorIdResult(singleton(1)); givenTcfServiceReturningBidderNamesResult(singleton(RUBICON)); @@ -675,8 +700,8 @@ public void shouldTolerateBiddersWithoutUsersyncUrl() throws IOException { given(routingContext.getBody()) .willReturn(givenRequestBody(CookieSyncRequest.builder().bidders(asList(RUBICON, APPNEXUS)).build())); - rubiconUsersyncer = new Usersyncer(RUBICON, "", null, null, null, false); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "", null, null, null, false); + rubiconUsersyncer = createUsersyncer(RUBICON, "", null); + appnexusUsersyncer = createUsersyncer(APPNEXUS_COOKIE, "", null); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -704,8 +729,8 @@ bidderCatalog, tcfDefinerService, privacyEnforcementService, null, false, emptyL given(routingContext.getBody()) .willReturn(givenRequestBody(CookieSyncRequest.builder().bidders(asList(RUBICON, APPNEXUS)).build())); - rubiconUsersyncer = new Usersyncer(RUBICON, "", null, null, null, false); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "", null, null, null, false); + rubiconUsersyncer = createUsersyncer(RUBICON, "", null); + appnexusUsersyncer = createUsersyncer(APPNEXUS_COOKIE, "", null); givenUsersyncersReturningFamilyName(); given(bidderCatalog.isActive(RUBICON)).willReturn(true); @@ -713,7 +738,7 @@ bidderCatalog, tcfDefinerService, privacyEnforcementService, null, false, emptyL given(bidderCatalog.bidderInfoByName(APPNEXUS)) .willReturn(BidderInfo.create(true, null, null, - null, null, 2, true, true, false)); + null, null, null, 2, true, true, false)); givenTcfServiceReturningBidderNamesResult(singleton(RUBICON)); @@ -735,16 +760,15 @@ public void shouldUpdateCookieSyncSetAndRejectByTcfMetricForEachRejectedAndSynce given(routingContext.getBody()) .willReturn(givenRequestBody(CookieSyncRequest.builder().bidders(asList(RUBICON, APPNEXUS)).build())); - rubiconUsersyncer = new Usersyncer(RUBICON, "", null, null, null, false); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "", null, null, null, false); + rubiconUsersyncer = createUsersyncer(RUBICON, "", null); + appnexusUsersyncer = createUsersyncer(APPNEXUS_COOKIE, "", null); givenUsersyncersReturningFamilyName(); given(bidderCatalog.isActive(RUBICON)).willReturn(true); given(bidderCatalog.isActive(APPNEXUS)).willReturn(true); given(bidderCatalog.bidderInfoByName(APPNEXUS)) - .willReturn(BidderInfo.create(true, null, null, - null, null, 2, true, true, false)); + .willReturn(BidderInfo.create(true, null, null, null, null, null, 2, true, true, false)); givenTcfServiceReturningVendorIdResult(singleton(1)); givenTcfServiceReturningBidderNamesResult(singleton(RUBICON)); @@ -767,8 +791,8 @@ public void shouldUpdateCookieSyncMatchesMetricForEachAlreadySyncedBidder() { given(routingContext.getBody()) .willReturn(givenRequestBody(CookieSyncRequest.builder().bidders(asList(RUBICON, APPNEXUS)).build())); - rubiconUsersyncer = new Usersyncer(RUBICON, "url", null, null, null, false); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "url", null, null, null, false); + rubiconUsersyncer = createUsersyncer(RUBICON, "url", null); + appnexusUsersyncer = createUsersyncer(APPNEXUS_COOKIE, "url", null); givenUsersyncersReturningFamilyName(); given(bidderCatalog.isActive(RUBICON)).willReturn(true); @@ -798,8 +822,8 @@ public void shouldRespondWithNoCookieStatusIfHostVendorRejectedByTcf() throws IO given(routingContext.getBody()) .willReturn(givenRequestBody(CookieSyncRequest.builder().bidders(asList(RUBICON, APPNEXUS)).build())); - rubiconUsersyncer = new Usersyncer(RUBICON, "", null, null, null, false); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "", null, null, null, false); + rubiconUsersyncer = createUsersyncer(RUBICON, "", null); + appnexusUsersyncer = createUsersyncer(APPNEXUS_COOKIE, "", null); givenUsersyncersReturningFamilyName(); given(bidderCatalog.isActive(RUBICON)).willReturn(true); @@ -833,7 +857,7 @@ public void shouldRespondWithNoCookieStatusIfNoLiveUids() throws IOException { given(bidderCatalog.isActive(anyString())).willReturn(true); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "http://adnxsexample.com", null, null, "redirect", false); + appnexusUsersyncer = createUsersyncer(APPNEXUS_COOKIE, "http://adnxsexample.com", "redirect"); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -869,9 +893,10 @@ public void shouldRespondWithExpectedUsersyncInfo() throws IOException { given(bidderCatalog.isActive(anyString())).willReturn(true); - appnexusUsersyncer = new Usersyncer( - APPNEXUS_COOKIE, "http://adnxsexample.com/sync?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}", null, null, - "redirect", false); + appnexusUsersyncer = createUsersyncer( + APPNEXUS_COOKIE, + "http://adnxsexample.com/sync?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}", + "redirect"); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -887,6 +912,43 @@ public void shouldRespondWithExpectedUsersyncInfo() throws IOException { .containsOnly("http://adnxsexample.com/sync?gdpr=1&gdpr_consent=gdpr_consent1"); } + @Test + public void shouldRespondWithUsersyncMethodAllowedByRequest() throws IOException { + // given + given(routingContext.getBody()) + .willReturn(givenRequestBody(CookieSyncRequest.builder() + .bidders(singletonList(RUBICON)) + .filterSettings(CookieSyncRequest.FilterSettings.of( + CookieSyncRequest.MethodFilter.of( + new TextNode("*"), + CookieSyncRequest.FilterType.exclude), + null)) + .build())); + + given(bidderCatalog.isActive(anyString())).willReturn(true); + + rubiconUsersyncer = Usersyncer.of( + RUBICON, + Usersyncer.UsersyncMethod.of("iframe", "iframe-url", null, false), + Usersyncer.UsersyncMethod.of("redirect", "redirect-url", null, false)); + givenUsersyncersReturningFamilyName(); + + givenTcfServiceReturningVendorIdResult(singleton(1)); + givenTcfServiceReturningBidderNamesResult(set(RUBICON)); + + // when + cookieSyncHandler.handle(routingContext); + + // then + final CookieSyncResponse cookieSyncResponse = captureCookieSyncResponse(); + assertThat(cookieSyncResponse).isEqualTo(CookieSyncResponse.of("no_cookie", + singletonList(BidderUsersyncStatus.builder() + .bidder(RUBICON) + .noCookie(true) + .usersync(UsersyncInfo.of("redirect-url", "redirect", false)) + .build()))); + } + @Test public void shouldRespondWithUpdatedUsersyncInfoIfHostCookieAndUidsDiffers() throws IOException { // given @@ -899,7 +961,7 @@ public void shouldRespondWithUpdatedUsersyncInfoIfHostCookieAndUidsDiffers() thr TcfContext.empty()))); given(bidderCatalog.isActive(RUBICON)).willReturn(true); - rubiconUsersyncer = new Usersyncer(RUBICON, "http://rubiconexample.com", null, null, "redirect", false); + rubiconUsersyncer = createUsersyncer(RUBICON, "http://rubiconexample.com", "redirect"); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -919,7 +981,7 @@ public void shouldRespondWithUpdatedUsersyncInfoIfHostCookieAndUidsDiffers() thr .extracting(BidderUsersyncStatus::getUsersync) .containsOnly( UsersyncInfo.of("http://external-url/setuid?bidder=rubicon&gdpr=&gdpr_consent=&us_privacy=" - + "&uid=host%2Fcookie%2Fvalue", "redirect", false)); + + "&f=i&uid=host%2Fcookie%2Fvalue", "redirect", false)); } @Test @@ -939,9 +1001,10 @@ public void shouldRespondWithOriginalUsersyncInfoIfNoHostCookieFamilyInBiddersCo TcfContext.empty()))); given(bidderCatalog.isActive(APPNEXUS)).willReturn(true); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, + appnexusUsersyncer = createUsersyncer( + APPNEXUS_COOKIE, "http://adnxsexample.com/sync?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}", - null, null, "redirect", false); + "redirect"); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -969,7 +1032,7 @@ public void shouldRespondWithOriginalUsersyncInfoIfNoHostCookieInRequest() throw given(bidderCatalog.isActive(RUBICON)).willReturn(true); - rubiconUsersyncer = new Usersyncer(RUBICON, "http://rubiconexample.com", null, null, "redirect", false); + rubiconUsersyncer = createUsersyncer(RUBICON, "http://rubiconexample.com", "redirect"); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -997,7 +1060,7 @@ public void shouldRespondWithOriginalUsersyncInfoIfHostCookieAndUidsAreEqual() t given(bidderCatalog.isActive(RUBICON)).willReturn(true); - rubiconUsersyncer = new Usersyncer(RUBICON, "http://rubiconexample.com", null, null, "redirect", false); + rubiconUsersyncer = createUsersyncer(RUBICON, "http://rubiconexample.com", "redirect"); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -1018,32 +1081,6 @@ public void shouldRespondWithOriginalUsersyncInfoIfHostCookieAndUidsAreEqual() t .containsOnly(UsersyncInfo.of("http://rubiconexample.com", "redirect", false)); } - @Test - public void shouldRespondWithExpectedUsersyncInfoForBidderAlias() throws IOException { - // given - given(routingContext.getBody()).willReturn(givenRequestBody( - CookieSyncRequest.builder().bidders(singletonList("rubiconAlias")).gdpr(0).build())); - - given(bidderCatalog.isActive(RUBICON)).willReturn(true); - given(bidderCatalog.isAlias("rubiconAlias")).willReturn(true); - given(bidderCatalog.nameByAlias("rubiconAlias")).willReturn(RUBICON); - - rubiconUsersyncer = new Usersyncer(RUBICON, "http://rubiconexample.com", null, null, "redirect", false); - givenUsersyncersReturningFamilyName(); - - givenTcfServiceReturningVendorIdResult(singleton(1)); - givenTcfServiceReturningBidderNamesResult(emptySet()); - - // when - cookieSyncHandler.handle(routingContext); - - // then - final CookieSyncResponse cookieSyncResponse = captureCookieSyncResponse(); - assertThat(cookieSyncResponse.getBidderStatus()) - .extracting(bidderStatus -> bidderStatus.getUsersync().getUrl()) - .containsOnly("http://rubiconexample.com"); - } - @Test public void shouldTolerateMissingTcfParamsInRequestForUsersyncInfo() throws IOException { // given @@ -1058,9 +1095,10 @@ public void shouldTolerateMissingTcfParamsInRequestForUsersyncInfo() throws IOEx given(bidderCatalog.isActive(anyString())).willReturn(true); given(bidderCatalog.names()).willReturn(singleton(APPNEXUS)); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, - "http://adnxsexample.com/sync?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}", null, null, "redirect", - false); + appnexusUsersyncer = createUsersyncer( + APPNEXUS_COOKIE, + "http://adnxsexample.com/sync?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}", + "redirect"); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -1091,11 +1129,13 @@ public void shouldLimitBidderStatuses() throws IOException { .cookieSync(AccountCookieSyncConfig.of(5, 5, null)) .build())); - rubiconUsersyncer = new Usersyncer(RUBICON, - "http://adnxsexample.com/sync?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}", - null, null, "redirect", false); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "http://rubiconexample.com", null, null, "redirect", - false); + rubiconUsersyncer = Usersyncer.of(RUBICON, + Usersyncer.UsersyncMethod.of("redirect", + "http://adnxsexample.com/sync?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}", + null, false), null); + appnexusUsersyncer = Usersyncer.of(APPNEXUS_COOKIE, + Usersyncer.UsersyncMethod.of("redirect", + "http://rubiconexample.com", null, false), null); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -1125,11 +1165,11 @@ public void shouldLimitBidderStatusesWithAccountDefaultLimit() throws IOExceptio .cookieSync(AccountCookieSyncConfig.of(1, null, null)) .build())); - rubiconUsersyncer = new Usersyncer(RUBICON, - "http://adnxsexample.com/sync?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}", - null, null, "redirect", false); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "http://rubiconexample.com", null, null, "redirect", - false); + rubiconUsersyncer = Usersyncer.of(RUBICON, + Usersyncer.UsersyncMethod.of("redirect", + "http://adnxsexample.com/sync?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}", null, false), null); + appnexusUsersyncer = Usersyncer.of(APPNEXUS_COOKIE, + Usersyncer.UsersyncMethod.of("redirect", "http://rubiconexample.com", null, false), null); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -1159,11 +1199,11 @@ public void shouldLimitBidderStatusesWithAccountMaxLimit() throws IOException { .cookieSync(AccountCookieSyncConfig.of(5, 1, null)) .build())); - rubiconUsersyncer = new Usersyncer(RUBICON, + rubiconUsersyncer = createUsersyncer( + RUBICON, "http://adnxsexample.com/sync?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}", - null, null, "redirect", false); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "http://rubiconexample.com", null, null, "redirect", - false); + "redirect"); + appnexusUsersyncer = createUsersyncer(APPNEXUS_COOKIE, "http://rubiconexample.com", "redirect"); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -1190,11 +1230,11 @@ public void shouldLimitBidderStatusesWithLiveUids() throws IOException { given(bidderCatalog.isActive(anyString())).willReturn(true); - rubiconUsersyncer = new Usersyncer(RUBICON, + rubiconUsersyncer = createUsersyncer( + RUBICON, "http://adnxsexample.com/sync?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}", - null, null, "redirect", false); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "http://rubiconexample.com", null, null, "redirect", - false); + "redirect"); + appnexusUsersyncer = createUsersyncer(APPNEXUS_COOKIE, "http://rubiconexample.com", "redirect"); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -1216,11 +1256,11 @@ public void shouldNotLimitBidderStatusesIfLimitIsBiggerThanBiddersList() throws given(bidderCatalog.isActive(anyString())).willReturn(true); - rubiconUsersyncer = new Usersyncer(RUBICON, + rubiconUsersyncer = createUsersyncer( + RUBICON, "http://adnxsexample.com/sync?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}", - null, null, "redirect", false); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "http://rubiconexample.com", null, null, "redirect", - false); + "redirect"); + appnexusUsersyncer = createUsersyncer(APPNEXUS_COOKIE, "http://rubiconexample.com", "redirect"); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -1261,8 +1301,8 @@ public void shouldPassSuccessfulEventToAnalyticsReporter() { given(bidderCatalog.isActive(anyString())).willReturn(true); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "http://adnxsexample.com", null, null, "redirect", false); - rubiconUsersyncer = new Usersyncer(RUBICON, "", null, null, null, false); + appnexusUsersyncer = createUsersyncer(APPNEXUS_COOKIE, "http://adnxsexample.com", "redirect"); + rubiconUsersyncer = createUsersyncer(RUBICON, "", null); givenUsersyncersReturningFamilyName(); givenTcfServiceReturningVendorIdResult(singleton(1)); @@ -1284,7 +1324,7 @@ public void shouldPassSuccessfulEventToAnalyticsReporter() { } @Test - public void handleShouldRespondWithNoCookieWhenBothCcpaAndGdprRejectBidders() throws IOException { + public void shouldRespondWithNoCookieWhenBothCcpaAndGdprRejectBidders() throws IOException { // given given(uidsCookieService.parseFromRequest(any())).willReturn(new UidsCookie( Uids.builder().uids(emptyMap()).build(), jacksonMapper)); @@ -1292,17 +1332,17 @@ public void handleShouldRespondWithNoCookieWhenBothCcpaAndGdprRejectBidders() th given(routingContext.getBody()) .willReturn(givenRequestBody(CookieSyncRequest.builder().bidders(asList(RUBICON, APPNEXUS)).build())); - rubiconUsersyncer = new Usersyncer(RUBICON, "", null, null, null, false); - appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "", null, null, null, false); + rubiconUsersyncer = createUsersyncer(RUBICON, "", null); + appnexusUsersyncer = createUsersyncer(APPNEXUS_COOKIE, "", null); givenUsersyncersReturningFamilyName(); given(bidderCatalog.isActive(RUBICON)).willReturn(true); given(bidderCatalog.isActive(APPNEXUS)).willReturn(true); - given(bidderCatalog.bidderInfoByName(RUBICON)).willReturn(BidderInfo.create(true, null, null, - null, null, 2, true, true, false)); - given(bidderCatalog.bidderInfoByName(APPNEXUS)).willReturn(BidderInfo.create(true, null, null, - null, null, 2, true, false, false)); + given(bidderCatalog.bidderInfoByName(RUBICON)).willReturn( + BidderInfo.create(true, null, null, null, null, null, 2, true, true, false)); + given(bidderCatalog.bidderInfoByName(APPNEXUS)).willReturn( + BidderInfo.create(true, null, null, null, null, null, 2, true, false, false)); given(privacyEnforcementService.isCcpaEnforced(any(), any())).willReturn(true); @@ -1358,6 +1398,16 @@ private void givenUsersyncersReturningFamilyName() { given(bidderCatalog.usersyncerByName(APPNEXUS)).willReturn(appnexusUsersyncer); } + private static Usersyncer createUsersyncer(String cookieFamilyName, + String usersyncUrl, + String type) { + + return Usersyncer.of( + cookieFamilyName, + Usersyncer.UsersyncMethod.of(type, usersyncUrl, null, false), + null); + } + private CookieSyncResponse captureCookieSyncResponse() throws IOException { final ArgumentCaptor cookieSyncResponseCaptor = ArgumentCaptor.forClass(String.class); verify(httpResponse).end(cookieSyncResponseCaptor.capture()); diff --git a/src/test/java/org/prebid/server/handler/SetuidHandlerTest.java b/src/test/java/org/prebid/server/handler/SetuidHandlerTest.java index e703ff2d0a4..a9a563b9db5 100644 --- a/src/test/java/org/prebid/server/handler/SetuidHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/SetuidHandlerTest.java @@ -3,6 +3,7 @@ import io.vertx.core.Future; import io.vertx.core.http.CaseInsensitiveHeaders; import io.vertx.core.http.Cookie; +import io.vertx.core.http.HttpHeaders; import io.vertx.core.http.HttpServerRequest; import io.vertx.core.http.HttpServerResponse; import io.vertx.ext.web.RoutingContext; @@ -47,6 +48,7 @@ import static java.util.Arrays.asList; import static java.util.Collections.emptyMap; +import static java.util.Collections.singleton; import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.anyInt; @@ -106,12 +108,17 @@ public void setUp() { given(routingContext.response()).willReturn(httpResponse); given(httpResponse.headers()).willReturn(new CaseInsensitiveHeaders()); + given(httpResponse.putHeader(any(CharSequence.class), any(CharSequence.class))).willReturn(httpResponse); given(uidsCookieService.toCookie(any())).willReturn(Cookie.cookie("test", "test")); + given(bidderCatalog.names()).willReturn(new HashSet<>(asList("rubicon", "audienceNetwork"))); given(bidderCatalog.isActive(any())).willReturn(true); - given(bidderCatalog.usersyncerByName(any())).willReturn( - new Usersyncer(RUBICON, null, null, null, false)); + + given(bidderCatalog.usersyncerByName(eq(RUBICON))).willReturn( + Usersyncer.of(RUBICON, Usersyncer.UsersyncMethod.of("redirect", null, null, false), null)); + given(bidderCatalog.usersyncerByName(eq(FACEBOOK))).willReturn( + Usersyncer.of(FACEBOOK, Usersyncer.UsersyncMethod.of("redirect", null, null, false), null)); final Clock clock = Clock.fixed(Instant.now(), ZoneId.systemDefault()); final TimeoutFactory timeoutFactory = new TimeoutFactory(clock); @@ -187,6 +194,26 @@ public void shouldRespondWithErrorIfBidderParamIsInvalid() { verify(metrics).updateUserSyncBadRequestMetric(); } + @Test + public void shouldRespondWithBadRequestStatusIfGdprConsentIsInvalid() { + // given + given(httpRequest.getParam("bidder")).willReturn(RUBICON); + given(uidsCookieService.parseFromRequest(any())) + .willReturn(new UidsCookie(Uids.builder().uids(emptyMap()).build(), jacksonMapper)); + + tcfContext = TcfContext.builder().gdpr("1").isConsentValid(false).build(); + given(privacyEnforcementService.contextFromSetuidRequest(any(), any(), any())) + .willReturn(Future.succeededFuture(PrivacyContext.of(null, tcfContext))); + + // when + setuidHandler.handle(routingContext); + + // then + verify(metrics).updateUserSyncTcfInvalidMetric(RUBICON); + verify(httpResponse).setStatusCode(eq(400)); + verify(httpResponse).end(eq("Invalid request format: Consent string is invalid")); + } + @Test public void shouldPassUnsuccessfulEventToAnalyticsReporterIfUidMissingInRequest() { // given @@ -226,12 +253,12 @@ public void shouldRespondWithoutCookieIfGdprProcessingPreventsCookieSetting() { // then verify(routingContext, never()).addCookie(any(Cookie.class)); - verify(httpResponse).setStatusCode(eq(200)); + verify(httpResponse).setStatusCode(eq(451)); verify(httpResponse).end(eq("The gdpr_consent param prevents cookies from being saved")); verify(metrics).updateUserSyncTcfBlockedMetric(RUBICON); final SetuidEvent setuidEvent = captureSetuidEvent(); - assertThat(setuidEvent).isEqualTo(SetuidEvent.builder().status(200).build()); + assertThat(setuidEvent).isEqualTo(SetuidEvent.builder().status(451).build()); } @Test @@ -337,7 +364,7 @@ public void shouldRemoveUidFromCookieIfMissingInRequest() throws IOException { .willReturn(new UidsCookie(Uids.builder().uids(uids).build(), jacksonMapper)); given(httpRequest.getParam("bidder")).willReturn(RUBICON); - given(httpRequest.getParam("format")).willReturn("img"); + given(httpRequest.getParam("f")).willReturn("i"); // this uids cookie stands for {"tempUIDs":{"adnxs":{"uid":"12345"}}} given(uidsCookieService.toCookie(any())).willReturn(Cookie @@ -368,9 +395,9 @@ public void shouldIgnoreFacebookSentinel() throws IOException { // this uids cookie value stands for {"tempUIDs":{"audienceNetwork":{"uid":"facebookUid"}}} given(uidsCookieService.toCookie(any())).willReturn(Cookie .cookie("uids", "eyJ0ZW1wVUlEcyI6eyJhdWRpZW5jZU5ldHdvcmsiOnsidWlkIjoiZmFjZWJvb2tVaWQifX19")); - + given(bidderCatalog.names()).willReturn(singleton(FACEBOOK)); given(bidderCatalog.usersyncerByName(any())).willReturn( - new Usersyncer(FACEBOOK, null, null, null, false)); + Usersyncer.of(FACEBOOK, Usersyncer.UsersyncMethod.of("iframe", null, null, false), null)); final Clock clock = Clock.fixed(Instant.now(), ZoneId.systemDefault()); final TimeoutFactory timeoutFactory = new TimeoutFactory(clock); @@ -411,7 +438,6 @@ public void shouldRespondWithCookieFromRequestParam() throws IOException { .cookie("uids", "eyJ0ZW1wVUlEcyI6eyJydWJpY29uIjp7InVpZCI6Iko1VkxDV1FQLTI2LUNXRlQifX19")); given(httpRequest.getParam("bidder")).willReturn(RUBICON); - given(httpRequest.getParam("format")).willReturn("img"); given(httpRequest.getParam("uid")).willReturn("J5VLCWQP-26-CWFT"); given(httpResponse.setStatusCode(anyInt())).willReturn(httpResponse); @@ -421,14 +447,152 @@ public void shouldRespondWithCookieFromRequestParam() throws IOException { // then verify(routingContext, never()).addCookie(any(Cookie.class)); - verify(httpResponse).sendFile(any()); - final String uidsCookie = getUidsCookie(); final Uids decodedUids = decodeUids(uidsCookie); assertThat(decodedUids.getUids()).hasSize(1); assertThat(decodedUids.getUids().get(RUBICON).getUid()).isEqualTo("J5VLCWQP-26-CWFT"); } + @Test + public void shouldSendPixelWhenFParamIsEqualToIWhenTypeIsIframe() { + // given + given(uidsCookieService.parseFromRequest(any())) + .willReturn(new UidsCookie(Uids.builder().uids(emptyMap()).build(), jacksonMapper)); + + // {"tempUIDs":{"rubicon":{"uid":"J5VLCWQP-26-CWFT"}}} + given(uidsCookieService.toCookie(any())).willReturn(Cookie + .cookie("uids", "eyJ0ZW1wVUlEcyI6eyJydWJpY29uIjp7InVpZCI6Iko1VkxDV1FQLTI2LUNXRlQifX19")); + given(httpRequest.getParam("bidder")).willReturn(RUBICON); + given(httpRequest.getParam("f")).willReturn("i"); + given(httpRequest.getParam("uid")).willReturn("J5VLCWQP-26-CWFT"); + + given(httpResponse.setStatusCode(anyInt())).willReturn(httpResponse); + + // when + setuidHandler.handle(routingContext); + + // then + verify(routingContext, never()).addCookie(any(Cookie.class)); + verify(httpResponse).sendFile(any()); + } + + @Test + public void shouldSendEmptyResponseWhenFParamIsEqualToBWhenTypeIsRedirect() { + // given + given(uidsCookieService.parseFromRequest(any())) + .willReturn(new UidsCookie(Uids.builder().uids(emptyMap()).build(), jacksonMapper)); + + // {"tempUIDs":{"rubicon":{"uid":"J5VLCWQP-26-CWFT"}}} + given(uidsCookieService.toCookie(any())).willReturn(Cookie + .cookie("uids", "eyJ0ZW1wVUlEcyI6eyJydWJpY29uIjp7InVpZCI6Iko1VkxDV1FQLTI2LUNXRlQifX19")); + + given(httpRequest.getParam("bidder")).willReturn(RUBICON); + given(httpRequest.getParam("f")).willReturn("b"); + given(httpRequest.getParam("uid")).willReturn("J5VLCWQP-26-CWFT"); + given(bidderCatalog.names()).willReturn(singleton(RUBICON)); + given(bidderCatalog.usersyncerByName(any())) + .willReturn(Usersyncer.of(RUBICON, Usersyncer.UsersyncMethod.of("redirect", null, null, false), null)); + + given(httpResponse.setStatusCode(anyInt())).willReturn(httpResponse); + setuidHandler = new SetuidHandler( + 2000, + uidsCookieService, + applicationSettings, + bidderCatalog, + privacyEnforcementService, + tcfDefinerService, + null, + analyticsReporterDelegator, + metrics, + new TimeoutFactory(Clock.fixed(Instant.now(), ZoneId.systemDefault()))); + + // when + setuidHandler.handle(routingContext); + + // then + verify(routingContext, never()).addCookie(any(Cookie.class)); + verify(httpResponse, never()).sendFile(any()); + verify(httpResponse).putHeader(eq(HttpHeaders.CONTENT_LENGTH), eq("0")); + verify(httpResponse).putHeader(eq(HttpHeaders.CONTENT_TYPE), eq(HttpHeaders.TEXT_HTML)); + } + + @Test + public void shouldSendEmptyResponseWhenFParamNotDefinedAndTypeIsIframe() { + // given + given(uidsCookieService.parseFromRequest(any())) + .willReturn(new UidsCookie(Uids.builder().uids(emptyMap()).build(), jacksonMapper)); + + // {"tempUIDs":{"rubicon":{"uid":"J5VLCWQP-26-CWFT"}}} + given(uidsCookieService.toCookie(any())).willReturn(Cookie + .cookie("uids", "eyJ0ZW1wVUlEcyI6eyJydWJpY29uIjp7InVpZCI6Iko1VkxDV1FQLTI2LUNXRlQifX19")); + + given(bidderCatalog.usersyncerByName(eq(RUBICON))).willReturn( + Usersyncer.of(RUBICON, Usersyncer.UsersyncMethod.of("iframe", null, null, false), null)); + + given(httpRequest.getParam("bidder")).willReturn(RUBICON); + given(httpRequest.getParam("uid")).willReturn("J5VLCWQP-26-CWFT"); + + given(httpResponse.setStatusCode(anyInt())).willReturn(httpResponse); + + setuidHandler = new SetuidHandler( + 2000, + uidsCookieService, + applicationSettings, + bidderCatalog, + privacyEnforcementService, + tcfDefinerService, + null, + analyticsReporterDelegator, + metrics, + new TimeoutFactory(Clock.fixed(Instant.now(), ZoneId.systemDefault()))); + + // when + setuidHandler.handle(routingContext); + + // then + verify(routingContext, never()).addCookie(any(Cookie.class)); + verify(httpResponse, never()).sendFile(any()); + verify(httpResponse).putHeader(eq(HttpHeaders.CONTENT_LENGTH), eq("0")); + verify(httpResponse).putHeader(eq(HttpHeaders.CONTENT_TYPE), eq(HttpHeaders.TEXT_HTML)); + } + + @Test + public void shouldSendPixelWhenFParamNotDefinedAndTypeIsRedirect() { + // given + given(uidsCookieService.parseFromRequest(any())) + .willReturn(new UidsCookie(Uids.builder().uids(emptyMap()).build(), jacksonMapper)); + + // {"tempUIDs":{"rubicon":{"uid":"J5VLCWQP-26-CWFT"}}} + given(uidsCookieService.toCookie(any())).willReturn(Cookie + .cookie("uids", "eyJ0ZW1wVUlEcyI6eyJydWJpY29uIjp7InVpZCI6Iko1VkxDV1FQLTI2LUNXRlQifX19")); + given(httpRequest.getParam("bidder")).willReturn(RUBICON); + given(bidderCatalog.names()).willReturn(singleton(RUBICON)); + given(bidderCatalog.usersyncerByName(any())) + .willReturn(Usersyncer.of(RUBICON, Usersyncer.UsersyncMethod.of("redirect", null, null, false), null)); + given(httpRequest.getParam("uid")).willReturn("J5VLCWQP-26-CWFT"); + + given(httpResponse.setStatusCode(anyInt())).willReturn(httpResponse); + + setuidHandler = new SetuidHandler( + 2000, + uidsCookieService, + applicationSettings, + bidderCatalog, + privacyEnforcementService, + tcfDefinerService, + null, + analyticsReporterDelegator, + metrics, + new TimeoutFactory(Clock.fixed(Instant.now(), ZoneId.systemDefault()))); + + // when + setuidHandler.handle(routingContext); + + // then + verify(routingContext, never()).addCookie(any(Cookie.class)); + verify(httpResponse).sendFile(any()); + } + @Test public void shouldUpdateUidInCookieWithRequestValue() throws IOException { // given @@ -442,15 +606,16 @@ public void shouldUpdateUidInCookieWithRequestValue() throws IOException { given(httpRequest.getParam("uid")).willReturn("updatedUid"); // {"tempUIDs":{"adnxs":{"uid":"12345"}, "rubicon":{"uid":"updatedUid"}}} - given(uidsCookieService.toCookie(any())).willReturn(Cookie - .cookie("uids", "eyJ0ZW1wVUlEcyI6eyJhZG54cyI6eyJ1aWQiOiIxMjM0NSJ9LCAicnViaWNvbiI6eyJ1aWQiOiJ1cGRhdGVkVW" - + "lkIn19fQ==")); + given(uidsCookieService.toCookie(any())) + .willReturn(Cookie.cookie("uids", + "eyJ0ZW1wVUlEcyI6eyJhZG54cyI6eyJ1aWQiOiIxMjM0NSJ9LCAicnViaWNvbiI6eyJ1aWQiOiJ1cGRhdGVkVW" + + "lkIn19fQ==")); // when setuidHandler.handle(routingContext); // then - verify(httpResponse).end(); + verify(httpResponse).sendFile(any()); verify(routingContext, never()).addCookie(any(Cookie.class)); final String uidsCookie = getUidsCookie(); @@ -483,7 +648,7 @@ public void shouldRespondWithCookieIfUserIsNotInGdprScope() throws IOException { // then verify(routingContext, never()).addCookie(any(Cookie.class)); - verify(httpResponse).end(); + verify(httpResponse).sendFile(any()); final String uidsCookie = getUidsCookie(); final Uids decodedUids = decodeUids(uidsCookie); @@ -498,6 +663,7 @@ public void shouldSkipTcfChecksAndRespondWithCookieIfHostVendorIdNotDefined() th setuidHandler = new SetuidHandler(2000, uidsCookieService, applicationSettings, bidderCatalog, privacyEnforcementService, tcfDefinerService, null, analyticsReporterDelegator, metrics, new TimeoutFactory(clock)); + given(tcfDefinerService.resultForVendorIds(anySet(), any())) .willReturn(Future.succeededFuture(TcfResponse.of(false, emptyMap(), null))); @@ -519,7 +685,7 @@ public void shouldSkipTcfChecksAndRespondWithCookieIfHostVendorIdNotDefined() th // then verify(tcfDefinerService, never()).resultForVendorIds(anySet(), any()); verify(routingContext, never()).addCookie(any(Cookie.class)); - verify(httpResponse).end(); + verify(httpResponse).sendFile(any()); final String uidsCookie = getUidsCookie(); final Uids decodedUids = decodeUids(uidsCookie); @@ -569,9 +735,10 @@ public void shouldPassUnsuccessfulEventToAnalyticsReporterIfFacebookSentinel() { given(httpRequest.getParam("bidder")).willReturn(FACEBOOK); given(httpRequest.getParam("uid")).willReturn("0"); + given(bidderCatalog.names()).willReturn(singleton(FACEBOOK)); given(bidderCatalog.usersyncerByName(any())).willReturn( - new Usersyncer(FACEBOOK, null, null, null, false)); + Usersyncer.of(FACEBOOK, Usersyncer.UsersyncMethod.of("redirect", null, null, false), null)); final Clock clock = Clock.fixed(Instant.now(), ZoneId.systemDefault()); final TimeoutFactory timeoutFactory = new TimeoutFactory(clock); diff --git a/src/test/java/org/prebid/server/handler/info/BidderDetailsHandlerTest.java b/src/test/java/org/prebid/server/handler/info/BidderDetailsHandlerTest.java index 2ee73684045..f26988d2fb5 100644 --- a/src/test/java/org/prebid/server/handler/info/BidderDetailsHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/info/BidderDetailsHandlerTest.java @@ -54,29 +54,26 @@ public void setUp() { given(httpRequest.getParam(anyString())).willReturn("bidderName1"); - given(bidderCatalog.names()).willReturn(new HashSet<>(asList("bidderName1", "bidderName2"))); - given(bidderCatalog.bidderInfoByName(anyString())).willReturn(givenBidderInfo()); + given(bidderCatalog.names()).willReturn(new HashSet<>( + asList("bidderName1", "bidderName2", "bidderAlias1", "bidderAlias2"))); given(bidderCatalog.isActive("bidderName1")).willReturn(true); given(bidderCatalog.isActive("bidderName2")).willReturn(false); - - given(bidderCatalog.aliases()).willReturn(new HashSet<>(asList("bidderAlias1", "bidderAlias2"))); - given(bidderCatalog.nameByAlias("bidderAlias1")).willReturn("bidderName1"); - given(bidderCatalog.nameByAlias("bidderAlias2")).willReturn("bidderName2"); + given(bidderCatalog.isActive("bidderAlias1")).willReturn(true); + given(bidderCatalog.isActive("bidderAlias2")).willReturn(false); + given(bidderCatalog.bidderInfoByName(eq("bidderName1"))).willReturn(givenBidderInfo()); + given(bidderCatalog.bidderInfoByName(eq("bidderAlias1"))).willReturn(givenBidderInfo("bidderName1")); handler = new BidderDetailsHandler(bidderCatalog, jacksonMapper); } @Test - public void creationShouldFailIfAllAliasIsConfigured() { - given(bidderCatalog.aliases()).willReturn(singleton("all")); + public void creationShouldFailIfAllNameIsConfigured() { + given(bidderCatalog.names()).willReturn(singleton("all")); assertThatIllegalArgumentException().isThrownBy(() -> new BidderDetailsHandler(bidderCatalog, jacksonMapper)); } @Test public void shouldRespondWithExpectedHeaders() { - // given - handler = new BidderDetailsHandler(bidderCatalog, jacksonMapper); - // when handler.handle(routingContext); @@ -164,8 +161,21 @@ public void shouldRespondWithExpectedBodyForAllQueryParam() { + "{\"app\":{\"mediaTypes\":[\"mediaType1\"]},\"site\":{\"mediaTypes\":[\"mediaType2\"]}}}}")); } + private static BidderInfo givenBidderInfo(String aliasOf) { + return BidderInfo.create( + true, + aliasOf, + "test@email.org", + singletonList("mediaType1"), + singletonList("mediaType2"), + null, + 0, + true, + true, + false); + } + private static BidderInfo givenBidderInfo() { - return BidderInfo.create(true, "test@email.org", singletonList("mediaType1"), - singletonList("mediaType2"), null, 0, true, true, false); + return givenBidderInfo(null); } } diff --git a/src/test/java/org/prebid/server/handler/info/BiddersHandlerTest.java b/src/test/java/org/prebid/server/handler/info/BiddersHandlerTest.java index a110fcd584d..128551cf545 100644 --- a/src/test/java/org/prebid/server/handler/info/BiddersHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/info/BiddersHandlerTest.java @@ -80,25 +80,4 @@ public void shouldRespondWithExpectedBodyAndExcludeNotActiveBidders() { // then verify(httpResponse).end(eq("[\"bidder1\",\"bidder2\"]")); } - - @Test - public void shouldRespondWithExpectedBodyAndExcludeNotActiveBidderAliases() { - // given - given(bidderCatalog.names()).willReturn(new HashSet<>(asList("bidder1", "bidder2"))); - given(bidderCatalog.aliases()).willReturn(new HashSet<>(asList("bidder1-alias", "bidder2-alias"))); - - given(bidderCatalog.nameByAlias(eq("bidder1-alias"))).willReturn("bidder1"); - given(bidderCatalog.nameByAlias(eq("bidder2-alias"))).willReturn("bidder2"); - - given(bidderCatalog.isActive(eq("bidder1"))).willReturn(true); - given(bidderCatalog.isActive(eq("bidder2"))).willReturn(false); - - handler = new BiddersHandler(bidderCatalog, jacksonMapper); - - // when - handler.handle(routingContext); - - // then - verify(httpResponse).end(eq("[\"bidder1\",\"bidder1-alias\"]")); - } } diff --git a/src/test/java/org/prebid/server/handler/openrtb2/AmpHandlerTest.java b/src/test/java/org/prebid/server/handler/openrtb2/AmpHandlerTest.java index 913b9e5b09c..c39ae5b29f9 100644 --- a/src/test/java/org/prebid/server/handler/openrtb2/AmpHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/openrtb2/AmpHandlerTest.java @@ -26,7 +26,7 @@ import org.prebid.server.analytics.AnalyticsReporterDelegator; import org.prebid.server.analytics.model.AmpEvent; import org.prebid.server.analytics.model.HttpContext; -import org.prebid.server.auction.AmpRequestFactory; +import org.prebid.server.auction.requestfactory.AmpRequestFactory; import org.prebid.server.auction.AmpResponsePostProcessor; import org.prebid.server.auction.ExchangeService; import org.prebid.server.auction.model.AuctionContext; diff --git a/src/test/java/org/prebid/server/handler/openrtb2/AuctionHandlerTest.java b/src/test/java/org/prebid/server/handler/openrtb2/AuctionHandlerTest.java index 1b32003b15b..a1be2e97e78 100644 --- a/src/test/java/org/prebid/server/handler/openrtb2/AuctionHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/openrtb2/AuctionHandlerTest.java @@ -22,7 +22,7 @@ import org.prebid.server.analytics.AnalyticsReporterDelegator; import org.prebid.server.analytics.model.AuctionEvent; import org.prebid.server.analytics.model.HttpContext; -import org.prebid.server.auction.AuctionRequestFactory; +import org.prebid.server.auction.requestfactory.AuctionRequestFactory; import org.prebid.server.auction.ExchangeService; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.cookie.UidsCookie; diff --git a/src/test/java/org/prebid/server/handler/openrtb2/VideoHandlerTest.java b/src/test/java/org/prebid/server/handler/openrtb2/VideoHandlerTest.java index b415f96497f..e57a36a58ed 100644 --- a/src/test/java/org/prebid/server/handler/openrtb2/VideoHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/openrtb2/VideoHandlerTest.java @@ -19,7 +19,7 @@ import org.prebid.server.VertxTest; import org.prebid.server.analytics.AnalyticsReporterDelegator; import org.prebid.server.auction.ExchangeService; -import org.prebid.server.auction.VideoRequestFactory; +import org.prebid.server.auction.requestfactory.VideoRequestFactory; import org.prebid.server.auction.VideoResponseFactory; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.WithPodErrors; diff --git a/src/test/java/org/prebid/server/it/AdheseTest.java b/src/test/java/org/prebid/server/it/AdheseTest.java index 8c714060b30..e1b8b21ff14 100644 --- a/src/test/java/org/prebid/server/it/AdheseTest.java +++ b/src/test/java/org/prebid/server/it/AdheseTest.java @@ -20,11 +20,10 @@ public class AdheseTest extends IntegrationTest { @Test public void openrtb2AuctionShouldRespondWithBidsFromAdhese() throws IOException, JSONException { - WIRE_MOCK_RULE.stubFor(WireMock.post(WireMock.urlPathEqualTo("/adhese-exchange/sl_adhese_prebid_demo_-" - + "leaderboard/ag55/cigent;brussels/tlall/xtconsentValue/xfhttp%3A%2F%2Fwww.example.com/xzifaId")) + WIRE_MOCK_RULE.stubFor(WireMock.post(WireMock.urlPathEqualTo("/adhese-exchange")) .withHeader("Accept", WireMock.equalTo("application/json")) .withHeader("Content-Type", WireMock.equalTo("application/json;charset=UTF-8")) - .withRequestBody(WireMock.absent()) + .withRequestBody(WireMock.equalToJson("{\"slots\":[{\"slotname\":\"_adhese_prebid_demo_-leaderboard\"}],\"parameters\":{\"ag\":[\"55\"],\"ci\":[\"gent\",\"brussels\"],\"tl\":[\"all\"],\"xt\":[\"consentValue\"],\"xf\":[\"http://www.example.com\"],\"xz\":[\"ifaId\"]}}")) .willReturn(WireMock.aResponse().withBody(jsonFrom("openrtb2/adhese/test-adhese-bid-response.json")))); // pre-bid cache diff --git a/src/test/java/org/prebid/server/it/AdyoulikeTest.java b/src/test/java/org/prebid/server/it/AdyoulikeTest.java new file mode 100644 index 00000000000..3491ed27f4c --- /dev/null +++ b/src/test/java/org/prebid/server/it/AdyoulikeTest.java @@ -0,0 +1,58 @@ +package org.prebid.server.it; + +import io.restassured.response.Response; +import org.json.JSONException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.skyscreamer.jsonassert.JSONAssert; +import org.skyscreamer.jsonassert.JSONCompareMode; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.equalToIgnoreCase; +import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static io.restassured.RestAssured.given; +import static java.util.Collections.singletonList; + +@RunWith(SpringRunner.class) +public class AdyoulikeTest extends IntegrationTest { + + @Test + public void openrtb2AuctionShouldRespondWithBidsFromAdyoulike() throws IOException, JSONException { + // given + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/adyoulike-exchange")) + .withHeader("Accept", equalTo("application/json")) + .withHeader("Content-Type", equalTo("application/json;charset=UTF-8")) + .withHeader("x-openrtb-version", equalToIgnoreCase("2.5")) + .withRequestBody(equalToJson(jsonFrom("openrtb2/adyoulike/test-adyoulike-bid-request.json"))) + .willReturn(aResponse().withBody(jsonFrom("openrtb2/adyoulike/test-adyoulike-bid-response.json")))); + + // pre-bid cache + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/cache")) + .withRequestBody(equalToJson(jsonFrom("openrtb2/adyoulike/test-cache-adyoulike-request.json"))) + .willReturn(aResponse().withBody(jsonFrom("openrtb2/adyoulike/test-cache-adyoulike-response.json")))); + + // when + final Response response = given(SPEC) + .header("Referer", "http://www.example.com") + .header("X-Forwarded-For", "193.168.244.1") + .header("User-Agent", "userAgent") + .header("Origin", "http://www.example.com") + // this uids cookie value stands for {"uids":{"adyoulike":"ADL-UID"}} + .cookie("uids", "eyJ1aWRzIjp7ImFkeW91bGlrZSI6IkFETC1VSUQifX0=") + .body(jsonFrom("openrtb2/adyoulike/test-auction-adyoulike-request.json")) + .post("/openrtb2/auction"); + + // then + final String expectedAuctionResponse = openrtbAuctionResponseFrom( + "openrtb2/adyoulike/test-auction-adyoulike-response.json", + response, singletonList("adyoulike")); + + JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), JSONCompareMode.NON_EXTENSIBLE); + } +} diff --git a/src/test/java/org/prebid/server/it/ApplicationTest.java b/src/test/java/org/prebid/server/it/ApplicationTest.java index d40853d0a23..82927c1bfa3 100644 --- a/src/test/java/org/prebid/server/it/ApplicationTest.java +++ b/src/test/java/org/prebid/server/it/ApplicationTest.java @@ -1,5 +1,6 @@ package org.prebid.server.it; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; @@ -35,11 +36,13 @@ import java.io.IOException; import java.time.Instant; import java.time.temporal.ChronoUnit; -import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; +import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.function.Function; @@ -84,24 +87,28 @@ public void openrtb2AuctionShouldRespondWithBidsFromRubiconAndAppnexus() throws .withHeader("Content-Type", equalToIgnoreCase("application/json;charset=utf-8")) .withHeader("Accept", equalTo("application/json")) .withHeader("User-Agent", equalTo("prebid-server/1.0")) + .withHeader("Sec-GPC", equalTo("1")) .withRequestBody(equalToJson(jsonFrom("openrtb2/rubicon_appnexus/test-rubicon-bid-request-1.json"))) .willReturn(aResponse().withBody(jsonFrom( "openrtb2/rubicon_appnexus/test-rubicon-bid-response-1.json")))); // rubicon bid response for imp 2 WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/rubicon-exchange")) + .withHeader("Sec-GPC", equalTo("1")) .withRequestBody(equalToJson(jsonFrom("openrtb2/rubicon_appnexus/test-rubicon-bid-request-2.json"))) .willReturn(aResponse().withBody(jsonFrom( "openrtb2/rubicon_appnexus/test-rubicon-bid-response-2.json")))); // appnexus bid response for imp 3 WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/appnexus-exchange")) + .withHeader("Sec-GPC", equalTo("1")) .withRequestBody(equalToJson(jsonFrom("openrtb2/rubicon_appnexus/test-appnexus-bid-request-1.json"))) .willReturn(aResponse().withBody(jsonFrom( "openrtb2/rubicon_appnexus/test-appnexus-bid-response-1.json")))); // appnexus bid response for imp 3 with alias parameters WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/appnexus-exchange")) + .withHeader("Sec-GPC", equalTo("1")) .withRequestBody(equalToJson(jsonFrom("openrtb2/rubicon_appnexus/test-appnexus-bid-request-2.json"))) .willReturn(aResponse().withBody(jsonFrom( "openrtb2/rubicon_appnexus/test-appnexus-bid-response-2.json")))); @@ -121,6 +128,7 @@ public void openrtb2AuctionShouldRespondWithBidsFromRubiconAndAppnexus() throws .header("Referer", "http://www.example.com") .header("User-Agent", "userAgent") .header("Origin", "http://www.example.com") + .header("Sec-GPC", 1) // this uids cookie value stands for {"uids":{"rubicon":"J5VLCWQP-26-CWFT","adnxs":"12345"}} .cookie("uids", "eyJ1aWRzIjp7InJ1Ymljb24iOiJKNVZMQ1dRUC0yNi1DV0ZUIiwiYWRueHMiOiIxMjM0NSJ9fQ==") .body(jsonFrom("openrtb2/rubicon_appnexus/test-auction-rubicon-appnexus-request.json")) @@ -134,6 +142,44 @@ public void openrtb2AuctionShouldRespondWithBidsFromRubiconAndAppnexus() throws JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), openrtbCacheDebugComparator()); } + @Test + public void testOpenrtb2AuctionCoreFunctionality() throws IOException, JSONException { + // given + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/rubicon-exchange")) + .withHeader("Accept", equalTo("application/json")) + .withHeader("Content-Type", equalTo("application/json;charset=UTF-8")) + .withQueryParam("tk_xint", equalTo("rp-pbs")) + .withRequestBody(equalToJson( + jsonFrom("openrtb2/rubicon_core_functionality/test-rubicon-bid-request.json"))) + .willReturn(aResponse().withBody( + jsonFrom("openrtb2/rubicon_core_functionality/test-rubicon-bid-response.json")))); + + // pre-bid cache + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/cache")) + .withRequestBody(equalToJson( + jsonFrom("openrtb2/rubicon_core_functionality/test-cache-rubicon-request.json"))) + .willReturn(aResponse().withBody( + jsonFrom("openrtb2/rubicon_core_functionality/test-cache-rubicon-response.json")))); + + // when + final Response response = given(SPEC) + .header("Referer", "http://www.example.com") + .header("X-Forwarded-For", "193.168.244.1") + .header("User-Agent", "userAgent") + .header("Origin", "http://www.example.com") + // this uids cookie value stands for {"uids":{"rubicon":"RUB-UID"}} + .cookie("uids", "eyJ1aWRzIjp7InJ1Ymljb24iOiJSVUItVUlEIn19") + .body(jsonFrom("openrtb2/rubicon_core_functionality/test-auction-rubicon-request.json")) + .post("/openrtb2/auction"); + + // then + final String expectedAuctionResponse = openrtbAuctionResponseFrom( + "openrtb2/rubicon_core_functionality/test-auction-rubicon-response.json", + response, singletonList("rubicon")); + + JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), JSONCompareMode.NON_EXTENSIBLE); + } + @Test public void openrtb2MultiBidAuctionShouldRespondWithBidsFromRubiconAndAppnexus() throws IOException, JSONException { // given @@ -163,8 +209,7 @@ public void openrtb2MultiBidAuctionShouldRespondWithBidsFromRubiconAndAppnexus() .willReturn(aResponse() .withTransformers("cache-response-transformer") .withTransformerParameter("matcherName", - "openrtb2/rubicon_appnexus_multi_bid/test-cache-matcher-rubicon-appnexus.json") - )); + "openrtb2/rubicon_appnexus_multi_bid/test-cache-matcher-rubicon-appnexus.json"))); // when final Response response = given(SPEC) @@ -348,6 +393,7 @@ public void cookieSyncShouldReturnBidderStatusWithExpectedUsersyncInfo() { "http://localhost:8080/setuid?bidder=rubicon" + "&gdpr=1&gdpr_consent=" + gdprConsent + "&us_privacy=1YNN" + + "&f=i" + "&uid=host-cookie-uid", "redirect", false)) .build(), @@ -358,6 +404,7 @@ public void cookieSyncShouldReturnBidderStatusWithExpectedUsersyncInfo() { "//usersync-url/getuid?http%3A%2F%2Flocalhost%3A8080%2Fsetuid%3Fbidder" + "%3Dadnxs%26gdpr%3D1%26gdpr_consent%3D" + gdprConsent + "%26us_privacy%3D1YNN" + + "%26f%3Di" + "%26uid%3D%24UID", "redirect", false)) .build(), @@ -455,34 +502,47 @@ public void optionsRequestShouldRespondWithOriginalPolicyHeaders() { } @Test - public void biddersParamsShouldReturnBidderSchemas() throws JSONException { - // given - final Map bidderNameToSchema = getBidderNamesFromParamFiles().stream() - .collect(Collectors.toMap(Function.identity(), ApplicationTest::jsonSchemaToJsonNode)); - + public void biddersParamsShouldReturnBidderSchemas() throws JSONException, IOException { // when final Response response = given(SPEC) .when() .get("/bidders/params"); // then - JSONAssert.assertEquals(bidderNameToSchema.toString(), response.asString(), JSONCompareMode.NON_EXTENSIBLE); + final Map responseAsMap = jacksonMapper.decodeValue(response.asString(), + new TypeReference>() { + }); + + final List bidders = getBidderNamesFromParamFiles(); + final Map aliases = getBidderAliasesFromConfigFiles(); + final Map expectedMap = CollectionUtils.union(bidders, aliases.keySet()).stream() + .collect(Collectors.toMap( + Function.identity(), + bidderName -> jsonSchemaToJsonNode(aliases.getOrDefault(bidderName, bidderName)))); + + assertThat(responseAsMap.keySet()).containsOnlyElementsOf(expectedMap.keySet()); + assertThat(responseAsMap).containsAllEntriesOf(expectedMap); + + JSONAssert.assertEquals(expectedMap.toString(), response.asString(), JSONCompareMode.NON_EXTENSIBLE); } @Test - public void infoBiddersShouldReturnRegisteredActiveBidderNames() throws JSONException, IOException { - // given - final List bidderNames = getBidderNamesFromParamFiles(); - final List bidderAliases = getBidderAliasesFromConfigFiles(); - + public void infoBiddersShouldReturnRegisteredActiveBidderNames() throws IOException { // when final Response response = given(SPEC) .when() .get("/info/bidders"); // then - final String expectedResponse = CollectionUtils.union(bidderNames, bidderAliases).toString(); - JSONAssert.assertEquals(expectedResponse, response.asString(), JSONCompareMode.NON_EXTENSIBLE); + final List responseAsList = jacksonMapper.decodeValue(response.asString(), + new TypeReference>() { + }); + + final List bidders = getBidderNamesFromParamFiles(); + final Map aliases = getBidderAliasesFromConfigFiles(); + final Collection expectedBidders = CollectionUtils.union(bidders, aliases.keySet()); + + assertThat(responseAsList).containsOnlyElementsOf(expectedBidders); } @Test @@ -642,27 +702,30 @@ private static List getBidderNamesFromParamFiles() { return Collections.emptyList(); } - private static List getBidderAliasesFromConfigFiles() throws IOException { + private static Map getBidderAliasesFromConfigFiles() throws IOException { final String folderPath = "src/main/resources/bidder-config"; final File folder = new File(folderPath); final String[] files = folder.list(); if (files != null) { final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); - final List aliases = new ArrayList<>(); + final Map aliases = new HashMap<>(); for (String fileName : files) { final JsonNode configNode = mapper.readValue(new File(folderPath, fileName), JsonNode.class); - final JsonNode aliasesNode = configNode.get("adapters").fields().next().getValue().get("aliases"); - - if (!aliasesNode.isNull()) { - for (String alias : aliasesNode.textValue().split(",")) { - aliases.add(alias.trim()); + final Map.Entry bidderEntry = configNode.get("adapters").fields().next(); + final String bidderName = bidderEntry.getKey(); + final JsonNode aliasesNode = bidderEntry.getValue().get("aliases"); + + if (aliasesNode.isObject()) { + Iterator iterator = aliasesNode.fieldNames(); + while (iterator.hasNext()) { + aliases.put(iterator.next().trim(), bidderName); } } } return aliases; } - return Collections.emptyList(); + return Collections.emptyMap(); } private static JsonNode jsonSchemaToJsonNode(String bidderName) { diff --git a/src/test/java/org/prebid/server/it/DecenteradsTest.java b/src/test/java/org/prebid/server/it/DecenteradsTest.java new file mode 100644 index 00000000000..4143ce9a5f9 --- /dev/null +++ b/src/test/java/org/prebid/server/it/DecenteradsTest.java @@ -0,0 +1,63 @@ +package org.prebid.server.it; + +import io.restassured.response.Response; +import org.json.JSONException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.skyscreamer.jsonassert.JSONAssert; +import org.skyscreamer.jsonassert.JSONCompareMode; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static io.restassured.RestAssured.given; +import static java.util.Collections.singletonList; + +@RunWith(SpringRunner.class) +public class DecenteradsTest extends IntegrationTest { + + @Test + public void openrtb2AuctionShouldRespondWithBidsFromDecenterads() throws IOException, JSONException { + // given + // Decenterads bid response for imp 001 + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/decenterads-exchange")) + .withRequestBody(equalToJson(jsonFrom("openrtb2/decenterads/test-decenterads-bid-request-1.json"))) + .willReturn(aResponse() + .withBody(jsonFrom("openrtb2/decenterads/test-decenterads-bid-response-1.json")))); + + // Decenterads bid response for imp 002 + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/decenterads-exchange")) + .withRequestBody(equalToJson(jsonFrom("openrtb2/decenterads/test-decenterads-bid-request-2.json"))) + .willReturn(aResponse() + .withBody(jsonFrom("openrtb2/decenterads/test-decenterads-bid-response-2.json")))); + + // pre-bid cache + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/cache")) + .withRequestBody(equalToBidCacheRequest( + jsonFrom("openrtb2/decenterads/test-cache-decenterads-request.json"))) + .willReturn(aResponse().withTransformers("cache-response-transformer") + .withTransformerParameter("matcherName", + "openrtb2/decenterads/test-cache-matcher-decenterads.json"))); + // when + final Response response = given(SPEC) + .header("Referer", "http://www.example.com") + .header("X-Forwarded-For", "193.168.244.1") + .header("User-Agent", "userAgent") + .header("Origin", "http://www.example.com") + // this uids cookie value stands for {"uids":{"decenterads":"DC-UID"}} + .cookie("uids", "eyJ1aWRzIjp7ImRlY2VudGVyYWRzIjoiREMtVUlEIn19") + .body(jsonFrom("openrtb2/decenterads/test-auction-decenterads-request.json")) + .post("/openrtb2/auction"); + + // then + final String expectedAuctionResponse = openrtbAuctionResponseFrom( + "openrtb2/decenterads/test-auction-decenterads-response.json", + response, singletonList("decenterads")); + + JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), JSONCompareMode.NON_EXTENSIBLE); + } +} diff --git a/src/test/java/org/prebid/server/it/EplanningTest.java b/src/test/java/org/prebid/server/it/EplanningTest.java index 172f51f3cab..c836d7d093b 100644 --- a/src/test/java/org/prebid/server/it/EplanningTest.java +++ b/src/test/java/org/prebid/server/it/EplanningTest.java @@ -27,7 +27,7 @@ public class EplanningTest extends IntegrationTest { public void openrtb2AuctionShouldRespondWithBidsFromEplanning() throws IOException, JSONException { // given // eplanning bid response for imp15 - WIRE_MOCK_RULE.stubFor(get(urlPathEqualTo("/eplanning-exchange/12345/1/example.com/ROS")) + WIRE_MOCK_RULE.stubFor(get(urlPathEqualTo("/eplanning-exchange/12345/1/www.example.com/ROS")) .withQueryParam("r", equalTo("pbs")) .withQueryParam("ncb", equalTo("1")) .withQueryParam("ur", equalTo("https://www.example.com")) diff --git a/src/test/java/org/prebid/server/it/EpomTest.java b/src/test/java/org/prebid/server/it/EpomTest.java new file mode 100644 index 00000000000..9c199dfdfc6 --- /dev/null +++ b/src/test/java/org/prebid/server/it/EpomTest.java @@ -0,0 +1,54 @@ +package org.prebid.server.it; + +import io.restassured.response.Response; +import org.json.JSONException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.skyscreamer.jsonassert.JSONAssert; +import org.skyscreamer.jsonassert.JSONCompareMode; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static io.restassured.RestAssured.given; +import static java.util.Collections.singletonList; + +@RunWith(SpringRunner.class) +public class EpomTest extends IntegrationTest { + + @Test + public void openrtb2AuctionShouldRespondWithBidsFromTheMediaEpom() throws IOException, JSONException { + // given + // Epom bid response for imp 001 + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/epom-exchange")) + .withRequestBody(equalToJson(jsonFrom("openrtb2/epom/test-epom-bid-request-1.json"))) + .willReturn(aResponse().withBody(jsonFrom("openrtb2/epom/test-epom-bid-response-1.json")))); + + // pre-bid cache + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/cache")) + .withRequestBody(equalToJson(jsonFrom("openrtb2/epom/test-cache-epom-request.json"))) + .willReturn(aResponse().withBody(jsonFrom("openrtb2/epom/test-cache-epom-response.json")))); + + // when + final Response response = given(SPEC) + .header("Referer", "http://www.example.com") + .header("X-Forwarded-For", "193.168.244.1") + .header("User-Agent", "userAgent") + .header("Origin", "http://www.example.com") + // this uids cookie value stands for {"uids":{"epom":"EP-UID"}} + .cookie("uids", "eyJ1aWRzIjp7ImVwb20iOiJFUC1VSUQifX0=") + .body(jsonFrom("openrtb2/epom/test-auction-epom-request.json")) + .post("/openrtb2/auction"); + + // then + final String expectedAuctionResponse = openrtbAuctionResponseFrom( + "openrtb2/epom/test-auction-epom-response.json", + response, singletonList("epom")); + + JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), JSONCompareMode.NON_EXTENSIBLE); + } +} diff --git a/src/test/java/org/prebid/server/it/IntegrationTest.java b/src/test/java/org/prebid/server/it/IntegrationTest.java index 50562374cc7..b94ddb29a29 100644 --- a/src/test/java/org/prebid/server/it/IntegrationTest.java +++ b/src/test/java/org/prebid/server/it/IntegrationTest.java @@ -142,7 +142,7 @@ private static String cacheResponseFromRequestJson( final List responseCacheObjects = new ArrayList<>(); for (PutObject putItem : puts) { final String id = putItem.getType().equals("json") - ? putItem.getValue().get("id").textValue() + "@" + putItem.getValue().get("price") + ? putItem.getValue().get("id").textValue() + "@" + resolvePriceForJsonMediaType(putItem) : putItem.getValue().textValue(); final String uuid = jsonNodeMatcher.get(id).textValue(); @@ -154,6 +154,12 @@ private static String cacheResponseFromRequestJson( } } + private static String resolvePriceForJsonMediaType(PutObject putItem) { + final JsonNode extObject = putItem.getValue().get("ext"); + final JsonNode origBidCpm = extObject != null ? extObject.get("origbidcpm") : null; + return origBidCpm != null ? origBidCpm.toString() : putItem.getValue().get("price").toString(); + } + /** * Cache debug fields "requestbody" and "responsebody" are escaped JSON strings. * This comparator allows to compare them with actual values as usual JSON objects. diff --git a/src/test/java/org/prebid/server/it/JixieTest.java b/src/test/java/org/prebid/server/it/JixieTest.java new file mode 100644 index 00000000000..3a834f86735 --- /dev/null +++ b/src/test/java/org/prebid/server/it/JixieTest.java @@ -0,0 +1,59 @@ +package org.prebid.server.it; + +import io.restassured.response.Response; +import org.json.JSONException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.skyscreamer.jsonassert.JSONAssert; +import org.skyscreamer.jsonassert.JSONCompareMode; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static io.restassured.RestAssured.given; +import static java.util.Collections.singletonList; + +@RunWith(SpringRunner.class) +public class JixieTest extends IntegrationTest { + + @Test + public void openrtb2AuctionShouldRespondWithBidsFromJixie() throws IOException, JSONException { + // given + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/jixie-exchange")) + .withHeader("Accept", equalTo("application/json")) + .withHeader("Content-Type", equalTo("application/json;charset=UTF-8")) + .withHeader("User-Agent", equalTo("testUa")) + .withHeader("X-Forwarded-For", equalTo("193.168.244.1")) + .withHeader("Referer", equalTo("awesomePage")) + .withRequestBody(equalToJson(jsonFrom("openrtb2/jixie/test-jixie-bid-request.json"))) + .willReturn(aResponse().withBody(jsonFrom("openrtb2/jixie/test-jixie-bid-response.json")))); + + // pre-bid cache + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/cache")) + .withRequestBody(equalToJson(jsonFrom("openrtb2/jixie/test-cache-jixie-request.json"))) + .willReturn(aResponse().withBody(jsonFrom("openrtb2/jixie/test-cache-jixie-response.json")))); + + // when + final Response response = given(SPEC) + .header("Referer", "http://www.example.com") + .header("X-Forwarded-For", "193.168.244.1") + .header("User-Agent", "userAgent") + .header("Origin", "http://www.example.com") + // this uids cookie value stands for {"uids":{"jixie":"JX-UID"}} + .cookie("uids", "eyJ1aWRzIjp7ImppeGllIjoiSlgtVUlEIn19") + .body(jsonFrom("openrtb2/jixie/test-auction-jixie-request.json")) + .post("/openrtb2/auction"); + + // then + final String expectedAuctionResponse = openrtbAuctionResponseFrom( + "openrtb2/jixie/test-auction-jixie-response.json", + response, singletonList("jixie")); + + JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), JSONCompareMode.NON_EXTENSIBLE); + } +} diff --git a/src/test/java/org/prebid/server/it/MobfoxpbTest.java b/src/test/java/org/prebid/server/it/MobfoxpbTest.java index d34dfa4077b..6881f2732cb 100644 --- a/src/test/java/org/prebid/server/it/MobfoxpbTest.java +++ b/src/test/java/org/prebid/server/it/MobfoxpbTest.java @@ -28,6 +28,9 @@ public void openrtb2AuctionShouldRespondWithBidsFromMobfoxpb() throws IOExceptio WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/mobfoxpb-exchange")) .withHeader("Accept", equalTo("application/json")) .withHeader("Content-Type", equalTo("application/json;charset=UTF-8")) + .withQueryParam("c", equalTo("rtb")) + .withQueryParam("m", equalTo("req")) + .withQueryParam("key", equalTo("someKey")) .withRequestBody(equalToJson(jsonFrom("openrtb2/mobfoxpb/test-mobfoxpb-bid-request-1.json"))) .willReturn(aResponse().withBody(jsonFrom("openrtb2/mobfoxpb/test-mobfoxpb-bid-response-1.json")))); diff --git a/src/test/java/org/prebid/server/it/OnetagTest.java b/src/test/java/org/prebid/server/it/OnetagTest.java new file mode 100644 index 00000000000..aa7562e0bd4 --- /dev/null +++ b/src/test/java/org/prebid/server/it/OnetagTest.java @@ -0,0 +1,60 @@ +package org.prebid.server.it; + +import io.restassured.response.Response; +import org.json.JSONException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.skyscreamer.jsonassert.JSONAssert; +import org.skyscreamer.jsonassert.JSONCompareMode; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.equalToIgnoreCase; +import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static io.restassured.RestAssured.given; +import static java.util.Collections.singletonList; + +@RunWith(SpringRunner.class) +public class OnetagTest extends IntegrationTest { + + @Test + public void openrtb2AuctionShouldRespondWithBidsFromOnetag() throws IOException, JSONException { + // given + // Onetag bid response for imp + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/onetag-exchange")) + .withHeader("Accept", equalTo("application/json")) + .withHeader("Content-Type", equalToIgnoreCase("application/json;charset=UTF-8")) + .withRequestBody(equalToJson(jsonFrom("openrtb2/onetag/test-onetag-bid-request.json"))) + .willReturn(aResponse().withBody( + jsonFrom("openrtb2/onetag/test-onetag-bid-response.json")))); + + // pre-bid cache + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/cache")) + .withRequestBody(equalToJson(jsonFrom("openrtb2/onetag/test-cache-onetag-request.json"))) + .willReturn(aResponse().withBody( + jsonFrom("openrtb2/onetag/test-cache-onetag-response.json")))); + + // when + final Response response = given(SPEC) + .header("Referer", "http://www.example.com") + .header("X-Forwarded-For", "193.168.244.1") + .header("User-Agent", "userAgent") + .header("Origin", "http://www.example.com") + // this uids cookie value stands for {"uids":{"onetag":"OT-UID"}} + .cookie("uids", "eyJ1aWRzIjp7Im9uZXRhZyI6Ik9ULVVJRCJ9fQ==") + .body(jsonFrom("openrtb2/onetag/test-auction-onetag-request.json")) + .post("/openrtb2/auction"); + + // then + final String expectedAuctionResponse = openrtbAuctionResponseFrom( + "openrtb2/onetag/test-auction-onetag-response.json", + response, singletonList("onetag")); + + JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), JSONCompareMode.NON_EXTENSIBLE); + } +} diff --git a/src/test/java/org/prebid/server/it/OutbrainTest.java b/src/test/java/org/prebid/server/it/OutbrainTest.java new file mode 100644 index 00000000000..b34c8fd2502 --- /dev/null +++ b/src/test/java/org/prebid/server/it/OutbrainTest.java @@ -0,0 +1,56 @@ +package org.prebid.server.it; + +import io.restassured.response.Response; +import org.json.JSONException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.skyscreamer.jsonassert.JSONAssert; +import org.skyscreamer.jsonassert.JSONCompareMode; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static io.restassured.RestAssured.given; +import static java.util.Collections.singletonList; + +@RunWith(SpringRunner.class) +public class OutbrainTest extends IntegrationTest { + + @Test + public void openrtb2AuctionShouldRespondWithBidsFromOutbrain() throws IOException, JSONException { + // given + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/outbrain-exchange")) + .withHeader("Accept", equalTo("application/json")) + .withHeader("Content-Type", equalTo("application/json;charset=UTF-8")) + .withRequestBody(equalToJson(jsonFrom("openrtb2/outbrain/test-outbrain-bid-request.json"))) + .willReturn(aResponse().withBody(jsonFrom("openrtb2/outbrain/test-outbrain-bid-response.json")))); + + // pre-bid cache + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/cache")) + .withRequestBody(equalToJson(jsonFrom("openrtb2/outbrain/test-cache-outbrain-request.json"))) + .willReturn(aResponse().withBody(jsonFrom("openrtb2/outbrain/test-cache-outbrain-response.json")))); + + // when + final Response response = given(SPEC) + .header("Referer", "http://www.example.com") + .header("X-Forwarded-For", "193.168.244.1") + .header("User-Agent", "userAgent") + .header("Origin", "http://www.example.com") + // this uids cookie value stands for {"uids":{"outbrain":"OB-UID"}} + .cookie("uids", "eyJ1aWRzIjp7Im91dGJyYWluIjoiT0ItVUlEIn19") + .body(jsonFrom("openrtb2/outbrain/test-auction-outbrain-request.json")) + .post("/openrtb2/auction"); + + // then + final String expectedAuctionResponse = openrtbAuctionResponseFrom( + "openrtb2/outbrain/test-auction-outbrain-response.json", + response, singletonList("outbrain")); + + JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), JSONCompareMode.NON_EXTENSIBLE); + } +} diff --git a/src/test/java/org/prebid/server/it/PangleTest.java b/src/test/java/org/prebid/server/it/PangleTest.java new file mode 100644 index 00000000000..f9bc8acd738 --- /dev/null +++ b/src/test/java/org/prebid/server/it/PangleTest.java @@ -0,0 +1,57 @@ +package org.prebid.server.it; + +import io.restassured.response.Response; +import org.json.JSONException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.skyscreamer.jsonassert.JSONAssert; +import org.skyscreamer.jsonassert.JSONCompareMode; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static io.restassured.RestAssured.given; +import static java.util.Collections.singletonList; + +@RunWith(SpringRunner.class) +public class PangleTest extends IntegrationTest { + + @Test + public void openrtb2AuctionShouldRespondWithBidsFromPangle() throws IOException, JSONException { + // given + // Pangle bid response for imp 001 + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/pangle-exchange")) + .withRequestBody(equalToJson(jsonFrom("openrtb2/pangle/test-pangle-bid-request-1.json"))) + .willReturn(aResponse().withBody(jsonFrom("openrtb2/pangle/test-pangle-bid-response-1.json")))); + + // pre-bid cache + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/cache")) + .withRequestBody(equalToBidCacheRequest( + jsonFrom("openrtb2/pangle/test-cache-pangle-request.json"))) + .willReturn(aResponse() + .withTransformers("cache-response-transformer") + .withTransformerParameter("matcherName", "openrtb2/pangle/test-cache-matcher-pangle.json"))); + + // when + final Response response = given(SPEC) + .header("Referer", "http://www.example.com") + .header("X-Forwarded-For", "193.168.244.1") + .header("User-Agent", "userAgent") + .header("Origin", "http://www.example.com") + // this uids cookie value stands for {"uids":{"pangle":"PG-UID"}} + .cookie("uids", "eyJ1aWRzIjp7InBhbmdsZSI6IlBHLVVJRCJ9fQ==") + .body(jsonFrom("openrtb2/pangle/test-auction-pangle-request.json")) + .post("/openrtb2/auction"); + + // then + final String expectedAuctionResponse = openrtbAuctionResponseFrom( + "openrtb2/pangle/test-auction-pangle-response.json", + response, singletonList("pangle")); + + JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), JSONCompareMode.NON_EXTENSIBLE); + } +} diff --git a/src/test/java/org/prebid/server/it/RubiconTest.java b/src/test/java/org/prebid/server/it/RubiconTest.java new file mode 100644 index 00000000000..4a017e4b93f --- /dev/null +++ b/src/test/java/org/prebid/server/it/RubiconTest.java @@ -0,0 +1,61 @@ +package org.prebid.server.it; + +import io.restassured.response.Response; +import org.json.JSONException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.skyscreamer.jsonassert.JSONAssert; +import org.skyscreamer.jsonassert.JSONCompareMode; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static io.restassured.RestAssured.given; +import static java.util.Collections.singletonList; + +@RunWith(SpringRunner.class) +public class RubiconTest extends IntegrationTest { + + @Test + public void testOpenrtb2AuctionCoreFunctionality() throws IOException, JSONException { + // given + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/rubicon-exchange")) + .withHeader("Accept", equalTo("application/json")) + .withHeader("Content-Type", equalTo("application/json;charset=UTF-8")) + .withQueryParam("tk_xint", equalTo("rp-pbs")) + .withRequestBody(equalToJson( + jsonFrom("openrtb2/rubicon/test-rubicon-bid-request.json"))) + .willReturn(aResponse().withBody( + jsonFrom("openrtb2/rubicon/test-rubicon-bid-response.json")))); + + // pre-bid cache + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/cache")) + .withRequestBody(equalToJson( + jsonFrom("openrtb2/rubicon/test-cache-rubicon-request.json"))) + .willReturn(aResponse().withBody( + jsonFrom("openrtb2/rubicon/test-cache-rubicon-response.json")))); + + // when + final Response response = given(SPEC) + .header("Referer", "http://www.example.com") + .header("X-Forwarded-For", "193.168.244.1") + .header("User-Agent", "userAgent") + .header("Origin", "http://www.example.com") + // this uids cookie value stands for {"uids":{"rubicon":"RUB-UID"}} + .cookie("uids", "eyJ1aWRzIjp7InJ1Ymljb24iOiJSVUItVUlEIn19") + .body(jsonFrom("openrtb2/rubicon/test-auction-rubicon-request.json")) + .post("/openrtb2/auction"); + + // then + final String expectedAuctionResponse = openrtbAuctionResponseFrom( + "openrtb2/rubicon/test-auction-rubicon-response.json", + response, singletonList("rubicon")); + + JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), JSONCompareMode.NON_EXTENSIBLE); + } +} diff --git a/src/test/java/org/prebid/server/it/TappxTest.java b/src/test/java/org/prebid/server/it/TappxTest.java index fe12b651953..e86e6f115ae 100644 --- a/src/test/java/org/prebid/server/it/TappxTest.java +++ b/src/test/java/org/prebid/server/it/TappxTest.java @@ -28,7 +28,7 @@ public void openrtb2AuctionShouldRespondWithBidsFromTappx() throws IOException, // tappx bid response for imp 12 WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/tappx-exchange")) .withQueryParam("tappxkey", equalTo("pub-12345-android-9876")) - .withQueryParam("v", equalTo("1.1")) + .withQueryParam("v", equalTo("1.2")) .withQueryParam("type_cnn", equalTo("prebid")) .withHeader("Content-Type", equalToIgnoreCase("application/json;charset=utf-8")) .withHeader("Accept", equalTo("application/json")) diff --git a/src/test/java/org/prebid/server/it/TelariaTest.java b/src/test/java/org/prebid/server/it/TelariaTest.java index 888cd133839..c1437e977a9 100644 --- a/src/test/java/org/prebid/server/it/TelariaTest.java +++ b/src/test/java/org/prebid/server/it/TelariaTest.java @@ -33,7 +33,7 @@ public void openrtb2AuctionShouldRespondWithBidsFromTelaria() throws IOException .withHeader("X-Forwarded-For", equalTo("193.168.244.1")) .withHeader("x-openrtb-version", equalTo("2.5")) .withHeader("Accept-Language", equalTo("en")) - .withHeader("Content-Length", equalTo("633")) + .withHeader("Content-Length", equalTo("656")) .withHeader("DNT", equalTo("2")) .withHeader("Host", equalTo("localhost:8090")) .withRequestBody(equalToJson(jsonFrom("openrtb2/telaria/test-telaria-bid-request-1.json"))) diff --git a/src/test/java/org/prebid/server/it/UnicornTest.java b/src/test/java/org/prebid/server/it/UnicornTest.java new file mode 100644 index 00000000000..8d0ec0c2646 --- /dev/null +++ b/src/test/java/org/prebid/server/it/UnicornTest.java @@ -0,0 +1,58 @@ +package org.prebid.server.it; + +import io.restassured.response.Response; +import org.json.JSONException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.skyscreamer.jsonassert.JSONAssert; +import org.skyscreamer.jsonassert.JSONCompareMode; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static io.restassured.RestAssured.given; +import static java.util.Collections.singletonList; + +@RunWith(SpringRunner.class) +public class UnicornTest extends IntegrationTest { + + @Test + public void openrtb2AuctionShouldRespondWithBidsFromUnicorn() throws IOException, JSONException { + // given + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/unicorn-exchange")) + .withHeader("Accept", equalTo("application/json")) + .withHeader("Content-Type", equalTo("application/json;charset=UTF-8")) + .withHeader("User-Agent", equalTo("userAgent")) + .withHeader("X-Forwarded-For", equalTo("193.168.244.1")) + .withRequestBody(equalToJson(jsonFrom("openrtb2/unicorn/test-unicorn-bid-request.json"))) + .willReturn(aResponse().withBody(jsonFrom("openrtb2/unicorn/test-unicorn-bid-response.json")))); + + // pre-bid cache + WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/cache")) + .withRequestBody(equalToJson(jsonFrom("openrtb2/unicorn/test-cache-unicorn-request.json"))) + .willReturn(aResponse().withBody(jsonFrom("openrtb2/unicorn/test-cache-unicorn-response.json")))); + + // when + final Response response = given(SPEC) + .header("Referer", "http://www.example.com") + .header("X-Forwarded-For", "193.168.244.1") + .header("User-Agent", "userAgent") + .header("Origin", "http://www.example.com") + // this uids cookie value stands for {"uids":{"unicorn":"UC-UID"}} + .cookie("uids", "eyJ1aWRzIjp7InVuaWNvcm4iOiJVQy1VSUQifX0=") + .body(jsonFrom("openrtb2/unicorn/test-auction-unicorn-request.json")) + .post("/openrtb2/auction"); + + // then + final String expectedAuctionResponse = openrtbAuctionResponseFrom( + "openrtb2/unicorn/test-auction-unicorn-response.json", + response, singletonList("unicorn")); + + JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), JSONCompareMode.NON_EXTENSIBLE); + } +} diff --git a/src/test/java/org/prebid/server/json/IntegerFlagDeserializerTest.java b/src/test/java/org/prebid/server/json/IntegerFlagDeserializerTest.java new file mode 100644 index 00000000000..c0eacfe9174 --- /dev/null +++ b/src/test/java/org/prebid/server/json/IntegerFlagDeserializerTest.java @@ -0,0 +1,92 @@ +package org.prebid.server.json; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.exc.MismatchedInputException; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.doThrow; + +public class IntegerFlagDeserializerTest { + + @Rule + public final MockitoRule mockitoRule = MockitoJUnit.rule(); + + private IntegerFlagDeserializer integerFlagDeserializer; + + @Mock + private JsonParser jsonParser; + + @Mock + private DeserializationContext deserializationContext; + + @Before + public void setUp() { + integerFlagDeserializer = new IntegerFlagDeserializer(); + } + + @Test + public void deserializeShouldReturnOneWhenFieldIsBooleanAndHasValueTrue() throws IOException { + // given + given(jsonParser.getCurrentToken()).willReturn(JsonToken.VALUE_TRUE); + + // when + final Integer result = integerFlagDeserializer.deserialize(jsonParser, deserializationContext); + + // then + assertThat(result).isEqualTo(1); + } + + @Test + public void deserializeShouldReturnZeroWhenFieldIsBooleanAndHasValueFalse() throws IOException { + // given + given(jsonParser.getCurrentToken()).willReturn(JsonToken.VALUE_FALSE); + + // when + final Integer result = integerFlagDeserializer.deserialize(jsonParser, deserializationContext); + + // then + assertThat(result).isEqualTo(0); + } + + @Test + public void deserializeShouldReturnIntegerValueWhenFieldIsInt() throws IOException { + // given + given(jsonParser.getCurrentToken()).willReturn(JsonToken.VALUE_NUMBER_INT); + given(jsonParser.getValueAsInt()).willReturn(1); + + // when + final Integer result = integerFlagDeserializer.deserialize(jsonParser, deserializationContext); + + // then + assertThat(result).isEqualTo(1); + } + + @Test + public void deserializeShouldThrowJsonParsingExceptionWhenTypeIsNotBooleanOrInt() throws IOException { + // given + given(jsonParser.getCurrentToken()).willReturn(JsonToken.VALUE_STRING); + doThrow(MismatchedInputException.from(jsonParser, Integer.class, "errorMessage")) + .when(deserializationContext) + .reportWrongTokenException(eq(JsonToken.class), eq(JsonToken.VALUE_NUMBER_INT), anyString()); + + // when and then + assertThatThrownBy(() -> integerFlagDeserializer.deserialize(jsonParser, deserializationContext)) + .isInstanceOf(JsonProcessingException.class) + .hasMessage("errorMessage"); + } +} diff --git a/src/test/java/org/prebid/server/metric/MetricsTest.java b/src/test/java/org/prebid/server/metric/MetricsTest.java index 630ac19da8f..c3241d1795a 100644 --- a/src/test/java/org/prebid/server/metric/MetricsTest.java +++ b/src/test/java/org/prebid/server/metric/MetricsTest.java @@ -18,7 +18,6 @@ import org.mockito.Mockito; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.metric.model.AccountMetricsVerbosityLevel; import java.util.EnumMap; @@ -29,7 +28,6 @@ import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; @@ -38,7 +36,7 @@ public class MetricsTest { private static final String RUBICON = "rubicon"; - private static final String INVALID_BIDDER = "invalid"; + private static final String CONVERSANT = "conversant"; private static final String ACCOUNT_ID = "accountId"; @Rule @@ -47,8 +45,6 @@ public class MetricsTest { private MetricRegistry metricRegistry; @Mock private AccountMetricsVerbosity accountMetricsVerbosity; - @Mock - private BidderCatalog bidderCatalog; private Metrics metrics; @@ -56,9 +52,8 @@ public class MetricsTest { public void setUp() { metricRegistry = new MetricRegistry(); given(accountMetricsVerbosity.forAccount(anyString())).willReturn(AccountMetricsVerbosityLevel.detailed); - given(bidderCatalog.isValidName(any())).willReturn(true); - metrics = new Metrics(metricRegistry, CounterType.counter, accountMetricsVerbosity, bidderCatalog); + metrics = new Metrics(metricRegistry, CounterType.counter, accountMetricsVerbosity); } @Test @@ -455,86 +450,69 @@ public void updateAccountRequestMetricsShouldIncrementMetrics() { @Test public void updateAdapterRequestTypeAndNoCookieMetricsShouldUpdateMetricsAsExpected() { - // given - given(bidderCatalog.isValidName(INVALID_BIDDER)).willReturn(false); // when metrics.updateAdapterRequestTypeAndNoCookieMetrics(RUBICON, MetricName.openrtb2app, true); metrics.updateAdapterRequestTypeAndNoCookieMetrics(RUBICON, MetricName.amp, false); - metrics.updateAdapterRequestTypeAndNoCookieMetrics(INVALID_BIDDER, MetricName.openrtb2app, false); - metrics.updateAdapterRequestTypeAndNoCookieMetrics(INVALID_BIDDER, MetricName.amp, false); // then assertThat(metricRegistry.counter("adapter.rubicon.requests.type.openrtb2-app").getCount()).isEqualTo(1); assertThat(metricRegistry.counter("adapter.rubicon.no_cookie_requests").getCount()).isOne(); assertThat(metricRegistry.counter("adapter.rubicon.requests.type.amp").getCount()).isOne(); - assertThat(metricRegistry.counter("adapter.UNKNOWN.requests.type.openrtb2-app").getCount()).isOne(); - assertThat(metricRegistry.counter("adapter.UNKNOWN.requests.type.amp").getCount()).isOne(); } @Test public void updateAdapterResponseTimeShouldUpdateMetrics() { - // given - given(bidderCatalog.isValidName(INVALID_BIDDER)).willReturn(false); - // when metrics.updateAdapterResponseTime(RUBICON, ACCOUNT_ID, 500); - metrics.updateAdapterResponseTime(INVALID_BIDDER, ACCOUNT_ID, 500); - metrics.updateAdapterResponseTime(INVALID_BIDDER, ACCOUNT_ID, 500); + metrics.updateAdapterResponseTime(CONVERSANT, ACCOUNT_ID, 500); + metrics.updateAdapterResponseTime(CONVERSANT, ACCOUNT_ID, 500); // then assertThat(metricRegistry.timer("adapter.rubicon.request_time").getCount()).isOne(); assertThat(metricRegistry.timer("account.accountId.adapter.rubicon.request_time").getCount()).isOne(); - assertThat(metricRegistry.timer("adapter.UNKNOWN.request_time").getCount()).isEqualTo(2); - assertThat(metricRegistry.timer("account.accountId.adapter.UNKNOWN.request_time").getCount()).isEqualTo(2); + assertThat(metricRegistry.timer("adapter.conversant.request_time").getCount()).isEqualTo(2); + assertThat(metricRegistry.timer("account.accountId.adapter.conversant.request_time").getCount()).isEqualTo(2); } @Test public void updateAdapterRequestNobidMetricsShouldIncrementMetrics() { - // given - given(bidderCatalog.isValidName(INVALID_BIDDER)).willReturn(false); - // when metrics.updateAdapterRequestNobidMetrics(RUBICON, ACCOUNT_ID); - metrics.updateAdapterRequestNobidMetrics(INVALID_BIDDER, ACCOUNT_ID); - metrics.updateAdapterRequestNobidMetrics(INVALID_BIDDER, ACCOUNT_ID); + metrics.updateAdapterRequestNobidMetrics(CONVERSANT, ACCOUNT_ID); + metrics.updateAdapterRequestNobidMetrics(CONVERSANT, ACCOUNT_ID); // then assertThat(metricRegistry.counter("adapter.rubicon.requests.nobid").getCount()).isOne(); assertThat(metricRegistry.counter("account.accountId.adapter.rubicon.requests.nobid").getCount()).isOne(); - assertThat(metricRegistry.counter("adapter.UNKNOWN.requests.nobid").getCount()).isEqualTo(2); - assertThat(metricRegistry.counter("account.accountId.adapter.UNKNOWN.requests.nobid").getCount()).isEqualTo(2); + assertThat(metricRegistry.counter("adapter.conversant.requests.nobid").getCount()).isEqualTo(2); + assertThat(metricRegistry.counter("account.accountId.adapter.conversant.requests.nobid").getCount()) + .isEqualTo(2); } @Test public void updateAdapterRequestGotbidsMetricsShouldIncrementMetrics() { - // given - given(bidderCatalog.isValidName(INVALID_BIDDER)).willReturn(false); - // when metrics.updateAdapterRequestGotbidsMetrics(RUBICON, ACCOUNT_ID); - metrics.updateAdapterRequestGotbidsMetrics(INVALID_BIDDER, ACCOUNT_ID); - metrics.updateAdapterRequestGotbidsMetrics(INVALID_BIDDER, ACCOUNT_ID); + metrics.updateAdapterRequestGotbidsMetrics(CONVERSANT, ACCOUNT_ID); + metrics.updateAdapterRequestGotbidsMetrics(CONVERSANT, ACCOUNT_ID); // then assertThat(metricRegistry.counter("adapter.rubicon.requests.gotbids").getCount()).isOne(); assertThat(metricRegistry.counter("account.accountId.adapter.rubicon.requests.gotbids").getCount()) .isOne(); - assertThat(metricRegistry.counter("adapter.UNKNOWN.requests.gotbids").getCount()).isEqualTo(2); - assertThat(metricRegistry.counter("account.accountId.adapter.UNKNOWN.requests.gotbids").getCount()) + assertThat(metricRegistry.counter("adapter.conversant.requests.gotbids").getCount()).isEqualTo(2); + assertThat(metricRegistry.counter("account.accountId.adapter.conversant.requests.gotbids").getCount()) .isEqualTo(2); } @Test public void updateAdapterBidMetricsShouldUpdateMetrics() { - // given - given(bidderCatalog.isValidName(INVALID_BIDDER)).willReturn(false); - // when metrics.updateAdapterBidMetrics(RUBICON, ACCOUNT_ID, 1234L, true, "banner"); metrics.updateAdapterBidMetrics(RUBICON, ACCOUNT_ID, 1234L, false, "video"); - metrics.updateAdapterBidMetrics(INVALID_BIDDER, ACCOUNT_ID, 1234L, false, "banner"); - metrics.updateAdapterBidMetrics(INVALID_BIDDER, ACCOUNT_ID, 1234L, false, "banner"); + metrics.updateAdapterBidMetrics(CONVERSANT, ACCOUNT_ID, 1234L, false, "banner"); + metrics.updateAdapterBidMetrics(CONVERSANT, ACCOUNT_ID, 1234L, false, "banner"); // then assertThat(metricRegistry.histogram("adapter.rubicon.prices").getCount()).isEqualTo(2); @@ -543,55 +521,47 @@ public void updateAdapterBidMetricsShouldUpdateMetrics() { assertThat(metricRegistry.counter("account.accountId.adapter.rubicon.bids_received").getCount()).isEqualTo(2); assertThat(metricRegistry.counter("adapter.rubicon.banner.adm_bids_received").getCount()).isOne(); assertThat(metricRegistry.counter("adapter.rubicon.video.nurl_bids_received").getCount()).isOne(); - assertThat(metricRegistry.histogram("adapter.UNKNOWN.prices").getCount()).isEqualTo(2); - assertThat(metricRegistry.histogram("account.accountId.adapter.UNKNOWN.prices").getCount()).isEqualTo(2); - assertThat(metricRegistry.counter("adapter.UNKNOWN.bids_received").getCount()).isEqualTo(2); - assertThat(metricRegistry.counter("account.accountId.adapter.UNKNOWN.bids_received").getCount()).isEqualTo(2); - assertThat(metricRegistry.counter("adapter.UNKNOWN.banner.nurl_bids_received").getCount()).isEqualTo(2); + assertThat(metricRegistry.histogram("adapter.conversant.prices").getCount()).isEqualTo(2); + assertThat(metricRegistry.histogram("account.accountId.adapter.conversant.prices").getCount()).isEqualTo(2); + assertThat(metricRegistry.counter("adapter.conversant.bids_received").getCount()).isEqualTo(2); + assertThat(metricRegistry.counter("account.accountId.adapter.conversant.bids_received").getCount()) + .isEqualTo(2); + assertThat(metricRegistry.counter("adapter.conversant.banner.nurl_bids_received").getCount()).isEqualTo(2); } @Test public void updateAdapterRequestErrorMetricShouldIncrementMetrics() { - // given - given(bidderCatalog.isValidName(INVALID_BIDDER)).willReturn(false); - // when metrics.updateAdapterRequestErrorMetric(RUBICON, MetricName.badinput); - metrics.updateAdapterRequestErrorMetric(INVALID_BIDDER, MetricName.badinput); - metrics.updateAdapterRequestErrorMetric(INVALID_BIDDER, MetricName.badinput); + metrics.updateAdapterRequestErrorMetric(CONVERSANT, MetricName.badinput); + metrics.updateAdapterRequestErrorMetric(CONVERSANT, MetricName.badinput); // then assertThat(metricRegistry.counter("adapter.rubicon.requests.badinput").getCount()).isOne(); - assertThat(metricRegistry.counter("adapter.UNKNOWN.requests.badinput").getCount()).isEqualTo(2); + assertThat(metricRegistry.counter("adapter.conversant.requests.badinput").getCount()).isEqualTo(2); } @Test public void updateSizeValidationMetricsShouldIncrementMetrics() { - // given - given(bidderCatalog.isValidName(INVALID_BIDDER)).willReturn(false); - // when metrics.updateSizeValidationMetrics(RUBICON, ACCOUNT_ID, MetricName.err); - metrics.updateSizeValidationMetrics(INVALID_BIDDER, ACCOUNT_ID, MetricName.err); + metrics.updateSizeValidationMetrics(CONVERSANT, ACCOUNT_ID, MetricName.err); // then assertThat(metricRegistry.counter("adapter.rubicon.response.validation.size.err").getCount()).isEqualTo(1); - assertThat(metricRegistry.counter("adapter.UNKNOWN.response.validation.size.err").getCount()).isEqualTo(1); + assertThat(metricRegistry.counter("adapter.conversant.response.validation.size.err").getCount()).isEqualTo(1); assertThat(metricRegistry.counter("account.accountId.response.validation.size.err").getCount()).isEqualTo(2); } @Test public void updateSecureValidationMetricsShouldIncrementMetrics() { - // given - given(bidderCatalog.isValidName(INVALID_BIDDER)).willReturn(false); - // when metrics.updateSecureValidationMetrics(RUBICON, ACCOUNT_ID, MetricName.err); - metrics.updateSecureValidationMetrics(INVALID_BIDDER, ACCOUNT_ID, MetricName.err); + metrics.updateSecureValidationMetrics(CONVERSANT, ACCOUNT_ID, MetricName.err); // then assertThat(metricRegistry.counter("adapter.rubicon.response.validation.secure.err").getCount()).isEqualTo(1); - assertThat(metricRegistry.counter("adapter.UNKNOWN.response.validation.secure.err").getCount()).isEqualTo(1); + assertThat(metricRegistry.counter("adapter.conversant.response.validation.secure.err").getCount()).isEqualTo(1); assertThat(metricRegistry.counter("account.accountId.response.validation.secure.err").getCount()).isEqualTo(2); } @@ -642,17 +612,14 @@ public void updateUserSyncTcfBlockedMetricShouldIncrementMetric() { @Test public void updateCookieSyncTcfBlockedMetricShouldIncrementMetric() { - // given - given(bidderCatalog.isValidName(INVALID_BIDDER)).willReturn(false); - // when metrics.updateCookieSyncTcfBlockedMetric(RUBICON); - metrics.updateCookieSyncTcfBlockedMetric(INVALID_BIDDER); - metrics.updateCookieSyncTcfBlockedMetric(INVALID_BIDDER); + metrics.updateCookieSyncTcfBlockedMetric(CONVERSANT); + metrics.updateCookieSyncTcfBlockedMetric(CONVERSANT); // then assertThat(metricRegistry.counter("cookie_sync.rubicon.tcf.blocked").getCount()).isOne(); - assertThat(metricRegistry.counter("cookie_sync.UNKNOWN.tcf.blocked").getCount()).isEqualTo(2); + assertThat(metricRegistry.counter("cookie_sync.conversant.tcf.blocked").getCount()).isEqualTo(2); } @Test @@ -675,22 +642,20 @@ public void updateCookieSyncMatchesMetricShouldIncrementMetric() { @Test public void updateAuctionTcfMetricsShouldIncrementMetrics() { - // given - given(bidderCatalog.isValidName(INVALID_BIDDER)).willReturn(false); // when metrics.updateAuctionTcfMetrics(RUBICON, MetricName.openrtb2web, true, true, true, true); - metrics.updateAuctionTcfMetrics(INVALID_BIDDER, MetricName.openrtb2web, false, true, true, false); - metrics.updateAuctionTcfMetrics(INVALID_BIDDER, MetricName.openrtb2app, true, false, false, true); + metrics.updateAuctionTcfMetrics(CONVERSANT, MetricName.openrtb2web, false, true, true, false); + metrics.updateAuctionTcfMetrics(CONVERSANT, MetricName.openrtb2app, true, false, false, true); // then assertThat(metricRegistry.counter("adapter.rubicon.openrtb2-web.tcf.userid_removed").getCount()).isOne(); assertThat(metricRegistry.counter("adapter.rubicon.openrtb2-web.tcf.geo_masked").getCount()).isOne(); assertThat(metricRegistry.counter("adapter.rubicon.openrtb2-web.tcf.analytics_blocked").getCount()).isOne(); assertThat(metricRegistry.counter("adapter.rubicon.openrtb2-web.tcf.request_blocked").getCount()).isOne(); - assertThat(metricRegistry.counter("adapter.UNKNOWN.openrtb2-web.tcf.geo_masked").getCount()).isOne(); - assertThat(metricRegistry.counter("adapter.UNKNOWN.openrtb2-web.tcf.analytics_blocked").getCount()).isOne(); - assertThat(metricRegistry.counter("adapter.UNKNOWN.openrtb2-app.tcf.userid_removed").getCount()).isOne(); - assertThat(metricRegistry.counter("adapter.UNKNOWN.openrtb2-app.tcf.request_blocked").getCount()).isOne(); + assertThat(metricRegistry.counter("adapter.conversant.openrtb2-web.tcf.geo_masked").getCount()).isOne(); + assertThat(metricRegistry.counter("adapter.conversant.openrtb2-web.tcf.analytics_blocked").getCount()).isOne(); + assertThat(metricRegistry.counter("adapter.conversant.openrtb2-app.tcf.userid_removed").getCount()).isOne(); + assertThat(metricRegistry.counter("adapter.conversant.openrtb2-app.tcf.request_blocked").getCount()).isOne(); } @Test @@ -1070,7 +1035,7 @@ private void verifyCreatesConfiguredCounterType(Consumer metricsConsume // when metricsConsumer.accept(new Metrics(metricRegistry, CounterType.valueOf(counterType.name()), - accountMetricsVerbosity, bidderCatalog)); + accountMetricsVerbosity)); // then softly.assertThat(metricRegistry.getMetrics()).hasValueSatisfying(new Condition<>( diff --git a/src/test/java/org/prebid/server/privacy/gdpr/GdprServiceTest.java b/src/test/java/org/prebid/server/privacy/gdpr/GdprServiceTest.java index a2e137974b4..3f87c79664f 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/GdprServiceTest.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/GdprServiceTest.java @@ -23,11 +23,11 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.BDDMockito.given; import static org.prebid.server.assertion.FutureAssertion.assertThat; -import static org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.FIVE; -import static org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.FOUR; -import static org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.ONE; -import static org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.THREE; -import static org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.TWO; +import static org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode.FIVE; +import static org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode.FOUR; +import static org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode.ONE; +import static org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode.THREE; +import static org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode.TWO; public class GdprServiceTest extends VertxTest { diff --git a/src/test/java/org/prebid/server/privacy/gdpr/Tcf2ServiceTest.java b/src/test/java/org/prebid/server/privacy/gdpr/Tcf2ServiceTest.java index c4b26c3a470..c080f277659 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/Tcf2ServiceTest.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/Tcf2ServiceTest.java @@ -48,10 +48,10 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.prebid.server.assertion.FutureAssertion.assertThat; -import static org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.FOUR; -import static org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.ONE; -import static org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.SEVEN; -import static org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.TWO; +import static org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode.FOUR; +import static org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode.ONE; +import static org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode.SEVEN; +import static org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode.TWO; public class Tcf2ServiceTest extends VertxTest { @@ -84,6 +84,11 @@ public class Tcf2ServiceTest extends VertxTest { private Purpose purpose4; private Purpose purpose7; + private Purpose weakPurpose1; + private Purpose weakPurpose2; + private Purpose weakPurpose4; + private Purpose weakPurpose7; + private SpecialFeature specialFeature1; private SpecialFeatures specialFeatures; @@ -124,6 +129,11 @@ private void initPurposes() { .p4(purpose4) .p7(purpose7) .build(); + + weakPurpose1 = Purpose.of(EnforcePurpose.basic, false, emptyList()); + weakPurpose2 = Purpose.of(EnforcePurpose.no, false, emptyList()); + weakPurpose4 = Purpose.of(EnforcePurpose.no, false, emptyList()); + weakPurpose7 = Purpose.of(EnforcePurpose.basic, false, emptyList()); } private void initSpecialFeatures() { @@ -260,6 +270,41 @@ public void permissionsForShouldMergeAccountSpecialFeatures() { singletonList(expectedVendorPermission)); } + @Test + public void permissionsForShouldSplitIntoWeakPurposesWhenAccountHaveBasicEnforcementBidders() { + // given + final VendorIdResolver vendorIdResolver = mock(VendorIdResolver.class); + given(vendorIdResolver.resolve(eq("b1"))).willReturn(1); + given(vendorIdResolver.resolve(eq("b2"))).willReturn(2); + + final AccountGdprConfig accountGdprConfig = AccountGdprConfig.builder() + .basicEnforcementVendors(singletonList("b2")) + .build(); + + // when + final Future> result = + target.permissionsFor(new HashSet<>(asList("b1", "b2")), vendorIdResolver, tcString, accountGdprConfig); + + // then + final VendorPermission expectedVendorPermission1 = + VendorPermission.of(1, "b1", PrivacyEnforcementAction.restrictAll()); + final VendorPermission expectedVendorPermission2 = + VendorPermission.of(2, "b2", PrivacyEnforcementAction.restrictAll()); + final VendorPermissionWithGvl expectedVendorPermissionWitGvl1 = + VendorPermissionWithGvl.of(expectedVendorPermission1, VendorV2.empty(1)); + final VendorPermissionWithGvl expectedVendorPermissionWitGvl2 = + VendorPermissionWithGvl.of(expectedVendorPermission2, VendorV2.empty(2)); + + verifyEachPurposeStrategyReceive(singletonList(expectedVendorPermissionWitGvl1)); + verifyEachPurposeStrategyReceiveWeak(singletonList(expectedVendorPermissionWitGvl2)); + verifyEachSpecialFeatureStrategyReceive(asList(expectedVendorPermission2, expectedVendorPermission1)); + + verify(vendorIdResolver, times(2)).resolve(anyString()); + verify(tcString).getVendorListVersion(); + + assertThat(result).succeededWith(asList(expectedVendorPermission2, expectedVendorPermission1)); + } + @Test public void permissionsForShouldReturnBidderNamesResult() { // given @@ -338,10 +383,20 @@ public void permissionsForShouldReturnAllDeniedWhenP1TIIsNoAccessAllowed() { assertThat(result).succeededWith( singletonList(VendorPermission.of(1, "rubicon", PrivacyEnforcementAction.restrictAll()))); + final VendorPermission expectedVendorPermission1 = VendorPermission.of(1, "rubicon", + PrivacyEnforcementAction.restrictAll()); + final VendorPermissionWithGvl expectedVendorPermissionWitGvl1 = VendorPermissionWithGvl.of( + expectedVendorPermission1, VendorV2.empty(1)); + final List standardPermissions = singletonList(expectedVendorPermissionWitGvl1); + verify(purposeStrategyOne, never()).processTypePurposeStrategy(any(), any(), anyCollection(), anyBoolean()); - verify(purposeStrategyTwo).processTypePurposeStrategy(any(), any(), anyCollection(), anyBoolean()); - verify(purposeStrategySeven).processTypePurposeStrategy(any(), any(), anyCollection(), anyBoolean()); - verify(purposeStrategyFour).processTypePurposeStrategy(any(), any(), anyCollection(), anyBoolean()); + verify(purposeStrategyTwo).processTypePurposeStrategy(any(), any(), eq(standardPermissions), eq(false)); + verify(purposeStrategySeven).processTypePurposeStrategy(any(), any(), eq(standardPermissions), eq(false)); + verify(purposeStrategyFour).processTypePurposeStrategy(any(), any(), eq(standardPermissions), eq(false)); + + verify(purposeStrategyTwo).processTypePurposeStrategy(any(), any(), eq(emptyList()), eq(true)); + verify(purposeStrategySeven).processTypePurposeStrategy(any(), any(), eq(emptyList()), eq(true)); + verify(purposeStrategyFour).processTypePurposeStrategy(any(), any(), eq(emptyList()), eq(true)); verify(specialFeaturesStrategyOne).processSpecialFeaturesStrategy(any(), any(), anyCollection()); } @@ -364,11 +419,21 @@ public void permissionsForShouldAllowAllWhenP1TIIsAccessAllowed() { target.permissionsFor(singleton(1), tcString); // then + final VendorPermission expectedVendorPermission1 = VendorPermission.of(1, "rubicon", + PrivacyEnforcementAction.restrictAll()); + final VendorPermissionWithGvl expectedVendorPermissionWitGvl1 = VendorPermissionWithGvl.of( + expectedVendorPermission1, VendorV2.empty(1)); + final List standardPermissions = singletonList(expectedVendorPermissionWitGvl1); + verify(purposeStrategyOne, never()).processTypePurposeStrategy(any(), any(), anyCollection(), anyBoolean()); verify(purposeStrategyOne).allow(any()); - verify(purposeStrategyTwo).processTypePurposeStrategy(any(), any(), anyCollection(), anyBoolean()); - verify(purposeStrategySeven).processTypePurposeStrategy(any(), any(), anyCollection(), anyBoolean()); - verify(purposeStrategyFour).processTypePurposeStrategy(any(), any(), anyCollection(), anyBoolean()); + verify(purposeStrategyTwo).processTypePurposeStrategy(any(), any(), eq(standardPermissions), eq(false)); + verify(purposeStrategySeven).processTypePurposeStrategy(any(), any(), eq(standardPermissions), eq(false)); + verify(purposeStrategyFour).processTypePurposeStrategy(any(), any(), eq(standardPermissions), eq(false)); + + verify(purposeStrategyTwo).processTypePurposeStrategy(any(), any(), eq(emptyList()), eq(true)); + verify(purposeStrategySeven).processTypePurposeStrategy(any(), any(), eq(emptyList()), eq(true)); + verify(purposeStrategyFour).processTypePurposeStrategy(any(), any(), eq(emptyList()), eq(true)); verify(specialFeaturesStrategyOne).processSpecialFeaturesStrategy(any(), any(), anyCollection()); } @@ -391,11 +456,15 @@ public void permissionsForShouldNotAllowAllWhenP1TIsFalseAndP1TIIsAccessAllowed( target.permissionsFor(singleton(1), tcString); // then + final VendorPermission expectedVendorPermission1 = VendorPermission.of(1, "rubicon", + PrivacyEnforcementAction.restrictAll()); + final VendorPermissionWithGvl expectedVendorPermissionWitGvl1 = VendorPermissionWithGvl.of( + expectedVendorPermission1, VendorV2.empty(1)); + final List standardPermissions = singletonList(expectedVendorPermissionWitGvl1); + verify(purposeStrategyOne, never()).allow(any()); - verify(purposeStrategyOne).processTypePurposeStrategy(any(), any(), anyCollection(), anyBoolean()); - verify(purposeStrategyTwo).processTypePurposeStrategy(any(), any(), anyCollection(), anyBoolean()); - verify(purposeStrategySeven).processTypePurposeStrategy(any(), any(), anyCollection(), anyBoolean()); - verify(purposeStrategyFour).processTypePurposeStrategy(any(), any(), anyCollection(), anyBoolean()); + verifyEachPurposeStrategyReceive(standardPermissions); + verifyEachPurposeStrategyReceiveWeak(emptyList()); verify(specialFeaturesStrategyOne).processSpecialFeaturesStrategy(any(), any(), anyCollection()); } @@ -407,6 +476,13 @@ public void verifyEachPurposeStrategyReceive(List vendo verify(purposeStrategySeven).processTypePurposeStrategy(tcString, purpose7, vendorPermissionWithGvls, false); } + public void verifyEachPurposeStrategyReceiveWeak(List vendorPermissionWithGvls) { + verify(purposeStrategyOne).processTypePurposeStrategy(tcString, weakPurpose1, vendorPermissionWithGvls, true); + verify(purposeStrategyTwo).processTypePurposeStrategy(tcString, weakPurpose2, vendorPermissionWithGvls, true); + verify(purposeStrategyFour).processTypePurposeStrategy(tcString, weakPurpose4, vendorPermissionWithGvls, true); + verify(purposeStrategySeven).processTypePurposeStrategy(tcString, weakPurpose7, vendorPermissionWithGvls, true); + } + public void verifyEachSpecialFeatureStrategyReceive(List vendorPermission) { verify(specialFeaturesStrategyOne).processSpecialFeaturesStrategy(tcString, specialFeature1, vendorPermission); } diff --git a/src/test/java/org/prebid/server/privacy/gdpr/TcfDefinerServiceTest.java b/src/test/java/org/prebid/server/privacy/gdpr/TcfDefinerServiceTest.java index 17617a8e285..f8c1d7aab64 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/TcfDefinerServiceTest.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/TcfDefinerServiceTest.java @@ -9,6 +9,7 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.prebid.server.auction.IpAddressHelper; +import org.prebid.server.auction.model.IpAddress; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.geolocation.GeoLocationService; import org.prebid.server.geolocation.model.GeoInfo; @@ -232,10 +233,11 @@ public void resolveTcfContextShouldConsiderPresenceOfConsentStringAsInScope() { assertThat(result.result()).extracting( TcfContext::getGdpr, TcfContext::getConsentString, + TcfContext::getIsConsentValid, TcfContext::getGeoInfo, TcfContext::getInEea, TcfContext::getIpAddress) - .containsExactly("1", "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA", null, null, null); + .containsExactly("1", "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA", true, null, null, null); assertThat(result.result().getConsent()).isNotNull(); verifyZeroInteractions(geoLocationService); @@ -267,6 +269,7 @@ public void resolveTcfContextShouldReturnGdprFromCountryWhenGdprFromRequestIsNot @Test public void resolveTcfContextShouldReturnGdprFromGeoLocationServiceWhenGdprFromRequestIsNotValid() { // given + given(ipAddressHelper.toIpAddress(anyString())).willReturn(IpAddress.of("ip", IpAddress.IP.v4)); given(ipAddressHelper.maskIpv4(anyString())).willReturn("ip-masked"); final GeoInfo geoInfo = GeoInfo.builder().vendor("vendor").country("ua").build(); @@ -366,6 +369,37 @@ public void resolveTcfContextShouldConsultDefaultValueAndSkipGeoLookupWhenIpIsNu verifyZeroInteractions(geoLocationService); } + @Test + public void resolveTcfContextShouldReturnTcfContextWithConsentValidAsTrue() { + // when + final Future result = tcfDefinerService.resolveTcfContext( + Privacy.of("1", "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA", null, null), null, null, MetricName.setuid, null, + null); + + // then + assertThat(result).isSucceeded(); + assertThat(result.result()).extracting( + TcfContext::getGdpr, + TcfContext::getConsentString, + TcfContext::getIsConsentValid) + .containsExactly("1", "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA", true); + } + + @Test + public void resolveTcfContextShouldReturnTcfContextWithConsentValidAsFalse() { + // when + final Future result = tcfDefinerService.resolveTcfContext( + Privacy.of("1", "invalid", null, null), null, null, MetricName.setuid, null, null); + + // then + assertThat(result).isSucceeded(); + assertThat(result.result()).extracting( + TcfContext::getGdpr, + TcfContext::getConsentString, + TcfContext::getIsConsentValid) + .containsExactly("1", "invalid", false); + } + @Test public void resolveTcfContextShouldIncrementMissingConsentStringMetric() { // when diff --git a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeEightStrategyTest.java b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeEightStrategyTest.java index 13c50e18de0..a7838f91918 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeEightStrategyTest.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeEightStrategyTest.java @@ -13,6 +13,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV2; import org.prebid.server.settings.model.EnforcePurpose; import org.prebid.server.settings.model.Purpose; @@ -32,8 +33,8 @@ public class PurposeEightStrategyTest { - private static final org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose PURPOSE = - org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.EIGHT; + private static final PurposeCode PURPOSE_CODE = + PurposeCode.EIGHT; @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); @@ -85,7 +86,7 @@ public void allowNaturallyShouldReturnExpectedValue() { @Test public void getPurposeIdShouldReturnExpectedValue() { // when and then - assertThat(target.getPurpose()).isEqualTo(PURPOSE); + assertThat(target.getPurpose()).isEqualTo(PURPOSE_CODE); } @Test @@ -120,7 +121,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -156,7 +157,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -193,7 +194,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -229,7 +230,7 @@ public void processTypePurposeStrategyShouldPassEmptyListWithFullEnforcementsWhe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -271,7 +272,7 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyVendorExcept assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } @@ -315,9 +316,9 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyWhenVendorPe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } diff --git a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeFiveStrategyTest.java b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeFiveStrategyTest.java index 0465bfce725..2314b95f39f 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeFiveStrategyTest.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeFiveStrategyTest.java @@ -13,6 +13,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV2; import org.prebid.server.settings.model.EnforcePurpose; import org.prebid.server.settings.model.Purpose; @@ -32,8 +33,8 @@ public class PurposeFiveStrategyTest { - private static final org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose PURPOSE = - org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.FIVE; + private static final PurposeCode PURPOSE_CODE = + PurposeCode.FIVE; @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); @@ -85,7 +86,7 @@ public void allowNaturallyShouldReturnExpectedValue() { @Test public void getPurposeIdShouldReturnExpectedValue() { // when and then - assertThat(target.getPurpose()).isEqualTo(PURPOSE); + assertThat(target.getPurpose()).isEqualTo(PURPOSE_CODE); } @Test @@ -120,7 +121,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -156,7 +157,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -193,7 +194,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -229,7 +230,7 @@ public void processTypePurposeStrategyShouldPassEmptyListWithFullEnforcementsWhe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -271,7 +272,7 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyVendorExcept assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } @@ -315,9 +316,9 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyWhenVendorPe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } diff --git a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeFourStrategyTest.java b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeFourStrategyTest.java index d0f1795c292..8caa0d96aea 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeFourStrategyTest.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeFourStrategyTest.java @@ -13,6 +13,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV2; import org.prebid.server.settings.model.EnforcePurpose; import org.prebid.server.settings.model.Purpose; @@ -32,8 +33,8 @@ public class PurposeFourStrategyTest { - private static final org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose PURPOSE = - org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.FOUR; + private static final PurposeCode PURPOSE_CODE = + PurposeCode.FOUR; @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); @@ -85,7 +86,7 @@ public void allowNaturallyShouldReturnExpectedValue() { @Test public void getPurposeIdShouldReturnExpectedValue() { // when and then - assertThat(target.getPurpose()).isEqualTo(PURPOSE); + assertThat(target.getPurpose()).isEqualTo(PURPOSE_CODE); } @Test @@ -120,7 +121,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -157,7 +158,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -195,7 +196,7 @@ public void processTypePurposeStrategyShouldPassEmptyListWithEnforcementsWhenAll assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -231,7 +232,7 @@ public void processTypePurposeStrategyShouldPassEmptyListWithFullEnforcementsWhe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -273,7 +274,7 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyVendorExcept assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } @@ -317,9 +318,9 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyWhenVendorPe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } diff --git a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeNineStrategyTest.java b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeNineStrategyTest.java index 0856f237e12..17afe4913be 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeNineStrategyTest.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeNineStrategyTest.java @@ -13,6 +13,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV2; import org.prebid.server.settings.model.EnforcePurpose; import org.prebid.server.settings.model.Purpose; @@ -32,8 +33,8 @@ public class PurposeNineStrategyTest { - private static final org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose PURPOSE = - org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.NINE; + private static final PurposeCode PURPOSE_CODE = + PurposeCode.NINE; @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); @@ -85,7 +86,7 @@ public void allowNaturallyShouldReturnExpectedValue() { @Test public void getPurposeIdShouldReturnExpectedValue() { // when and then - assertThat(target.getPurpose()).isEqualTo(PURPOSE); + assertThat(target.getPurpose()).isEqualTo(PURPOSE_CODE); } @Test @@ -120,7 +121,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -156,7 +157,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -193,7 +194,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -229,7 +230,7 @@ public void processTypePurposeStrategyShouldPassEmptyListWithFullEnforcementsWhe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -271,7 +272,7 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyVendorExcept assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } @@ -314,9 +315,9 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyWhenVendorPe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } diff --git a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeOneStrategyTest.java b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeOneStrategyTest.java index d508b952c9b..afb2ca9bf2c 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeOneStrategyTest.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeOneStrategyTest.java @@ -13,6 +13,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV2; import org.prebid.server.settings.model.EnforcePurpose; import org.prebid.server.settings.model.Purpose; @@ -32,8 +33,8 @@ public class PurposeOneStrategyTest { - private static final org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose PURPOSE = - org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.ONE; + private static final PurposeCode PURPOSE_CODE = + PurposeCode.ONE; @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); @@ -85,7 +86,7 @@ public void allowNaturallyShouldReturnExpectedValue() { @Test public void getPurposeIdShouldReturnExpectedValue() { // when and then - assertThat(target.getPurpose()).isEqualTo(PURPOSE); + assertThat(target.getPurpose()).isEqualTo(PURPOSE_CODE); } @Test @@ -120,7 +121,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -157,7 +158,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -195,7 +196,7 @@ public void processTypePurposeStrategyShouldPassEmptyListWithEnforcementsWhenAll assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -231,7 +232,7 @@ public void processTypePurposeStrategyShouldPassEmptyListWithFullEnforcementsWhe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -273,7 +274,7 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyVendorExcept assertThat(result).usingFieldByFieldElementComparator() .isEqualTo(Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } @@ -317,9 +318,9 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyWhenVendorPe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } diff --git a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeSevenStrategyTest.java b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeSevenStrategyTest.java index 8d7b0806ce0..50739956a5f 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeSevenStrategyTest.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeSevenStrategyTest.java @@ -13,6 +13,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV2; import org.prebid.server.settings.model.EnforcePurpose; import org.prebid.server.settings.model.Purpose; @@ -32,8 +33,8 @@ public class PurposeSevenStrategyTest { - private static final org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose PURPOSE = - org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.SEVEN; + private static final PurposeCode PURPOSE_CODE = + PurposeCode.SEVEN; @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); @@ -85,7 +86,7 @@ public void allowNaturallyShouldReturnExpectedValue() { @Test public void getPurposeIdShouldReturnExpectedValue() { // when and then - assertThat(target.getPurpose()).isEqualTo(PURPOSE); + assertThat(target.getPurpose()).isEqualTo(PURPOSE_CODE); } @Test @@ -120,7 +121,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -157,7 +158,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -195,7 +196,7 @@ public void processTypePurposeStrategyShouldPassEmptyListWithEnforcementsWhenAll assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -231,7 +232,7 @@ public void processTypePurposeStrategyShouldPassEmptyListWithFullEnforcementsWhe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -273,7 +274,7 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyVendorExcept assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } @@ -317,9 +318,9 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyWhenVendorPe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } diff --git a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeSixStrategyTest.java b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeSixStrategyTest.java index c9dc22660ad..d569fb5e82c 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeSixStrategyTest.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeSixStrategyTest.java @@ -13,6 +13,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV2; import org.prebid.server.settings.model.EnforcePurpose; import org.prebid.server.settings.model.Purpose; @@ -32,8 +33,8 @@ public class PurposeSixStrategyTest { - private static final org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose PURPOSE = - org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.SIX; + private static final PurposeCode PURPOSE_CODE = + PurposeCode.SIX; @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); @@ -85,7 +86,7 @@ public void allowNaturallyShouldReturnExpectedValue() { @Test public void getPurposeIdShouldReturnExpectedValue() { // when and then - assertThat(target.getPurpose()).isEqualTo(PURPOSE); + assertThat(target.getPurpose()).isEqualTo(PURPOSE_CODE); } @Test @@ -120,7 +121,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -156,7 +157,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -193,7 +194,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -229,7 +230,7 @@ public void processTypePurposeStrategyShouldPassEmptyListWithFullEnforcementsWhe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -271,7 +272,7 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyVendorExcept assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } @@ -315,9 +316,9 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyWhenVendorPe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } diff --git a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeTenStrategyTest.java b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeTenStrategyTest.java index d24a1b04544..7a4e081e266 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeTenStrategyTest.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeTenStrategyTest.java @@ -13,6 +13,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV2; import org.prebid.server.settings.model.EnforcePurpose; import org.prebid.server.settings.model.Purpose; @@ -32,8 +33,8 @@ public class PurposeTenStrategyTest { - private static final org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose PURPOSE = - org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.TEN; + private static final PurposeCode PURPOSE_CODE = + PurposeCode.TEN; @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); @@ -85,7 +86,7 @@ public void allowNaturallyShouldReturnExpectedValue() { @Test public void getPurposeIdShouldReturnExpectedValue() { // when and then - assertThat(target.getPurpose()).isEqualTo(PURPOSE); + assertThat(target.getPurpose()).isEqualTo(PURPOSE_CODE); } @Test @@ -120,7 +121,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -156,7 +157,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -193,7 +194,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -229,7 +230,7 @@ public void processTypePurposeStrategyShouldPassEmptyListWithFullEnforcementsWhe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -271,7 +272,7 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyVendorExcept assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } @@ -314,9 +315,9 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyWhenVendorPe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } diff --git a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeThreeStrategyTest.java b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeThreeStrategyTest.java index a233c3a78ed..6e436c05796 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeThreeStrategyTest.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeThreeStrategyTest.java @@ -13,6 +13,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV2; import org.prebid.server.settings.model.EnforcePurpose; import org.prebid.server.settings.model.Purpose; @@ -32,8 +33,8 @@ public class PurposeThreeStrategyTest { - private static final org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose PURPOSE = - org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.THREE; + private static final PurposeCode PURPOSE_CODE = + PurposeCode.THREE; @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); @@ -85,7 +86,7 @@ public void allowNaturallyShouldReturnExpectedValue() { @Test public void getPurposeIdShouldReturnExpectedValue() { // when and then - assertThat(target.getPurpose()).isEqualTo(PURPOSE); + assertThat(target.getPurpose()).isEqualTo(PURPOSE_CODE); } @Test @@ -120,7 +121,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -156,7 +157,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -193,7 +194,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -229,7 +230,7 @@ public void processTypePurposeStrategyShouldPassEmptyListWithFullEnforcementsWhe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -271,7 +272,7 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyVendorExcept assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } @@ -315,9 +316,9 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyWhenVendorPe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } diff --git a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeTwoStrategyTest.java b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeTwoStrategyTest.java index 03f322df0b2..85857d6a76a 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeTwoStrategyTest.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/PurposeTwoStrategyTest.java @@ -13,6 +13,7 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.BasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.FullEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.NoEnforcePurposeStrategy; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV2; import org.prebid.server.settings.model.EnforcePurpose; import org.prebid.server.settings.model.Purpose; @@ -32,8 +33,8 @@ public class PurposeTwoStrategyTest { - private static final org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose PURPOSE = - org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.TWO; + private static final PurposeCode PURPOSE_CODE = + PurposeCode.TWO; @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); @@ -85,7 +86,7 @@ public void allowNaturallyShouldReturnExpectedValue() { @Test public void getPurposeIdShouldReturnExpectedValue() { // when and then - assertThat(target.getPurpose()).isEqualTo(PURPOSE); + assertThat(target.getPurpose()).isEqualTo(PURPOSE_CODE); } @Test @@ -120,7 +121,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -156,7 +157,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(vendorPermissionWitGvl1, vendorPermissionWitGvl3), singletonList(vendorPermissionWitGvl2), false); } @@ -193,7 +194,7 @@ public void processTypePurposeStrategyShouldPassListWithEnforcementsAndExcludeBi assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -229,7 +230,7 @@ public void processTypePurposeStrategyShouldPassEmptyListWithFullEnforcementsWhe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, emptyList(), + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, emptyList(), vendorPermissionsWithGvl, true); } @@ -271,7 +272,7 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyVendorExcept assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE, tcString, + verify(fullEnforcePurposeStrategy, times(2)).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } @@ -315,9 +316,9 @@ public void processTypePurposeStrategyShouldAllowPurposeAndNaturallyWhenVendorPe assertThat(result).usingFieldByFieldElementComparator().isEqualTo( Arrays.asList(vendorPermission1Changed, vendorPermission2Changed, vendorPermission3Changed)); - verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(noEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); - verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE, tcString, + verify(basicEnforcePurposeStrategy).allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl3), excludedVendorPermissionsWithGvl, true); } diff --git a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/BasicEnforcePurposeStrategyTest.java b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/BasicEnforcePurposeStrategyTest.java index f0c67aae420..6c8a3947453 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/BasicEnforcePurposeStrategyTest.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/BasicEnforcePurposeStrategyTest.java @@ -11,7 +11,7 @@ import org.prebid.server.privacy.gdpr.model.PrivacyEnforcementAction; import org.prebid.server.privacy.gdpr.model.VendorPermission; import org.prebid.server.privacy.gdpr.model.VendorPermissionWithGvl; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV2; import java.util.Arrays; @@ -27,7 +27,7 @@ public class BasicEnforcePurposeStrategyTest { - private static final Purpose PURPOSE = Purpose.ONE; + private static final PurposeCode PURPOSE_CODE = PurposeCode.ONE; @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); @@ -69,7 +69,7 @@ public void allowedByTypeStrategyShouldReturnEmptyListWhenVendorIsNotAllowedAndV final List vendorPermissionWithGvls = singletonList(vendorPermissionWitGvl); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -85,7 +85,7 @@ public void allowedByTypeStrategyShouldReturnEmptyListWhenVendorIsNotAllowedAndV final List vendorPermissionWithGvls = singletonList(vendorPermissionWitGvl); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then @@ -103,7 +103,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenVendorIsAllowedAnd given(allowedVendors.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then @@ -121,7 +121,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenVendorIsAllowedAnd given(allowedVendors.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -139,7 +139,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenVendorLIIsAllowedA given(allowedVendorsLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then @@ -157,7 +157,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenVendorLIIsAllowedA given(allowedVendorsLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -176,7 +176,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenPurposeLIAndPurpos given(purposesLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -195,7 +195,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenPurposeLIAndPurpos given(purposesLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then @@ -215,10 +215,10 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenPurposeLIAndVendor vendorPermissionWitGvl2); given(allowedVendors.contains(anyInt())).willReturn(true); - given(purposesLI.contains(PURPOSE.code())).willReturn(true); + given(purposesLI.contains(PURPOSE_CODE.code())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -238,10 +238,10 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenPurposeAndVendorLI vendorPermissionWitGvl2); given(allowedVendorsLI.contains(anyInt())).willReturn(true); - given(purposesConsent.contains(PURPOSE.code())).willReturn(true); + given(purposesConsent.contains(PURPOSE_CODE.code())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -259,7 +259,7 @@ public void allowedByTypeStrategyShouldReturnExcludedVendors() { VendorV2.empty(2)); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, singleton(vendorPermissionWitGvl1), singleton(vendorPermissionWitGvl2), true); // then diff --git a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/FullEnforcePurposeStrategyTest.java b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/FullEnforcePurposeStrategyTest.java index 0e1d830d40f..3c4d88ebc41 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/FullEnforcePurposeStrategyTest.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/FullEnforcePurposeStrategyTest.java @@ -13,7 +13,7 @@ import org.prebid.server.privacy.gdpr.model.PrivacyEnforcementAction; import org.prebid.server.privacy.gdpr.model.VendorPermission; import org.prebid.server.privacy.gdpr.model.VendorPermissionWithGvl; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV2; import java.util.Arrays; @@ -34,7 +34,7 @@ public class FullEnforcePurposeStrategyTest { - private static final Purpose PURPOSE = Purpose.ONE; + private static final PurposeCode PURPOSE_CODE = PurposeCode.ONE; @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); @@ -66,7 +66,7 @@ public void setUp() { given(tcString.getPublisherRestrictions()).willReturn(singletonList(publisherRestriction)); - given(publisherRestriction.getPurposeId()).willReturn(PURPOSE.code()); + given(publisherRestriction.getPurposeId()).willReturn(PURPOSE_CODE.code()); given(publisherRestriction.getVendorIds()).willReturn(vendorIds); given(publisherRestriction.getRestrictionType()).willReturn(RestrictionType.UNDEFINED); @@ -83,12 +83,12 @@ public void setUp() { public void shouldReturnOnlyExcludedAllowedWhenMultiplePublisherRestrictionsProvided() { // given final IntIterable requireConsentIterable = mock(IntIterable.class); - final PublisherRestriction publisherRestriction1 = new PublisherRestriction(PURPOSE.code(), + final PublisherRestriction publisherRestriction1 = new PublisherRestriction(PURPOSE_CODE.code(), RestrictionType.REQUIRE_CONSENT, requireConsentIterable); given(requireConsentIterable.spliterator()).willReturn(singletonList(1).spliterator()); final IntIterable notAllowedIterable = mock(IntIterable.class); - final PublisherRestriction publisherRestriction2 = new PublisherRestriction(PURPOSE.code(), + final PublisherRestriction publisherRestriction2 = new PublisherRestriction(PURPOSE_CODE.code(), RestrictionType.NOT_ALLOWED, notAllowedIterable); given(notAllowedIterable.spliterator()).willReturn(Arrays.asList(4, 2).spliterator()); @@ -112,7 +112,7 @@ public void shouldReturnOnlyExcludedAllowedWhenMultiplePublisherRestrictionsProv VendorV2.empty(5)); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(requireConsentPermission, notAllowedPermission, notMentionedPermission), Arrays.asList(excludedNotMentionedPermission, excludedNotAllowedPermission), true); @@ -124,13 +124,13 @@ public void shouldReturnOnlyExcludedAllowedWhenMultiplePublisherRestrictionsProv public void shouldReturnExpectedWhenMultiplePublisherRestrictionsProvided() { // given final IntIterable requireConsentIterable = mock(IntIterable.class); - final PublisherRestriction publisherRestriction1 = new PublisherRestriction(PURPOSE.code(), + final PublisherRestriction publisherRestriction1 = new PublisherRestriction(PURPOSE_CODE.code(), RestrictionType.REQUIRE_CONSENT, requireConsentIterable); given(requireConsentIterable.spliterator()).willReturn(singletonList(1).spliterator()); given(requireConsentIterable.contains(eq(1))).willReturn(true); final IntIterable notAllowedIterable = mock(IntIterable.class); - final PublisherRestriction publisherRestriction2 = new PublisherRestriction(PURPOSE.code(), + final PublisherRestriction publisherRestriction2 = new PublisherRestriction(PURPOSE_CODE.code(), RestrictionType.NOT_ALLOWED, notAllowedIterable); given(notAllowedIterable.spliterator()).willReturn(Arrays.asList(4, 2).spliterator()); given(notAllowedIterable.contains(eq(4))).willReturn(true); @@ -145,20 +145,20 @@ public void shouldReturnExpectedWhenMultiplePublisherRestrictionsProvided() { final VendorPermission vendorPermission4 = VendorPermission.of(4, null, PrivacyEnforcementAction.restrictAll()); final VendorPermission vendorPermission5 = VendorPermission.of(5, null, PrivacyEnforcementAction.restrictAll()); final VendorPermissionWithGvl requireConsentPermission = VendorPermissionWithGvl.of(vendorPermission1, - VendorV2.builder().id(1).purposes(EnumSet.of(PURPOSE)).build()); + VendorV2.builder().id(1).purposes(EnumSet.of(PURPOSE_CODE)).build()); final VendorPermissionWithGvl notAllowedPermission = VendorPermissionWithGvl.of(vendorPermission2, - VendorV2.builder().id(2).purposes(EnumSet.of(PURPOSE)).build()); + VendorV2.builder().id(2).purposes(EnumSet.of(PURPOSE_CODE)).build()); final VendorPermissionWithGvl excludedNotMentionedPermission = VendorPermissionWithGvl.of(vendorPermission3, - VendorV2.builder().id(3).purposes(EnumSet.of(PURPOSE)).build()); + VendorV2.builder().id(3).purposes(EnumSet.of(PURPOSE_CODE)).build()); final VendorPermissionWithGvl excludedNotAllowedPermission = VendorPermissionWithGvl.of(vendorPermission4, - VendorV2.builder().id(4).purposes(EnumSet.of(PURPOSE)).build()); + VendorV2.builder().id(4).purposes(EnumSet.of(PURPOSE_CODE)).build()); final VendorPermissionWithGvl notMentionedPermission = VendorPermissionWithGvl.of(vendorPermission5, - VendorV2.builder().id(5).purposes(EnumSet.of(PURPOSE)).build()); + VendorV2.builder().id(5).purposes(EnumSet.of(PURPOSE_CODE)).build()); given(purposesConsent.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, Arrays.asList(requireConsentPermission, notAllowedPermission, notMentionedPermission), Arrays.asList(excludedNotMentionedPermission, excludedNotAllowedPermission), false); @@ -173,8 +173,8 @@ public void shouldReturnExpectedWhenMultiplePublisherRestrictionsProvided() { public void shouldAllowWhenInGvlPurposeAndPurposeConsentAllowed() { // given final VendorV2 vendorGvl = VendorV2.builder() - .purposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.noneOf(Purpose.class)) + .purposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.noneOf(PurposeCode.class)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -184,21 +184,21 @@ public void shouldAllowWhenInGvlPurposeAndPurposeConsentAllowed() { given(purposesConsent.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then assertThat(result).usingFieldByFieldElementComparator().containsOnly(vendorPermission); - verify(purposesConsent).contains(PURPOSE.code()); + verify(purposesConsent).contains(PURPOSE_CODE.code()); } @Test public void shouldAllowWhenInGvlPurposeAndPurposeConsentAllowedAndRequireConsent() { // given final VendorV2 vendorGvl = VendorV2.builder() - .purposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.noneOf(Purpose.class)) + .purposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.noneOf(PurposeCode.class)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -210,21 +210,21 @@ public void shouldAllowWhenInGvlPurposeAndPurposeConsentAllowedAndRequireConsent given(purposesConsent.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then assertThat(result).usingFieldByFieldElementComparator().containsOnly(vendorPermission); - verify(purposesConsent).contains(PURPOSE.code()); + verify(purposesConsent).contains(PURPOSE_CODE.code()); } @Test public void shouldEmptyWhenInGvlPurposeAndPurposeConsentAllowedAndRequireLI() { // given final VendorV2 vendorGvl = VendorV2.builder() - .purposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.noneOf(Purpose.class)) + .purposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.noneOf(PurposeCode.class)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -236,7 +236,7 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeConsentAllowedAndRequireLI() { given(purposesConsent.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -249,8 +249,8 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeConsentAllowedAndRequireLI() { public void shouldEmptyWhenInGvlPurposeAndPurposeLIAllowed() { // given final VendorV2 vendorGvl = VendorV2.builder() - .purposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.noneOf(Purpose.class)) + .purposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.noneOf(PurposeCode.class)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -260,13 +260,13 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeLIAllowed() { given(purposesLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then assertThat(result).isEmpty(); - verify(purposesConsent).contains(PURPOSE.code()); + verify(purposesConsent).contains(PURPOSE_CODE.code()); verifyZeroInteractions(purposesLI); } @@ -274,8 +274,8 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeLIAllowed() { public void shouldAllowWhenInGvlPurposeAndPurposeConsentAllowedAndVendorConsentAllowedAndEnforced() { // given final VendorV2 vendorGvl = VendorV2.builder() - .purposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.noneOf(Purpose.class)) + .purposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.noneOf(PurposeCode.class)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -286,13 +286,13 @@ public void shouldAllowWhenInGvlPurposeAndPurposeConsentAllowedAndVendorConsentA given(allowedVendors.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then assertThat(result).usingFieldByFieldElementComparator().containsOnly(vendorPermission); - verify(purposesConsent).contains(PURPOSE.code()); + verify(purposesConsent).contains(PURPOSE_CODE.code()); verify(allowedVendors).contains(1); } @@ -300,8 +300,8 @@ public void shouldAllowWhenInGvlPurposeAndPurposeConsentAllowedAndVendorConsentA public void shouldEmptyWhenInGvlPurposeAndPurposeConsentAllowedAndVendorLIAllowedAndEnforced() { // given final VendorV2 vendorGvl = VendorV2.builder() - .purposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.noneOf(Purpose.class)) + .purposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.noneOf(PurposeCode.class)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -312,13 +312,13 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeConsentAllowedAndVendorLIAllowe given(allowedVendorsLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then assertThat(result).isEmpty(); - verify(purposesConsent).contains(PURPOSE.code()); + verify(purposesConsent).contains(PURPOSE_CODE.code()); verifyZeroInteractions(purposesLI); } @@ -328,8 +328,8 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeConsentAllowedAndVendorLIAllowe public void shouldAllowWhenInGvlPurposeLIAndPurposeLI() { // given final VendorV2 vendorGvl = VendorV2.builder() - .legIntPurposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.noneOf(Purpose.class)) + .legIntPurposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.noneOf(PurposeCode.class)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -339,21 +339,21 @@ public void shouldAllowWhenInGvlPurposeLIAndPurposeLI() { given(purposesLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then assertThat(result).usingFieldByFieldElementComparator().containsOnly(vendorPermission); - verify(purposesLI).contains(PURPOSE.code()); + verify(purposesLI).contains(PURPOSE_CODE.code()); } @Test public void shouldAllowWhenInGvlPurposeLIAndPurposeLIAndRequireLI() { // given final VendorV2 vendorGvl = VendorV2.builder() - .legIntPurposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.noneOf(Purpose.class)) + .legIntPurposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.noneOf(PurposeCode.class)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -365,21 +365,21 @@ public void shouldAllowWhenInGvlPurposeLIAndPurposeLIAndRequireLI() { given(purposesLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then assertThat(result).usingFieldByFieldElementComparator().containsOnly(vendorPermission); - verify(purposesLI).contains(PURPOSE.code()); + verify(purposesLI).contains(PURPOSE_CODE.code()); } @Test public void shouldEmptyWhenInGvlPurposeLIAndPurposeLIAndRequireConsent() { // given final VendorV2 vendorGvl = VendorV2.builder() - .legIntPurposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.noneOf(Purpose.class)) + .legIntPurposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.noneOf(PurposeCode.class)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -392,7 +392,7 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeLIAndRequireConsent() { given(purposesLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -405,8 +405,8 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeLIAndRequireConsent() { public void shouldAllowWhenInGvlPurposeLIAndPurposeLIAndVendorLIAllowedAndEnforced() { // given final VendorV2 vendorGvl = VendorV2.builder() - .legIntPurposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.noneOf(Purpose.class)) + .legIntPurposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.noneOf(PurposeCode.class)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -417,13 +417,13 @@ public void shouldAllowWhenInGvlPurposeLIAndPurposeLIAndVendorLIAllowedAndEnforc given(allowedVendorsLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then assertThat(result).usingFieldByFieldElementComparator().containsOnly(vendorPermission); - verify(purposesLI).contains(PURPOSE.code()); + verify(purposesLI).contains(PURPOSE_CODE.code()); verify(allowedVendorsLI).contains(1); } @@ -431,8 +431,8 @@ public void shouldAllowWhenInGvlPurposeLIAndPurposeLIAndVendorLIAllowedAndEnforc public void shouldEmptyWhenInGvlPurposeLIAndPurposeConsentAllowedAndVendorConsentAllowedAndEnforced() { // given final VendorV2 vendorGvl = VendorV2.builder() - .legIntPurposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.noneOf(Purpose.class)) + .legIntPurposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.noneOf(PurposeCode.class)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -444,13 +444,13 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeConsentAllowedAndVendorConsen given(allowedVendors.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then assertThat(result).isEmpty(); - verify(purposesLI).contains(PURPOSE.code()); + verify(purposesLI).contains(PURPOSE_CODE.code()); verifyZeroInteractions(allowedVendors); } @@ -462,8 +462,8 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeConsentAllowedAndVendorConsen public void shouldAllowWhenInGvlPurposeAndPurposeConsentAllowedAndFlexibleAndRequireConsent() { // given final VendorV2 vendorGvl = VendorV2.builder() - .purposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .purposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -475,21 +475,21 @@ public void shouldAllowWhenInGvlPurposeAndPurposeConsentAllowedAndFlexibleAndReq given(purposesConsent.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then assertThat(result).usingFieldByFieldElementComparator().containsOnly(vendorPermission); - verify(purposesConsent).contains(PURPOSE.code()); + verify(purposesConsent).contains(PURPOSE_CODE.code()); } @Test public void shouldAllowWhenInGvlPurposeAndPurposeConsentAndVendorConsentAndEnforcedAndFlexibleAndRequireConsent() { // given final VendorV2 vendorGvl = VendorV2.builder() - .purposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .purposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -502,13 +502,13 @@ public void shouldAllowWhenInGvlPurposeAndPurposeConsentAndVendorConsentAndEnfor given(allowedVendors.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then assertThat(result).usingFieldByFieldElementComparator().containsOnly(vendorPermission); - verify(purposesConsent).contains(PURPOSE.code()); + verify(purposesConsent).contains(PURPOSE_CODE.code()); verify(allowedVendors).contains(1); } @@ -516,8 +516,8 @@ public void shouldAllowWhenInGvlPurposeAndPurposeConsentAndVendorConsentAndEnfor public void shouldEmptyWhenInGvlPurposeAndPurposeLIAllowedAndFlexibleAndRequireConsent() { // given final VendorV2 vendorGvl = VendorV2.builder() - .purposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .purposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -529,7 +529,7 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeLIAllowedAndFlexibleAndRequireC given(purposesLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -542,8 +542,8 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeLIAllowedAndFlexibleAndRequireC public void shouldEmptyWhenInGvlPurposeAndPurposeLIAndVendorLIAllowedAndEnforcedAndFlexibleAndRequireConsent() { // given final VendorV2 vendorGvl = VendorV2.builder() - .purposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .purposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -556,7 +556,7 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeLIAndVendorLIAllowedAndEnforced given(allowedVendorsLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then @@ -570,8 +570,8 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeLIAndVendorLIAllowedAndEnforced public void shouldEmptyWhenInGvlPurposeAndPurposeConsentAndVendorLIAndEnforcedAndFlexibleAndRequireConsent() { // given final VendorV2 vendorGvl = VendorV2.builder() - .purposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .purposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -584,21 +584,21 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeConsentAndVendorLIAndEnforcedAn given(allowedVendorsLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then assertThat(result).isEmpty(); - verify(purposesConsent).contains(PURPOSE.code()); + verify(purposesConsent).contains(PURPOSE_CODE.code()); } @Test public void shouldEmptyWhenInGvlPurposeAndPurposeLIAndVendorConsentAndEnforcedAndFlexibleAndRequireConsent() { // given final VendorV2 vendorGvl = VendorV2.builder() - .purposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .purposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -611,7 +611,7 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeLIAndVendorConsentAndEnforcedAn given(allowedVendors.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then @@ -624,8 +624,8 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeLIAndVendorConsentAndEnforcedAn public void shouldEmptyWhenInGvlPurposeAndPurposeConsentAllowedAndFlexibleAndRequireLI() { // given final VendorV2 vendorGvl = VendorV2.builder() - .purposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .purposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -637,7 +637,7 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeConsentAllowedAndFlexibleAndReq given(purposesConsent.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -650,8 +650,8 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeConsentAllowedAndFlexibleAndReq public void shouldEmptyWhenInGvlPurposeAndPurposeConsentAndVendorConsentAndEnforcedAndFlexibleAndRequireLI() { // given final VendorV2 vendorGvl = VendorV2.builder() - .purposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .purposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -664,7 +664,7 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeConsentAndVendorConsentAndEnfor given(allowedVendors.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then @@ -678,8 +678,8 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeConsentAndVendorConsentAndEnfor public void shouldAllowWhenInGvlPurposeAndPurposeLIAllowedAndFlexibleAndRequireLI() { // given final VendorV2 vendorGvl = VendorV2.builder() - .purposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .purposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -691,21 +691,21 @@ public void shouldAllowWhenInGvlPurposeAndPurposeLIAllowedAndFlexibleAndRequireL given(purposesLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then assertThat(result).usingFieldByFieldElementComparator().containsOnly(vendorPermission); - verify(purposesLI).contains(PURPOSE.code()); + verify(purposesLI).contains(PURPOSE_CODE.code()); } @Test public void shouldAllowWhenInGvlPurposeAndPurposeLIAndVendorLIAllowedAndEnforcedAndFlexibleAndRequireLI() { // given final VendorV2 vendorGvl = VendorV2.builder() - .purposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .purposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -718,13 +718,13 @@ public void shouldAllowWhenInGvlPurposeAndPurposeLIAndVendorLIAllowedAndEnforced given(allowedVendorsLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then assertThat(result).usingFieldByFieldElementComparator().containsOnly(vendorPermission); - verify(purposesLI).contains(PURPOSE.code()); + verify(purposesLI).contains(PURPOSE_CODE.code()); verify(allowedVendorsLI).contains(1); } @@ -732,8 +732,8 @@ public void shouldAllowWhenInGvlPurposeAndPurposeLIAndVendorLIAllowedAndEnforced public void shouldEmptyWhenInGvlPurposeAndPurposeConsentAndVendorLIAllowedAndEnforcedAndFlexibleAndRequireLI() { // given final VendorV2 vendorGvl = VendorV2.builder() - .purposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .purposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -746,7 +746,7 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeConsentAndVendorLIAllowedAndEnf given(allowedVendorsLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then @@ -760,8 +760,8 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeConsentAndVendorLIAllowedAndEnf public void shouldEmptyWhenInGvlPurposeAndPurposeLIAndVendorConsentAllowedAndEnforcedAndFlexibleAndRequireLI() { // given final VendorV2 vendorGvl = VendorV2.builder() - .purposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .purposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -774,13 +774,13 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeLIAndVendorConsentAllowedAndEnf given(allowedVendors.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then assertThat(result).isEmpty(); - verify(purposesLI).contains(PURPOSE.code()); + verify(purposesLI).contains(PURPOSE_CODE.code()); verifyZeroInteractions(allowedVendors); } @@ -792,8 +792,8 @@ public void shouldEmptyWhenInGvlPurposeAndPurposeLIAndVendorConsentAllowedAndEnf public void shouldAllowWhenInGvlPurposeLIAndPurposeConsentAllowedAndFlexibleAndRequireConsent() { // given final VendorV2 vendorGvl = VendorV2.builder() - .legIntPurposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .legIntPurposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -805,21 +805,21 @@ public void shouldAllowWhenInGvlPurposeLIAndPurposeConsentAllowedAndFlexibleAndR given(purposesConsent.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then assertThat(result).usingFieldByFieldElementComparator().containsOnly(vendorPermission); - verify(purposesConsent).contains(PURPOSE.code()); + verify(purposesConsent).contains(PURPOSE_CODE.code()); } @Test public void shouldAllowWhenInGvlPurposeLIAndPurposeAndVendorConsentAndEnforcedAndFlexibleAndRequireConsent() { // given final VendorV2 vendorGvl = VendorV2.builder() - .legIntPurposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .legIntPurposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -832,13 +832,13 @@ public void shouldAllowWhenInGvlPurposeLIAndPurposeAndVendorConsentAndEnforcedAn given(allowedVendors.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then assertThat(result).usingFieldByFieldElementComparator().containsOnly(vendorPermission); - verify(purposesConsent).contains(PURPOSE.code()); + verify(purposesConsent).contains(PURPOSE_CODE.code()); verify(allowedVendors).contains(1); } @@ -846,8 +846,8 @@ public void shouldAllowWhenInGvlPurposeLIAndPurposeAndVendorConsentAndEnforcedAn public void shouldEmptyWhenInGvlPurposeLIAndPurposeLIAllowedAndFlexibleAndRequireConsent() { // given final VendorV2 vendorGvl = VendorV2.builder() - .legIntPurposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .legIntPurposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -859,7 +859,7 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeLIAllowedAndFlexibleAndRequir given(purposesLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -872,8 +872,8 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeLIAllowedAndFlexibleAndRequir public void shouldEmptyWhenInGvlPurposeLIAndPurposeLIAndVendorLIAllowedAndEnforcedAndFlexibleAndRequireConsent() { // given final VendorV2 vendorGvl = VendorV2.builder() - .legIntPurposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .legIntPurposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -886,7 +886,7 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeLIAndVendorLIAllowedAndEnforc given(allowedVendorsLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then @@ -900,8 +900,8 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeLIAndVendorLIAllowedAndEnforc public void shouldEmptyWhenInGvlPurposeLIAndPurposeConsentAndVendorLIAndEnforcedAndFlexibleAndRequireConsent() { // given final VendorV2 vendorGvl = VendorV2.builder() - .legIntPurposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .legIntPurposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -914,13 +914,13 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeConsentAndVendorLIAndEnforced given(allowedVendorsLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then assertThat(result).isEmpty(); - verify(purposesConsent).contains(PURPOSE.code()); + verify(purposesConsent).contains(PURPOSE_CODE.code()); verifyZeroInteractions(allowedVendorsLI); } @@ -928,8 +928,8 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeConsentAndVendorLIAndEnforced public void shouldEmptyWhenInGvlPurposeLIAndPurposeLIAndVendorConsentAndEnforcedAndFlexibleAndRequireConsent() { // given final VendorV2 vendorGvl = VendorV2.builder() - .legIntPurposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .legIntPurposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -942,13 +942,13 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeLIAndVendorConsentAndEnforced given(allowedVendors.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then assertThat(result).isEmpty(); - verify(allowedVendors).contains(PURPOSE.code()); + verify(allowedVendors).contains(PURPOSE_CODE.code()); verifyZeroInteractions(purposesLI); } @@ -958,8 +958,8 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeLIAndVendorConsentAndEnforced public void shouldEmptyWhenInGvlPurposeLIAndPurposeConsentAllowedAndFlexibleAndRequireLI() { // given final VendorV2 vendorGvl = VendorV2.builder() - .legIntPurposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .legIntPurposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -971,7 +971,7 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeConsentAllowedAndFlexibleAndR given(purposesConsent.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -984,8 +984,8 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeConsentAllowedAndFlexibleAndR public void shouldEmptyWhenInGvlPurposeLIAndPurposeConsentAndVendorConsentAndEnforcedAndFlexibleAndRequireLI() { // given final VendorV2 vendorGvl = VendorV2.builder() - .legIntPurposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .legIntPurposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -998,7 +998,7 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeConsentAndVendorConsentAndEnf given(allowedVendors.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then @@ -1012,8 +1012,8 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeConsentAndVendorConsentAndEnf public void shouldAllowWhenInGvlPurposeLIAndPurposeLIAllowedAndFlexibleAndRequireLI() { // given final VendorV2 vendorGvl = VendorV2.builder() - .legIntPurposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .legIntPurposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -1025,21 +1025,21 @@ public void shouldAllowWhenInGvlPurposeLIAndPurposeLIAllowedAndFlexibleAndRequir given(purposesLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then assertThat(result).usingFieldByFieldElementComparator().containsOnly(vendorPermission); - verify(purposesLI).contains(PURPOSE.code()); + verify(purposesLI).contains(PURPOSE_CODE.code()); } @Test public void shouldAllowWhenInGvlPurposeLIAndPurposeLIAndVendorLIAllowedAndEnforcedAndFlexibleAndRequireLI() { // given final VendorV2 vendorGvl = VendorV2.builder() - .legIntPurposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .legIntPurposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -1052,13 +1052,13 @@ public void shouldAllowWhenInGvlPurposeLIAndPurposeLIAndVendorLIAllowedAndEnforc given(allowedVendorsLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then assertThat(result).usingFieldByFieldElementComparator().containsOnly(vendorPermission); - verify(purposesLI).contains(PURPOSE.code()); + verify(purposesLI).contains(PURPOSE_CODE.code()); verify(allowedVendorsLI).contains(1); } @@ -1066,8 +1066,8 @@ public void shouldAllowWhenInGvlPurposeLIAndPurposeLIAndVendorLIAllowedAndEnforc public void shouldEmptyWhenInGvlPurposeLIAndPurposeConsentAndVendorLIAllowedAndEnforcedAndFlexibleAndRequireLI() { // given final VendorV2 vendorGvl = VendorV2.builder() - .legIntPurposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .legIntPurposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -1080,7 +1080,7 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeConsentAndVendorLIAllowedAndE given(allowedVendorsLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then @@ -1094,8 +1094,8 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeConsentAndVendorLIAllowedAndE public void shouldEmptyWhenInGvlPurposeLIAndPurposeLIAndVendorConsentAllowedAndEnforcedAndFlexibleAndRequireLI() { // given final VendorV2 vendorGvl = VendorV2.builder() - .legIntPurposes(EnumSet.of(PURPOSE)) - .flexiblePurposes(EnumSet.of(PURPOSE)) + .legIntPurposes(EnumSet.of(PURPOSE_CODE)) + .flexiblePurposes(EnumSet.of(PURPOSE_CODE)) .build(); final VendorPermission vendorPermission = VendorPermission.of(1, null, PrivacyEnforcementAction.restrictAll()); @@ -1108,7 +1108,7 @@ public void shouldEmptyWhenInGvlPurposeLIAndPurposeLIAndVendorConsentAllowedAndE given(allowedVendors.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then @@ -1129,7 +1129,7 @@ public void shouldReturnExcludedVendors() { VendorV2.empty(2)); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, singleton(vendorPermissionWitGvl1), singleton(vendorPermissionWitGvl2), true); // then diff --git a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/NoEnforcePurposeStrategyTest.java b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/NoEnforcePurposeStrategyTest.java index cef5a8c9f01..5942a673f90 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/NoEnforcePurposeStrategyTest.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/NoEnforcePurposeStrategyTest.java @@ -11,7 +11,7 @@ import org.prebid.server.privacy.gdpr.model.PrivacyEnforcementAction; import org.prebid.server.privacy.gdpr.model.VendorPermission; import org.prebid.server.privacy.gdpr.model.VendorPermissionWithGvl; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV2; import java.util.Arrays; @@ -27,7 +27,7 @@ public class NoEnforcePurposeStrategyTest { - private static final Purpose PURPOSE = Purpose.ONE; + private static final PurposeCode PURPOSE_CODE = PurposeCode.ONE; @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); @@ -61,7 +61,7 @@ public void allowedByTypeStrategyShouldReturnExpectedListWhenVendorIsNotAllowedA final List vendorPermissionWithGvls = singletonList(vendorPermissionWitGvl); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -77,7 +77,7 @@ public void allowedByTypeStrategyShouldReturnEmptyListWhenVendorIsNotAllowedAndV final List vendorPermissionWithGvls = singletonList(vendorPermissionWitGvl); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then @@ -95,7 +95,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenVendorIsAllowedAnd given(allowedVendors.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then @@ -113,7 +113,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenVendorIsAllowedAnd given(allowedVendors.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -131,7 +131,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenVendorLIIsAllowedA given(allowedVendorsLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPurposeWithGvls, emptyList(), true); // then @@ -149,7 +149,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenVendorLIIsAllowedA given(allowedVendorsLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPurposeWithGvls, emptyList(), false); // then @@ -172,7 +172,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenVendorIsAllowedFor given(allowedVendors.contains(eq(2))).willReturn(false); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPurposeWithGvls, emptyList(), false); // then @@ -194,7 +194,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenVendorIsAllowedFor given(allowedVendors.contains(eq(2))).willReturn(false); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPurposeWithGvls, emptyList(), true); // then @@ -217,7 +217,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenPurposeAndVendorLI given(allowedVendorsLI.contains(eq(2))).willReturn(false); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPurposeWithGvls, emptyList(), false); // then @@ -240,7 +240,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenPurposeAndVendorLI given(allowedVendorsLI.contains(eq(2))).willReturn(false); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPurposeWithGvls, emptyList(), true); // then @@ -258,7 +258,7 @@ public void allowedByTypeStrategyShouldReturnExcludedVendors() { VendorV2.empty(1)); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, singletonList(vendorPermissionWitGvl1), singletonList(vendorPermissionWitGvl2), true); // then diff --git a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/PurposeTwoBasicEnforcePurposeStrategyTest.java b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/PurposeTwoBasicEnforcePurposeStrategyTest.java index a11192fa5f0..125ee817059 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/PurposeTwoBasicEnforcePurposeStrategyTest.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/tcfstrategies/purpose/typestrategies/PurposeTwoBasicEnforcePurposeStrategyTest.java @@ -11,7 +11,7 @@ import org.prebid.server.privacy.gdpr.model.PrivacyEnforcementAction; import org.prebid.server.privacy.gdpr.model.VendorPermission; import org.prebid.server.privacy.gdpr.model.VendorPermissionWithGvl; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV2; import java.util.Arrays; @@ -27,7 +27,7 @@ public class PurposeTwoBasicEnforcePurposeStrategyTest { - private static final Purpose PURPOSE = Purpose.ONE; + private static final PurposeCode PURPOSE_CODE = PurposeCode.ONE; @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); @@ -69,7 +69,7 @@ public void allowedByTypeStrategyShouldReturnEmptyListWhenVendorIsNotAllowedAndV final List vendorPermissionWithGvls = singletonList(vendorPermissionWitGvl); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -85,7 +85,7 @@ public void allowedByTypeStrategyShouldReturnEmptyListWhenVendorIsNotAllowedAndV final List vendorPermissionWithGvls = singletonList(vendorPermissionWitGvl); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then @@ -103,7 +103,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenVendorIsAllowedAnd given(allowedVendors.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then @@ -121,7 +121,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenVendorIsAllowedAnd given(allowedVendors.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -139,7 +139,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenVendorLIIsAllowedA given(allowedVendorsLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then @@ -157,7 +157,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenVendorLIIsAllowedA given(allowedVendorsLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -176,7 +176,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenPurposeLIAndPurpos given(purposesLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -195,7 +195,7 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenPurposeLIAndPurpos given(purposesLI.contains(anyInt())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), true); // then @@ -215,10 +215,10 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenPurposeLIAndVendor vendorPermissionWitGvl2); given(allowedVendors.contains(anyInt())).willReturn(true); - given(purposesLI.contains(PURPOSE.code())).willReturn(true); + given(purposesLI.contains(PURPOSE_CODE.code())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -238,10 +238,10 @@ public void allowedByTypeStrategyShouldReturnExpectedValueWhenPurposeAndVendorLI vendorPermissionWitGvl2); given(allowedVendorsLI.contains(anyInt())).willReturn(true); - given(purposesConsent.contains(PURPOSE.code())).willReturn(true); + given(purposesConsent.contains(PURPOSE_CODE.code())).willReturn(true); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, vendorPermissionWithGvls, emptyList(), false); // then @@ -259,7 +259,7 @@ public void allowedByTypeStrategyShouldReturnExcludedVendors() { VendorV2.empty(2)); // when - final Collection result = target.allowedByTypeStrategy(PURPOSE, tcString, + final Collection result = target.allowedByTypeStrategy(PURPOSE_CODE, tcString, singleton(vendorPermissionWitGvl1), singleton(vendorPermissionWitGvl2), true); // then diff --git a/src/test/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV1Test.java b/src/test/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV1Test.java index 3eafba4980a..7a2dee7d416 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV1Test.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV1Test.java @@ -43,8 +43,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.prebid.server.assertion.FutureAssertion.assertThat; -import static org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.ONE; -import static org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.TWO; +import static org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode.ONE; +import static org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode.TWO; public class VendorListServiceV1Test extends VertxTest { diff --git a/src/test/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV2Test.java b/src/test/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV2Test.java index 6f335c4a6c2..e21cfadf86a 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV2Test.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV2Test.java @@ -19,7 +19,7 @@ import org.prebid.server.exception.PreBidException; import org.prebid.server.metric.Metrics; import org.prebid.server.privacy.gdpr.vendorlist.proto.Feature; -import org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose; +import org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode; import org.prebid.server.privacy.gdpr.vendorlist.proto.SpecialFeature; import org.prebid.server.privacy.gdpr.vendorlist.proto.SpecialPurpose; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorListV2; @@ -47,8 +47,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.prebid.server.assertion.FutureAssertion.assertThat; -import static org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.ONE; -import static org.prebid.server.privacy.gdpr.vendorlist.proto.Purpose.TWO; +import static org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode.ONE; +import static org.prebid.server.privacy.gdpr.vendorlist.proto.PurposeCode.TWO; public class VendorListServiceV2Test extends VertxTest { @@ -151,7 +151,7 @@ public void shouldStartUsingFallbackVersionIfDeprecatedIsTrue() { .id(52) .purposes(EnumSet.of(ONE)) .legIntPurposes(EnumSet.of(TWO)) - .flexiblePurposes(EnumSet.noneOf(Purpose.class)) + .flexiblePurposes(EnumSet.noneOf(PurposeCode.class)) .specialPurposes(EnumSet.noneOf(SpecialPurpose.class)) .features(EnumSet.noneOf(Feature.class)) .specialFeatures(EnumSet.noneOf(SpecialFeature.class)) @@ -441,7 +441,7 @@ public void shouldReturnVendorListFromCache() throws JsonProcessingException { .id(52) .purposes(EnumSet.of(ONE)) .legIntPurposes(EnumSet.of(TWO)) - .flexiblePurposes(EnumSet.noneOf(Purpose.class)) + .flexiblePurposes(EnumSet.noneOf(PurposeCode.class)) .specialPurposes(EnumSet.noneOf(SpecialPurpose.class)) .features(EnumSet.noneOf(Feature.class)) .specialFeatures(EnumSet.noneOf(SpecialFeature.class)) @@ -455,7 +455,7 @@ public void shouldKeepPurposesForAllVendors() throws JsonProcessingException { .id(52) .purposes(EnumSet.of(ONE)) .legIntPurposes(EnumSet.of(TWO)) - .flexiblePurposes(EnumSet.noneOf(Purpose.class)) + .flexiblePurposes(EnumSet.noneOf(PurposeCode.class)) .specialPurposes(EnumSet.noneOf(SpecialPurpose.class)) .features(EnumSet.noneOf(Feature.class)) .specialFeatures(EnumSet.noneOf(SpecialFeature.class)) @@ -464,7 +464,7 @@ public void shouldKeepPurposesForAllVendors() throws JsonProcessingException { .id(42) .purposes(EnumSet.of(ONE)) .legIntPurposes(EnumSet.of(TWO)) - .flexiblePurposes(EnumSet.noneOf(Purpose.class)) + .flexiblePurposes(EnumSet.noneOf(PurposeCode.class)) .specialPurposes(EnumSet.noneOf(SpecialPurpose.class)) .features(EnumSet.noneOf(Feature.class)) .specialFeatures(EnumSet.noneOf(SpecialFeature.class)) @@ -506,7 +506,7 @@ public void shouldReturnFallbackIfVendorListNotFound() { .id(52) .purposes(EnumSet.of(ONE)) .legIntPurposes(EnumSet.of(TWO)) - .flexiblePurposes(EnumSet.noneOf(Purpose.class)) + .flexiblePurposes(EnumSet.noneOf(PurposeCode.class)) .specialPurposes(EnumSet.noneOf(SpecialPurpose.class)) .features(EnumSet.noneOf(Feature.class)) .specialFeatures(EnumSet.noneOf(SpecialFeature.class)) @@ -590,7 +590,7 @@ private static VendorListV2 givenVendorList() { .id(52) .purposes(EnumSet.of(ONE)) .legIntPurposes(EnumSet.of(TWO)) - .flexiblePurposes(EnumSet.noneOf(Purpose.class)) + .flexiblePurposes(EnumSet.noneOf(PurposeCode.class)) .specialPurposes(EnumSet.noneOf(SpecialPurpose.class)) .features(EnumSet.noneOf(Feature.class)) .specialFeatures(EnumSet.noneOf(SpecialFeature.class)) diff --git a/src/test/java/org/prebid/server/spring/config/bidder/util/UsersyncerCreatorTest.java b/src/test/java/org/prebid/server/spring/config/bidder/util/UsersyncerCreatorTest.java new file mode 100644 index 00000000000..95d6aee6d55 --- /dev/null +++ b/src/test/java/org/prebid/server/spring/config/bidder/util/UsersyncerCreatorTest.java @@ -0,0 +1,119 @@ +package org.prebid.server.spring.config.bidder.util; + +import org.junit.Test; +import org.prebid.server.bidder.Usersyncer; +import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; + +import java.net.MalformedURLException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class UsersyncerCreatorTest { + + @Test + public void createShouldReturnUsersyncerWithConcatenatedExternalAndRedirectUrl() { + // given + final UsersyncConfigurationProperties config = new UsersyncConfigurationProperties(); + config.setCookieFamilyName("rubicon"); + config.setUrl("//usersync-url"); + config.setRedirectUrl("/redirect-url"); + config.setType("redirect"); + config.setSupportCors(true); + + // when and then + assertThat(UsersyncerCreator.create("http://localhost:8000").apply(config)) + .extracting(usersyncer -> usersyncer.getPrimaryMethod().getRedirectUrl()) + .containsOnly("http://localhost:8000/redirect-url"); + } + + @Test + public void createShouldReturnUsersyncerWithEmptyRedirectUrlWhenItWasNotDefined() { + // given + final UsersyncConfigurationProperties config = new UsersyncConfigurationProperties(); + config.setCookieFamilyName("rubicon"); + config.setUrl("//usersync-url"); + config.setType("redirect"); + config.setSupportCors(true); + + // when and then + assertThat(UsersyncerCreator.create(null).apply(config)) + .extracting(usersyncer -> usersyncer.getPrimaryMethod().getRedirectUrl()) + .containsOnly(""); + } + + @Test + public void createShouldValidateExternalUrl() { + // given + final UsersyncConfigurationProperties config = new UsersyncConfigurationProperties(); + config.setUrl("//usersync-url"); + config.setRedirectUrl("not-valid-url"); + config.setType("redirect"); + config.setSupportCors(true); + + // given, when and then + assertThatThrownBy(() -> UsersyncerCreator.create(null).apply(config)) + .hasCauseExactlyInstanceOf(MalformedURLException.class) + .hasMessage("URL supplied is not valid: null"); + } + + @Test + public void createShouldReturnUsersyncerWithPrimaryAndSecondaryMethods() { + // given + final UsersyncConfigurationProperties config = new UsersyncConfigurationProperties(); + config.setCookieFamilyName("rubicon"); + config.setUrl("//usersync-url"); + config.setRedirectUrl("/redirect-url"); + config.setType("redirect"); + config.setSupportCors(true); + + final UsersyncConfigurationProperties.SecondaryConfigurationProperties secondaryMethodConfig = + new UsersyncConfigurationProperties.SecondaryConfigurationProperties(); + secondaryMethodConfig.setUrl("//usersync-url-secondary"); + secondaryMethodConfig.setRedirectUrl("/redirect-url-secondary"); + secondaryMethodConfig.setType("iframe"); + secondaryMethodConfig.setSupportCors(false); + + config.setSecondary(secondaryMethodConfig); + + // when and then + assertThat(UsersyncerCreator.create("http://localhost:8000").apply(config)).isEqualTo( + Usersyncer.of( + "rubicon", + Usersyncer.UsersyncMethod.of( + "redirect", + "//usersync-url", + "http://localhost:8000/redirect-url", + true), + Usersyncer.UsersyncMethod.of( + "iframe", + "//usersync-url-secondary", + "http://localhost:8000/redirect-url-secondary", + false))); + } + + @Test + public void createShouldFailWhenSecondaryMethodPresentAndPrimaryAbsent() { + // given + final UsersyncConfigurationProperties config = new UsersyncConfigurationProperties(); + config.setUrl(""); + config.setCookieFamilyName("rubicon"); + config.setType("redirect"); + config.setSupportCors(true); + + final UsersyncConfigurationProperties.SecondaryConfigurationProperties secondaryMethodConfig = + new UsersyncConfigurationProperties.SecondaryConfigurationProperties(); + secondaryMethodConfig.setUrl("//usersync-url-secondary"); + secondaryMethodConfig.setRedirectUrl("/redirect-url-secondary"); + secondaryMethodConfig.setType("iframe"); + secondaryMethodConfig.setSupportCors(false); + + config.setSecondary(secondaryMethodConfig); + + // when and then + assertThatThrownBy(() -> UsersyncerCreator.create("http://localhost:8000").apply(config)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageStartingWith("Invalid usersync configuration: primary method is missing while secondary is" + + " present. Configuration:"); + } +} diff --git a/src/test/java/org/prebid/server/util/HttpUtilTest.java b/src/test/java/org/prebid/server/util/HttpUtilTest.java index 889b402b4f6..cfb5ef81049 100644 --- a/src/test/java/org/prebid/server/util/HttpUtilTest.java +++ b/src/test/java/org/prebid/server/util/HttpUtilTest.java @@ -94,21 +94,21 @@ public void addHeaderIfValueIsNotEmptyShouldNotAddHeaderIfValueIsNull() { } @Test - public void getDomainFromUrlShouldReturnDomain() { + public void getHostFromUrlShouldReturnDomain() { // given and when - final String domain = HttpUtil.getDomainFromUrl("http://rubicon.com/ad"); + final String host = HttpUtil.getHostFromUrl("http://www.rubicon.com/ad"); // then - assertThat(domain).isEqualTo("rubicon.com"); + assertThat(host).isEqualTo("www.rubicon.com"); } @Test - public void getDomainFromUrlShouldReturnNullIfUrlIsMalformed() { + public void getHostFromUrlShouldReturnNullIfUrlIsMalformed() { // given and when - final String domain = HttpUtil.getDomainFromUrl("rubicon.com"); + final String host = HttpUtil.getHostFromUrl("www.rubicon.com"); // then - assertThat(domain).isNull(); + assertThat(host).isNull(); } @Test diff --git a/src/test/java/org/prebid/server/validation/BidderParamValidatorTest.java b/src/test/java/org/prebid/server/validation/BidderParamValidatorTest.java index b240b9ef8c3..abf6f8393a5 100644 --- a/src/test/java/org/prebid/server/validation/BidderParamValidatorTest.java +++ b/src/test/java/org/prebid/server/validation/BidderParamValidatorTest.java @@ -20,6 +20,7 @@ import org.prebid.server.proto.openrtb.ext.request.rubicon.ExtImpRubicon; import org.prebid.server.proto.openrtb.ext.request.somoaudience.ExtImpSomoaudience; import org.prebid.server.proto.openrtb.ext.request.sovrn.ExtImpSovrn; +import org.prebid.server.proto.response.BidderInfo; import org.prebid.server.util.ResourceUtil; import java.io.IOException; @@ -31,12 +32,15 @@ import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; public class BidderParamValidatorTest extends VertxTest { private static final String RUBICON = "rubicon"; private static final String APPNEXUS = "appnexus"; + private static final String APPNEXUS_ALIAS = "appnexusAlias"; private static final String ADFORM = "adform"; private static final String BRIGHTROLL = "brightroll"; private static final String SOVRN = "sovrn"; @@ -57,9 +61,21 @@ public class BidderParamValidatorTest extends VertxTest { @Before public void setUp() { - given(bidderCatalog.names()).willReturn(new HashSet<>( - asList(RUBICON, APPNEXUS, ADFORM, BRIGHTROLL, SOVRN, ADTELLIGENT, FACEBOOK, OPENX, EPLANNING, - SOMOAUDIENCE, BEACHFRONT))); + given(bidderCatalog.names()).willReturn(new HashSet<>(asList( + RUBICON, + APPNEXUS, + APPNEXUS_ALIAS, + ADFORM, + BRIGHTROLL, + SOVRN, + ADTELLIGENT, + FACEBOOK, + OPENX, + EPLANNING, + SOMOAUDIENCE, + BEACHFRONT))); + given(bidderCatalog.bidderInfoByName(anyString())).willReturn(givenBidderInfo()); + given(bidderCatalog.bidderInfoByName(eq(APPNEXUS_ALIAS))).willReturn(givenBidderInfo(APPNEXUS)); bidderParamValidator = BidderParamValidator.create(bidderCatalog, "static/bidder-params", jacksonMapper); } @@ -138,6 +154,34 @@ public void validateShouldNotReturnValidationMessagesWhenAppnexusImpExtIsOk() { assertThat(messages).isEmpty(); } + @Test + public void validateShouldReturnValidationMessagesWhenAppnexusAliasImpExtNotValid() { + // given + final ExtImpAppnexus ext = ExtImpAppnexus.builder().member("memberId").build(); + + final JsonNode node = mapper.convertValue(ext, JsonNode.class); + + // when + final Set messages = bidderParamValidator.validate(APPNEXUS_ALIAS, node); + + // then + assertThat(messages.size()).isEqualTo(4); + } + + @Test + public void validateShouldNotReturnValidationMessagesWhenAppnexusAliasImpExtIsOk() { + // given + final ExtImpAppnexus ext = ExtImpAppnexus.builder().placementId(1).build(); + + final JsonNode node = mapper.convertValue(ext, JsonNode.class); + + // when + final Set messages = bidderParamValidator.validate(APPNEXUS_ALIAS, node); + + // then + assertThat(messages).isEmpty(); + } + @Test public void validateShouldNotReturnValidationMessagesWhenAdformImpExtIsOk() { // given @@ -394,4 +438,22 @@ public void schemaShouldReturnSchemasString() throws IOException { assertThat(result).isEqualTo(ResourceUtil.readFromClasspath( "org/prebid/server/validation/schema//valid/test-schemas.json")); } + + private static BidderInfo givenBidderInfo(String aliasOf) { + return BidderInfo.create( + true, + aliasOf, + null, + null, + null, + null, + 0, + true, + true, + false); + } + + private static BidderInfo givenBidderInfo() { + return givenBidderInfo(null); + } } diff --git a/src/test/java/org/prebid/server/validation/RequestValidatorTest.java b/src/test/java/org/prebid/server/validation/RequestValidatorTest.java index c8735a1f282..17862c945c2 100644 --- a/src/test/java/org/prebid/server/validation/RequestValidatorTest.java +++ b/src/test/java/org/prebid/server/validation/RequestValidatorTest.java @@ -37,6 +37,7 @@ import org.mockito.junit.MockitoRule; import org.prebid.server.VertxTest; import org.prebid.server.bidder.BidderCatalog; +import org.prebid.server.proto.openrtb.ext.request.BidAdjustmentMediaType; import org.prebid.server.proto.openrtb.ext.request.ExtDevice; import org.prebid.server.proto.openrtb.ext.request.ExtDeviceInt; import org.prebid.server.proto.openrtb.ext.request.ExtDevicePrebid; @@ -46,10 +47,11 @@ import org.prebid.server.proto.openrtb.ext.request.ExtPriceGranularity; import org.prebid.server.proto.openrtb.ext.request.ExtRegs; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestBidadjustmentfactors; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; -import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidSchain; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidData; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidDataEidPermissions; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidSchain; import org.prebid.server.proto.openrtb.ext.request.ExtRequestTargeting; import org.prebid.server.proto.openrtb.ext.request.ExtSite; import org.prebid.server.proto.openrtb.ext.request.ExtStoredAuctionResponse; @@ -62,6 +64,7 @@ import java.math.BigDecimal; import java.util.Collections; +import java.util.EnumMap; import java.util.LinkedHashSet; import java.util.function.Function; @@ -2709,12 +2712,14 @@ public void validateShouldReturnValidationMessageWhenMetricValueIsNotValid() { @Test public void validateShouldReturnValidationMessageWhenAdjustmentFactorNegative() { // given + final ExtRequestBidadjustmentfactors givenAdjustments = ExtRequestBidadjustmentfactors.builder().build(); + givenAdjustments.addFactor("rubicon", BigDecimal.valueOf(-1.1)); final BidRequest bidRequest = validBidRequestBuilder() .ext(ExtRequest.of( ExtRequestPrebid.builder() - .bidadjustmentfactors(singletonMap("rubicon", BigDecimal.valueOf(-1.1))).build())) + .bidadjustmentfactors(givenAdjustments) + .build())) .build(); - // when final ValidationResult result = requestValidator.validate(bidRequest); @@ -2724,13 +2729,38 @@ public void validateShouldReturnValidationMessageWhenAdjustmentFactorNegative() "request.ext.prebid.bidadjustmentfactors.rubicon must be a positive number. Got -1.100000"); } + @Test + public void validateShouldReturnValidationMessageWhenAdjustmentMediaFactorNegative() { + // given + final ExtRequestBidadjustmentfactors givenAdjustments = ExtRequestBidadjustmentfactors.builder() + .mediatypes(new EnumMap<>(Collections.singletonMap(BidAdjustmentMediaType.banner, + Collections.singletonMap("rubicon", BigDecimal.valueOf(-1.1))))) + .build(); + final BidRequest bidRequest = validBidRequestBuilder() + .ext(ExtRequest.of( + ExtRequestPrebid.builder() + .bidadjustmentfactors(givenAdjustments) + .build())) + .build(); + // when + final ValidationResult result = requestValidator.validate(bidRequest); + + // then + assertThat(result.getErrors()).hasSize(1) + .containsOnly( + "request.ext.prebid.bidadjustmentfactors.banner.rubicon " + + "must be a positive number. Got -1.100000"); + } + @Test public void validateShouldReturnValidationMessageWhenBidderUnknown() { // given + final ExtRequestBidadjustmentfactors givenAdjustments = ExtRequestBidadjustmentfactors.builder().build(); + givenAdjustments.addFactor("unknownBidder", BigDecimal.valueOf(1.1F)); final BidRequest bidRequest = validBidRequestBuilder() .ext(ExtRequest.of( ExtRequestPrebid.builder() - .bidadjustmentfactors(singletonMap("unknownBidder", BigDecimal.valueOf(1.1F))) + .bidadjustmentfactors(givenAdjustments) .build())) .build(); @@ -2743,12 +2773,40 @@ public void validateShouldReturnValidationMessageWhenBidderUnknown() { } @Test - public void validateShouldEmptyValidationMessagesWhenBidderIsKnownAndAdjustmentIsValid() { + public void validateShouldReturnValidationMessageWhenMediaBidderUnknown() { // given + final ExtRequestBidadjustmentfactors givenAdjustments = ExtRequestBidadjustmentfactors.builder() + .mediatypes(new EnumMap<>(Collections.singletonMap(BidAdjustmentMediaType.xNative, + Collections.singletonMap("unknownBidder", BigDecimal.valueOf(1.1))))) + .build(); final BidRequest bidRequest = validBidRequestBuilder() .ext(ExtRequest.of( ExtRequestPrebid.builder() - .bidadjustmentfactors(singletonMap("rubicon", BigDecimal.valueOf(1.1))).build())) + .bidadjustmentfactors(givenAdjustments) + .build())) + .build(); + // when + final ValidationResult result = requestValidator.validate(bidRequest); + + // then + assertThat(result.getErrors()).hasSize(1) + .containsOnly( + "request.ext.prebid.bidadjustmentfactors.native.unknownBidder is not a known bidder or alias"); + } + + @Test + public void validateShouldReturnEmptyValidationMessagesWhenBidderIsKnownAndAdjustmentIsValid() { + // given + final ExtRequestBidadjustmentfactors givenAdjustments = ExtRequestBidadjustmentfactors.builder() + .mediatypes(new EnumMap<>(Collections.singletonMap(BidAdjustmentMediaType.xNative, + Collections.singletonMap("rubicon", BigDecimal.valueOf(2.1))))) + .build(); + givenAdjustments.addFactor("rubicon", BigDecimal.valueOf(1.1)); + final BidRequest bidRequest = validBidRequestBuilder() + .ext(ExtRequest.of( + ExtRequestPrebid.builder() + .bidadjustmentfactors(givenAdjustments) + .build())) .build(); // when @@ -2759,14 +2817,19 @@ public void validateShouldEmptyValidationMessagesWhenBidderIsKnownAndAdjustmentI } @Test - public void validateShouldEmptyValidationMessagesWhenBidderIsKnownAliasForCoreBidderAndAdjustmentIsValid() { + public void validateShouldReturnEmptyValidationMessagesWhenBidderIsKnownAliasForCoreBidderAndAdjustmentIsValid() { // given final String rubiconAlias = "rubicon_alias"; + final ExtRequestBidadjustmentfactors givenAdjustments = ExtRequestBidadjustmentfactors.builder() + .mediatypes(new EnumMap<>(Collections.singletonMap(BidAdjustmentMediaType.xNative, + Collections.singletonMap("rubicon_alias", BigDecimal.valueOf(2.1))))) + .build(); + givenAdjustments.addFactor(rubiconAlias, BigDecimal.valueOf(1.1)); final BidRequest bidRequest = validBidRequestBuilder() .ext(ExtRequest.of( ExtRequestPrebid.builder() .aliases(singletonMap(rubiconAlias, "rubicon")) - .bidadjustmentfactors(singletonMap(rubiconAlias, BigDecimal.valueOf(1.1))) + .bidadjustmentfactors(givenAdjustments) .build())) .build(); @@ -2778,23 +2841,24 @@ public void validateShouldEmptyValidationMessagesWhenBidderIsKnownAliasForCoreBi } @Test - public void validateShouldEmptyValidationMessagesWhenBidderIsKnownBidderConfigAliasAndAdjustmentIsValid() { + public void validateShouldReturnEmptyValidationMessagesWhenBidderIsKnownBidderConfigAliasAndAdjustmentIsValid() { // given final String rubiconAlias = "rubicon_alias"; + final ExtRequestBidadjustmentfactors givenAdjustments = ExtRequestBidadjustmentfactors.builder().build(); + givenAdjustments.addFactor(rubiconAlias, BigDecimal.valueOf(1.1)); final BidRequest bidRequest = validBidRequestBuilder() .ext(ExtRequest.of( ExtRequestPrebid.builder() - .bidadjustmentfactors(singletonMap(rubiconAlias, BigDecimal.valueOf(1.1))) + .aliases(singletonMap(rubiconAlias, "rubicon")) + .bidadjustmentfactors(givenAdjustments) .build())) .build(); - given(bidderCatalog.isAlias(any())).willReturn(true); - // when final ValidationResult result = requestValidator.validate(bidRequest); // then - verify(bidderCatalog).isAlias(rubiconAlias); + verify(bidderCatalog).isValidName(rubiconAlias); assertThat(result.getErrors()).isEmpty(); } diff --git a/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java b/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java index a9a5cb6dbea..c9fe5a0d907 100644 --- a/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java +++ b/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java @@ -28,7 +28,6 @@ import static java.util.Collections.singletonList; import static java.util.function.UnaryOperator.identity; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.verify; @@ -61,20 +60,15 @@ public void setUp() { @Test public void validateShouldFailedIfBidderBidCurrencyIsIncorrect() { - assertThatIllegalArgumentException().isThrownBy(() -> - responseBidValidator.validate( - BidderBid.of( - Bid.builder() - .id("bidId1") - .impid("impId1") - .crid("crid1") - .price(BigDecimal.ONE) - .build(), - null, - "USDD"), - BIDDER_NAME, - givenAuctionContext(), - bidderAliases)); + // when + final ValidationResult result = responseBidValidator.validate( + givenBid(BidType.banner, "invalid", identity()), + BIDDER_NAME, + givenAuctionContext(), + bidderAliases); + + // then + assertThat(result.getErrors()).containsOnly("BidResponse currency \"invalid\" is not valid"); } @Test @@ -84,7 +78,7 @@ public void validateShouldFailIfMissingBid() { BidderBid.of(null, null, "USD"), BIDDER_NAME, givenAuctionContext(), bidderAliases); // then - assertThat(result.getErrors()).containsOnly("Empty bid object submitted."); + assertThat(result.getErrors()).containsOnly("Empty bid object submitted"); } @Test @@ -132,24 +126,27 @@ public void validateShouldFailIfBidHasNegativePrice() { @Test public void validateShouldFailedIfNonDealBidHasZeroPrice() { + // when final ValidationResult result = responseBidValidator.validate( givenBid(builder -> builder.price(BigDecimal.valueOf(0))), BIDDER_NAME, givenAuctionContext(), bidderAliases); - assertThat(result.getErrors()).hasSize(1) - .containsOnly("Non deal bid \"bidId1\" has 0 price"); + // then + assertThat(result.getErrors()).hasSize(1).containsOnly("Non deal bid \"bidId1\" has 0 price"); } @Test public void validateShouldSuccessForDealZeroPriceBid() { + // when final ValidationResult result = responseBidValidator.validate( givenBid(builder -> builder.price(BigDecimal.valueOf(0)).dealid("dealId")), BIDDER_NAME, givenAuctionContext(), bidderAliases); + // then assertThat(result.hasErrors()).isFalse(); } @@ -189,7 +186,10 @@ public void validateShouldFailIfBannerBidWidthIsGreaterThanImposedByImp() { public void validateShouldFailIfBannerBidHeightIsGreaterThanImposedByImp() { // when final ValidationResult result = responseBidValidator.validate( - givenBid(builder -> builder.w(50).h(250)), BIDDER_NAME, givenAuctionContext(), bidderAliases); + givenBid(builder -> builder.w(50).h(250)), + BIDDER_NAME, + givenAuctionContext(), + bidderAliases); // then assertThat(result.getErrors()) @@ -294,35 +294,41 @@ public void validateShouldReturnSuccessIfBidHasInsecureCreativeInInsecureContext @Test public void validateShouldFailedIfVideoBidHasNoNurlAndAdm() { + // when final ValidationResult result = responseBidValidator.validate( givenBid(BidType.video, builder -> builder.adm(null).nurl(null)), BIDDER_NAME, givenAuctionContext(), bidderAliases); - assertThat(result.getErrors()).hasSize(1) + // then + assertThat(result.getErrors()) .containsOnly("Bid \"bidId1\" with video type missing adm and nurl"); } @Test public void validateShouldReturnSuccessfulResultForValidVideoBidWithNurl() { + // when final ValidationResult result = responseBidValidator.validate( givenBid(BidType.video, builder -> builder.adm(null)), BIDDER_NAME, givenAuctionContext(), bidderAliases); + // then assertThat(result.hasErrors()).isFalse(); } @Test public void validateShouldReturnSuccessfulResultForValidVideoBidWithAdm() { + // when final ValidationResult result = responseBidValidator.validate( givenBid(BidType.video, builder -> builder.nurl(null)), BIDDER_NAME, givenAuctionContext(), bidderAliases); + // then assertThat(result.hasErrors()).isFalse(); } @@ -470,6 +476,10 @@ private static BidderBid givenBid(UnaryOperator bidCustomizer) { } private static BidderBid givenBid(BidType type, UnaryOperator bidCustomizer) { + return givenBid(type, "USD", bidCustomizer); + } + + private static BidderBid givenBid(BidType type, String bidCurrency, UnaryOperator bidCustomizer) { final Bid.BidBuilder bidBuilder = Bid.builder() .id("bidId1") .adm("adm1") @@ -481,7 +491,7 @@ private static BidderBid givenBid(BidType type, UnaryOperator bi .adm("https://site.com/creative.jpg") .price(BigDecimal.ONE); - return BidderBid.of(bidCustomizer.apply(bidBuilder).build(), type, "USD"); + return BidderBid.of(bidCustomizer.apply(bidBuilder).build(), type, bidCurrency); } private static AuctionContext givenAuctionContext(BidRequest bidRequest, Account account) { diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index 1e5164187c0..a6a4bba85d5 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -7,6 +7,6 @@ - + \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/amp/test-appnexus-bid-request.json b/src/test/resources/org/prebid/server/it/amp/test-appnexus-bid-request.json index 82252f4438a..cc13f2cd19d 100644 --- a/src/test/resources/org/prebid/server/it/amp/test-appnexus-bid-request.json +++ b/src/test/resources/org/prebid/server/it/amp/test-appnexus-bid-request.json @@ -29,7 +29,8 @@ "domain": "google.com", "page": "https://google.com", "publisher": { - "id": "accountId" + "id": "accountId", + "domain": "google.com" }, "ext": { "amp": 1 @@ -94,7 +95,7 @@ "ow": "980", "oh": "120", "tag_id": "test-amp-stored-request", - "targeting" : "%7B%22gam-key1%22%3A%22val1%22%2C%22gam-key2%22%3A%22val2%22%7D", + "targeting": "%7B%22gam-key1%22%3A%22val1%22%2C%22gam-key2%22%3A%22val2%22%7D", "slot": "overwrite-tagId", "account": "accountId", "timeout": "10000000" diff --git a/src/test/resources/org/prebid/server/it/amp/test-cache-request.json b/src/test/resources/org/prebid/server/it/amp/test-cache-request.json index 7c28d6d1435..95464bcc14a 100644 --- a/src/test/resources/org/prebid/server/it/amp/test-cache-request.json +++ b/src/test/resources/org/prebid/server/it/amp/test-cache-request.json @@ -20,7 +20,8 @@ ] } ] - } + }, + "origbidcpm": 12.09 } } }, @@ -47,9 +48,11 @@ "bidder_id": 2, "bid_ad_type": 0, "ranking_price": 0.0 - } + }, + "origbidcpm": 5.5, + "origbidcur": "USD" } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/cache/update/test-auction-response.json b/src/test/resources/org/prebid/server/it/cache/update/test-auction-response.json index aed8243dab0..61f318451dd 100644 --- a/src/test/resources/org/prebid/server/it/cache/update/test-auction-response.json +++ b/src/test/resources/org/prebid/server/it/cache/update/test-auction-response.json @@ -22,7 +22,8 @@ "hb_size_rubicon": "120x600", "hb_bidder_rubicon": "rubicon" } - } + }, + "origbidcpm": 4.26 } }, { @@ -64,7 +65,8 @@ 1 ] } - } + }, + "origbidcpm": 3 } } ], diff --git a/src/test/resources/org/prebid/server/it/cache/update/test-rubicon-bid-request1.json b/src/test/resources/org/prebid/server/it/cache/update/test-rubicon-bid-request1.json index f9ec67ccca9..a6e90ad23f1 100644 --- a/src/test/resources/org/prebid/server/it/cache/update/test-rubicon-bid-request1.json +++ b/src/test/resources/org/prebid/server/it/cache/update/test-rubicon-bid-request1.json @@ -37,7 +37,7 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { "ext": { diff --git a/src/test/resources/org/prebid/server/it/cache/update/test-rubicon-bid-request2.json b/src/test/resources/org/prebid/server/it/cache/update/test-rubicon-bid-request2.json index 7f48b548c57..2766113a429 100644 --- a/src/test/resources/org/prebid/server/it/cache/update/test-rubicon-bid-request2.json +++ b/src/test/resources/org/prebid/server/it/cache/update/test-rubicon-bid-request2.json @@ -38,7 +38,7 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { "ext": { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/acuityads/test-acuityads-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/acuityads/test-acuityads-bid-request.json index 6dd80f90a72..43a4cbd40a9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/acuityads/test-acuityads-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/acuityads/test-acuityads-bid-request.json @@ -11,10 +11,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/acuityads/test-auction-acuityads-response.json b/src/test/resources/org/prebid/server/it/openrtb2/acuityads/test-auction-acuityads-response.json index abad9534372..0b93547a87d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/acuityads/test-auction-acuityads-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/acuityads/test-auction-acuityads-response.json @@ -31,7 +31,8 @@ "cacheId": "3c0769d8-0dd9-465c-8bf3-f570605ba698" } } - } + }, + "origbidcpm": 0.01 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/acuityads/test-cache-acuityads-request.json b/src/test/resources/org/prebid/server/it/openrtb2/acuityads/test-cache-acuityads-request.json index ca8e3ab2f6a..383f37b4df9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/acuityads/test-cache-acuityads-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/acuityads/test-cache-acuityads-request.json @@ -8,7 +8,10 @@ "price": 0.01, "id": "testid", "impid": "testimpid", - "cid": "8048" + "cid": "8048", + "ext": { + "origbidcpm": 0.01 + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adform/test-auction-adform-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adform/test-auction-adform-response.json index 14012439af8..7576195d232 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adform/test-auction-adform-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adform/test-auction-adform-response.json @@ -34,7 +34,9 @@ "cacheId": "ca2a4dd3-f974-4eff-be5c-986bf4e083ce" } } - } + }, + "origbidcpm": 0.5, + "origbidcur": "USD" } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adform/test-cache-adform-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adform/test-cache-adform-request.json index bc8cdee5269..26a321bbb8e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adform/test-cache-adform-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adform/test-cache-adform-request.json @@ -9,7 +9,11 @@ "adm": "banner", "crid": "crid12", "w": 400, - "h": 300 + "h": 300, + "ext": { + "origbidcpm": 0.5, + "origbidcur": "USD" + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adgeneration/test-auction-adgeneration-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adgeneration/test-auction-adgeneration-response.json index 587664f62ca..d90d275e956 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adgeneration/test-auction-adgeneration-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adgeneration/test-auction-adgeneration-response.json @@ -37,7 +37,9 @@ "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 46.6, + "origbidcur": "USD" } } ], @@ -56,4 +58,4 @@ "auctiontimestamp": 1000 } } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adgeneration/test-cache-adgeneration-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adgeneration/test-cache-adgeneration-request.json index 63fb9c70fc4..4bb4c33440d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adgeneration/test-cache-adgeneration-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adgeneration/test-cache-adgeneration-request.json @@ -10,8 +10,12 @@ "crid": "Dummy_supership.jp", "dealid": "test-deal-id", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 46.6, + "origbidcur": "USD" + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adhese/test-auction-adhese-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adhese/test-auction-adhese-response.json index 20b4699efc1..d624b162f8f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adhese/test-auction-adhese-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adhese/test-auction-adhese-response.json @@ -40,7 +40,9 @@ "cacheId": "a5d3a873-d06e-4f2f-8556-120e05d62b28" } } - } + }, + "origbidcpm": 1.00, + "origbidcur": "USD" } } ], @@ -59,4 +61,4 @@ }, "tmaxrequest": 5000 } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adhese/test-cache-adhese-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adhese/test-cache-adhese-request.json index d2827ac7466..348ad5694e8 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adhese/test-cache-adhese-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adhese/test-cache-adhese-request.json @@ -12,9 +12,11 @@ "w": 728, "h": 90, "ext": { - "adType": "leaderboard" + "adType": "leaderboard", + "origbidcpm": 1, + "origbidcur": "USD" } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adkernel/test-adkernel-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adkernel/test-adkernel-bid-request.json index 13eac22e83d..534ed405cc7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adkernel/test-adkernel-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adkernel/test-adkernel-bid-request.json @@ -14,7 +14,7 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adkernel/test-auction-adkernel-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adkernel/test-auction-adkernel-response.json index ef8116a9727..48a11b705a1 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adkernel/test-auction-adkernel-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adkernel/test-auction-adkernel-response.json @@ -35,7 +35,8 @@ "cacheId": "71615e3d-8a18-4099-a807-3952199b532a" } } - } + }, + "origbidcpm": 2.25 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adkernel/test-cache-adkernel-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adkernel/test-cache-adkernel-request.json index 24e8a750053..46e0f16459f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adkernel/test-cache-adkernel-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adkernel/test-cache-adkernel-request.json @@ -12,7 +12,10 @@ "tag-example.com" ], "cid": "1001", - "crid": "2002" + "crid": "2002", + "ext": { + "origbidcpm": 2.25 + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adkerneladn/test-auction-adkerneladn-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adkerneladn/test-auction-adkerneladn-response.json index 19e0218fcf8..f97e4ebd45a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adkerneladn/test-auction-adkerneladn-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adkerneladn/test-auction-adkerneladn-response.json @@ -45,7 +45,8 @@ "cacheId": "a3558327-7696-4606-a5e9-43413bd7faea" } } - } + }, + "origbidcpm": 2.25 } }, { @@ -87,7 +88,8 @@ "cacheId": "aedec380-879a-4029-8e7a-5a51676c887c" } } - } + }, + "origbidcpm": 0.5 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adkerneladn/test-cache-adkerneladn-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adkerneladn/test-cache-adkerneladn-request.json index 5c65a9406db..7328b9759fd 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adkerneladn/test-cache-adkerneladn-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adkerneladn/test-cache-adkerneladn-request.json @@ -15,7 +15,10 @@ "crid": "crid022", "cat": [ "IAB2" - ] + ], + "ext": { + "origbidcpm": 2.25 + } } }, { @@ -35,7 +38,10 @@ "IAB2" ], "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 0.5 + } } }, { @@ -44,4 +50,4 @@ "expiry": 120 } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adman/test-adman-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/adman/test-adman-bid-request-1.json index fffdc0d462a..54bc6612320 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adman/test-adman-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adman/test-adman-bid-request-1.json @@ -20,10 +20,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adman/test-adman-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/adman/test-adman-bid-request-2.json index 46343b73e4a..e8cca50ef51 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adman/test-adman-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adman/test-adman-bid-request-2.json @@ -19,10 +19,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adman/test-auction-adman-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adman/test-auction-adman-response.json index 9aced8de0dc..2562e18083c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adman/test-auction-adman-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adman/test-auction-adman-response.json @@ -34,7 +34,8 @@ "cacheId": "9092799c-93b0-4e11-a232-2c0151d5d275" } } - } + }, + "origbidcpm": 1.25 } }, { @@ -83,7 +84,8 @@ "cacheId": "99dc3357-34ac-4819-9f68-0820039a542f" } } - } + }, + "origbidcpm": 2.25 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adman/test-cache-adman-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adman/test-cache-adman-request.json index 58471d39985..c393baa5ecf 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adman/test-cache-adman-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adman/test-cache-adman-request.json @@ -9,7 +9,10 @@ "adm": "adm001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 1.25 + } } }, { @@ -29,7 +32,10 @@ "IAB2" ], "w": 640, - "h": 480 + "h": 480, + "ext": { + "origbidcpm": 2.25 + } } }, { @@ -38,4 +44,4 @@ "expiry": 120 } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/admixer/test-admixer-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/admixer/test-admixer-bid-request.json index d913ab94f75..59ade909a5b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/admixer/test-admixer-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/admixer/test-admixer-bid-request.json @@ -47,7 +47,8 @@ "domain": "example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/admixer/test-auction-admixer-response.json b/src/test/resources/org/prebid/server/it/openrtb2/admixer/test-auction-admixer-response.json index 8e404dd82c2..a5daef3a66a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/admixer/test-auction-admixer-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/admixer/test-auction-admixer-response.json @@ -31,7 +31,8 @@ "url": "{{ cache.resource_url }}f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 0.01 }, "id": "1", "impid": "impId001", @@ -53,4 +54,4 @@ }, "tmaxrequest": 3000 } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/admixer/test-cache-admixer-request.json b/src/test/resources/org/prebid/server/it/openrtb2/admixer/test-cache-admixer-request.json index c6692479e4a..cdadbec00c4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/admixer/test-cache-admixer-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/admixer/test-cache-admixer-request.json @@ -10,9 +10,10 @@ "cid": "test_cid", "crid": "test_banner_crid", "ext": { - "format": "BANNER" + "format": "BANNER", + "origbidcpm": 0.01 } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adocean/test-auction-adocean-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adocean/test-auction-adocean-response.json index c8de82b117d..1f0dcb454d4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adocean/test-auction-adocean-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adocean/test-auction-adocean-response.json @@ -34,7 +34,9 @@ "cacheId": "ca2a4dd3-f974-4eff-be5c-986bf4e083ce" } } - } + }, + "origbidcpm": 10, + "origbidcur": "EUR" } } ], @@ -56,7 +58,7 @@ "cache": [ { "uri": "{{ cache.endpoint }}", - "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"adoceanmyaozpniqismex\",\"impid\":\"impId12\",\"price\":10,\"adm\":\" \",\"crid\":\"0af345b42983cc4bc0\",\"w\":300,\"h\":250}}]}", + "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"adoceanmyaozpniqismex\",\"impid\":\"impId12\",\"price\":10,\"adm\":\" \",\"crid\":\"0af345b42983cc4bc0\",\"w\":300,\"h\":250,\"ext\":{\"origbidcpm\":10,\"origbidcur\":\"EUR\"}}}]}", "responsebody": "{\"responses\":[{\"uuid\":\"ca2a4dd3-f974-4eff-be5c-986bf4e083ce\"}]}", "status": 200 } @@ -89,10 +91,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adocean/test-cache-adocean-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adocean/test-cache-adocean-request.json index 950f2ead307..ff29e737082 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adocean/test-cache-adocean-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adocean/test-cache-adocean-request.json @@ -9,8 +9,12 @@ "adm": " ", "crid": "0af345b42983cc4bc0", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 10, + "origbidcur": "EUR" + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adoppler/test-adoppler-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/adoppler/test-adoppler-bid-request-1.json index 516c7b029d8..7a8288b83c0 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adoppler/test-adoppler-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adoppler/test-adoppler-bid-request-1.json @@ -16,10 +16,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adoppler/test-auction-adoppler-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adoppler/test-auction-adoppler-response.json index fe66263a7ee..994436d63d4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adoppler/test-auction-adoppler-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adoppler/test-auction-adoppler-response.json @@ -37,6 +37,7 @@ } } }, + "origbidcpm": 3.33, "bidder": { "ads": { "video": { @@ -62,4 +63,4 @@ }, "tmaxrequest": 3000 } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adoppler/test-cache-adoppler-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adoppler/test-cache-adoppler-request.json index 0acc8877698..84882986b0a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adoppler/test-cache-adoppler-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adoppler/test-cache-adoppler-request.json @@ -19,9 +19,10 @@ "video": { "duration": 121 } - } + }, + "origbidcpm": 3.33 } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adot/test-adot-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adot/test-adot-bid-request.json index 32fea525079..7aff609c78f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adot/test-adot-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adot/test-adot-bid-request.json @@ -17,20 +17,21 @@ } ], "device": { - "ua" : "userAgent", + "ua": "userAgent", "pxratio": 4.2, - "ip" : "193.168.244.1", + "ip": "193.168.244.1", "dnt": 2, "language": "en", "ifa": "ifaId" }, "site": { - "domain" : "example.com", - "page" : "http://www.example.com", + "domain": "www.example.com", + "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, - "ext" : { + "ext": { "amp": 0 } }, @@ -65,8 +66,8 @@ } }, "auctiontimestamp": 1000, - "channel" : { - "name" : "web" + "channel": { + "name": "web" } } }, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adot/test-auction-adot-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adot/test-auction-adot-response.json index 592b15c557f..7a5b68f431e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adot/test-auction-adot-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adot/test-auction-adot-response.json @@ -35,6 +35,7 @@ } } }, + "origbidcpm": 1.16346, "bidder": { "adot": { "media_type": "banner" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adot/test-cache-adot-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adot/test-cache-adot-request.json index 108b95bc4ca..b819f42ff94 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adot/test-cache-adot-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adot/test-cache-adot-request.json @@ -13,7 +13,8 @@ "ext": { "adot": { "media_type": "banner" - } + }, + "origbidcpm": 1.16346 } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adpone/test-adpone-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adpone/test-adpone-bid-request.json index 0bd175eb819..ddc709af3ca 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adpone/test-adpone-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adpone/test-adpone-bid-request.json @@ -19,10 +19,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adpone/test-auction-adpone-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adpone/test-auction-adpone-response.json index d364f881b12..9be20ec68ab 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adpone/test-auction-adpone-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adpone/test-auction-adpone-response.json @@ -36,7 +36,8 @@ "cacheId": "01005d2c-555d-41c6-995d-335663819de0" } } - } + }, + "origbidcpm": 6.66 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adpone/test-cache-adpone-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adpone/test-cache-adpone-request.json index 8b7ec8bb518..81b4d940e3d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adpone/test-cache-adpone-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adpone/test-cache-adpone-request.json @@ -11,8 +11,11 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 6.66 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-adprime-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-adprime-bid-request-1.json index 7a63bef2b5e..a02def7d735 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-adprime-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-adprime-bid-request-1.json @@ -20,10 +20,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 @@ -76,8 +77,8 @@ } }, "auctiontimestamp": 1000, - "channel" : { - "name" : "web" + "channel": { + "name": "web" } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-adprime-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-adprime-bid-request-2.json index 0bf48da7981..e1dffccdfd6 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-adprime-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-adprime-bid-request-2.json @@ -19,10 +19,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 @@ -75,8 +76,8 @@ } }, "auctiontimestamp": 1000, - "channel" : { - "name" : "web" + "channel": { + "name": "web" } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-auction-adprime-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-auction-adprime-response.json index 61b973e5af7..5f8730c2da0 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-auction-adprime-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-auction-adprime-response.json @@ -34,7 +34,8 @@ "cacheId": "9092799c-93b0-4e11-a232-2c0151d5d275" } } - } + }, + "origbidcpm": 1.25 } }, { @@ -83,7 +84,8 @@ "cacheId": "99dc3357-34ac-4819-9f68-0820039a542f" } } - } + }, + "origbidcpm": 2.25 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-cache-adprime-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-cache-adprime-request.json index 58471d39985..c393baa5ecf 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-cache-adprime-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adprime/test-cache-adprime-request.json @@ -9,7 +9,10 @@ "adm": "adm001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 1.25 + } } }, { @@ -29,7 +32,10 @@ "IAB2" ], "w": 640, - "h": 480 + "h": 480, + "ext": { + "origbidcpm": 2.25 + } } }, { @@ -38,4 +44,4 @@ "expiry": 120 } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adtarget/test-adtarget-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/adtarget/test-adtarget-bid-request-1.json index dd5c18952c8..5710aebfbd8 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adtarget/test-adtarget-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adtarget/test-adtarget-bid-request-1.json @@ -23,10 +23,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adtarget/test-auction-adtarget-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adtarget/test-auction-adtarget-response.json index c6f9798b729..9f8315b4af2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adtarget/test-auction-adtarget-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adtarget/test-auction-adtarget-response.json @@ -34,7 +34,8 @@ "cacheId": "f5c5f34c-ad41-4894-b42b-dd5c86978a4a" } } - } + }, + "origbidcpm": 8.43 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adtarget/test-cache-adtarget-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adtarget/test-cache-adtarget-request.json index 25d582fd85c..1435c8dccf3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adtarget/test-cache-adtarget-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adtarget/test-cache-adtarget-request.json @@ -9,8 +9,11 @@ "adm": "adm14", "crid": "crid14", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 8.43 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adtelligent/test-adtelligent-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/adtelligent/test-adtelligent-bid-request-1.json index c5624a8178b..a2fdbf78672 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adtelligent/test-adtelligent-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adtelligent/test-adtelligent-bid-request-1.json @@ -23,10 +23,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adtelligent/test-auction-adtelligent-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adtelligent/test-auction-adtelligent-response.json index 4eeef9fce47..b35f2382588 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adtelligent/test-auction-adtelligent-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adtelligent/test-auction-adtelligent-response.json @@ -34,7 +34,8 @@ "cacheId": "f5c5f34c-ad41-4894-b42b-dd5c86978a4a" } } - } + }, + "origbidcpm": 8.43 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adtelligent/test-cache-adtelligent-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adtelligent/test-cache-adtelligent-request.json index 25d582fd85c..1435c8dccf3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/adtelligent/test-cache-adtelligent-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/adtelligent/test-cache-adtelligent-request.json @@ -9,8 +9,11 @@ "adm": "adm14", "crid": "crid14", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 8.43 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/advangelists/test-auction-advangelists-response.json b/src/test/resources/org/prebid/server/it/openrtb2/advangelists/test-auction-advangelists-response.json index 6bdcf3da2fa..ce7b7a00b09 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/advangelists/test-auction-advangelists-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/advangelists/test-auction-advangelists-response.json @@ -31,7 +31,8 @@ "cacheId": "3c0769d8-0dd9-465c-8bf3-f570605ba698" } } - } + }, + "origbidcpm": 0.01 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/advangelists/test-cache-advangelists-request.json b/src/test/resources/org/prebid/server/it/openrtb2/advangelists/test-cache-advangelists-request.json index ca8e3ab2f6a..383f37b4df9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/advangelists/test-cache-advangelists-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/advangelists/test-cache-advangelists-request.json @@ -8,7 +8,10 @@ "price": 0.01, "id": "testid", "impid": "testimpid", - "cid": "8048" + "cid": "8048", + "ext": { + "origbidcpm": 0.01 + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-adyoulike-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-adyoulike-bid-request.json new file mode 100644 index 00000000000..191555cc4fe --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-adyoulike-bid-request.json @@ -0,0 +1,68 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId001", + "banner": { + "w": 300, + "h": 250 + }, + "tagid": "somePlacement", + "ext": { + "bidder": { + "placement": "somePlacement" + } + } + } + ], + "site": { + "page": "awesomePage", + "publisher": { + "id": "publisherId" + }, + "ext": { + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "ip": "193.168.244.1" + }, + "user": { + "buyeruid": "ADL-UID" + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "regs": { + "ext": { + "gdpr": 0 + } + }, + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + }, + "includewinners": true, + "includebidderkeys": true + }, + "cache": { + "bids": {} + }, + "auctiontimestamp": 1000, + "channel": { + "name": "web" + } + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-adyoulike-bid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-adyoulike-bid-response.json new file mode 100644 index 00000000000..95a93284e04 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-adyoulike-bid-response.json @@ -0,0 +1,20 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "id": "bid001", + "impid": "impId001", + "price": 3.33, + "adid": "adid001", + "crid": "crid001", + "cid": "cid001", + "adm": "adm001", + "h": 250, + "w": 300 + } + ] + } + ] +} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-auction-adyoulike-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-auction-adyoulike-request.json new file mode 100644 index 00000000000..053ac3b015b --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-auction-adyoulike-request.json @@ -0,0 +1,52 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId001", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "adyoulike": { + "placement": "somePlacement" + } + } + } + ], + "site": { + "page": "awesomePage", + "publisher": { + "id": "publisherId" + } + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + } + }, + "cache": { + "bids": {} + }, + "auctiontimestamp": 1000 + } + }, + "regs": { + "ext": { + "gdpr": 0 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-auction-adyoulike-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-auction-adyoulike-response.json new file mode 100644 index 00000000000..af0c434d62a --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-auction-adyoulike-response.json @@ -0,0 +1,59 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "id": "bid001", + "impid": "impId001", + "price": 3.33, + "adm": "adm001", + "adid": "adid001", + "cid": "cid001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "banner", + "targeting": { + "hb_pb": "3.30", + "hb_size_adyoulike": "300x250", + "hb_bidder_adyoulike": "adyoulike", + "hb_cache_path": "{{ cache.path }}", + "hb_size": "300x250", + "hb_cache_host_adyoulike": "{{ cache.host }}", + "hb_cache_path_adyoulike": "{{ cache.path }}", + "hb_cache_id_adyoulike": "f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "hb_bidder": "adyoulike", + "hb_cache_id": "f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "hb_pb_adyoulike": "3.30", + "hb_cache_host": "{{ cache.host }}" + }, + "cache": { + "bids": { + "url": "{{ cache.resource_url }}f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" + } + } + }, + "origbidcpm": 3.33 + } + } + ], + "seat": "adyoulike", + "group": 0 + } + ], + "cur": "USD", + "ext": { + "responsetimemillis": { + "adyoulike": "{{ adyoulike.response_time_ms }}", + "cache": "{{ cache.response_time_ms }}" + }, + "prebid": { + "auctiontimestamp": 1000 + }, + "tmaxrequest": 5000 + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-cache-adyoulike-request.json b/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-cache-adyoulike-request.json new file mode 100644 index 00000000000..424a76e0ac4 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-cache-adyoulike-request.json @@ -0,0 +1,21 @@ +{ + "puts": [ + { + "type": "json", + "value": { + "id": "bid001", + "impid": "impId001", + "price": 3.33, + "adm": "adm001", + "adid": "adid001", + "cid": "cid001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "origbidcpm": 3.33 + } + } + } + ] +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-cache-adyoulike-response.json b/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-cache-adyoulike-response.json new file mode 100644 index 00000000000..93d0b8de2cd --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/adyoulike/test-cache-adyoulike-response.json @@ -0,0 +1,7 @@ +{ + "responses": [ + { + "uuid": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/openrtb2/aja/test-aja-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/aja/test-aja-bid-request-1.json index a8d33c18829..f27ec0d725a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/aja/test-aja-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/aja/test-aja-bid-request-1.json @@ -15,10 +15,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/aja/test-aja-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/aja/test-aja-bid-request-2.json index 7dd8fe7d4ef..cd7cdf14ede 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/aja/test-aja-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/aja/test-aja-bid-request-2.json @@ -18,10 +18,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/aja/test-auction-aja-response.json b/src/test/resources/org/prebid/server/it/openrtb2/aja/test-auction-aja-response.json index f3927626bfe..41b4e26b7a2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/aja/test-auction-aja-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/aja/test-auction-aja-response.json @@ -11,7 +11,7 @@ "psacentral.org" ], "nurl": "https://example.com/nurl", - "adm":"prebid.org wrapper", + "adm": "prebid.org wrapper", "cid": "cid002", "crid": "crid002", "w": 300, @@ -46,7 +46,8 @@ "cacheId": "44a52b06-b29f-4819-a05f-db36b9e7b8fc" } } - } + }, + "origbidcpm": 9.99 } }, { @@ -82,7 +83,8 @@ "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 3.33 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/aja/test-cache-aja-request.json b/src/test/resources/org/prebid/server/it/openrtb2/aja/test-cache-aja-request.json index 127a65adcc2..fd30a5cc539 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/aja/test-cache-aja-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/aja/test-cache-aja-request.json @@ -11,7 +11,10 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 3.33 + } } }, { @@ -24,10 +27,14 @@ "psacentral.org" ], "nurl": "https://example.com/nurl", + "adm": "prebid.org wrapper", "cid": "cid002", "crid": "crid002", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 9.99 + } } }, { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/amx/test-amx-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/amx/test-amx-bid-request.json index 3c064c54c7c..89510d11947 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/amx/test-amx-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/amx/test-amx-bid-request.json @@ -11,19 +11,20 @@ "h": 480 }, "tagid": "testAdUnitId", - "ext" : { - "bidder" : { - "tagId" : "testTagId", - "adUnitId" : "testAdUnitId" + "ext": { + "bidder": { + "tagId": "testTagId", + "adUnitId": "testAdUnitId" } } } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "testTagId" + "id": "testTagId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/amx/test-amx-bid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/amx/test-amx-bid-response.json index 3f362e2f62d..cf06d5fa781 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/amx/test-amx-bid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/amx/test-amx-bid-response.json @@ -13,7 +13,9 @@ "nurl": "https://example.com/nurl", "cid": "8048", "ext": { - "himp": ["https://example.com/imp-tracker/pixel.gif?param=1¶m2=2"], + "himp": [ + "https://example.com/imp-tracker/pixel.gif?param=1¶m2=2" + ], "startdelay": 0 } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/amx/test-auction-amx-request.json b/src/test/resources/org/prebid/server/it/openrtb2/amx/test-auction-amx-request.json index f38e58bc429..c8dd76e9c34 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/amx/test-auction-amx-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/amx/test-auction-amx-request.json @@ -16,7 +16,7 @@ "adUnitId": "testAdUnitId" } }, - "tagid" : "testAdUnitId" + "tagid": "testAdUnitId" } ], "device": { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/amx/test-auction-amx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/amx/test-auction-amx-response.json index 6945a023670..ffd21bb3c2e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/amx/test-auction-amx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/amx/test-auction-amx-response.json @@ -34,6 +34,7 @@ } } }, + "origbidcpm": 0.01, "bidder": { "himp": [ "https://example.com/imp-tracker/pixel.gif?param=1¶m2=2" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/amx/test-cache-amx-request.json b/src/test/resources/org/prebid/server/it/openrtb2/amx/test-cache-amx-request.json index 5764e471148..edf786668eb 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/amx/test-cache-amx-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/amx/test-cache-amx-request.json @@ -5,15 +5,18 @@ "value": { "id": "testid", "price": 0.01, - "nurl" : "", + "nurl": "", "adm": "00:00:15", "adid": "2068416", "cid": "8048", "crid": "24080", "impid": "testimpid", "ext": { - "himp": ["https://example.com/imp-tracker/pixel.gif?param=1¶m2=2"], - "startdelay": 0 + "himp": [ + "https://example.com/imp-tracker/pixel.gif?param=1¶m2=2" + ], + "startdelay": 0, + "origbidcpm": 0.01 } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/applogy/test-applogy-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/applogy/test-applogy-bid-request-1.json index 8b3218be6fc..ff5649aed93 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/applogy/test-applogy-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/applogy/test-applogy-bid-request-1.json @@ -21,10 +21,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/applogy/test-applogy-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/applogy/test-applogy-bid-request-2.json index 4e5fc9dfbc8..baad9262d94 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/applogy/test-applogy-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/applogy/test-applogy-bid-request-2.json @@ -22,10 +22,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/applogy/test-auction-applogy-response.json b/src/test/resources/org/prebid/server/it/openrtb2/applogy/test-auction-applogy-response.json index f5d2424bf08..761a1500a26 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/applogy/test-auction-applogy-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/applogy/test-auction-applogy-response.json @@ -36,7 +36,8 @@ "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 3.33 } }, { @@ -79,7 +80,8 @@ "cacheId": "44a52b06-b29f-4819-a05f-db36b9e7b8fc" } } - } + }, + "origbidcpm": 5.55 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/applogy/test-cache-applogy-request.json b/src/test/resources/org/prebid/server/it/openrtb2/applogy/test-cache-applogy-request.json index 883ffec2c36..53a307b9388 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/applogy/test-cache-applogy-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/applogy/test-cache-applogy-request.json @@ -11,7 +11,10 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 3.33 + } } }, { @@ -25,7 +28,10 @@ "cid": "cid002", "crid": "crid002", "w": 1024, - "h": 576 + "h": 576, + "ext": { + "origbidcpm": 5.55 + } } }, { @@ -34,4 +40,4 @@ "expiry": 120 } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-auction-avocet-response.json b/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-auction-avocet-response.json index 5b0c273da41..c88a04b3b73 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-auction-avocet-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-auction-avocet-response.json @@ -52,7 +52,8 @@ "cacheId": "ce120de7-25d0-4384-8983-8a9462149c8c" } } - } + }, + "origbidcpm": 0.5 } } ], @@ -67,7 +68,7 @@ "cache": [ { "uri": "{{ cache.endpoint }}", - "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"7706636740145184841\",\"impid\":\"test-imp-banner-id\",\"price\":0.5,\"adm\":\"some-test-ad\",\"adid\":\"29681110\",\"adomain\":[\"advertsite.com\"],\"cid\":\"772\",\"crid\":\"29681110\",\"api\":1,\"w\":1024,\"h\":576,\"ext\":{\"avocet\":{\"duration\":30}}}},{\"type\":\"xml\",\"value\":\"some-test-ad\",\"expiry\":120}]}", + "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"7706636740145184841\",\"impid\":\"test-imp-banner-id\",\"price\":0.5,\"adm\":\"some-test-ad\",\"adid\":\"29681110\",\"adomain\":[\"advertsite.com\"],\"cid\":\"772\",\"crid\":\"29681110\",\"api\":1,\"w\":1024,\"h\":576,\"ext\":{\"avocet\":{\"duration\":30},\"origbidcpm\":0.5}}},{\"type\":\"xml\",\"value\":\"some-test-ad\",\"expiry\":120}]}", "responsebody": "{\"responses\":[{\"uuid\":\"78f9a6dd-d08c-4b80-ba0f-0159b9add9bf\"},{\"uuid\":\"ce120de7-25d0-4384-8983-8a9462149c8c\"}]}", "status": 200 } @@ -75,7 +76,7 @@ "avocet": [ { "uri": "{{ avocet.exchange_uri }}", - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"test-imp-banner-id\",\"banner\":{\"format\":[{\"w\":300,\"h\":250}],\"w\":500,\"h\":400},\"ext\":{\"bidder\":{\"placement\":\"5ea9601ac865f911007f1b6a\"}}}],\"site\":{\"domain\":\"example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"id\":\"publisherId\"},\"ext\":{\"amp\":0}},\"device\":{\"ua\":\"userAgent\",\"dnt\":2,\"ip\":\"193.168.244.1\",\"pxratio\":4.2,\"language\":\"en\",\"ifa\":\"ifaId\"},\"user\":{\"buyeruid\":\"AV-UID\",\"ext\":{\"consent\":\"consentValue\"}},\"at\":1,\"tmax\":5000,\"cur\":[\"USD\"],\"source\":{\"fd\":1,\"tid\":\"tid\"},\"regs\":{\"ext\":{\"gdpr\":0}},\"ext\":{\"prebid\":{\"debug\":1,\"targeting\":{\"pricegranularity\":{\"precision\":2,\"ranges\":[{\"max\":20,\"increment\":0.1}]},\"includewinners\":true,\"includebidderkeys\":true},\"cache\":{\"bids\":{},\"vastxml\":{\"ttlseconds\":120}},\"auctiontimestamp\":1000,\"channel\":{\"name\":\"web\"}}}}", + "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"test-imp-banner-id\",\"banner\":{\"format\":[{\"w\":300,\"h\":250}],\"w\":500,\"h\":400},\"ext\":{\"bidder\":{\"placement\":\"5ea9601ac865f911007f1b6a\"}}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"id\":\"publisherId\",\"domain\":\"example.com\"},\"ext\":{\"amp\":0}},\"device\":{\"ua\":\"userAgent\",\"dnt\":2,\"ip\":\"193.168.244.1\",\"pxratio\":4.2,\"language\":\"en\",\"ifa\":\"ifaId\"},\"user\":{\"buyeruid\":\"AV-UID\",\"ext\":{\"consent\":\"consentValue\"}},\"at\":1,\"tmax\":5000,\"cur\":[\"USD\"],\"source\":{\"fd\":1,\"tid\":\"tid\"},\"regs\":{\"ext\":{\"gdpr\":0}},\"ext\":{\"prebid\":{\"debug\":1,\"targeting\":{\"pricegranularity\":{\"precision\":2,\"ranges\":[{\"max\":20,\"increment\":0.1}]},\"includewinners\":true,\"includebidderkeys\":true},\"cache\":{\"bids\":{},\"vastxml\":{\"ttlseconds\":120}},\"auctiontimestamp\":1000,\"channel\":{\"name\":\"web\"}}}}", "responsebody": "{\"id\":\"tid\",\"seatbid\":[{\"bid\":[{\"id\":\"7706636740145184841\",\"impid\":\"test-imp-banner-id\",\"price\":0.5,\"adid\":\"29681110\",\"adm\":\"some-test-ad\",\"adomain\":[\"advertsite.com\"],\"cid\":\"772\",\"crid\":\"29681110\",\"h\":576,\"w\":1024,\"api\":1,\"ext\":{\"avocet\":{\"duration\":30}}}]}]}", "status": 200 } @@ -108,10 +109,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-avocet-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-avocet-bid-request-1.json index db3cb3b5396..46af852c942 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-avocet-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-avocet-bid-request-1.json @@ -21,10 +21,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-avocet-bid-response-1.json b/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-avocet-bid-response-1.json index 95aea20e958..6ba42a35e35 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-avocet-bid-response-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-avocet-bid-response-1.json @@ -9,7 +9,9 @@ "price": 0.500000, "adid": "29681110", "adm": "some-test-ad", - "adomain": ["advertsite.com"], + "adomain": [ + "advertsite.com" + ], "cid": "772", "crid": "29681110", "h": 576, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-cache-avocet-request.json b/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-cache-avocet-request.json index 859a825806c..5d81aa72f02 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-cache-avocet-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/avocet/test-cache-avocet-request.json @@ -19,7 +19,8 @@ "ext": { "avocet": { "duration": 30 - } + }, + "origbidcpm": 0.500000 } } }, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-auction-beachfront-response.json b/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-auction-beachfront-response.json index b98f55e0f01..f8d297a7434 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-auction-beachfront-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-auction-beachfront-response.json @@ -34,7 +34,9 @@ "cacheId": "9c33f779-d352-4d85-8ad2-8a245dc276ce" } } - } + }, + "origbidcpm": 2.942807912826538, + "origbidcur": "USD" } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-beachfront-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-beachfront-bid-request-1.json index 3e10aa922ed..ee17ee9988c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-beachfront-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-beachfront-bid-request-1.json @@ -19,10 +19,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-beachfront-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-beachfront-bid-request-2.json index c412f204683..9b1bfbfcad0 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-beachfront-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-beachfront-bid-request-2.json @@ -18,10 +18,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-beachfront-bid-request-3.json b/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-beachfront-bid-request-3.json index 5e092cb18d8..be7b1446d63 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-beachfront-bid-request-3.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-beachfront-bid-request-3.json @@ -12,7 +12,7 @@ ] } ], - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "secure": 0, "isMobile": 0, @@ -22,7 +22,8 @@ "buyeruid": "BF-UID" }, "adapterName": "BF_PREBID_S2S", - "adapterVersion": "0.9.1", + "adapterVersion": "0.9.2", "ip": "193.168.244.1", - "requestId": "tid" -} \ No newline at end of file + "requestId": "tid", + "real204": true +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-cache-beachfront-request.json b/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-cache-beachfront-request.json index 66f5085cd81..a02c60a8931 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-cache-beachfront-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/beachfront/test-cache-beachfront-request.json @@ -9,8 +9,12 @@ "adm": "
", "crid": "crid_3", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 2.942807912826538, + "origbidcur": "USD" + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-auction-beintoo-request.json b/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-auction-beintoo-request.json index f22fe111f8d..77bf6494d39 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-auction-beintoo-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-auction-beintoo-request.json @@ -50,7 +50,6 @@ }, "ext": { "prebid": { - "debug": 1, "targeting": { "pricegranularity": { "precision": 2, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-auction-beintoo-response.json b/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-auction-beintoo-response.json index 6487685eeaf..be20b61a166 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-auction-beintoo-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-auction-beintoo-response.json @@ -35,7 +35,9 @@ "cacheId": "9a5d11a7-de5a-4ce4-8e89-d37f18a10045" } } - } + }, + "origbidcpm": 2.942808, + "origbidcur": "USD" } } ], @@ -45,116 +47,6 @@ ], "cur": "USD", "ext": { - "debug": { - "httpcalls": { - "beintoo": [ - { - "uri": "{{ beintoo.exchange_uri }}", - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"uuid\",\"banner\":{\"format\":[],\"w\":300,\"h\":250},\"tagid\":\"25251\",\"secure\":0}],\"site\":{\"domain\":\"example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"id\":\"publisherId\"},\"ext\":{\"amp\":0}},\"device\":{\"ua\":\"Android Chrome/60\",\"dnt\":2,\"ip\":\"193.168.244.1\",\"pxratio\":4.2,\"language\":\"en\",\"ifa\":\"ifaId\"},\"user\":{\"buyeruid\":\"BT-UID\",\"ext\":{\"consent\":\"consentValue\"}},\"at\":1,\"tmax\":5000,\"cur\":[\"USD\"],\"source\":{\"fd\":1,\"tid\":\"tid\"},\"regs\":{\"ext\":{\"gdpr\":0}},\"ext\":{\"prebid\":{\"debug\":1,\"targeting\":{\"pricegranularity\":{\"precision\":2,\"ranges\":[{\"max\":20,\"increment\":0.1}]},\"includewinners\":true,\"includebidderkeys\":true},\"cache\":{\"bids\":{},\"vastxml\":{\"ttlseconds\":120}},\"auctiontimestamp\":1000,\"channel\":{\"name\":\"web\"}}}}", - "responsebody": "{\"id\":\"some_test_auction\",\"seatbid\":[{\"seat\":\"12356\",\"bid\":[{\"id\":\"uuid\",\"adm\":\"
\",\"impid\":\"uuid\",\"ttl\":300,\"crid\":\"94395500\",\"w\":300,\"price\":2.942808,\"adid\":\"94395500\",\"h\":250}]}],\"cur\":\"USD\"}", - "status": 200 - } - ], - "cache": [ - { - "uri": "{{ cache.endpoint }}", - "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"uuid\",\"impid\":\"uuid\",\"price\":2.942808,\"adm\":\"
\",\"adid\":\"94395500\",\"crid\":\"94395500\",\"w\":300,\"h\":250}}]}", - "responsebody": "{\"responses\":[{\"uuid\":\"9a5d11a7-de5a-4ce4-8e89-d37f18a10045\"}]}", - "status": 200 - } - ] - }, - "resolvedrequest": { - "id": "tid", - "imp": [ - { - "id": "uuid", - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "ext": { - "prebid": { - "bidder": { - "beintoo": { - "tagid": "25251" - } - } - } - } - } - ], - "site": { - "domain": "example.com", - "page": "http://www.example.com", - "publisher": { - "id": "publisherId" - }, - "ext": { - "amp": 0 - } - }, - "device": { - "ua": "Android Chrome/60", - "dnt": 2, - "ip": "193.168.244.1", - "pxratio": 4.2, - "language": "en", - "ifa": "ifaId" - }, - "user": { - "ext": { - "consent": "consentValue" - } - }, - "at": 1, - "tmax": 5000, - "cur": [ - "USD" - ], - "source": { - "fd": 1, - "tid": "tid" - }, - "regs": { - "ext": { - "gdpr": 0 - } - }, - "ext": { - "prebid": { - "debug": 1, - "targeting": { - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "max": 20, - "increment": 0.1 - } - ] - }, - "includewinners": true, - "includebidderkeys": true - }, - "cache": { - "bids": {}, - "vastxml": { - "ttlseconds": 120 - } - }, - "auctiontimestamp": 1000, - "channel": { - "name": "web" - } - } - } - } - }, "responsetimemillis": { "cache": "{{ cache.response_time_ms }}", "beintoo": "{{ beintoo.response_time_ms }}" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-beintoo-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-beintoo-bid-request.json index 7948350ea6e..d746077204e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-beintoo-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-beintoo-bid-request.json @@ -13,10 +13,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 @@ -52,7 +53,6 @@ }, "ext": { "prebid": { - "debug": 1, "targeting": { "pricegranularity": { "precision": 2, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-cache-beintoo-request.json b/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-cache-beintoo-request.json index e1f7a597707..ab94570d5cc 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-cache-beintoo-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/beintoo/test-cache-beintoo-request.json @@ -10,7 +10,11 @@ "price": 2.942808, "crid": "94395500", "adid": "94395500", - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 2.942808, + "origbidcur": "USD" + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/between/test-auction-between-response.json b/src/test/resources/org/prebid/server/it/openrtb2/between/test-auction-between-response.json index 0e8a1ffcae8..42331a0d7fd 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/between/test-auction-between-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/between/test-auction-between-response.json @@ -36,7 +36,8 @@ "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 3.33 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/between/test-between-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/between/test-between-bid-request.json index dae47e6ea08..e642c53db3c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/between/test-between-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/between/test-between-bid-request.json @@ -5,12 +5,12 @@ "id": "impId001", "banner": { "format": [], - "w" : 300, - "h" : 250 + "w": 300, + "h": 250 }, - "bidfloor" : 12.2345, - "bidfloorcur" : "RUB", - "secure" : 0, + "bidfloor": 12.2345, + "bidfloorcur": "RUB", + "secure": 0, "ext": { "bidder": { "host": "lbs-ru1.ads", @@ -39,7 +39,7 @@ "ifa": "ifaId" }, "user": { - "buyeruid" : "BTW-UID" + "buyeruid": "BTW-UID" }, "at": 1, "tmax": 5000, @@ -74,8 +74,8 @@ "bids": {} }, "auctiontimestamp": 1000, - "channel" : { - "name" : "web" + "channel": { + "name": "web" } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/between/test-cache-between-request.json b/src/test/resources/org/prebid/server/it/openrtb2/between/test-cache-between-request.json index 60845624d51..424a76e0ac4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/between/test-cache-between-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/between/test-cache-between-request.json @@ -11,8 +11,11 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 3.33 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/brightroll/test-auction-brightroll-response.json b/src/test/resources/org/prebid/server/it/openrtb2/brightroll/test-auction-brightroll-response.json index 0ad98b1147b..2143fa051e0 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/brightroll/test-auction-brightroll-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/brightroll/test-auction-brightroll-response.json @@ -34,7 +34,8 @@ "cacheId": "3c7dedc8-dd68-4ba3-ba27-9d4e933cd4b3" } } - } + }, + "origbidcpm": 8.43 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/brightroll/test-brightroll-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/brightroll/test-brightroll-bid-request-1.json index 71c0a0389fe..29957ca0d8b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/brightroll/test-brightroll-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/brightroll/test-brightroll-bid-request-1.json @@ -32,10 +32,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/brightroll/test-cache-brightroll-request.json b/src/test/resources/org/prebid/server/it/openrtb2/brightroll/test-cache-brightroll-request.json index e63ae15fab1..6c9031bfb98 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/brightroll/test-cache-brightroll-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/brightroll/test-cache-brightroll-request.json @@ -9,8 +9,11 @@ "adm": "adm17", "crid": "crid17", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 8.43 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-auction-colossus-response.json b/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-auction-colossus-response.json index 092d59b8a0b..07870d131b3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-auction-colossus-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-auction-colossus-response.json @@ -34,7 +34,8 @@ "cacheId": "9092799c-93b0-4e11-a232-2c0151d5d275" } } - } + }, + "origbidcpm": 1.25 } }, { @@ -83,7 +84,8 @@ "cacheId": "99dc3357-34ac-4819-9f68-0820039a542f" } } - } + }, + "origbidcpm": 2.25 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-cache-colossus-request.json b/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-cache-colossus-request.json index 58471d39985..c393baa5ecf 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-cache-colossus-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-cache-colossus-request.json @@ -9,7 +9,10 @@ "adm": "adm001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 1.25 + } } }, { @@ -29,7 +32,10 @@ "IAB2" ], "w": 640, - "h": 480 + "h": 480, + "ext": { + "origbidcpm": 2.25 + } } }, { @@ -38,4 +44,4 @@ "expiry": 120 } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-colossus-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-colossus-bid-request-1.json index 0b0b7e7485b..75e809a036c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-colossus-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-colossus-bid-request-1.json @@ -20,10 +20,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 @@ -76,8 +77,8 @@ } }, "auctiontimestamp": 1000, - "channel" : { - "name" : "web" + "channel": { + "name": "web" } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-colossus-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-colossus-bid-request-2.json index a2b7360050b..32b1abca273 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-colossus-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/colossus/test-colossus-bid-request-2.json @@ -19,10 +19,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 @@ -75,8 +76,8 @@ } }, "auctiontimestamp": 1000, - "channel" : { - "name" : "web" + "channel": { + "name": "web" } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/connectad/test-auction-connectad-response.json b/src/test/resources/org/prebid/server/it/openrtb2/connectad/test-auction-connectad-response.json index b7e1cc8a733..0fae2a3a710 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/connectad/test-auction-connectad-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/connectad/test-auction-connectad-response.json @@ -34,7 +34,8 @@ "url": "{{ cache.resource_url }}f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 0.01 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/connectad/test-cache-connectad-request.json b/src/test/resources/org/prebid/server/it/openrtb2/connectad/test-cache-connectad-request.json index c6692479e4a..cdadbec00c4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/connectad/test-cache-connectad-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/connectad/test-cache-connectad-request.json @@ -10,9 +10,10 @@ "cid": "test_cid", "crid": "test_banner_crid", "ext": { - "format": "BANNER" + "format": "BANNER", + "origbidcpm": 0.01 } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/connectad/test-connectad-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/connectad/test-connectad-bid-request.json index 3c214cef05b..576d8c7a5c8 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/connectad/test-connectad-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/connectad/test-connectad-bid-request.json @@ -9,9 +9,9 @@ "h": 250 }, "tagid": "15", - "bidfloor" : 14.7, - "bidfloorcur" : "USD", - "secure" : 1, + "bidfloor": 14.7, + "bidfloorcur": "USD", + "secure": 1, "ext": { "bidder": { "networkId": 12, @@ -25,7 +25,8 @@ "domain": "example.com", "page": "https://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/consumable/test-auction-consumable-response.json b/src/test/resources/org/prebid/server/it/openrtb2/consumable/test-auction-consumable-response.json index e78b04b6df8..dad5c8d7b4a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/consumable/test-auction-consumable-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/consumable/test-auction-consumable-response.json @@ -35,7 +35,8 @@ "cacheId": "a5d3a873-d06e-4f2f-8556-120e05d62b28" } } - } + }, + "origbidcpm": 0.5 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/consumable/test-cache-consumable-request.json b/src/test/resources/org/prebid/server/it/openrtb2/consumable/test-cache-consumable-request.json index e15f6f829c4..4b8401a4022 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/consumable/test-cache-consumable-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/consumable/test-cache-consumable-request.json @@ -10,9 +10,12 @@ "crid": "1234567890", "w": 300, "h": 250, - "exp": 30 + "exp": 30, + "ext": { + "origbidcpm": 0.5 + } }, "expiry": 30 } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/conversant/alias/test-auction-conversant-response.json b/src/test/resources/org/prebid/server/it/openrtb2/conversant/alias/test-auction-conversant-response.json index 2a6bc6f5e3c..9777151aa0e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/conversant/alias/test-auction-conversant-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/conversant/alias/test-auction-conversant-response.json @@ -34,7 +34,8 @@ "cacheId": "618de608-9f7d-4152-82bf-81d34a617cfc" } } - } + }, + "origbidcpm": 5.0 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/conversant/alias/test-cache-conversant-request.json b/src/test/resources/org/prebid/server/it/openrtb2/conversant/alias/test-cache-conversant-request.json index 04019dc5b72..c03ef8836a4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/conversant/alias/test-cache-conversant-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/conversant/alias/test-cache-conversant-request.json @@ -9,8 +9,11 @@ "adm": "adm4", "crid": "crid4", "w": 300, - "h": 600 + "h": 600, + "ext": { + "origbidcpm": 5 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/conversant/alias/test-conversant-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/conversant/alias/test-conversant-bid-request.json index 653a4b9d51e..c85ab26fe0c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/conversant/alias/test-conversant-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/conversant/alias/test-conversant-bid-request.json @@ -24,10 +24,11 @@ ], "site": { "id": "siteId2", - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/conversant/test-auction-conversant-response.json b/src/test/resources/org/prebid/server/it/openrtb2/conversant/test-auction-conversant-response.json index 06c5adcab7b..a58466548d0 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/conversant/test-auction-conversant-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/conversant/test-auction-conversant-response.json @@ -34,7 +34,8 @@ "cacheId": "c9eb3deb-2054-40f5-9cf3-f9047dc240a2" } } - } + }, + "origbidcpm": 6.0 } }, { @@ -75,7 +76,8 @@ "cacheId": "8300a9d5-4654-4406-b6b9-7bc5060e8a36" } } - } + }, + "origbidcpm": 5.0 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/conversant/test-cache-conversant-request.json b/src/test/resources/org/prebid/server/it/openrtb2/conversant/test-cache-conversant-request.json index 05883337b06..8bdf96b6f6c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/conversant/test-cache-conversant-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/conversant/test-cache-conversant-request.json @@ -9,7 +9,10 @@ "adm": "adm4", "crid": "crid4", "w": 300, - "h": 600 + "h": 600, + "ext": { + "origbidcpm": 6 + } } }, { @@ -21,7 +24,10 @@ "adm": "adm41", "crid": "crid41", "w": 300, - "h": 600 + "h": 600, + "ext": { + "origbidcpm": 5 + } } }, { @@ -30,4 +36,4 @@ "expiry": 120 } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/conversant/test-conversant-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/conversant/test-conversant-bid-request.json index bf1337d38fc..3cbc0406e8a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/conversant/test-conversant-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/conversant/test-conversant-bid-request.json @@ -41,10 +41,11 @@ ], "site": { "id": "siteId", - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/cpmstar/test-auction-cpmstar-response.json b/src/test/resources/org/prebid/server/it/openrtb2/cpmstar/test-auction-cpmstar-response.json index 4f09a89542b..48cee000fce 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/cpmstar/test-auction-cpmstar-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/cpmstar/test-auction-cpmstar-response.json @@ -36,7 +36,8 @@ "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 3.33 } }, { @@ -79,7 +80,8 @@ "cacheId": "44a52b06-b29f-4819-a05f-db36b9e7b8fc" } } - } + }, + "origbidcpm": 5.55 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/cpmstar/test-cache-cpmstar-request.json b/src/test/resources/org/prebid/server/it/openrtb2/cpmstar/test-cache-cpmstar-request.json index 883ffec2c36..53a307b9388 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/cpmstar/test-cache-cpmstar-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/cpmstar/test-cache-cpmstar-request.json @@ -11,7 +11,10 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 3.33 + } } }, { @@ -25,7 +28,10 @@ "cid": "cid002", "crid": "crid002", "w": 1024, - "h": 576 + "h": 576, + "ext": { + "origbidcpm": 5.55 + } } }, { @@ -34,4 +40,4 @@ "expiry": 120 } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/cpmstar/test-cpmstar-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/cpmstar/test-cpmstar-bid-request-1.json index a07e42f638d..e0d83f61f4c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/cpmstar/test-cpmstar-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/cpmstar/test-cpmstar-bid-request-1.json @@ -36,10 +36,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 @@ -88,12 +89,11 @@ "includewinners": true, "includebidderkeys": true }, - "cache":{ - "bids":{ - + "cache": { + "bids": { }, - "vastxml":{ - "ttlseconds":120 + "vastxml": { + "ttlseconds": 120 } }, "auctiontimestamp": 1000, @@ -102,4 +102,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-auction-datablocks-request.json b/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-auction-datablocks-request.json index 6282fac2e20..efa548099d7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-auction-datablocks-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-auction-datablocks-request.json @@ -66,7 +66,6 @@ }, "ext": { "prebid": { - "debug": 1, "targeting": { "pricegranularity": { "precision": 2, @@ -97,4 +96,4 @@ "gdpr": 0 } } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-auction-datablocks-response.json b/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-auction-datablocks-response.json index 91d0f09bdff..f0a3d32d2b4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-auction-datablocks-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-auction-datablocks-response.json @@ -46,7 +46,8 @@ "cacheId": "62019cff-d657-42fc-8366-16c34e1fd28c" } } - } + }, + "origbidcpm": 9.99 } }, { @@ -82,7 +83,8 @@ "cacheId": "c1662cf6-f00a-4066-b71a-46d97abccc35" } } - } + }, + "origbidcpm": 7.77 } } ], @@ -92,144 +94,6 @@ ], "cur": "USD", "ext": { - "debug": { - "httpcalls": { - "cache": [ - { - "uri": "{{ cache.endpoint }}", - "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"bid001\",\"impid\":\"impId001\",\"price\":7.77,\"adm\":\"adm001\",\"adid\":\"adid001\",\"cid\":\"cid001\",\"crid\":\"crid001\",\"w\":300,\"h\":250}},{\"type\":\"json\",\"value\":{\"id\":\"bid002\",\"impid\":\"impId002\",\"price\":9.99,\"nurl\":\"https://example.com/nurl\",\"adomain\":[\"psacentral.org\"],\"cid\":\"cid002\",\"crid\":\"crid002\",\"w\":300,\"h\":250}},{\"type\":\"xml\",\"value\":\"prebid.org wrapper\",\"expiry\":120}]}", - "responsebody": "{\"responses\":[{\"uuid\":\"c1662cf6-f00a-4066-b71a-46d97abccc35\"},{\"uuid\":\"dbaa191c-5a56-4655-85eb-da079f94e09f\"},{\"uuid\":\"62019cff-d657-42fc-8366-16c34e1fd28c\"}]}", - "status": 200 - } - ], - "datablocks": [ - { - "uri": "{{ datablocks.exchange_uri }}?sid=2", - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId002\",\"video\":{\"mimes\":[\"video/mp4\"],\"w\":300,\"h\":250,\"pos\":1},\"ext\":{\"bidder\":{\"host\":\"localhost:8090\",\"sourceId\":2}}}],\"site\":{\"domain\":\"example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"id\":\"publisherId\"},\"ext\":{\"amp\":0}},\"device\":{\"ua\":\"userAgent\",\"dnt\":2,\"ip\":\"193.168.244.1\",\"pxratio\":4.2,\"language\":\"en\",\"ifa\":\"ifaId\"},\"user\":{\"buyeruid\":\"DB-UID\",\"ext\":{\"consent\":\"consentValue\"}},\"at\":1,\"tmax\":5000,\"cur\":[\"USD\"],\"source\":{\"fd\":1,\"tid\":\"tid\"},\"regs\":{\"ext\":{\"gdpr\":0}},\"ext\":{\"prebid\":{\"debug\":1,\"targeting\":{\"pricegranularity\":{\"precision\":2,\"ranges\":[{\"max\":20,\"increment\":0.1}]},\"includewinners\":true,\"includebidderkeys\":true},\"cache\":{\"bids\":{},\"vastxml\":{\"ttlseconds\":120}},\"auctiontimestamp\":1000,\"channel\":{\"name\":\"web\"}}}}", - "responsebody": "{\"id\":\"tid\",\"seatbid\":[{\"bid\":[{\"id\":\"bid002\",\"impid\":\"impId002\",\"price\":9.99,\"crid\":\"crid002\",\"cid\":\"cid002\",\"nurl\":\"https://example.com/nurl\",\"adomain\":[\"psacentral.org\"],\"h\":250,\"w\":300}],\"seat\":\"datablocks\"}]}", - "status": 200 - }, - { - "uri": "{{ datablocks.exchange_uri }}?sid=1", - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId001\",\"banner\":{\"format\":[{\"w\":300,\"h\":250}]},\"ext\":{\"bidder\":{\"host\":\"localhost:8090\",\"sourceId\":1}}}],\"site\":{\"domain\":\"example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"id\":\"publisherId\"},\"ext\":{\"amp\":0}},\"device\":{\"ua\":\"userAgent\",\"dnt\":2,\"ip\":\"193.168.244.1\",\"pxratio\":4.2,\"language\":\"en\",\"ifa\":\"ifaId\"},\"user\":{\"buyeruid\":\"DB-UID\",\"ext\":{\"consent\":\"consentValue\"}},\"at\":1,\"tmax\":5000,\"cur\":[\"USD\"],\"source\":{\"fd\":1,\"tid\":\"tid\"},\"regs\":{\"ext\":{\"gdpr\":0}},\"ext\":{\"prebid\":{\"debug\":1,\"targeting\":{\"pricegranularity\":{\"precision\":2,\"ranges\":[{\"max\":20,\"increment\":0.1}]},\"includewinners\":true,\"includebidderkeys\":true},\"cache\":{\"bids\":{},\"vastxml\":{\"ttlseconds\":120}},\"auctiontimestamp\":1000,\"channel\":{\"name\":\"web\"}}}}", - "responsebody": "{\"id\":\"tid\",\"seatbid\":[{\"bid\":[{\"id\":\"bid001\",\"impid\":\"impId001\",\"price\":7.77,\"adid\":\"adid001\",\"crid\":\"crid001\",\"cid\":\"cid001\",\"adm\":\"adm001\",\"h\":250,\"w\":300}],\"seat\":\"datablocks\"}]}", - "status": 200 - } - ] - }, - "resolvedrequest": { - "id": "tid", - "imp": [ - { - "id": "impId001", - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "ext": { - "prebid": { - "bidder": { - "datablocks": { - "host": "localhost:8090", - "sourceId": 1 - } - } - } - } - }, - { - "id": "impId002", - "video": { - "mimes": [ - "video/mp4" - ], - "w": 300, - "h": 250, - "pos": 1 - }, - "ext": { - "prebid": { - "bidder": { - "datablocks": { - "host": "localhost:8090", - "sourceId": 2 - } - } - } - } - } - ], - "site": { - "domain": "example.com", - "page": "http://www.example.com", - "publisher": { - "id": "publisherId" - }, - "ext": { - "amp": 0 - } - }, - "device": { - "ua": "userAgent", - "dnt": 2, - "ip": "193.168.244.1", - "pxratio": 4.2, - "language": "en", - "ifa": "ifaId" - }, - "user": { - "ext": { - "consent": "consentValue" - } - }, - "at": 1, - "tmax": 5000, - "cur": [ - "USD" - ], - "source": { - "fd": 1, - "tid": "tid" - }, - "regs": { - "ext": { - "gdpr": 0 - } - }, - "ext": { - "prebid": { - "debug": 1, - "targeting": { - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "max": 20, - "increment": 0.1 - } - ] - }, - "includewinners": true, - "includebidderkeys": true - }, - "cache": { - "bids": {}, - "vastxml": { - "ttlseconds": 120 - } - }, - "auctiontimestamp": 1000, - "channel": { - "name": "web" - } - } - } - } - }, "responsetimemillis": { "datablocks": "{{ datablocks.response_time_ms }}", "cache": "{{ cache.response_time_ms }}" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-cache-datablocks-request.json b/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-cache-datablocks-request.json index d22654a542b..bb6e149acf3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-cache-datablocks-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-cache-datablocks-request.json @@ -11,7 +11,10 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 7.77 + } } }, { @@ -24,10 +27,14 @@ "psacentral.org" ], "nurl": "https://example.com/nurl", + "adm": "prebid.org wrapper", "cid": "cid002", "crid": "crid002", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 9.99 + } } }, { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-datablocks-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-datablocks-bid-request-1.json index d83e947f165..e29faf1851d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-datablocks-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-datablocks-bid-request-1.json @@ -20,10 +20,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 @@ -59,7 +60,6 @@ }, "ext": { "prebid": { - "debug": 1, "targeting": { "pricegranularity": { "precision": 2, @@ -85,4 +85,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-datablocks-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-datablocks-bid-request-2.json index 0352ce9e783..6234c4e360e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-datablocks-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/datablocks/test-datablocks-bid-request-2.json @@ -20,10 +20,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 @@ -59,7 +60,6 @@ }, "ext": { "prebid": { - "debug": 1, "targeting": { "pricegranularity": { "precision": 2, @@ -85,4 +85,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-auction-decenterads-request.json b/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-auction-decenterads-request.json new file mode 100644 index 00000000000..d6be027bb98 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-auction-decenterads-request.json @@ -0,0 +1,83 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId001", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "decenterads": { + "placementId": "testPlacementId" + } + } + }, + { + "id": "impId002", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 640, + "h": 480 + }, + "ext": { + "decenterads": { + "placementId": "second-placementId" + } + } + } + ], + "device": { + "pxratio": 4.2, + "dnt": 2, + "language": "en", + "ifa": "ifaId" + }, + "site": { + "publisher": { + "id": "publisherId" + } + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "source": { + "fd": 1, + "tid": "tid" + }, + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + } + }, + "cache": { + "bids": {}, + "vastxml": { + "ttlseconds": 120 + } + }, + "auctiontimestamp": 1000 + } + }, + "regs": { + "ext": { + "gdpr": 0 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-auction-decenterads-response.json b/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-auction-decenterads-response.json new file mode 100644 index 00000000000..6ee0f6ed8e2 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-auction-decenterads-response.json @@ -0,0 +1,107 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "id": "bid001", + "impid": "impId001", + "price": 1.25, + "adm": "adm001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "banner", + "targeting": { + "hb_pb": "1.20", + "hb_cache_id_decenterads": "9092799c-93b0-4e11-a232-2c0151d5d275", + "hb_cache_path_decenterads": "{{ cache.path }}", + "hb_cache_path": "{{ cache.path }}", + "hb_pb_decenterads": "1.20", + "hb_size": "300x250", + "hb_bidder_decenterads": "decenterads", + "hb_size_decenterads": "300x250", + "hb_bidder": "decenterads", + "hb_cache_id": "9092799c-93b0-4e11-a232-2c0151d5d275", + "hb_cache_host": "{{ cache.host }}", + "hb_cache_host_decenterads": "{{ cache.host }}" + }, + "cache": { + "bids": { + "url": "{{ cache.resource_url }}9092799c-93b0-4e11-a232-2c0151d5d275", + "cacheId": "9092799c-93b0-4e11-a232-2c0151d5d275" + } + } + }, + "origbidcpm": 1.25 + } + }, + { + "id": "bid01", + "impid": "impId002", + "price": 2.25, + "adm": "adm002", + "adid": "29681110", + "adomain": [ + "video-example.com" + ], + "cid": "1001", + "crid": "crid002", + "cat": [ + "IAB2" + ], + "w": 640, + "h": 480, + "exp": 120, + "ext": { + "prebid": { + "type": "video", + "targeting": { + "hb_cache_id_decenterads": "83cdc325-c816-4d2e-bf2c-9213a70671dd", + "hb_cache_path_decenterads": "{{ cache.path }}", + "hb_size_decenterads": "640x480", + "hb_cache_id": "83cdc325-c816-4d2e-bf2c-9213a70671dd", + "hb_uuid_decenterads": "99dc3357-34ac-4819-9f68-0820039a542f", + "hb_pb": "2.20", + "hb_cache_path": "{{ cache.path }}", + "hb_uuid": "99dc3357-34ac-4819-9f68-0820039a542f", + "hb_pb_decenterads": "2.20", + "hb_size": "640x480", + "hb_bidder_decenterads": "decenterads", + "hb_bidder": "decenterads", + "hb_cache_host": "{{ cache.host }}", + "hb_cache_host_decenterads": "{{ cache.host }}" + }, + "cache": { + "bids": { + "url": "{{ cache.resource_url }}83cdc325-c816-4d2e-bf2c-9213a70671dd", + "cacheId": "83cdc325-c816-4d2e-bf2c-9213a70671dd" + }, + "vastXml": { + "url": "{{ cache.resource_url }}99dc3357-34ac-4819-9f68-0820039a542f", + "cacheId": "99dc3357-34ac-4819-9f68-0820039a542f" + } + } + }, + "origbidcpm": 2.25 + } + } + ], + "seat": "decenterads", + "group": 0 + } + ], + "cur": "USD", + "ext": { + "responsetimemillis": { + "decenterads": "{{ decenterads.response_time_ms }}", + "cache": "{{ cache.response_time_ms }}" + }, + "prebid": { + "auctiontimestamp": 1000 + }, + "tmaxrequest": 5000 + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-cache-decenterads-request.json b/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-cache-decenterads-request.json new file mode 100644 index 00000000000..c393baa5ecf --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-cache-decenterads-request.json @@ -0,0 +1,47 @@ +{ + "puts": [ + { + "type": "json", + "value": { + "id": "bid001", + "impid": "impId001", + "price": 1.25, + "adm": "adm001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "origbidcpm": 1.25 + } + } + }, + { + "type": "json", + "value": { + "id": "bid01", + "impid": "impId002", + "price": 2.25, + "adm": "adm002", + "adid": "29681110", + "adomain": [ + "video-example.com" + ], + "cid": "1001", + "crid": "crid002", + "cat": [ + "IAB2" + ], + "w": 640, + "h": 480, + "ext": { + "origbidcpm": 2.25 + } + } + }, + { + "type": "xml", + "value": "adm002", + "expiry": 120 + } + ] +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-cache-matcher-decenterads.json b/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-cache-matcher-decenterads.json new file mode 100644 index 00000000000..e438661be9f --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-cache-matcher-decenterads.json @@ -0,0 +1,5 @@ +{ + "bid001@1.25": "9092799c-93b0-4e11-a232-2c0151d5d275", + "bid01@2.25": "83cdc325-c816-4d2e-bf2c-9213a70671dd", + "adm002": "99dc3357-34ac-4819-9f68-0820039a542f" +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-decenterads-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-decenterads-bid-request-1.json new file mode 100644 index 00000000000..7fa4bca9e94 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-decenterads-bid-request-1.json @@ -0,0 +1,82 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId001", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "placementId": "testPlacementId" + } + } + ], + "site": { + "domain": "www.example.com", + "page": "http://www.example.com", + "publisher": { + "id": "publisherId", + "domain": "example.com" + }, + "ext": { + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "dnt": 2, + "ip": "193.168.244.1", + "pxratio": 4.2, + "language": "en", + "ifa": "ifaId" + }, + "user": { + "buyeruid": "DC-UID" + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "source": { + "fd": 1, + "tid": "tid" + }, + "regs": { + "ext": { + "gdpr": 0 + } + }, + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + }, + "includewinners": true, + "includebidderkeys": true + }, + "cache": { + "bids": {}, + "vastxml": { + "ttlseconds": 120 + } + }, + "auctiontimestamp": 1000, + "channel": { + "name": "web" + } + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-decenterads-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-decenterads-bid-request-2.json new file mode 100644 index 00000000000..07b99438750 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-decenterads-bid-request-2.json @@ -0,0 +1,81 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId002", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 640, + "h": 480 + }, + "ext": { + "placementId": "second-placementId" + } + } + ], + "site": { + "domain": "www.example.com", + "page": "http://www.example.com", + "publisher": { + "id": "publisherId", + "domain": "example.com" + }, + "ext": { + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "dnt": 2, + "ip": "193.168.244.1", + "pxratio": 4.2, + "language": "en", + "ifa": "ifaId" + }, + "user": { + "buyeruid": "DC-UID" + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "source": { + "fd": 1, + "tid": "tid" + }, + "regs": { + "ext": { + "gdpr": 0 + } + }, + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + }, + "includewinners": true, + "includebidderkeys": true + }, + "cache": { + "bids": {}, + "vastxml": { + "ttlseconds": 120 + } + }, + "auctiontimestamp": 1000, + "channel": { + "name": "web" + } + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-decenterads-bid-response-1.json b/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-decenterads-bid-response-1.json new file mode 100644 index 00000000000..89ec3dc2248 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-decenterads-bid-response-1.json @@ -0,0 +1,19 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "id": "bid001", + "impid": "impId001", + "price": 1.25, + "crid": "crid001", + "adm": "adm001", + "h": 250, + "w": 300 + } + ] + } + ], + "bidid": "bid001" +} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-decenterads-bid-response-2.json b/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-decenterads-bid-response-2.json new file mode 100644 index 00000000000..966ec782f17 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/decenterads/test-decenterads-bid-response-2.json @@ -0,0 +1,27 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "id": "bid01", + "impid": "impId002", + "price": 2.25, + "cid": "1001", + "crid": "crid002", + "adid": "29681110", + "adm": "adm002", + "cat": [ + "IAB2" + ], + "adomain": [ + "video-example.com" + ], + "h": 480, + "w": 640 + } + ] + } + ], + "bidid": "bid01" +} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-auction-deepintent-request.json b/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-auction-deepintent-request.json index e7507d0e050..89c88700e60 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-auction-deepintent-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-auction-deepintent-request.json @@ -7,9 +7,9 @@ "w": 320, "h": 250 }, - "displaymanager" : "di_prebid", - "displaymanagerver" : "2.0.0", - "tagid" : "possibleTagId", + "displaymanager": "di_prebid", + "displaymanagerver": "2.0.0", + "tagid": "possibleTagId", "ext": { "deepintent": { "tagId": "possibleTagId" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-auction-deepintent-response.json b/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-auction-deepintent-response.json index 25d77da5ec2..9050d8c2de1 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-auction-deepintent-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-auction-deepintent-response.json @@ -31,7 +31,8 @@ "cacheId": "3c0769d8-0dd9-465c-8bf3-f570605ba698" } } - } + }, + "origbidcpm": 0.01 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-cache-deepintent-request.json b/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-cache-deepintent-request.json index ca8e3ab2f6a..383f37b4df9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-cache-deepintent-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-cache-deepintent-request.json @@ -8,7 +8,10 @@ "price": 0.01, "id": "testid", "impid": "testimpid", - "cid": "8048" + "cid": "8048", + "ext": { + "origbidcpm": 0.01 + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-deepintent-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-deepintent-bid-request.json index 74055235383..2ce869b89ba 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-deepintent-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/deepintent/test-deepintent-bid-request.json @@ -7,22 +7,22 @@ "w": 320, "h": 250 }, - "displaymanager" : "di_prebid", - "displaymanagerver" : "2.0.0", - "tagid" : "possibleTagId", + "displaymanager": "di_prebid", + "displaymanagerver": "2.0.0", + "tagid": "possibleTagId", "ext": { "bidder": { "tagId": "possibleTagId" } } - } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-auction-dmx-request.json b/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-auction-dmx-request.json index 356d83d4fa6..a669cba13db 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-auction-dmx-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-auction-dmx-request.json @@ -14,10 +14,10 @@ }, "ext": { "dmx": { - "dmxid": "1007", - "memberid": "123456", - "seller_id": "1008", - "publisher_id": "10400" + "dmxid": "1007", + "memberid": "123456", + "seller_id": "1008", + "publisher_id": "10400" } } }, @@ -39,10 +39,10 @@ }, "ext": { "dmx": { - "dmxid": "1007", - "memberid": "123456", - "seller_id": "1008", - "publisher_id": "10400" + "dmxid": "1007", + "memberid": "123456", + "seller_id": "1008", + "publisher_id": "10400" } } } @@ -74,7 +74,6 @@ "fd": 1, "tid": "tid" }, - "user": { "ext": { "consent": "consentValue", diff --git a/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-auction-dmx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-auction-dmx-response.json index ab1fca88810..954f2eaf1eb 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-auction-dmx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-auction-dmx-response.json @@ -33,7 +33,8 @@ "url": "{{ cache.resource_url }}f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 0.01 } } ], @@ -52,4 +53,4 @@ }, "tmaxrequest": 3000 } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-cache-dmx-request.json b/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-cache-dmx-request.json index d969bb8dc78..c7f7c6561f7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-cache-dmx-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-cache-dmx-request.json @@ -9,9 +9,10 @@ "cid": "test_cid", "crid": "test_banner_crid", "ext": { - "format": "BANNER" + "format": "BANNER", + "origbidcpm": 0.01 } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-dmx-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-dmx-bid-request.json index 5b98f4e23a9..bcb2c37c056 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-dmx-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/dmx/test-dmx-bid-request.json @@ -9,10 +9,12 @@ "w": 300, "h": 250 } - ] + ], + "w": 300, + "h": 250 }, "tagid": "1007", - "secure" : 1, + "secure": 1, "ext": { "bidder": { "dmxid": "1007", @@ -38,13 +40,13 @@ "skipafter": 0 }, "tagid": "1007", - "secure" : 1, + "secure": 1, "ext": { "bidder": { "dmxid": "1007", "memberid": "123456", "seller_id": "1008", - "publisher_id" : "10400" + "publisher_id": "10400" } } } @@ -53,7 +55,8 @@ "domain": "example.com", "page": "http://www.example.com", "publisher": { - "id":"publisherId", + "id": "publisherId", + "domain": "example.com", "ext": { "dmx": { "id": "10400" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/emxdigital/test-auction-emxdigital-response.json b/src/test/resources/org/prebid/server/it/openrtb2/emxdigital/test-auction-emxdigital-response.json index 74d80b920ab..c78852f2907 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/emxdigital/test-auction-emxdigital-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/emxdigital/test-auction-emxdigital-response.json @@ -35,7 +35,9 @@ "cacheId": "9a5d11a7-de5a-4ce4-8e89-d37f18a10045" } } - } + }, + "origbidcpm": 2.942808, + "origbidcur": "USD" } } ], @@ -50,7 +52,7 @@ "emx_digital": [ { "uri": "{{ emx_digital.exchange_uri }}?t=1000&ts=2060541160", - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"uuid\",\"banner\":{\"format\":[],\"w\":300,\"h\":250},\"tagid\":\"25251\",\"secure\":0,\"ext\":{\"bidder\":{\"tagid\":\"25251\"}}}],\"site\":{\"domain\":\"example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"id\":\"publisherId\"},\"ext\":{\"amp\":0}},\"device\":{\"ua\":\"Android Chrome/60\",\"dnt\":2,\"ip\":\"193.168.244.1\",\"pxratio\":4.2,\"language\":\"en\",\"ifa\":\"ifaId\"},\"user\":{\"ext\":{\"consent\":\"consentValue\"}},\"at\":1,\"tmax\":5000,\"cur\":[\"USD\"],\"source\":{\"fd\":1,\"tid\":\"tid\"},\"regs\":{\"ext\":{\"gdpr\":0}},\"ext\":{\"prebid\":{\"debug\":1,\"targeting\":{\"pricegranularity\":{\"precision\":2,\"ranges\":[{\"max\":20,\"increment\":0.1}]},\"includewinners\":true,\"includebidderkeys\":true},\"cache\":{\"bids\":{},\"vastxml\":{\"ttlseconds\":120}},\"auctiontimestamp\":1000,\"channel\":{\"name\":\"web\"}}}}", + "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"uuid\",\"banner\":{\"format\":[],\"w\":300,\"h\":250},\"tagid\":\"25251\",\"secure\":0,\"ext\":{\"bidder\":{\"tagid\":\"25251\"}}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"id\":\"publisherId\",\"domain\":\"example.com\"},\"ext\":{\"amp\":0}},\"device\":{\"ua\":\"Android Chrome/60\",\"dnt\":2,\"ip\":\"193.168.244.1\",\"pxratio\":4.2,\"language\":\"en\",\"ifa\":\"ifaId\"},\"user\":{\"ext\":{\"consent\":\"consentValue\"}},\"at\":1,\"tmax\":5000,\"cur\":[\"USD\"],\"source\":{\"fd\":1,\"tid\":\"tid\"},\"regs\":{\"ext\":{\"gdpr\":0}},\"ext\":{\"prebid\":{\"debug\":1,\"targeting\":{\"pricegranularity\":{\"precision\":2,\"ranges\":[{\"max\":20,\"increment\":0.1}]},\"includewinners\":true,\"includebidderkeys\":true},\"cache\":{\"bids\":{},\"vastxml\":{\"ttlseconds\":120}},\"auctiontimestamp\":1000,\"channel\":{\"name\":\"web\"}}}}", "responsebody": "{\"id\":\"some_test_auction\",\"seatbid\":[{\"seat\":\"12356\",\"bid\":[{\"id\":\"uuid\",\"adm\":\"
\",\"impid\":\"uuid\",\"ttl\":300,\"crid\":\"94395500\",\"w\":300,\"price\":2.942808,\"adid\":\"94395500\",\"h\":250}]}],\"cur\":\"USD\"}", "status": 200 } @@ -58,7 +60,7 @@ "cache": [ { "uri": "{{ cache.endpoint }}", - "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"uuid\",\"impid\":\"uuid\",\"price\":2.942808,\"adm\":\"
\",\"adid\":\"94395500\",\"crid\":\"94395500\",\"w\":300,\"h\":250}}]}", + "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"uuid\",\"impid\":\"uuid\",\"price\":2.942808,\"adm\":\"
\",\"adid\":\"94395500\",\"crid\":\"94395500\",\"w\":300,\"h\":250,\"ext\":{\"origbidcpm\":2.942808,\"origbidcur\":\"USD\"}}}]}", "responsebody": "{\"responses\":[{\"uuid\":\"9a5d11a7-de5a-4ce4-8e89-d37f18a10045\"}]}", "status": 200 } @@ -89,10 +91,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/emxdigital/test-cache-emxdigital-request.json b/src/test/resources/org/prebid/server/it/openrtb2/emxdigital/test-cache-emxdigital-request.json index e1f7a597707..ab94570d5cc 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/emxdigital/test-cache-emxdigital-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/emxdigital/test-cache-emxdigital-request.json @@ -10,7 +10,11 @@ "price": 2.942808, "crid": "94395500", "adid": "94395500", - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 2.942808, + "origbidcur": "USD" + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/emxdigital/test-emxdigital-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/emxdigital/test-emxdigital-bid-request.json index 8b819c1bb3e..99a7df4eee2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/emxdigital/test-emxdigital-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/emxdigital/test-emxdigital-bid-request.json @@ -13,10 +13,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" } }, "device": { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-auction-engagebdr-request.json b/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-auction-engagebdr-request.json index ea9428f01b7..a1fa3b46ef7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-auction-engagebdr-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-auction-engagebdr-request.json @@ -25,7 +25,7 @@ }, "ext": { "engagebdr": { - "sspid":"88888" + "sspid": "88888" } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-auction-engagebdr-response.json b/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-auction-engagebdr-response.json index 220d77bd2dc..f81e3bc43f8 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-auction-engagebdr-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-auction-engagebdr-response.json @@ -47,7 +47,9 @@ "cacheId": "6628e262-d023-406b-b3e9-9a9aded76a7d" } } - } + }, + "origbidcpm": 9.81, + "origbidcur": "USD" } }, { @@ -87,7 +89,9 @@ "cacheId": "739f1ac0-3ac3-4c02-8b74-ceb1fa4d96a1" } } - } + }, + "origbidcpm": 9.81, + "origbidcur": "USD" } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-cache-engagebdr-request.json b/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-cache-engagebdr-request.json index f331fc452b9..ca658c64465 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-cache-engagebdr-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-cache-engagebdr-request.json @@ -15,7 +15,11 @@ "cid": "campaign1", "crid": "abcde-12345", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 9.81, + "origbidcur": "USD" + } } }, { @@ -33,7 +37,11 @@ "cid": "campaign1", "crid": "abcde-12345", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 9.81, + "origbidcur": "USD" + } } }, { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-engagebdr-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-engagebdr-bid-request-1.json index 1126f469c70..4cfdbb1a3c5 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-engagebdr-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-engagebdr-bid-request-1.json @@ -15,10 +15,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-engagebdr-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-engagebdr-bid-request-2.json index 6ffe58b473f..5a4fececd17 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-engagebdr-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-engagebdr-bid-request-2.json @@ -19,10 +19,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-engagebdr-bid-response-1.json b/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-engagebdr-bid-response-1.json index 7af6c8903d4..deaf8fc1a1c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-engagebdr-bid-response-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-engagebdr-bid-response-1.json @@ -4,7 +4,7 @@ { "bid": [ { - "id" : "test-imp-id1", + "id": "test-imp-id1", "impid": "impId021", "price": 9.81, "adid": "abcde-12345", diff --git a/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-engagebdr-bid-response-2.json b/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-engagebdr-bid-response-2.json index 313136e0be1..c32bf75d400 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-engagebdr-bid-response-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/engagebdr/test-engagebdr-bid-response-2.json @@ -9,7 +9,7 @@ "price": 9.81, "adid": "abcde-12345", "adm": "\nStatic VASTStatic VAST Tag", - "adomain":[ + "adomain": [ "advertiserdomain.com" ], "iurl": "https://cdn0.bnmla.com/vtest.xml", diff --git a/src/test/resources/org/prebid/server/it/openrtb2/eplanning/test-auction-eplanning-response.json b/src/test/resources/org/prebid/server/it/openrtb2/eplanning/test-auction-eplanning-response.json index f5f19965a02..28957592517 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/eplanning/test-auction-eplanning-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/eplanning/test-auction-eplanning-response.json @@ -35,7 +35,8 @@ "cacheId": "6fb008f6-9e09-43ad-830b-ffed21345119" } } - } + }, + "origbidcpm": 0.5 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/eplanning/test-cache-eplanning-request.json b/src/test/resources/org/prebid/server/it/openrtb2/eplanning/test-cache-eplanning-request.json index 99455d2b388..12332199b4e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/eplanning/test-cache-eplanning-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/eplanning/test-cache-eplanning-request.json @@ -10,8 +10,11 @@ "adid": "adid12345", "crid": "abcdef123456789", "w": 600, - "h": 300 + "h": 300, + "ext": { + "origbidcpm": 0.5 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/epom/test-auction-epom-request.json b/src/test/resources/org/prebid/server/it/openrtb2/epom/test-auction-epom-request.json new file mode 100644 index 00000000000..33b672d43c3 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/epom/test-auction-epom-request.json @@ -0,0 +1,72 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId001", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "epom": { + } + } + } + ], + "device": { + "pxratio": 4.2, + "dnt": 2, + "language": "en", + "ifa": "ifaId" + }, + "site": { + "publisher": { + "id": "publisherId" + } + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "source": { + "fd": 1, + "tid": "tid" + }, + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + } + }, + "cache": { + "bids": {}, + "vastxml": { + "ttlseconds": 120 + } + }, + "auctiontimestamp": 1000 + } + }, + "user": { + "ext": { + "consent": "consentValue" + } + }, + "regs": { + "ext": { + "gdpr": 0 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/epom/test-auction-epom-response.json b/src/test/resources/org/prebid/server/it/openrtb2/epom/test-auction-epom-response.json new file mode 100644 index 00000000000..791d65de4fd --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/epom/test-auction-epom-response.json @@ -0,0 +1,59 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "id": "bid001", + "impid": "impId001", + "price": 3.33, + "adm": "adm001", + "adid": "adid001", + "cid": "cid001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "banner", + "targeting": { + "hb_cache_host_epom": "{{ cache.host }}", + "hb_cache_path_epom": "{{ cache.path }}", + "hb_cache_id": "a5d3a873-d06e-4f2f-8556-120e05d62b28", + "hb_pb": "3.30", + "hb_size_epom": "300x250", + "hb_cache_path": "{{ cache.path }}", + "hb_size": "300x250", + "hb_pb_epom": "3.30", + "hb_cache_id_epom": "a5d3a873-d06e-4f2f-8556-120e05d62b28", + "hb_bidder_epom": "epom", + "hb_bidder": "epom", + "hb_cache_host": "{{ cache.host }}" + }, + "cache": { + "bids": { + "url": "{{ cache.resource_url }}a5d3a873-d06e-4f2f-8556-120e05d62b28", + "cacheId": "a5d3a873-d06e-4f2f-8556-120e05d62b28" + } + } + }, + "origbidcpm" : 3.33 + } + } + ], + "seat": "epom", + "group": 0 + } + ], + "cur": "USD", + "ext": { + "responsetimemillis": { + "epom": "{{ epom.response_time_ms }}", + "cache": "{{ cache.response_time_ms }}" + }, + "prebid": { + "auctiontimestamp": 1000 + }, + "tmaxrequest": 5000 + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/epom/test-cache-epom-request.json b/src/test/resources/org/prebid/server/it/openrtb2/epom/test-cache-epom-request.json new file mode 100644 index 00000000000..63d1e4fd66a --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/epom/test-cache-epom-request.json @@ -0,0 +1,21 @@ +{ + "puts": [ + { + "type": "json", + "value": { + "id": "bid001", + "impid": "impId001", + "price": 3.33, + "adm": "adm001", + "adid": "adid001", + "cid": "cid001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "origbidcpm" : 3.33 + } + } + } + ] +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/epom/test-cache-epom-response.json b/src/test/resources/org/prebid/server/it/openrtb2/epom/test-cache-epom-response.json new file mode 100644 index 00000000000..773491fa9b0 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/epom/test-cache-epom-response.json @@ -0,0 +1,7 @@ +{ + "responses": [ + { + "uuid": "a5d3a873-d06e-4f2f-8556-120e05d62b28" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/openrtb2/epom/test-epom-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/epom/test-epom-bid-request-1.json new file mode 100644 index 00000000000..2197bd76cd3 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/epom/test-epom-bid-request-1.json @@ -0,0 +1,86 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId001", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + } + } + } + ], + "site": { + "domain": "www.example.com", + "page": "http://www.example.com", + "publisher": { + "id": "publisherId", + "domain": "example.com" + }, + "ext": { + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "dnt": 2, + "ip": "193.168.244.1", + "pxratio": 4.2, + "language": "en", + "ifa": "ifaId" + }, + "user": { + "buyeruid": "EP-UID", + "ext": { + "consent": "consentValue" + } + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "source": { + "fd": 1, + "tid": "tid" + }, + "regs": { + "ext": { + "gdpr": 0 + } + }, + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + }, + "includewinners": true, + "includebidderkeys": true + }, + "cache": { + "bids": {}, + "vastxml": { + "ttlseconds": 120 + } + }, + "auctiontimestamp": 1000, + "channel": { + "name": "web" + } + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/epom/test-epom-bid-response-1.json b/src/test/resources/org/prebid/server/it/openrtb2/epom/test-epom-bid-response-1.json new file mode 100644 index 00000000000..95a93284e04 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/epom/test-epom-bid-response-1.json @@ -0,0 +1,20 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "id": "bid001", + "impid": "impId001", + "price": 3.33, + "adid": "adid001", + "crid": "crid001", + "cid": "cid001", + "adm": "adm001", + "h": 250, + "w": 300 + } + ] + } + ] +} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/openrtb2/facebook/test-auction-facebook-response.json b/src/test/resources/org/prebid/server/it/openrtb2/facebook/test-auction-facebook-response.json index b6addc2d715..99320a8e3b4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/facebook/test-auction-facebook-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/facebook/test-auction-facebook-response.json @@ -35,7 +35,8 @@ "cacheId": "446d71ac-0337-4871-9fda-4552323a269b" } } - } + }, + "origbidcpm": 10.0 } }, { @@ -70,7 +71,8 @@ "cacheId": "3d90394a-0301-4faf-b0e8-5d26a88f6ef0" } } - } + }, + "origbidcpm": 9.0 } }, { @@ -112,7 +114,8 @@ "cacheId": "6d7addba-3984-4a69-b84f-6f1daa02b407" } } - } + }, + "origbidcpm": 15.0 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/facebook/test-cache-facebook-request.json b/src/test/resources/org/prebid/server/it/openrtb2/facebook/test-cache-facebook-request.json index b166d3f5a8b..0242592d867 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/facebook/test-cache-facebook-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/facebook/test-cache-facebook-request.json @@ -10,7 +10,10 @@ "adid": "10", "crid": "10", "w": 0, - "h": 0 + "h": 0, + "ext": { + "origbidcpm": 15 + } } }, { @@ -23,7 +26,10 @@ "adid": "10", "crid": "10", "w": 0, - "h": 0 + "h": 0, + "ext": { + "origbidcpm": 10 + } } }, { @@ -36,7 +42,10 @@ "adid": "10", "crid": "10", "w": 0, - "h": 50 + "h": 50, + "ext": { + "origbidcpm": 9 + } } }, { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/gamma/test-auction-gamma-response.json b/src/test/resources/org/prebid/server/it/openrtb2/gamma/test-auction-gamma-response.json index ba9bb7be433..cc55636d5e0 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/gamma/test-auction-gamma-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/gamma/test-auction-gamma-response.json @@ -39,7 +39,9 @@ "cacheId": "7e703396-6b75-4a10-9ef3-bc61ca7ce437" } } - } + }, + "origbidcpm": 0.5, + "origbidcur": "USD" } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/gamma/test-cache-gamma-request.json b/src/test/resources/org/prebid/server/it/openrtb2/gamma/test-cache-gamma-request.json index 88543083ace..f22078d8d15 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/gamma/test-cache-gamma-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/gamma/test-cache-gamma-request.json @@ -14,7 +14,11 @@ "cid": "958", "crid": "29681110", "h": 250, - "w": 300 + "w": 300, + "ext": { + "origbidcpm": 0.500000, + "origbidcur": "USD" + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/gamoshi/test-auction-gamoshi-response.json b/src/test/resources/org/prebid/server/it/openrtb2/gamoshi/test-auction-gamoshi-response.json index 39e226734ab..07acaeb922e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/gamoshi/test-auction-gamoshi-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/gamoshi/test-auction-gamoshi-response.json @@ -36,7 +36,8 @@ "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 3.33 } }, { @@ -79,7 +80,8 @@ "cacheId": "44a52b06-b29f-4819-a05f-db36b9e7b8fc" } } - } + }, + "origbidcpm": 5.55 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/gamoshi/test-cache-gamoshi-request.json b/src/test/resources/org/prebid/server/it/openrtb2/gamoshi/test-cache-gamoshi-request.json index 883ffec2c36..53a307b9388 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/gamoshi/test-cache-gamoshi-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/gamoshi/test-cache-gamoshi-request.json @@ -11,7 +11,10 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 3.33 + } } }, { @@ -25,7 +28,10 @@ "cid": "cid002", "crid": "crid002", "w": 1024, - "h": 576 + "h": 576, + "ext": { + "origbidcpm": 5.55 + } } }, { @@ -34,4 +40,4 @@ "expiry": 120 } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/gamoshi/test-gamoshi-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/gamoshi/test-gamoshi-bid-request-1.json index e1af7fe1880..f95f6346929 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/gamoshi/test-gamoshi-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/gamoshi/test-gamoshi-bid-request-1.json @@ -40,10 +40,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/grid/test-auction-grid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/grid/test-auction-grid-response.json index 8b377341d58..b42e942dab7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/grid/test-auction-grid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/grid/test-auction-grid-response.json @@ -36,7 +36,8 @@ "cacheId": "a5d3a873-d06e-4f2f-8556-120e05d62b28" } } - } + }, + "origbidcpm": 3.33 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/grid/test-cache-grid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/grid/test-cache-grid-request.json index 60845624d51..424a76e0ac4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/grid/test-cache-grid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/grid/test-cache-grid-request.json @@ -11,8 +11,11 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 3.33 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/grid/test-grid-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/grid/test-grid-bid-request-1.json index 59837eb72e4..c0c1a403cad 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/grid/test-grid-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/grid/test-grid-bid-request-1.json @@ -19,10 +19,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-auction-gumgum-request.json b/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-auction-gumgum-request.json index 380e5d38f4b..fc969d36bc0 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-auction-gumgum-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-auction-gumgum-request.json @@ -31,7 +31,7 @@ }, "ext": { "gumgum": { - "zone": "second_zone" + "pubId": 737 } } }, @@ -55,7 +55,8 @@ }, "ext": { "gumgum": { - "zone": "third_zone" + "zone": "third_zone", + "irisid": "iris_6f9285823a48bne5" } } } @@ -103,7 +104,7 @@ } }, "user": { - "buyeruid" : "GUM-UID", + "buyeruid": "GUM-UID", "ext": { "consent": "consentValue" } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-auction-gumgum-response.json b/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-auction-gumgum-response.json index 800002e5d10..2e47a9fd3f4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-auction-gumgum-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-auction-gumgum-response.json @@ -32,7 +32,8 @@ "cacheId": "78f9a6dd-d08c-4b80-ba0f-0159b9add9bf" } } - } + }, + "origbidcpm": 1.25 } }, { @@ -64,7 +65,8 @@ "cacheId": "eaf3e2cd-57af-42d1-9daf-38836ae7bca7" } } - } + }, + "origbidcpm": 2 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-cache-gumgum-request.json b/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-cache-gumgum-request.json index 40f661376f1..da9c4a20184 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-cache-gumgum-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-cache-gumgum-request.json @@ -9,7 +9,10 @@ "adm": "adm001", "adid": "adid001", "cid": "cid001", - "crid": "crid001" + "crid": "crid001", + "ext": { + "origbidcpm": 1.25 + } } }, { @@ -21,8 +24,11 @@ "adm": "adm002", "adid": "adid002", "cid": "cid002", - "crid": "crid002" + "crid": "crid002", + "ext": { + "origbidcpm": 2 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-gumgum-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-gumgum-bid-request-1.json index 7ff815c64da..7bef09d89a9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-gumgum-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/gumgum/test-gumgum-bid-request-1.json @@ -33,13 +33,16 @@ }, "ext": { "bidder": { - "zone": "second_zone" + "pubId": 737 } } }, { "id": "impId003", "video": { + "ext": { + "irisid": "iris_6f9285823a48bne5" + }, "mimes": [ "video/mp4" ], @@ -57,17 +60,19 @@ }, "ext": { "bidder": { - "zone": "third_zone" + "zone": "third_zone", + "irisid": "iris_6f9285823a48bne5" } } } ], "site": { "id": "third_zone", - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "737", + "domain" : "example.com" }, "ext": { "amp": 0 @@ -82,7 +87,7 @@ "ifa": "ifaId" }, "user": { - "buyeruid" : "GUM-UID", + "buyeruid": "GUM-UID", "ext": { "consent": "consentValue" } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/improvedigital/test-auction-improvedigital-response.json b/src/test/resources/org/prebid/server/it/openrtb2/improvedigital/test-auction-improvedigital-response.json index 90aec3ab37d..5c54a7d91b3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/improvedigital/test-auction-improvedigital-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/improvedigital/test-auction-improvedigital-response.json @@ -36,7 +36,8 @@ "cacheId": "83dedee7-ebfe-4224-a71b-d7fb4a43b7a9" } } - } + }, + "origbidcpm": 3.33 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/improvedigital/test-cache-improvedigital-request.json b/src/test/resources/org/prebid/server/it/openrtb2/improvedigital/test-cache-improvedigital-request.json index 60845624d51..424a76e0ac4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/improvedigital/test-cache-improvedigital-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/improvedigital/test-cache-improvedigital-request.json @@ -11,8 +11,11 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 3.33 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/improvedigital/test-improvedigital-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/improvedigital/test-improvedigital-bid-request-1.json index 09055b884ef..ccf3722a0b0 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/improvedigital/test-improvedigital-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/improvedigital/test-improvedigital-bid-request-1.json @@ -23,10 +23,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/inmobi/test-auction-inmobi-response.json b/src/test/resources/org/prebid/server/it/openrtb2/inmobi/test-auction-inmobi-response.json index 131053efa04..de597b7c6eb 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/inmobi/test-auction-inmobi-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/inmobi/test-auction-inmobi-response.json @@ -36,7 +36,8 @@ "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 3.33 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/inmobi/test-cache-inmobi-request.json b/src/test/resources/org/prebid/server/it/openrtb2/inmobi/test-cache-inmobi-request.json index 60845624d51..424a76e0ac4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/inmobi/test-cache-inmobi-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/inmobi/test-cache-inmobi-request.json @@ -11,8 +11,11 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 3.33 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/inmobi/test-inmobi-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/inmobi/test-inmobi-bid-request.json index 5d7d532cc71..ca39bc67ae1 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/inmobi/test-inmobi-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/inmobi/test-inmobi-bid-request.json @@ -21,10 +21,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 @@ -39,7 +40,7 @@ "ifa": "ifaId" }, "user": { - "buyeruid" : "IM-UID" + "buyeruid": "IM-UID" }, "at": 1, "tmax": 5000, @@ -74,8 +75,8 @@ "bids": {} }, "auctiontimestamp": 1000, - "channel" : { - "name" : "web" + "channel": { + "name": "web" } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/invibes/test-auction-invibes-response.json b/src/test/resources/org/prebid/server/it/openrtb2/invibes/test-auction-invibes-response.json index e645a933457..808afd59e82 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/invibes/test-auction-invibes-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/invibes/test-auction-invibes-response.json @@ -1,58 +1,60 @@ { - "id":"tid", - "seatbid":[ + "id": "tid", + "seatbid": [ { - "bid":[ + "bid": [ { - "id":"bid001", - "impid":"impId001", - "price":1.3, - "adm":"adm001", - "adid":"adid001", - "cid":"cid001", - "crid":"crid001", - "w":300, - "h":250, - "ext":{ - "prebid":{ - "type":"banner", - "targeting":{ - "hb_pb_invibes":"1.30", - "hb_cache_id_invibes":"f0ab9105-cb21-4e59-b433-70f5ad6671cb", - "hb_bidder_invibes":"invibes", - "hb_cache_id":"f0ab9105-cb21-4e59-b433-70f5ad6671cb", - "hb_pb":"1.30", - "hb_cache_path":"/cache", - "hb_size":"300x250", - "hb_bidder":"invibes", - "hb_size_invibes":"300x250", - "hb_cache_host":"{{ cache.host }}", - "hb_cache_path_invibes":"{{ cache.path }}", + "id": "bid001", + "impid": "impId001", + "price": 1.3, + "adm": "adm001", + "adid": "adid001", + "cid": "cid001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "banner", + "targeting": { + "hb_pb_invibes": "1.30", + "hb_cache_id_invibes": "f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "hb_bidder_invibes": "invibes", + "hb_cache_id": "f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "hb_pb": "1.30", + "hb_cache_path": "/cache", + "hb_size": "300x250", + "hb_bidder": "invibes", + "hb_size_invibes": "300x250", + "hb_cache_host": "{{ cache.host }}", + "hb_cache_path_invibes": "{{ cache.path }}", "hb_cache_host_invibes": "{{ cache.host }}" }, - "cache":{ - "bids":{ - "url":"{{ cache.resource_url }}f0ab9105-cb21-4e59-b433-70f5ad6671cb", - "cacheId":"f0ab9105-cb21-4e59-b433-70f5ad6671cb" + "cache": { + "bids": { + "url": "{{ cache.resource_url }}f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 1.3, + "origbidcur": "USD" } } ], - "seat":"invibes", - "group":0 + "seat": "invibes", + "group": 0 } ], - "cur":"USD", - "ext":{ - "responsetimemillis":{ - "cache":"{{ cache.response_time_ms }}", - "invibes":"{{ invibes.response_time_ms }}" + "cur": "USD", + "ext": { + "responsetimemillis": { + "cache": "{{ cache.response_time_ms }}", + "invibes": "{{ invibes.response_time_ms }}" }, - "tmaxrequest":3000, - "prebid":{ - "auctiontimestamp":1000 + "tmaxrequest": 3000, + "prebid": { + "auctiontimestamp": 1000 } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/invibes/test-cache-invibes-request.json b/src/test/resources/org/prebid/server/it/openrtb2/invibes/test-cache-invibes-request.json index 7007994992c..e9b35443c42 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/invibes/test-cache-invibes-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/invibes/test-cache-invibes-request.json @@ -7,11 +7,15 @@ "impid": "impId001", "price": 1.3, "adm": "adm001", - "adid" : "adid001", - "cid" : "cid001", - "crid" : "crid001", - "w" : 300, - "h" : 250 + "adid": "adid001", + "cid": "cid001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "origbidcpm": 1.3, + "origbidcur": "USD" + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/invibes/test-invibes-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/invibes/test-invibes-bid-request.json index 5f5a1df81d2..4f2b48f5ee7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/invibes/test-invibes-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/invibes/test-invibes-bid-request.json @@ -1,10 +1,10 @@ { - "BidParamsJson" :"{\"PlacementIds\":[\"plcId\"],\"BidVersion\":\"4\",\"Properties\":{\"plcId\":{\"Formats\":[{\"w\":300,\"h\":250}],\"ImpID\":\"impId001\"}}}", - "Location" :"http://www.example.com", - "Lid" : "IV-UID", - "IsTestBid" : false, - "GdprConsent" :"consentValue", - "Gdpr" : false, - "InvibBVLog" : false, - "VideoAdDebug" : false + "BidParamsJson": "{\"PlacementIds\":[\"plcId\"],\"BidVersion\":\"4\",\"Properties\":{\"plcId\":{\"Formats\":[{\"w\":300,\"h\":250}],\"ImpID\":\"impId001\"}}}", + "Location": "http://www.example.com", + "Lid": "IV-UID", + "IsTestBid": false, + "GdprConsent": "consentValue", + "Gdpr": false, + "InvibBVLog": false, + "VideoAdDebug": false } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-request.json b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-request.json index 6166d299b78..a2689c55d60 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-request.json @@ -36,7 +36,7 @@ "at": 1, "tmax": 5000, "cur": [ - "EUR" + "USD" ], "source": { "fd": 1, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-response.json b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-response.json index 4d09ed53984..d27caa71b1b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-auction-ix-response.json @@ -6,7 +6,7 @@ { "id": "975135373", "impid": "impId6", - "price": 4.125, + "price": 4.7, "adm": "adm6", "crid": "crid6", "w": 300, @@ -15,10 +15,10 @@ "prebid": { "type": "banner", "targeting": { - "hb_pb_ix": "4.10", + "hb_pb_ix": "4.70", "hb_cache_id": "3bd85b54-a5c5-4852-956e-44e8a7b6b5bc", "hb_bidder_ix": "ix", - "hb_pb": "4.10", + "hb_pb": "4.70", "hb_size_ix": "300x250", "hb_cache_path": "{{ cache.path }}", "hb_cache_path_ix": "{{ cache.path }}", @@ -34,7 +34,8 @@ "cacheId": "3bd85b54-a5c5-4852-956e-44e8a7b6b5bc" } } - } + }, + "origbidcpm": 4.7 } } ], @@ -42,7 +43,7 @@ "group": 0 } ], - "cur": "EUR", + "cur": "USD", "ext": { "responsetimemillis": { "ix": "{{ ix.response_time_ms }}", diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-cache-ix-request.json b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-cache-ix-request.json index 515ce3171c0..7d2917f79f7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-cache-ix-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-cache-ix-request.json @@ -5,11 +5,14 @@ "value": { "id": "975135373", "impid": "impId6", - "price": 4.125, + "price": 4.7, "adm": "adm6", "crid": "crid6", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 4.7 + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-request-1.json index ca28223533b..de0dab9493c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-request-1.json @@ -21,10 +21,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "10002" + "id": "10002", + "domain" : "example.com" }, "ext": { "amp": 0 @@ -47,7 +48,7 @@ "at": 1, "tmax": 5000, "cur": [ - "EUR" + "USD" ], "source": { "fd": 1, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-request-2.json index 47cfe63d4bb..fe28dc74d8c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ix/test-ix-bid-request-2.json @@ -21,10 +21,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "10002" + "id": "10002", + "domain" : "example.com" }, "ext": { "amp": 0 @@ -47,7 +48,7 @@ "at": 1, "tmax": 5000, "cur": [ - "EUR" + "USD" ], "source": { "fd": 1, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-auction-jixie-request.json b/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-auction-jixie-request.json new file mode 100644 index 00000000000..20501c37754 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-auction-jixie-request.json @@ -0,0 +1,57 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId001", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "jixie": { + "unit": "possible_unit_value" + } + } + } + ], + "device": { + "ua": "testUa", + "ip": "193.168.244.1" + }, + "site": { + "page": "awesomePage" + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "source": { + "fd": 1, + "tid": "tid" + }, + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + } + }, + "cache": { + "bids": {} + }, + "auctiontimestamp": 1000 + } + }, + "regs": { + "ext": { + "gdpr": 0 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-auction-jixie-response.json b/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-auction-jixie-response.json new file mode 100644 index 00000000000..d5ed36aedfe --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-auction-jixie-response.json @@ -0,0 +1,59 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "id": "bid001", + "impid": "impId001", + "price": 3.33, + "adm": "adm001", + "adid": "adid001", + "cid": "cid001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "banner", + "targeting": { + "hb_pb": "3.30", + "hb_size_jixie": "300x250", + "hb_bidder_jixie": "jixie", + "hb_cache_path": "{{ cache.path }}", + "hb_size": "300x250", + "hb_cache_host_jixie": "{{ cache.host }}", + "hb_cache_path_jixie": "{{ cache.path }}", + "hb_cache_id_jixie": "f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "hb_bidder": "jixie", + "hb_cache_id": "f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "hb_pb_jixie": "3.30", + "hb_cache_host": "{{ cache.host }}" + }, + "cache": { + "bids": { + "url": "{{ cache.resource_url }}f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" + } + } + }, + "origbidcpm" : 3.33 + } + } + ], + "seat": "jixie", + "group": 0 + } + ], + "cur": "USD", + "ext": { + "responsetimemillis": { + "jixie": "{{ jixie.response_time_ms }}", + "cache": "{{ cache.response_time_ms }}" + }, + "prebid": { + "auctiontimestamp": 1000 + }, + "tmaxrequest": 5000 + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-cache-jixie-request.json b/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-cache-jixie-request.json new file mode 100644 index 00000000000..63d1e4fd66a --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-cache-jixie-request.json @@ -0,0 +1,21 @@ +{ + "puts": [ + { + "type": "json", + "value": { + "id": "bid001", + "impid": "impId001", + "price": 3.33, + "adm": "adm001", + "adid": "adid001", + "cid": "cid001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "origbidcpm" : 3.33 + } + } + } + ] +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-cache-jixie-response.json b/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-cache-jixie-response.json new file mode 100644 index 00000000000..93d0b8de2cd --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-cache-jixie-response.json @@ -0,0 +1,7 @@ +{ + "responses": [ + { + "uuid": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-jixie-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-jixie-bid-request.json new file mode 100644 index 00000000000..96b5094d7cd --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-jixie-bid-request.json @@ -0,0 +1,68 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId001", + "banner": { + "w" : 300, + "h" : 250 + }, + "ext": { + "bidder": { + "unit": "possible_unit_value" + } + } + } + ], + "site": { + "page": "awesomePage", + "ext": { + "amp": 0 + } + }, + "device": { + "ua": "testUa", + "ip": "193.168.244.1" + }, + "user": { + "buyeruid" : "JX-UID" + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "source": { + "fd": 1, + "tid": "tid" + }, + "regs": { + "ext": { + "gdpr": 0 + } + }, + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + }, + "includewinners": true, + "includebidderkeys": true + }, + "cache": { + "bids": {} + }, + "auctiontimestamp": 1000, + "channel" : { + "name" : "web" + } + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-jixie-bid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-jixie-bid-response.json new file mode 100644 index 00000000000..95a93284e04 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/jixie/test-jixie-bid-response.json @@ -0,0 +1,20 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "id": "bid001", + "impid": "impId001", + "price": 3.33, + "adid": "adid001", + "crid": "crid001", + "cid": "cid001", + "adm": "adm001", + "h": 250, + "w": 300 + } + ] + } + ] +} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-auction-kidoz-response.json b/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-auction-kidoz-response.json index 323318350e1..e002c0c4ebf 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-auction-kidoz-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-auction-kidoz-response.json @@ -36,7 +36,8 @@ "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 3.33 } }, { @@ -79,7 +80,8 @@ "cacheId": "44a52b06-b29f-4819-a05f-db36b9e7b8fc" } } - } + }, + "origbidcpm": 5.55 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-cache-kidoz-request.json b/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-cache-kidoz-request.json index 883ffec2c36..53a307b9388 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-cache-kidoz-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-cache-kidoz-request.json @@ -11,7 +11,10 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 3.33 + } } }, { @@ -25,7 +28,10 @@ "cid": "cid002", "crid": "crid002", "w": 1024, - "h": 576 + "h": 576, + "ext": { + "origbidcpm": 5.55 + } } }, { @@ -34,4 +40,4 @@ "expiry": 120 } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-kidoz-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-kidoz-bid-request-1.json index 4642e4ee4c5..ed5484da4e9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-kidoz-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-kidoz-bid-request-1.json @@ -20,10 +20,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-kidoz-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-kidoz-bid-request-2.json index 1001ba1ae91..ff5edc6f2b9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-kidoz-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/kidoz/test-kidoz-bid-request-2.json @@ -1,21 +1,21 @@ { "id": "tid", - "imp":[ + "imp": [ { - "id":"impId002", - "video":{ - "mimes":[ + "id": "impId002", + "video": { + "mimes": [ "video/mp4" ], - "protocols":[ + "protocols": [ 2, 5 ], - "w":1024, - "h":576 + "w": 1024, + "h": 576 }, - "ext":{ - "bidder":{ + "ext": { + "bidder": { "access_token": "test-token-1", "publisher_id": "test-publisher-1" } @@ -23,10 +23,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 @@ -97,4 +98,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/krushmedia/test-auction-krushmedia-response.json b/src/test/resources/org/prebid/server/it/openrtb2/krushmedia/test-auction-krushmedia-response.json index 22e48c8f0b4..799fb0c9578 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/krushmedia/test-auction-krushmedia-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/krushmedia/test-auction-krushmedia-response.json @@ -31,7 +31,8 @@ "cacheId": "3c0769d8-0dd9-465c-8bf3-f570605ba698" } } - } + }, + "origbidcpm": 0.01 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/krushmedia/test-cache-krushmedia-request.json b/src/test/resources/org/prebid/server/it/openrtb2/krushmedia/test-cache-krushmedia-request.json index ca8e3ab2f6a..383f37b4df9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/krushmedia/test-cache-krushmedia-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/krushmedia/test-cache-krushmedia-request.json @@ -8,7 +8,10 @@ "price": 0.01, "id": "testid", "impid": "testimpid", - "cid": "8048" + "cid": "8048", + "ext": { + "origbidcpm": 0.01 + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/krushmedia/test-krushmedia-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/krushmedia/test-krushmedia-bid-request.json index 0c095490aa8..f0376b9ec7f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/krushmedia/test-krushmedia-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/krushmedia/test-krushmedia-bid-request.json @@ -11,10 +11,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-auction-kubient-request.json b/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-auction-kubient-request.json index 1cc440f4aaa..5dcf2dab6d5 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-auction-kubient-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-auction-kubient-request.json @@ -46,7 +46,6 @@ }, "ext": { "prebid": { - "debug": 1, "targeting": { "pricegranularity": { "precision": 2, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-auction-kubient-response.json b/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-auction-kubient-response.json index f606cc5a73d..2852eee7d9e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-auction-kubient-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-auction-kubient-response.json @@ -39,7 +39,8 @@ "cacheId": "78f9a6dd-d08c-4b80-ba0f-0159b9add9bf" } } - } + }, + "origbidcpm": 0.5 } } ], @@ -49,118 +50,6 @@ ], "cur": "USD", "ext": { - "debug": { - "httpcalls": { - "cache": [ - { - "uri": "{{ cache.endpoint }}", - "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"7706636740145184841\",\"impid\":\"test-imp-banner-id\",\"price\":0.5,\"adm\":\"some-test-ad\",\"adid\":\"29681110\",\"adomain\":[\"advertsite.com\"],\"cid\":\"772\",\"crid\":\"29681110\",\"w\":1024,\"h\":576}}]}", - "responsebody": "{\"responses\":[{\"uuid\":\"78f9a6dd-d08c-4b80-ba0f-0159b9add9bf\"}]}", - "status": 200 - } - ], - "kubient": [ - { - "uri": "{{ kubient.exchange_uri }}", - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"test-imp-banner-id\",\"banner\":{\"format\":[{\"w\":300,\"h\":250}],\"w\":500,\"h\":400},\"ext\":{\"bidder\":{\"zoneid\":\"9042\"}}}],\"site\":{\"domain\":\"example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"id\":\"publisherId\"},\"ext\":{\"amp\":0}},\"device\":{\"ua\":\"userAgent\",\"dnt\":2,\"ip\":\"193.168.244.1\",\"pxratio\":4.2,\"language\":\"en\",\"ifa\":\"ifaId\"},\"user\":{\"ext\":{\"consent\":\"consentValue\"}},\"at\":1,\"tmax\":5000,\"cur\":[\"USD\"],\"source\":{\"fd\":1,\"tid\":\"tid\"},\"regs\":{\"ext\":{\"gdpr\":0}},\"ext\":{\"prebid\":{\"debug\":1,\"targeting\":{\"pricegranularity\":{\"precision\":2,\"ranges\":[{\"max\":20,\"increment\":0.1}]},\"includewinners\":true,\"includebidderkeys\":true},\"cache\":{\"bids\":{},\"vastxml\":{\"ttlseconds\":120}},\"auctiontimestamp\":1000,\"channel\":{\"name\":\"web\"}}}}", - "responsebody": "{\"id\":\"tid\",\"seatbid\":[{\"bid\":[{\"id\":\"7706636740145184841\",\"impid\":\"test-imp-banner-id\",\"price\":0.5,\"adid\":\"29681110\",\"adm\":\"some-test-ad\",\"adomain\":[\"advertsite.com\"],\"cid\":\"772\",\"crid\":\"29681110\",\"h\":576,\"w\":1024}]}]}", - "status": 200 - } - ] - }, - "resolvedrequest": { - "id": "tid", - "imp": [ - { - "id": "test-imp-banner-id", - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ], - "w": 500, - "h": 400 - }, - "ext": { - "prebid": { - "bidder": { - "kubient": { - "zoneid": "9042" - } - } - } - } - } - ], - "site": { - "domain": "example.com", - "page": "http://www.example.com", - "publisher": { - "id": "publisherId" - }, - "ext": { - "amp": 0 - } - }, - "device": { - "ua": "userAgent", - "dnt": 2, - "ip": "193.168.244.1", - "pxratio": 4.2, - "language": "en", - "ifa": "ifaId" - }, - "user": { - "ext": { - "consent": "consentValue" - } - }, - "at": 1, - "tmax": 5000, - "cur": [ - "USD" - ], - "source": { - "fd": 1, - "tid": "tid" - }, - "regs": { - "ext": { - "gdpr": 0 - } - }, - "ext": { - "prebid": { - "debug": 1, - "targeting": { - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "max": 20, - "increment": 0.1 - } - ] - }, - "includewinners": true, - "includebidderkeys": true - }, - "cache": { - "bids": {}, - "vastxml": { - "ttlseconds": 120 - } - }, - "auctiontimestamp": 1000, - "channel": { - "name": "web" - } - } - } - } - }, "responsetimemillis": { "cache": "{{ cache.response_time_ms }}", "kubient": "{{ kubient.response_time_ms }}" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-cache-kubient-request.json b/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-cache-kubient-request.json index a97a73381ff..ecd360287a8 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-cache-kubient-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-cache-kubient-request.json @@ -8,11 +8,16 @@ "price": 0.500000, "adid": "29681110", "adm": "some-test-ad", - "adomain": ["advertsite.com"], + "adomain": [ + "advertsite.com" + ], "cid": "772", "crid": "29681110", "h": 576, - "w": 1024 + "w": 1024, + "ext": { + "origbidcpm": 0.500000 + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-kubient-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-kubient-bid-request-1.json index 30fc51dafc9..38d0c216072 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-kubient-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-kubient-bid-request-1.json @@ -21,10 +21,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 @@ -59,7 +60,6 @@ }, "ext": { "prebid": { - "debug": 1, "targeting": { "pricegranularity": { "precision": 2, @@ -85,4 +85,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-kubient-bid-response-1.json b/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-kubient-bid-response-1.json index 92517b36952..35da8708c10 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-kubient-bid-response-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/kubient/test-kubient-bid-response-1.json @@ -9,7 +9,9 @@ "price": 0.500000, "adid": "29681110", "adm": "some-test-ad", - "adomain": ["advertsite.com"], + "adomain": [ + "advertsite.com" + ], "cid": "772", "crid": "29681110", "h": 576, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/lifestreet/test-auction-lifestreet-response.json b/src/test/resources/org/prebid/server/it/openrtb2/lifestreet/test-auction-lifestreet-response.json index c70626ce831..058ed3c61f7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/lifestreet/test-auction-lifestreet-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/lifestreet/test-auction-lifestreet-response.json @@ -34,7 +34,8 @@ "cacheId": "f0bfa534-ca56-42bc-9b91-a801f8f202c2" } } - } + }, + "origbidcpm": 4.75 } }, { @@ -75,7 +76,8 @@ "cacheId": "7e5320e5-ad46-439e-a7eb-f4cb826d8ab6" } } - } + }, + "origbidcpm": 3.75 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/lifestreet/test-cache-lifestreet-request.json b/src/test/resources/org/prebid/server/it/openrtb2/lifestreet/test-cache-lifestreet-request.json index 74abb79fcbe..48e647cf0ac 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/lifestreet/test-cache-lifestreet-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/lifestreet/test-cache-lifestreet-request.json @@ -9,7 +9,10 @@ "adm": "adm71", "crid": "crid71", "w": 300, - "h": 600 + "h": 600, + "ext": { + "origbidcpm": 3.75 + } } }, { @@ -21,7 +24,10 @@ "adm": "adm7", "crid": "crid7", "w": 300, - "h": 600 + "h": 600, + "ext": { + "origbidcpm": 4.75 + } } }, { @@ -30,4 +36,4 @@ "expiry": 120 } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/lifestreet/test-lifestreet-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/lifestreet/test-lifestreet-bid-request-1.json index 4a2a5c7ad2f..d56f6d93755 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/lifestreet/test-lifestreet-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/lifestreet/test-lifestreet-bid-request-1.json @@ -16,10 +16,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/lifestreet/test-lifestreet-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/lifestreet/test-lifestreet-bid-request-2.json index ba3bfcd9393..669bcd59306 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/lifestreet/test-lifestreet-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/lifestreet/test-lifestreet-bid-request-2.json @@ -19,10 +19,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/lockerdome/test-auction-lockerdome-response.json b/src/test/resources/org/prebid/server/it/openrtb2/lockerdome/test-auction-lockerdome-response.json index e23846981a2..99b376a8b79 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/lockerdome/test-auction-lockerdome-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/lockerdome/test-auction-lockerdome-response.json @@ -36,7 +36,8 @@ "cacheId": "22e22b17-47cb-46fa-a65b-d4c3bc1b4996" } } - } + }, + "origbidcpm": 7.35 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/lockerdome/test-cache-lockerdome-request.json b/src/test/resources/org/prebid/server/it/openrtb2/lockerdome/test-cache-lockerdome-request.json index 91fa1bdb4d3..6b0984b240f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/lockerdome/test-cache-lockerdome-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/lockerdome/test-cache-lockerdome-request.json @@ -11,8 +11,11 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 7.35 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/lockerdome/test-lockerdome-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/lockerdome/test-lockerdome-bid-request.json index 76ec286f60b..ec48ce88859 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/lockerdome/test-lockerdome-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/lockerdome/test-lockerdome-bid-request.json @@ -19,10 +19,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/logicad/test-auction-logicad-response.json b/src/test/resources/org/prebid/server/it/openrtb2/logicad/test-auction-logicad-response.json index 6b5285ded93..adf79d37d1c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/logicad/test-auction-logicad-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/logicad/test-auction-logicad-response.json @@ -31,7 +31,8 @@ "cacheId": "3c0769d8-0dd9-465c-8bf3-f570605ba698" } } - } + }, + "origbidcpm": 0.01 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/logicad/test-cache-logicad-request.json b/src/test/resources/org/prebid/server/it/openrtb2/logicad/test-cache-logicad-request.json index ca8e3ab2f6a..383f37b4df9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/logicad/test-cache-logicad-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/logicad/test-cache-logicad-request.json @@ -8,7 +8,10 @@ "price": 0.01, "id": "testid", "impid": "testimpid", - "cid": "8048" + "cid": "8048", + "ext": { + "origbidcpm": 0.01 + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/logicad/test-logicad-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/logicad/test-logicad-bid-request.json index 9e7a534c4f9..3c31d547a53 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/logicad/test-logicad-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/logicad/test-logicad-bid-request.json @@ -21,10 +21,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/lunamedia/test-auction-lunamedia-response.json b/src/test/resources/org/prebid/server/it/openrtb2/lunamedia/test-auction-lunamedia-response.json index 60258cf56da..520dbd094a2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/lunamedia/test-auction-lunamedia-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/lunamedia/test-auction-lunamedia-response.json @@ -31,7 +31,8 @@ "cacheId": "3c0769d8-0dd9-465c-8bf3-f570605ba698" } } - } + }, + "origbidcpm": 0.01 } } ], @@ -50,4 +51,4 @@ }, "tmaxrequest": 5000 } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/lunamedia/test-cache-lunamedia-request.json b/src/test/resources/org/prebid/server/it/openrtb2/lunamedia/test-cache-lunamedia-request.json index 378b8da504a..383f37b4df9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/lunamedia/test-cache-lunamedia-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/lunamedia/test-cache-lunamedia-request.json @@ -8,8 +8,11 @@ "price": 0.01, "id": "testid", "impid": "testimpid", - "cid": "8048" + "cid": "8048", + "ext": { + "origbidcpm": 0.01 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/marsmedia/test-auction-marsmedia-response.json b/src/test/resources/org/prebid/server/it/openrtb2/marsmedia/test-auction-marsmedia-response.json index 707de20c353..b818b43dff4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/marsmedia/test-auction-marsmedia-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/marsmedia/test-auction-marsmedia-response.json @@ -36,7 +36,8 @@ "cacheId": "b888d5e0-6fbf-47e9-affe-5bd9083adfc6" } } - } + }, + "origbidcpm": 7.35 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/marsmedia/test-cache-marsmedia-request.json b/src/test/resources/org/prebid/server/it/openrtb2/marsmedia/test-cache-marsmedia-request.json index 91fa1bdb4d3..6b0984b240f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/marsmedia/test-cache-marsmedia-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/marsmedia/test-cache-marsmedia-request.json @@ -11,8 +11,11 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 7.35 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/marsmedia/test-marsmedia-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/marsmedia/test-marsmedia-bid-request-1.json index 4a0c0913910..e348bf33f3b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/marsmedia/test-marsmedia-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/marsmedia/test-marsmedia-bid-request-1.json @@ -36,10 +36,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/mgid/test-auction-mgid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/mgid/test-auction-mgid-response.json index eade228010f..2ca20b7fdd8 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/mgid/test-auction-mgid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/mgid/test-auction-mgid-response.json @@ -36,6 +36,7 @@ } } }, + "origbidcpm": 3.5, "bidder": { "crtype": "banner" } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/mgid/test-cache-mgid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/mgid/test-cache-mgid-request.json index 89ac54117a4..8f1b0132887 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/mgid/test-cache-mgid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/mgid/test-cache-mgid-request.json @@ -12,9 +12,10 @@ "w": 300, "h": 250, "ext": { - "crtype": "banner" + "crtype": "banner", + "origbidcpm": 3.5 } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/mgid/test-mgid-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/mgid/test-mgid-bid-request.json index f301e145230..af3cbd9fd65 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/mgid/test-mgid-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/mgid/test-mgid-bid-request.json @@ -29,10 +29,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-auction-mobfoxpb-request.json b/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-auction-mobfoxpb-request.json index 74da4411016..473ea8c1011 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-auction-mobfoxpb-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-auction-mobfoxpb-request.json @@ -13,7 +13,7 @@ }, "ext": { "mobfoxpb": { - "TagID": "extTagId" + "key": "someKey" } } }, @@ -44,8 +44,8 @@ "ifa": "ifaId" }, "site": { - "domain" : "example.com", - "page" : "http://www.example.com", + "domain": "example.com", + "page": "http://www.example.com", "publisher": { "id": "publisherId" }, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-auction-mobfoxpb-response.json b/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-auction-mobfoxpb-response.json index 25931dc22c1..934d1f9d2ca 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-auction-mobfoxpb-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-auction-mobfoxpb-response.json @@ -39,6 +39,7 @@ } } }, + "origbidcpm": 3.33, "bidder": { "prebid": { "type": "banner" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-cache-mobfoxpb-request.json b/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-cache-mobfoxpb-request.json index 2a7a175910f..e6e268bf5c4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-cache-mobfoxpb-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-cache-mobfoxpb-request.json @@ -15,7 +15,8 @@ "ext": { "prebid": { "type": "banner" - } + }, + "origbidcpm": 3.33 } } } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-mobfoxpb-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-mobfoxpb-bid-request-1.json index 79522adb23d..a6c79abd8be 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-mobfoxpb-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/mobfoxpb/test-mobfoxpb-bid-request-1.json @@ -3,7 +3,6 @@ "imp": [ { "id": "impId001", - "tagid": "extTagId", "banner": { "format": [ { @@ -14,7 +13,7 @@ }, "ext": { "bidder": { - "TagID": "extTagId" + "key": "someKey" } } } @@ -31,7 +30,8 @@ "domain": "example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/mobilefuse/test-auction-mobilefuse-response.json b/src/test/resources/org/prebid/server/it/openrtb2/mobilefuse/test-auction-mobilefuse-response.json index 66111c86cef..505a1783054 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/mobilefuse/test-auction-mobilefuse-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/mobilefuse/test-auction-mobilefuse-response.json @@ -34,7 +34,8 @@ "url": "{{ cache.resource_url }}f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 0.01 } } ], @@ -53,4 +54,4 @@ }, "tmaxrequest": 3000 } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/mobilefuse/test-cache-mobilefuse-request.json b/src/test/resources/org/prebid/server/it/openrtb2/mobilefuse/test-cache-mobilefuse-request.json index c6692479e4a..cdadbec00c4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/mobilefuse/test-cache-mobilefuse-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/mobilefuse/test-cache-mobilefuse-request.json @@ -10,9 +10,10 @@ "cid": "test_cid", "crid": "test_banner_crid", "ext": { - "format": "BANNER" + "format": "BANNER", + "origbidcpm": 0.01 } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/mobilefuse/test-mobilefuse-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/mobilefuse/test-mobilefuse-bid-request.json index 31b5c38798c..08504c50f3a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/mobilefuse/test-mobilefuse-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/mobilefuse/test-mobilefuse-bid-request.json @@ -18,7 +18,8 @@ "domain": "example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/nanointeractive/test-auction-nanointeractive-request.json b/src/test/resources/org/prebid/server/it/openrtb2/nanointeractive/test-auction-nanointeractive-request.json index 4a55209e63a..431b6d16ad2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/nanointeractive/test-auction-nanointeractive-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/nanointeractive/test-auction-nanointeractive-request.json @@ -16,7 +16,9 @@ "ext": { "nanointeractive": { "pid": "58bfec94eb0a1916fa380163", - "nq": ["search query"], + "nq": [ + "search query" + ], "category": "Automotive", "subId": "a23", "ref": "https://nanointeractive.com" @@ -38,7 +40,9 @@ "ext": { "nanointeractive": { "pid": "58bfec94eb0a1916fa380163", - "nq": ["search query"], + "nq": [ + "search query" + ], "category": "Automotive", "subId": "a23", "ref": "https://nanointeractive.com" @@ -108,4 +112,4 @@ "gdpr": 0 } } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/nanointeractive/test-auction-nanointeractive-response.json b/src/test/resources/org/prebid/server/it/openrtb2/nanointeractive/test-auction-nanointeractive-response.json index 7457cc9f30b..1ddbb5f452e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/nanointeractive/test-auction-nanointeractive-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/nanointeractive/test-auction-nanointeractive-response.json @@ -34,7 +34,8 @@ "cacheId": "1e6fb739-d0e7-4b7c-9b00-21aa40dc3301" } } - } + }, + "origbidcpm": 5.78 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/nanointeractive/test-cache-nanointeractive-request.json b/src/test/resources/org/prebid/server/it/openrtb2/nanointeractive/test-cache-nanointeractive-request.json index e186c23ce1a..a59e391f468 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/nanointeractive/test-cache-nanointeractive-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/nanointeractive/test-cache-nanointeractive-request.json @@ -9,8 +9,11 @@ "adm": "adm+13", "crid": "crid13", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 5.78 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/nanointeractive/test-nanointeractive-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/nanointeractive/test-nanointeractive-bid-request-1.json index 2934f223725..e0c78e2260d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/nanointeractive/test-nanointeractive-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/nanointeractive/test-nanointeractive-bid-request-1.json @@ -51,11 +51,12 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "ref": "https://nanointeractive.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ninthdecimal/test-auction-ninthdecimal-response.json b/src/test/resources/org/prebid/server/it/openrtb2/ninthdecimal/test-auction-ninthdecimal-response.json index f42828d8358..8a957eabf41 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ninthdecimal/test-auction-ninthdecimal-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ninthdecimal/test-auction-ninthdecimal-response.json @@ -31,7 +31,8 @@ "cacheId": "3c0769d8-0dd9-465c-8bf3-f570605ba698" } } - } + }, + "origbidcpm": 0.01 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ninthdecimal/test-cache-ninthdecimal-request.json b/src/test/resources/org/prebid/server/it/openrtb2/ninthdecimal/test-cache-ninthdecimal-request.json index ca8e3ab2f6a..383f37b4df9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ninthdecimal/test-cache-ninthdecimal-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ninthdecimal/test-cache-ninthdecimal-request.json @@ -8,7 +8,10 @@ "price": 0.01, "id": "testid", "impid": "testimpid", - "cid": "8048" + "cid": "8048", + "ext": { + "origbidcpm": 0.01 + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/nobid/test-auction-nobid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/nobid/test-auction-nobid-response.json index 4e20fc3207b..30e94a5234e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/nobid/test-auction-nobid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/nobid/test-auction-nobid-response.json @@ -31,7 +31,8 @@ "cacheId": "3c0769d8-0dd9-465c-8bf3-f570605ba698" } } - } + }, + "origbidcpm": 0.01 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/nobid/test-cache-nobid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/nobid/test-cache-nobid-request.json index ca8e3ab2f6a..383f37b4df9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/nobid/test-cache-nobid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/nobid/test-cache-nobid-request.json @@ -8,7 +8,10 @@ "price": 0.01, "id": "testid", "impid": "testimpid", - "cid": "8048" + "cid": "8048", + "ext": { + "origbidcpm": 0.01 + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/nobid/test-nobid-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/nobid/test-nobid-bid-request.json index e0868c03cee..973371c223b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/nobid/test-nobid-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/nobid/test-nobid-bid-request.json @@ -10,17 +10,18 @@ "tagid": "impId021", "ext": { "bidder": { - "siteId" : 23, - "placementId" : 25 + "siteId": 23, + "placementId": 25 } } } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-auction-onetag-request.json b/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-auction-onetag-request.json new file mode 100644 index 00000000000..b676426d4d9 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-auction-onetag-request.json @@ -0,0 +1,66 @@ +{ + "id": "some-request-id", + "imp": [ + { + "id": "testimpid", + "banner": { + "w": 320, + "h": 250 + }, + "displaymanager": "di_prebid", + "displaymanagerver": "2.0.0", + "tagid": "possibleTagId", + "ext": { + "onetag": { + "pubId": "386276e072", + "ext": { + "key1": "value1", + "key2": "value2" + } + } + } + } + ], + "device": { + "ua": "userAgent", + "ip": "193.168.244.1" + }, + "site": { + "publisher": { + "id": "publisherId" + } + }, + "at": 1, + "tmax": 1000, + "cur": [ + "USD" + ], + "source": { + "fd": 1, + "tid": "tid" + }, + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + } + }, + "cache": { + "bids": {} + }, + "auctiontimestamp": 1000 + } + }, + "regs": { + "ext": { + "gdpr": 0 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-auction-onetag-response.json b/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-auction-onetag-response.json new file mode 100644 index 00000000000..69c159680c7 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-auction-onetag-response.json @@ -0,0 +1,54 @@ +{ + "id": "some-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "testid", + "impid": "testimpid", + "price": 0.01, + "adid": "2068416", + "cid": "8048", + "crid": "24080", + "ext": { + "prebid": { + "type": "banner", + "targeting": { + "hb_pb": "0.00", + "hb_cache_id_onetag": "3c0769d8-0dd9-465c-8bf3-f570605ba698", + "hb_bidder_onetag": "onetag", + "hb_bidder": "onetag", + "hb_cache_id": "3c0769d8-0dd9-465c-8bf3-f570605ba698", + "hb_pb_onetag": "0.00", + "hb_cache_host": "{{ cache.host }}", + "hb_cache_host_onetag": "{{ cache.host }}", + "hb_cache_path": "{{ cache.path }}", + "hb_cache_path_onetag": "{{ cache.path }}" + }, + "cache": { + "bids": { + "url": "{{ cache.resource_url }}3c0769d8-0dd9-465c-8bf3-f570605ba698", + "cacheId": "3c0769d8-0dd9-465c-8bf3-f570605ba698" + } + } + }, + "origbidcpm": 0.01 + } + } + ], + "seat": "onetag", + "group": 0 + } + ], + "cur": "USD", + "ext": { + "responsetimemillis": { + "onetag": "{{ onetag.response_time_ms }}", + "cache": "{{ cache.response_time_ms }}" + }, + "prebid": { + "auctiontimestamp": 1000 + }, + "tmaxrequest": 1000 + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-cache-onetag-request.json b/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-cache-onetag-request.json new file mode 100644 index 00000000000..383f37b4df9 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-cache-onetag-request.json @@ -0,0 +1,18 @@ +{ + "puts": [ + { + "type": "json", + "value": { + "crid": "24080", + "adid": "2068416", + "price": 0.01, + "id": "testid", + "impid": "testimpid", + "cid": "8048", + "ext": { + "origbidcpm": 0.01 + } + } + } + ] +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-cache-onetag-response.json b/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-cache-onetag-response.json new file mode 100644 index 00000000000..c0100536be1 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-cache-onetag-response.json @@ -0,0 +1,7 @@ +{ + "responses": [ + { + "uuid": "3c0769d8-0dd9-465c-8bf3-f570605ba698" + } + ] +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-onetag-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-onetag-bid-request.json new file mode 100644 index 00000000000..8408218f9fe --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-onetag-bid-request.json @@ -0,0 +1,75 @@ +{ + "id": "some-request-id", + "imp": [ + { + "id": "testimpid", + "banner": { + "w": 320, + "h": 250 + }, + "displaymanager": "di_prebid", + "displaymanagerver": "2.0.0", + "tagid": "possibleTagId", + "ext": { + "key1": "value1", + "key2": "value2" + } + } + ], + "site": { + "domain": "www.example.com", + "page": "http://www.example.com", + "publisher": { + "id": "publisherId", + "domain": "example.com" + }, + "ext": { + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "ip": "193.168.244.1" + }, + "user": { + "buyeruid": "OT-UID" + }, + "at": 1, + "tmax": 1000, + "cur": [ + "USD" + ], + "source": { + "fd": 1, + "tid": "tid" + }, + "regs": { + "ext": { + "gdpr": 0 + } + }, + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + }, + "includewinners": true, + "includebidderkeys": true + }, + "cache": { + "bids": {} + }, + "auctiontimestamp": 1000, + "channel": { + "name": "web" + } + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-onetag-bid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-onetag-bid-response.json new file mode 100644 index 00000000000..ca4e6ee1db4 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/onetag/test-onetag-bid-response.json @@ -0,0 +1,18 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "crid": "24080", + "adid": "2068416", + "price": 0.01, + "id": "testid", + "impid": "testimpid", + "cid": "8048" + } + ], + "type": "banner" + } + ] +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/openx/test-auction-openx-request.json b/src/test/resources/org/prebid/server/it/openrtb2/openx/test-auction-openx-request.json index 0c573d26446..6afacaf2b7d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/openx/test-auction-openx-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/openx/test-auction-openx-request.json @@ -1,7 +1,6 @@ { "id": "tid", "imp": [ - { "id": "impId011", "banner": { @@ -143,4 +142,4 @@ "gdpr": 0 } } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/openx/test-auction-openx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/openx/test-auction-openx-response.json index ffe12642c3b..c297478c724 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/openx/test-auction-openx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/openx/test-auction-openx-response.json @@ -34,7 +34,9 @@ "cacheId": "6f10452f-dbf8-4d5c-9f40-760080e08612" } } - } + }, + "origbidcpm": 5.78, + "origbidcur": "USD" } }, { @@ -68,7 +70,9 @@ "cacheId": "16649e72-5dd5-4ab9-ab83-df9a5f06d9d1" } } - } + }, + "origbidcpm": 5.78, + "origbidcur": "USD" } }, { @@ -109,7 +113,9 @@ "cacheId": "857b3394-c5ac-402c-9cca-54ae52b927fc" } } - } + }, + "origbidcpm": 5.78, + "origbidcur": "USD" } }, { @@ -150,7 +156,9 @@ "cacheId": "18b7676c-f024-4a06-aa1a-5d222a643603" } } - } + }, + "origbidcpm": 5.78, + "origbidcur": "USD" } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/openx/test-cache-openx-request.json b/src/test/resources/org/prebid/server/it/openrtb2/openx/test-cache-openx-request.json index de9ff41f810..971befb3df6 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/openx/test-cache-openx-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/openx/test-cache-openx-request.json @@ -9,7 +9,11 @@ "adm": "adm003", "crid": "crid00", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 5.78, + "origbidcur": "USD" + } } }, { @@ -21,7 +25,11 @@ "adm": "adm001", "crid": "crid00", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 5.78, + "origbidcur": "USD" + } } }, { @@ -33,7 +41,11 @@ "adm": "adm002", "crid": "crid00", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 5.78, + "origbidcur": "USD" + } } }, { @@ -45,7 +57,11 @@ "adm": "adm00", "crid": "crid00", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 5.78, + "origbidcur": "USD" + } } }, { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/openx/test-openx-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/openx/test-openx-bid-request-1.json index bd909861224..4f08b973723 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/openx/test-openx-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/openx/test-openx-bid-request-1.json @@ -43,10 +43,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/openx/test-openx-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/openx/test-openx-bid-request-2.json index de95eb016a6..fa044b34a27 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/openx/test-openx-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/openx/test-openx-bid-request-2.json @@ -21,10 +21,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/openx/test-openx-bid-request-3.json b/src/test/resources/org/prebid/server/it/openrtb2/openx/test-openx-bid-request-3.json index c5a2e86a49e..fbe0d9a7ea8 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/openx/test-openx-bid-request-3.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/openx/test-openx-bid-request-3.json @@ -21,10 +21,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 @@ -39,7 +40,7 @@ "ifa": "ifaId" }, "user": { - "buyeruid":"OX-UID", + "buyeruid": "OX-UID", "ext": { "consent": "consentValue" } @@ -62,4 +63,4 @@ "delDomain": "se-demo-d.openx.net", "bc": "hb_pbs_1.0.0" } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/orbidder/test-auction-orbidder-response.json b/src/test/resources/org/prebid/server/it/openrtb2/orbidder/test-auction-orbidder-response.json index 7a64ffe644a..394b4c8e078 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/orbidder/test-auction-orbidder-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/orbidder/test-auction-orbidder-response.json @@ -31,7 +31,8 @@ "url": "{{ cache.resource_url }}f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 0.01 }, "id": "1", "impid": "impId001", @@ -53,4 +54,4 @@ }, "tmaxrequest": 3000 } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/orbidder/test-cache-orbidder-request.json b/src/test/resources/org/prebid/server/it/openrtb2/orbidder/test-cache-orbidder-request.json index c6692479e4a..cdadbec00c4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/orbidder/test-cache-orbidder-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/orbidder/test-cache-orbidder-request.json @@ -10,9 +10,10 @@ "cid": "test_cid", "crid": "test_banner_crid", "ext": { - "format": "BANNER" + "format": "BANNER", + "origbidcpm": 0.01 } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/orbidder/test-orbidder-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/orbidder/test-orbidder-bid-request.json index 78558170715..0d6c22c34de 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/orbidder/test-orbidder-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/orbidder/test-orbidder-bid-request.json @@ -11,7 +11,7 @@ } ] }, - "tagid" : "2eb6bd58-865c-47ce-af7f-a918108c3fd2", + "tagid": "2eb6bd58-865c-47ce-af7f-a918108c3fd2", "ext": { "bidder": { "accountId": "orbidder-test", @@ -25,7 +25,8 @@ "domain": "example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-auction-outbrain-request.json b/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-auction-outbrain-request.json new file mode 100644 index 00000000000..d201548e64f --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-auction-outbrain-request.json @@ -0,0 +1,75 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId001", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "outbrain": { + "publisher": { + "id": "extPubId", + "name": "extPubName", + "domain": "extPubDomain" + }, + "tagid": "extTagId", + "bcat": [ + "bcatVal" + ], + "badv": [ + "badvVal" + ] + } + } + } + ], + "device": { + "pxratio": 4.2, + "dnt": 2, + "language": "en", + "ifa": "ifaId", + "ua": "testUa", + "ip": "193.168.244.1" + }, + "site": { + "page": "awesomePage", + "publisher": { + "id": "publisherId" + } + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "source": { + "fd": 1, + "tid": "tid" + }, + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + } + }, + "cache": { + "bids": {} + }, + "auctiontimestamp": 1000 + } + }, + "regs": { + "ext": { + "gdpr": 0 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-auction-outbrain-response.json b/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-auction-outbrain-response.json new file mode 100644 index 00000000000..1e8742d987c --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-auction-outbrain-response.json @@ -0,0 +1,59 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "id": "bid001", + "impid": "impId001", + "price": 3.33, + "adm": "adm001", + "adid": "adid001", + "cid": "cid001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "banner", + "targeting": { + "hb_pb": "3.30", + "hb_size_outbrain": "300x250", + "hb_bidder_outbrain": "outbrain", + "hb_cache_path": "{{ cache.path }}", + "hb_size": "300x250", + "hb_cache_host_outbrain": "{{ cache.host }}", + "hb_cache_path_outbrain": "{{ cache.path }}", + "hb_cache_id_outbrain": "f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "hb_bidder": "outbrain", + "hb_cache_id": "f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "hb_pb_outbrain": "3.30", + "hb_cache_host": "{{ cache.host }}" + }, + "cache": { + "bids": { + "url": "{{ cache.resource_url }}f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" + } + } + }, + "origbidcpm" : 3.33 + } + } + ], + "seat": "outbrain", + "group": 0 + } + ], + "cur": "USD", + "ext": { + "responsetimemillis": { + "outbrain": "{{ outbrain.response_time_ms }}", + "cache": "{{ cache.response_time_ms }}" + }, + "prebid": { + "auctiontimestamp": 1000 + }, + "tmaxrequest": 5000 + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-cache-outbrain-request.json b/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-cache-outbrain-request.json new file mode 100644 index 00000000000..424a76e0ac4 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-cache-outbrain-request.json @@ -0,0 +1,21 @@ +{ + "puts": [ + { + "type": "json", + "value": { + "id": "bid001", + "impid": "impId001", + "price": 3.33, + "adm": "adm001", + "adid": "adid001", + "cid": "cid001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "origbidcpm": 3.33 + } + } + } + ] +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-cache-outbrain-response.json b/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-cache-outbrain-response.json new file mode 100644 index 00000000000..93d0b8de2cd --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-cache-outbrain-response.json @@ -0,0 +1,7 @@ +{ + "responses": [ + { + "uuid": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-outbrain-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-outbrain-bid-request.json new file mode 100644 index 00000000000..952564e95ce --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-outbrain-bid-request.json @@ -0,0 +1,91 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId001", + "banner": { + "w": 300, + "h": 250 + }, + "tagid": "extTagId", + "ext": { + "bidder": { + "publisher": { + "id": "extPubId", + "name": "extPubName", + "domain": "extPubDomain" + }, + "tagid": "extTagId", + "bcat": [ + "bcatVal" + ], + "badv": [ + "badvVal" + ] + } + } + } + ], + "site": { + "page": "awesomePage", + "publisher": { + "id": "extPubId", + "name": "extPubName", + "domain": "extPubDomain" + }, + "ext": { + "amp": 0 + } + }, + "device": { + "ua": "testUa", + "ip": "193.168.244.1", + "dnt": 2, + "pxratio": 4.2, + "language": "en", + "ifa": "ifaId" + }, + "user": { + "buyeruid": "OB-UID" + }, + "at": 1, + "tmax": 5000, + "bcat" : [ "bcatVal" ], + "badv" : [ "badvVal" ], + "cur": [ + "USD" + ], + "source": { + "fd": 1, + "tid": "tid" + }, + "regs": { + "ext": { + "gdpr": 0 + } + }, + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + }, + "includewinners": true, + "includebidderkeys": true + }, + "cache": { + "bids": {} + }, + "auctiontimestamp": 1000, + "channel": { + "name": "web" + } + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-outbrain-bid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-outbrain-bid-response.json new file mode 100644 index 00000000000..95a93284e04 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/outbrain/test-outbrain-bid-response.json @@ -0,0 +1,20 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "id": "bid001", + "impid": "impId001", + "price": 3.33, + "adid": "adid001", + "crid": "crid001", + "cid": "cid001", + "adm": "adm001", + "h": 250, + "w": 300 + } + ] + } + ] +} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-auction-pangle-request.json b/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-auction-pangle-request.json new file mode 100644 index 00000000000..78aad361c2b --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-auction-pangle-request.json @@ -0,0 +1,77 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId001", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "prebid": { + "bidder": { + "pangle": { + "token": ".token" + } + } + } + } + } + ], + "device": { + "pxratio": 4.2, + "dnt": 2, + "language": "en", + "ifa": "ifaId" + }, + "site": { + "publisher": { + "id": "publisherId" + } + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "source": { + "fd": 1, + "tid": "tid" + }, + "user": { + "ext": { + "consent": "consentValue" + } + }, + "regs": { + "ext": { + "gdpr": 0 + } + }, + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + } + }, + "cache": { + "bids": {}, + "vastxml": { + "ttlseconds": 120 + } + }, + "auctiontimestamp": 1000 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-auction-pangle-response.json b/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-auction-pangle-response.json new file mode 100644 index 00000000000..79a23244932 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-auction-pangle-response.json @@ -0,0 +1,62 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "id": "bid001", + "impid": "impId001", + "price": 1.25, + "adm": "adm001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "banner", + "targeting": { + "hb_pb": "1.20", + "hb_cache_id_pangle": "9092799c-93b0-4e11-a232-2c0151d5d275", + "hb_cache_path_pangle": "{{ cache.path }}", + "hb_cache_path": "{{ cache.path }}", + "hb_pb_pangle": "1.20", + "hb_size": "300x250", + "hb_bidder_pangle": "pangle", + "hb_size_pangle": "300x250", + "hb_bidder": "pangle", + "hb_cache_id": "9092799c-93b0-4e11-a232-2c0151d5d275", + "hb_cache_host": "{{ cache.host }}", + "hb_cache_host_pangle": "{{ cache.host }}" + }, + "cache": { + "bids": { + "url": "{{ cache.resource_url }}9092799c-93b0-4e11-a232-2c0151d5d275", + "cacheId": "9092799c-93b0-4e11-a232-2c0151d5d275" + } + } + }, + "bidder": { + "pangle": { + "adtype": 1 + } + }, + "origbidcpm" : 1.25 + } + } + ], + "seat": "pangle", + "group": 0 + } + ], + "cur": "USD", + "ext": { + "responsetimemillis": { + "pangle": "{{ pangle.response_time_ms }}", + "cache": "{{ cache.response_time_ms }}" + }, + "prebid": { + "auctiontimestamp": 1000 + }, + "tmaxrequest": 5000 + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-cache-matcher-pangle.json b/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-cache-matcher-pangle.json new file mode 100644 index 00000000000..e438661be9f --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-cache-matcher-pangle.json @@ -0,0 +1,5 @@ +{ + "bid001@1.25": "9092799c-93b0-4e11-a232-2c0151d5d275", + "bid01@2.25": "83cdc325-c816-4d2e-bf2c-9213a70671dd", + "adm002": "99dc3357-34ac-4819-9f68-0820039a542f" +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-cache-pangle-request.json b/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-cache-pangle-request.json new file mode 100644 index 00000000000..952d0e304a7 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-cache-pangle-request.json @@ -0,0 +1,22 @@ +{ + "puts": [ + { + "type": "json", + "value": { + "id": "bid001", + "impid": "impId001", + "price": 1.25, + "adm": "adm001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "origbidcpm" : 1.25, + "pangle": { + "adtype": 1 + } + } + } + } + ] +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-pangle-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-pangle-bid-request-1.json new file mode 100644 index 00000000000..ea7ded68956 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-pangle-bid-request-1.json @@ -0,0 +1,88 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId001", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "token": ".token" + }, + "adtype" : 1 + } + } + ], + "site": { + "domain": "www.example.com", + "page": "http://www.example.com", + "publisher": { + "id": "publisherId", + "domain": "example.com" + }, + "ext": { + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "dnt": 2, + "ip": "193.168.244.1", + "pxratio": 4.2, + "language": "en", + "ifa": "ifaId" + }, + "user": { + "buyeruid": "PG-UID", + "ext": { + "consent": "consentValue" + } + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "source": { + "fd": 1, + "tid": "tid" + }, + "regs": { + "ext": { + "gdpr": 0 + } + }, + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + }, + "includewinners": true, + "includebidderkeys": true + }, + "cache": { + "bids": {}, + "vastxml": { + "ttlseconds": 120 + } + }, + "auctiontimestamp": 1000, + "channel": { + "name": "web" + } + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-pangle-bid-response-1.json b/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-pangle-bid-response-1.json new file mode 100644 index 00000000000..caa03582698 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/pangle/test-pangle-bid-response-1.json @@ -0,0 +1,24 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "id": "bid001", + "impid": "impId001", + "price": 1.25, + "crid": "crid001", + "adm": "adm001", + "h": 250, + "w": 300, + "ext": { + "pangle": { + "adtype": 1 + } + } + } + ] + } + ], + "bidid": "bid001" +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-request.json b/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-request.json index 98820ac6c53..c2b3cdf870e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-request.json @@ -17,13 +17,20 @@ "pubmatic": { "adSlot": "slot9@300x250:zzz", "publisherId": " publisherId ", - "keywords": [{ - "key": "pmZoneID", - "value": ["Zone1", "Zone2"] - }, + "keywords": [ + { + "key": "pmZoneID", + "value": [ + "Zone1", + "Zone2" + ] + }, { "key": "preference", - "value": ["sports", "movies"] + "value": [ + "sports", + "movies" + ] } ], "wrapper": { @@ -46,10 +53,14 @@ "pubmatic": { "adSlot": "slot9@300x250:zzz", "publisherId": "publisherId", - "keywords": [{ - "key": "pmZoneID", - "value": ["Zone1", "Zone2"] - } + "keywords": [ + { + "key": "pmZoneID", + "value": [ + "Zone1", + "Zone2" + ] + } ], "wrapper": { "version": 1, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-response.json b/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-response.json index e3540b10ae0..a2f715698c5 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-auction-pubmatic-response.json @@ -34,7 +34,8 @@ "cacheId": "19fdd2e5-8bd5-498d-abde-73ed5405c11e" } } - } + }, + "origbidcpm": 4.75 } }, { @@ -76,6 +77,7 @@ } } }, + "origbidcpm": 4.0, "bidder": { "BidType": 1 } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-cache-pubmatic-request.json b/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-cache-pubmatic-request.json index 009969220de..0f277bbb0d5 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-cache-pubmatic-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-cache-pubmatic-request.json @@ -11,7 +11,8 @@ "w": 300, "h": 600, "ext": { - "BidType": 1 + "BidType": 1, + "origbidcpm": 4 } } }, @@ -24,7 +25,10 @@ "adm": "adm9", "crid": "crid9", "w": 300, - "h": 600 + "h": 600, + "ext": { + "origbidcpm": 4.75 + } } }, { @@ -33,4 +37,4 @@ "expiry": 120 } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-pubmatic-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-pubmatic-bid-request-1.json index d4a5120aaf7..6693f9f1bc7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-pubmatic-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pubmatic/test-pubmatic-bid-request-1.json @@ -34,10 +34,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-auction-pubnative-response.json b/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-auction-pubnative-response.json index e0d02cf47b6..318897ab981 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-auction-pubnative-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-auction-pubnative-response.json @@ -43,7 +43,8 @@ "cacheId": "88ec8e12-07cc-4c36-b7ab-8982b6ab104e" } } - } + }, + "origbidcpm": 6.66 } }, { @@ -79,7 +80,8 @@ "cacheId": "f3518368-72c3-42db-99f5-44c249eb92d3" } } - } + }, + "origbidcpm": 3.33 } }, { @@ -111,7 +113,8 @@ "cacheId": "4be8fb3d-18dc-4759-ac9f-aa633bced257" } } - } + }, + "origbidcpm": 9.99 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-cache-pubnative-request.json b/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-cache-pubnative-request.json index 0f6887be877..8509cc66bd2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-cache-pubnative-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-cache-pubnative-request.json @@ -11,7 +11,10 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 3.33 + } } }, { @@ -25,7 +28,10 @@ "cid": "cid002", "crid": "crid002", "w": 640, - "h": 480 + "h": 480, + "ext": { + "origbidcpm": 6.66 + } } }, { @@ -37,7 +43,10 @@ "adm": "adm003", "adid": "adid003", "cid": "cid003", - "crid": "crid003" + "crid": "crid003", + "ext": { + "origbidcpm": 9.99 + } } }, { @@ -46,4 +55,4 @@ "expiry": 120 } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-pubnative-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-pubnative-bid-request-1.json index 4a4f9d894fe..e10fe78ee21 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-pubnative-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-pubnative-bid-request-1.json @@ -22,10 +22,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-pubnative-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-pubnative-bid-request-2.json index 62e1d9d9061..7528e643736 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-pubnative-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-pubnative-bid-request-2.json @@ -19,10 +19,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-pubnative-bid-request-3.json b/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-pubnative-bid-request-3.json index 6a9591a6ce6..80aa5071cd4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-pubnative-bid-request-3.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pubnative/test-pubnative-bid-request-3.json @@ -16,10 +16,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pulsepoint/test-auction-pulsepoint-response.json b/src/test/resources/org/prebid/server/it/openrtb2/pulsepoint/test-auction-pulsepoint-response.json index 1854292af69..123016b5073 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pulsepoint/test-auction-pulsepoint-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pulsepoint/test-auction-pulsepoint-response.json @@ -34,7 +34,8 @@ "cacheId": "b537fcb1-28c9-4cd1-bf74-abc7730fd1f4" } } - } + }, + "origbidcpm": 4.75 } }, { @@ -68,7 +69,8 @@ "cacheId": "a4073156-828d-4a22-acdc-84dc4529149e" } } - } + }, + "origbidcpm": 3.75 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pulsepoint/test-cache-pulsepoint-request.json b/src/test/resources/org/prebid/server/it/openrtb2/pulsepoint/test-cache-pulsepoint-request.json index 756aa43f132..562ae10e6a0 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pulsepoint/test-cache-pulsepoint-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pulsepoint/test-cache-pulsepoint-request.json @@ -9,7 +9,10 @@ "adm": "adm8", "crid": "crid8", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 4.75 + } } }, { @@ -21,8 +24,11 @@ "adm": "adm81", "crid": "crid81", "w": 120, - "h": 180 + "h": 180, + "ext": { + "origbidcpm": 3.75 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/pulsepoint/test-pulsepoint-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/pulsepoint/test-pulsepoint-bid-request-1.json index 028db59ce88..c571e445603 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/pulsepoint/test-pulsepoint-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/pulsepoint/test-pulsepoint-bid-request-1.json @@ -43,10 +43,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "321" + "id": "321", + "domain" : "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-auction-revcontent-request.json b/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-auction-revcontent-request.json index de925ea5805..758211b817b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-auction-revcontent-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-auction-revcontent-request.json @@ -60,7 +60,7 @@ } }, "user": { - "buyeruid" : "revcontent-UID" + "buyeruid": "revcontent-UID" }, "regs": { "ext": { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-auction-revcontent-response.json b/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-auction-revcontent-response.json index 514b458bea6..9cd08c95dfc 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-auction-revcontent-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-auction-revcontent-response.json @@ -36,7 +36,8 @@ "cacheId": "a5d3a873-d06e-4f2f-8556-120e05d62b28" } } - } + }, + "origbidcpm": 0.5 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-cache-revcontent-request.json b/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-cache-revcontent-request.json index 9f8bad8caff..ec7898f8cee 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-cache-revcontent-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-cache-revcontent-request.json @@ -11,7 +11,10 @@ "cid": "987", "crid": "12345678", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 0.5 + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-revcontent-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-revcontent-bid-request-1.json index b5075892f18..dea922cca4a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-revcontent-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-revcontent-bid-request-1.json @@ -17,10 +17,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-revcontent-bid-response-1.json b/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-revcontent-bid-response-1.json index 656c3af2365..b8c469f1f8a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-revcontent-bid-response-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/revcontent/test-revcontent-bid-response-1.json @@ -3,18 +3,20 @@ "seatbid": [ { "seat": "revcontent", - "bid": [{ - "id": "randomid", - "impid": "test-imp-id", - "price": 0.500000, - "adid": "12345678", - "adm": "
\\\"}\",\"adomain\":[\"appnexus.com\"],\"iurl\":\"http://nym1-ib.adnxs.com/cr?id=69595837\",\"cid\":\"958\",\"crid\":\"69595837\",\"ext\":{\"appnexus\":{\"brand_id\":1,\"brand_category_id\":1,\"auction_id\":5607483846416358664,\"bidder_id\":2,\"bid_ad_type\":3}}}]}],\"bidid\":\"5778926625248726496\",\"cur\":\"USD\"}", "status": 200 } @@ -345,7 +357,7 @@ "appnexusAlias": [ { "uri": "{{ appnexus.exchange_uri }}?member_id=104", - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId3\",\"banner\":{\"format\":[{\"w\":300,\"h\":250},{\"w\":300,\"h\":600}],\"w\":300,\"h\":250,\"pos\":1},\"tagid\":\"abc\",\"bidfloor\":1.0,\"ext\":{\"appnexus\":{\"keywords\":\"foo=barAlias,foo=bazAlias\",\"traffic_source_code\":\"trafficSourceAlias\"}}}],\"site\":{\"domain\":\"example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"id\":\"5001\"},\"ext\":{\"amp\":0}},\"device\":{\"ua\":\"userAgent\",\"dnt\":2,\"ip\":\"80.215.195.0\",\"pxratio\":4.2,\"language\":\"en\",\"ext\":{\"prebid\":{\"interstitial\":{\"minwidthperc\":50,\"minheightperc\":60}}}},\"user\":{\"data\":[{\"segment\":[{\"id\":\"segmentId1\"},{\"id\":\"segmentId2\"}],\"ext\":{\"taxonomyname\":\"Iab\"}}],\"ext\":{\"consent\":\"BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA\"}},\"at\":1,\"tmax\":5000,\"cur\":[\"USD\"],\"source\":{\"fd\":1,\"tid\":\"tid\",\"ext\":{\"schain\":{\"ver\":\"1.0\"}}},\"regs\":{\"ext\":{\"us_privacy\":\"1YNN\"}},\"ext\":{\"prebid\":{\"debug\":1,\"aliases\":{\"appnexusAlias\":\"appnexus\"},\"currency\":{\"rates\":{\"EUR\":{\"USD\":1.2406},\"USD\":{\"EUR\":0.811}},\"usepbsrates\":false},\"targeting\":{\"pricegranularity\":{\"precision\":2,\"ranges\":[{\"max\":20,\"increment\":0.1}]},\"includewinners\":true,\"includebidderkeys\":true},\"cache\":{\"bids\":{},\"vastxml\":{\"ttlseconds\":120}},\"events\":{},\"auctiontimestamp\":1000,\"integration\":\"dmbjs\",\"channel\":{\"name\":\"web\"}}}}", + "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId3\",\"banner\":{\"format\":[{\"w\":300,\"h\":250},{\"w\":300,\"h\":600}],\"w\":300,\"h\":250,\"pos\":1},\"tagid\":\"abc\",\"bidfloor\":1.0,\"ext\":{\"appnexus\":{\"keywords\":\"foo=barAlias,foo=bazAlias\",\"traffic_source_code\":\"trafficSourceAlias\"}}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"id\":\"5001\",\"domain\":\"example.com\"},\"ext\":{\"amp\":0}},\"device\":{\"ua\":\"userAgent\",\"dnt\":2,\"ip\":\"80.215.195.0\",\"pxratio\":4.2,\"language\":\"en\",\"ext\":{\"prebid\":{\"interstitial\":{\"minwidthperc\":50,\"minheightperc\":60}}}},\"user\":{\"data\":[{\"segment\":[{\"id\":\"segmentId1\"},{\"id\":\"segmentId2\"}],\"ext\":{\"segtax\":3}}],\"ext\":{\"consent\":\"BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA\"}},\"at\":1,\"tmax\":5000,\"cur\":[\"USD\"],\"source\":{\"fd\":1,\"tid\":\"tid\",\"ext\":{\"schain\":{\"ver\":\"1.0\"}}},\"regs\":{\"ext\":{\"us_privacy\":\"1YNN\"}},\"ext\":{\"prebid\":{\"debug\":1,\"aliases\":{\"appnexusAlias\":\"appnexus\"},\"currency\":{\"rates\":{\"EUR\":{\"USD\":1.2406},\"USD\":{\"EUR\":0.811}},\"usepbsrates\":false},\"targeting\":{\"pricegranularity\":{\"precision\":2,\"ranges\":[{\"max\":20,\"increment\":0.1}]},\"includewinners\":true,\"includebidderkeys\":true},\"cache\":{\"bids\":{},\"vastxml\":{\"ttlseconds\":120}},\"events\":{},\"auctiontimestamp\":1000,\"integration\":\"dmbjs\",\"channel\":{\"name\":\"web\"}}}}", "responsebody": "{\"id\":\"tid\",\"seatbid\":[{\"seat\":\"959\",\"bid\":[{\"id\":\"7706636740145184840\",\"impid\":\"impId3\",\"price\":5.0,\"adid\":\"29681110\",\"adm\":\"some-test-ad\",\"adomain\":[\"appnexus.com\"],\"iurl\":\"http://nym1-ib.adnxs.com/cr?id=29681110\",\"cid\":\"958\",\"crid\":\"29681110\",\"h\":250,\"w\":300,\"cat\":[\"IAB20-3\"],\"ext\":{\"appnexus\":{\"brand_id\":350,\"brand_category_id\":350,\"auction_id\":8189378542222915031,\"bidder_id\":2,\"bid_ad_type\":0,\"ranking_price\":0.0}}}]}],\"bidid\":\"5778926625248726496\",\"cur\":\"USD\"}", "status": 200 } @@ -353,13 +365,13 @@ "rubicon": [ { "uri": "{{ rubicon.exchange_uri }}?tk_xint=dmbjs", - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"video\":{\"mimes\":[\"mimes\"],\"minduration\":20,\"maxduration\":60,\"protocols\":[1],\"w\":300,\"h\":250,\"startdelay\":5,\"skipmin\":0,\"skipafter\":0,\"playbackmethod\":[1],\"ext\":{\"skip\":5,\"skipdelay\":1,\"rp\":{\"size_id\":15},\"videotype\":\"rewarded\"}},\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"rating\":[\"5-star\"],\"prodtype\":[\"tech\"],\"page\":[\"http://www.example.com\"]},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"dnt\":2,\"ip\":\"80.215.195.0\",\"pxratio\":4.2,\"language\":\"en\",\"ext\":{\"rp\":{\"pixelratio\":4.2}}},\"user\":{\"data\":[{\"segment\":[{\"id\":\"segmentId1\"},{\"id\":\"segmentId2\"}],\"ext\":{\"taxonomyname\":\"Iab\"}}],\"ext\":{\"consent\":\"BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA\",\"rp\":{\"target\":{\"ucat\":[\"new\"],\"search\":[\"iphone\"],\"iab\":[\"segmentId1\",\"segmentId2\"]}}}},\"at\":1,\"tmax\":5000,\"source\":{\"fd\":1,\"tid\":\"tid\",\"ext\":{\"schain\":{\"ver\":\"1.0\",\"complete\":1,\"nodes\":[{\"asi\":\"superads.com\",\"sid\":\"123\",\"hp\":1}]}}},\"regs\":{\"ext\":{\"us_privacy\":\"1YNN\"}}}", + "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"video\":{\"mimes\":[\"mimes\"],\"minduration\":20,\"maxduration\":60,\"protocols\":[1],\"w\":300,\"h\":250,\"startdelay\":5,\"skipmin\":0,\"skipafter\":0,\"playbackmethod\":[1],\"ext\":{\"skip\":5,\"skipdelay\":1,\"rp\":{\"size_id\":15},\"videotype\":\"rewarded\"}},\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"rating\":[\"5-star\"],\"prodtype\":[\"tech\"],\"page\":[\"http://www.example.com\"]},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"dnt\":2,\"ip\":\"80.215.195.0\",\"pxratio\":4.2,\"language\":\"en\",\"ext\":{\"rp\":{\"pixelratio\":4.2}}},\"user\":{\"data\":[{\"segment\":[{\"id\":\"segmentId1\"},{\"id\":\"segmentId2\"}],\"ext\":{\"segtax\":3}}],\"ext\":{\"consent\":\"BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA\",\"rp\":{\"target\":{\"ucat\":[\"new\"],\"search\":[\"iphone\"],\"iab\":[\"segmentId1\",\"segmentId2\"]}}}},\"at\":1,\"tmax\":5000,\"source\":{\"fd\":1,\"tid\":\"tid\",\"ext\":{\"schain\":{\"ver\":\"1.0\",\"complete\":1,\"nodes\":[{\"asi\":\"superads.com\",\"sid\":\"123\",\"hp\":1}]}}},\"regs\":{\"ext\":{\"us_privacy\":\"1YNN\"}}}", "responsebody": "{\"id\":\"bidResponseId1\",\"seatbid\":[{\"bid\":[{\"id\":\"880290288\",\"impid\":\"impId1\",\"price\":8.43,\"adm\":\"\",\"crid\":\"crid1\",\"w\":300,\"h\":250,\"ext\":{\"rp\":{\"targeting\":[{\"key\":\"rpfl_1001\",\"values\":[\"2_tier0100\"]}]}}}],\"seat\":\"seatId1\",\"group\":0}]}", "status": 200 }, { "uri": "{{ rubicon.exchange_uri }}?tk_xint=dmbjs", - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId2\",\"banner\":{\"format\":[{\"w\":300,\"h\":600}],\"w\":300,\"h\":600,\"ext\":{\"rp\":{\"size_id\":10,\"mime\":\"text/html\"}}},\"ext\":{\"rp\":{\"zone_id\":7001,\"target\":{\"page\":[\"http://www.example.com\"]},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":5001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":6001}}},\"device\":{\"ua\":\"userAgent\",\"dnt\":2,\"ip\":\"80.215.195.0\",\"pxratio\":4.2,\"language\":\"en\",\"ext\":{\"rp\":{\"pixelratio\":4.2}}},\"user\":{\"data\":[{\"segment\":[{\"id\":\"segmentId1\"},{\"id\":\"segmentId2\"}],\"ext\":{\"taxonomyname\":\"Iab\"}}],\"ext\":{\"consent\":\"BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA\",\"rp\":{\"target\":{\"iab\":[\"segmentId1\",\"segmentId2\"]}}}},\"at\":1,\"tmax\":5000,\"source\":{\"fd\":1,\"tid\":\"tid\",\"ext\":{\"schain\":{\"ver\":\"1.0\",\"complete\":1,\"nodes\":[{\"asi\":\"superads.com\",\"sid\":\"123\",\"hp\":1}]}}},\"regs\":{\"ext\":{\"us_privacy\":\"1YNN\"}}}", + "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId2\",\"banner\":{\"format\":[{\"w\":300,\"h\":600}],\"w\":300,\"h\":600,\"ext\":{\"rp\":{\"size_id\":10,\"mime\":\"text/html\"}}},\"ext\":{\"rp\":{\"zone_id\":7001,\"target\":{\"page\":[\"http://www.example.com\"]},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":5001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":6001}}},\"device\":{\"ua\":\"userAgent\",\"dnt\":2,\"ip\":\"80.215.195.0\",\"pxratio\":4.2,\"language\":\"en\",\"ext\":{\"rp\":{\"pixelratio\":4.2}}},\"user\":{\"data\":[{\"segment\":[{\"id\":\"segmentId1\"},{\"id\":\"segmentId2\"}],\"ext\":{\"segtax\":3}}],\"ext\":{\"consent\":\"BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA\",\"rp\":{\"target\":{\"iab\":[\"segmentId1\",\"segmentId2\"]}}}},\"at\":1,\"tmax\":5000,\"source\":{\"fd\":1,\"tid\":\"tid\",\"ext\":{\"schain\":{\"ver\":\"1.0\",\"complete\":1,\"nodes\":[{\"asi\":\"superads.com\",\"sid\":\"123\",\"hp\":1}]}}},\"regs\":{\"ext\":{\"us_privacy\":\"1YNN\"}}}", "responsebody": "{\"id\":\"bidResponseId2\",\"seatbid\":[{\"bid\":[{\"id\":\"466223845\",\"impid\":\"impId2\",\"price\":4.26,\"adm\":\"adm2\",\"crid\":\"crid2\",\"w\":300,\"h\":600}],\"seat\":\"seatId2\",\"group\":0}]}", "status": 200 } @@ -367,7 +379,7 @@ "cache": [ { "uri": "{{ cache.endpoint }}", - "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"7706636740145184840\",\"impid\":\"impId3\",\"price\":5,\"adm\":\"some-test-ad\",\"adid\":\"29681110\",\"adomain\":[\"appnexus.com\"],\"iurl\":\"http://nym1-ib.adnxs.com/cr?id=29681110\",\"cid\":\"958\",\"crid\":\"29681110\",\"cat\":[],\"w\":300,\"h\":250,\"ext\":{\"appnexus\":{\"brand_id\":350,\"brand_category_id\":350,\"auction_id\":8189378542222915031,\"bidder_id\":2,\"bid_ad_type\":0,\"ranking_price\":0.0}},\"wurl\":\"http://localhost:8080/event?t=win&b=7706636740145184840&a=5001&ts=1000&bidder=appnexusAlias&f=i&int=dmbjs\"}},{\"type\":\"json\",\"value\":{\"id\":\"466223845\",\"impid\":\"impId2\",\"price\":4.26,\"adm\":\"adm2\",\"crid\":\"crid2\",\"w\":300,\"h\":600,\"wurl\":\"http://localhost:8080/event?t=win&b=466223845&a=5001&ts=1000&bidder=rubicon&f=i&int=dmbjs\"}},{\"type\":\"json\",\"value\":{\"id\":\"a121a07f-1579-4465-bc5e-5c5b02a0c421\",\"impid\":\"impStoredAuctionResponse\",\"price\":0.9,\"crid\":\"crid1\",\"wurl\":\"http://localhost:8080/event?t=win&b=a121a07f-1579-4465-bc5e-5c5b02a0c421&a=5001&ts=1000&bidder=appnexus&f=i&int=dmbjs\"}},{\"type\":\"json\",\"value\":{\"id\":\"880290288\",\"impid\":\"impId1\",\"price\":8.43,\"adm\":\"\",\"crid\":\"crid1\",\"w\":300,\"h\":250,\"ext\":{\"rp\":{\"targeting\":[{\"key\":\"rpfl_1001\",\"values\":[\"2_tier0100\"]}]}},\"wurl\":\"http://localhost:8080/event?t=win&b=880290288&a=5001&ts=1000&bidder=rubicon&f=i&int=dmbjs\"}},{\"type\":\"json\",\"value\":{\"id\":\"f227a07f-1579-4465-bc5e-5c5b02a0c180\",\"impid\":\"impStoredAuctionResponse\",\"price\":0.8,\"crid\":\"crid1\",\"wurl\":\"http://localhost:8080/event?t=win&b=f227a07f-1579-4465-bc5e-5c5b02a0c180&a=5001&ts=1000&bidder=rubicon&f=i&int=dmbjs\"}},{\"type\":\"json\",\"value\":{\"id\":\"928185755156387460\",\"impid\":\"impId131\",\"price\":1,\"adm\":\"{\\\"assets\\\":[{\\\"id\\\":0,\\\"img\\\":{\\\"url\\\":\\\"http://vcdn.adnxs.com/p/creative-image/5e/b6/de/c3/5eb6dec3-4854-4dcd-980a-347f36ab502e.jpg\\\",\\\"w\\\":3000,\\\"h\\\":2250,\\\"ext\\\":{\\\"appnexus\\\":{\\\"prevent_crop\\\":0}}}},{\\\"id\\\":1,\\\"title\\\":{\\\"text\\\":\\\"This is an example Prebid Native creative\\\"}},{\\\"id\\\":2,\\\"data\\\":{\\\"value\\\":\\\"Prebid.org\\\"}},{\\\"id\\\":3,\\\"data\\\":{\\\"value\\\":\\\"ThisisaPrebidNativeCreative.Therearemanylikeit,butthisoneismine.\\\"}}],\\\"link\\\":{\\\"url\\\":\\\"http://nym1-ib.adnxs.com/click?AAAAAAAA8D8AAAAAAADwPwAAAAAAAAAAAAAAAAAA8D8AAAAAAADwPwhdYz3ZyNFNG3fXpZUyLXNZ0o5aAAAAACrElgC-AwAAvgMAAAIAAAC98iUEeP4QAAAAAABVU0QAVVNEAAEAAQARIAAAAAABAgQCAAAAAAEAhBaSXgAAAAA./pp=${AUCTION_PRICE}/cnd=%21OwwGAQiGmooHEL3llyEY-PxDIAQoADoRZGVmYXVsdCNOWU0yOjQwMjM./bn=75922/test=1/referrer=prebid.org/clickenc=http%3A%2F%2Fprebid.org%2Fdev-docs%2Fshow-native-ads.html\\\"},\\\"imptrackers\\\":[\\\"http://nym1-ib.adnxs.com/openrtb_win?e=wqT_3QLFBqBFAwAAAwDWAAUBCNmku9QFEIi6jeuTm_LoTRib7t2u2tLMlnMqNgkAAAECCPA_EQEHEAAA8D8ZCQkIAAAhCQkI8D8pEQkAMQkJqAAAMKqI2wQ4vgdAvgdIAlC95ZchWPj8Q2AAaJFAeJLRBIABAYoBA1VTRJIFBvBQmAEBoAEBqAEBsAEAuAECwAEEyAEC0AEJ2AEA4AEB8AEAigI7dWYoJ2EnLCAxMzc2ODYwLCAxNTE5MzA5NDAxKTt1ZigncicsIDY5NTk1ODM3Nh4A8IqSAvUBIXRETkdfUWlHbW9vSEVMM2xseUVZQUNENF9FTXdBRGdBUUFSSXZnZFFxb2piQkZnQVlMTURhQUJ3QUhnQWdBRUFpQUVBa0FFQm1BRUJvQUVCcUFFRHNBRUF1UUVwaTRpREFBRHdQOEVCS1l1SWd3QUE4RF9KQVhfelYzek1zXzBfMlFFQUFBAQMkRHdQLUFCQVBVQgEOLEFKZ0NBS0FDQUxVQwUQBEwwCQjwTE1BQ0FNZ0NBT0FDQU9nQ0FQZ0NBSUFEQVpBREFKZ0RBYWdEaHBxS0I3b0RFV1JsWm1GMWJIUWpUbGxOTWpvME1ESXqaAjkhT3d3R0FRNvgA8E4tUHhESUFRb0FEb1JaR1ZtWVhWc2RDTk9XVTB5T2pRd01qTS7YAugH4ALH0wHqAgpwcmViaWQub3Jn8gIRCgZBRFZfSUQSBzEzNzY4NjDyARQMQ1BHXwEUNDM1MDMwOTjyAhEKBUNQARPwmQgxNDg0NzIzOIADAYgDAZADAJgDFKADAaoDAMADkBzIAwDYAwDgAwDoAwD4AwOABACSBAkvb3BlbnJ0YjKYBACiBAwxNTIuMTkzLjYuNzSoBJrMI7IEDAgAEAAYACAAMAA4ALgEAMAEAMgEANIEEWRlZmF1bHQjTllNMjo0MDIz2gQCCADgBADwBL3llyGIBQGYBQCgBf____8FA1ABqgULc29tZS1yZXEtaWTABQDJBQAFARTwP9IFCQkFC2QAAADYBQHgBQHwBd4C-gUECAAQAJAGAZgGAA..&s=08b1535744639c904684afe46e3c6c0e4786089f&test=1&referrer=prebid.org&pp=${AUCTION_PRICE}\\\"],\\\"jstracker\\\":\\\"\\\"}\",\"adid\":\"69595837\",\"adomain\":[\"appnexus.com\"],\"iurl\":\"http://nym1-ib.adnxs.com/cr?id=69595837\",\"cid\":\"958\",\"crid\":\"69595837\",\"cat\":[\"IAB20-3\"],\"ext\":{\"appnexus\":{\"brand_id\":1,\"brand_category_id\":1,\"auction_id\":5607483846416358664,\"bidder_id\":2,\"bid_ad_type\":3}},\"wurl\":\"http://localhost:8080/event?t=win&b=928185755156387460&a=5001&ts=1000&bidder=appnexus&f=i&int=dmbjs\"}},{\"type\":\"json\",\"value\":{\"id\":\"7706636740145184841\",\"impid\":\"impId3\",\"price\":5.5,\"adm\":\"some-test-ad\",\"adid\":\"29681110\",\"adomain\":[\"appnexus.com\"],\"iurl\":\"http://nym1-ib.adnxs.com/cr?id=29681110\",\"cid\":\"958\",\"crid\":\"29681110\",\"w\":300,\"h\":250,\"ext\":{\"appnexus\":{\"brand_id\":1,\"auction_id\":8189378542222915032,\"bidder_id\":2,\"bid_ad_type\":0,\"ranking_price\":0.0}},\"wurl\":\"http://localhost:8080/event?t=win&b=7706636740145184841&a=5001&ts=1000&bidder=appnexus&f=i&int=dmbjs\"}},{\"type\":\"xml\",\"value\":\"\",\"expiry\":120}]}", + "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"7706636740145184840\",\"impid\":\"impId3\",\"price\":5,\"adm\":\"some-test-ad\",\"adid\":\"29681110\",\"adomain\":[\"appnexus.com\"],\"iurl\":\"http://nym1-ib.adnxs.com/cr?id=29681110\",\"cid\":\"958\",\"crid\":\"29681110\",\"cat\":[],\"w\":300,\"h\":250,\"ext\":{\"appnexus\":{\"brand_id\":350,\"brand_category_id\":350,\"auction_id\":8189378542222915031,\"bidder_id\":2,\"bid_ad_type\":0,\"ranking_price\":0.0},\"origbidcpm\":5,\"origbidcur\":\"USD\"},\"wurl\":\"http://localhost:8080/event?t=win&b=7706636740145184840&a=5001&ts=1000&bidder=appnexusAlias&f=i&int=dmbjs\"}},{\"type\":\"json\",\"value\":{\"id\":\"a121a07f-1579-4465-bc5e-5c5b02a0c421\",\"impid\":\"impStoredAuctionResponse\",\"price\":0.9,\"crid\":\"crid1\",\"ext\":{\"origbidcpm\":0.9,\"origbidcur\":\"USD\"},\"wurl\":\"http://localhost:8080/event?t=win&b=a121a07f-1579-4465-bc5e-5c5b02a0c421&a=5001&ts=1000&bidder=appnexus&f=i&int=dmbjs\"}},{\"type\":\"json\",\"value\":{\"id\":\"7706636740145184841\",\"impid\":\"impId3\",\"price\":5.5,\"adm\":\"some-test-ad\",\"adid\":\"29681110\",\"adomain\":[\"appnexus.com\"],\"iurl\":\"http://nym1-ib.adnxs.com/cr?id=29681110\",\"cid\":\"958\",\"crid\":\"29681110\",\"w\":300,\"h\":250,\"ext\":{\"appnexus\":{\"brand_id\":1,\"auction_id\":8189378542222915032,\"bidder_id\":2,\"bid_ad_type\":0,\"ranking_price\":0.0},\"origbidcpm\":5.5,\"origbidcur\":\"USD\"},\"wurl\":\"http://localhost:8080/event?t=win&b=7706636740145184841&a=5001&ts=1000&bidder=appnexus&f=i&int=dmbjs\"}},{\"type\":\"json\",\"value\":{\"id\":\"f227a07f-1579-4465-bc5e-5c5b02a0c180\",\"impid\":\"impStoredAuctionResponse\",\"price\":0.8,\"crid\":\"crid1\",\"ext\":{\"origbidcpm\":0.8,\"origbidcur\":\"USD\"},\"wurl\":\"http://localhost:8080/event?t=win&b=f227a07f-1579-4465-bc5e-5c5b02a0c180&a=5001&ts=1000&bidder=rubicon&f=i&int=dmbjs\"}},{\"type\":\"json\",\"value\":{\"id\":\"466223845\",\"impid\":\"impId2\",\"price\":4.26,\"adm\":\"adm2\",\"crid\":\"crid2\",\"w\":300,\"h\":600,\"ext\":{\"origbidcpm\":4.26},\"wurl\":\"http://localhost:8080/event?t=win&b=466223845&a=5001&ts=1000&bidder=rubicon&f=i&int=dmbjs\"}},{\"type\":\"json\",\"value\":{\"id\":\"928185755156387460\",\"impid\":\"impId131\",\"price\":1,\"adm\":\"{\\\"assets\\\":[{\\\"id\\\":0,\\\"img\\\":{\\\"url\\\":\\\"http://vcdn.adnxs.com/p/creative-image/5e/b6/de/c3/5eb6dec3-4854-4dcd-980a-347f36ab502e.jpg\\\",\\\"w\\\":3000,\\\"h\\\":2250,\\\"ext\\\":{\\\"appnexus\\\":{\\\"prevent_crop\\\":0}}}},{\\\"id\\\":1,\\\"title\\\":{\\\"text\\\":\\\"This is an example Prebid Native creative\\\"}},{\\\"id\\\":2,\\\"data\\\":{\\\"value\\\":\\\"Prebid.org\\\"}},{\\\"id\\\":3,\\\"data\\\":{\\\"value\\\":\\\"ThisisaPrebidNativeCreative.Therearemanylikeit,butthisoneismine.\\\"}}],\\\"link\\\":{\\\"url\\\":\\\"http://nym1-ib.adnxs.com/click?AAAAAAAA8D8AAAAAAADwPwAAAAAAAAAAAAAAAAAA8D8AAAAAAADwPwhdYz3ZyNFNG3fXpZUyLXNZ0o5aAAAAACrElgC-AwAAvgMAAAIAAAC98iUEeP4QAAAAAABVU0QAVVNEAAEAAQARIAAAAAABAgQCAAAAAAEAhBaSXgAAAAA./pp=${AUCTION_PRICE}/cnd=%21OwwGAQiGmooHEL3llyEY-PxDIAQoADoRZGVmYXVsdCNOWU0yOjQwMjM./bn=75922/test=1/referrer=prebid.org/clickenc=http%3A%2F%2Fprebid.org%2Fdev-docs%2Fshow-native-ads.html\\\"},\\\"imptrackers\\\":[\\\"http://nym1-ib.adnxs.com/openrtb_win?e=wqT_3QLFBqBFAwAAAwDWAAUBCNmku9QFEIi6jeuTm_LoTRib7t2u2tLMlnMqNgkAAAECCPA_EQEHEAAA8D8ZCQkIAAAhCQkI8D8pEQkAMQkJqAAAMKqI2wQ4vgdAvgdIAlC95ZchWPj8Q2AAaJFAeJLRBIABAYoBA1VTRJIFBvBQmAEBoAEBqAEBsAEAuAECwAEEyAEC0AEJ2AEA4AEB8AEAigI7dWYoJ2EnLCAxMzc2ODYwLCAxNTE5MzA5NDAxKTt1ZigncicsIDY5NTk1ODM3Nh4A8IqSAvUBIXRETkdfUWlHbW9vSEVMM2xseUVZQUNENF9FTXdBRGdBUUFSSXZnZFFxb2piQkZnQVlMTURhQUJ3QUhnQWdBRUFpQUVBa0FFQm1BRUJvQUVCcUFFRHNBRUF1UUVwaTRpREFBRHdQOEVCS1l1SWd3QUE4RF9KQVhfelYzek1zXzBfMlFFQUFBAQMkRHdQLUFCQVBVQgEOLEFKZ0NBS0FDQUxVQwUQBEwwCQjwTE1BQ0FNZ0NBT0FDQU9nQ0FQZ0NBSUFEQVpBREFKZ0RBYWdEaHBxS0I3b0RFV1JsWm1GMWJIUWpUbGxOTWpvME1ESXqaAjkhT3d3R0FRNvgA8E4tUHhESUFRb0FEb1JaR1ZtWVhWc2RDTk9XVTB5T2pRd01qTS7YAugH4ALH0wHqAgpwcmViaWQub3Jn8gIRCgZBRFZfSUQSBzEzNzY4NjDyARQMQ1BHXwEUNDM1MDMwOTjyAhEKBUNQARPwmQgxNDg0NzIzOIADAYgDAZADAJgDFKADAaoDAMADkBzIAwDYAwDgAwDoAwD4AwOABACSBAkvb3BlbnJ0YjKYBACiBAwxNTIuMTkzLjYuNzSoBJrMI7IEDAgAEAAYACAAMAA4ALgEAMAEAMgEANIEEWRlZmF1bHQjTllNMjo0MDIz2gQCCADgBADwBL3llyGIBQGYBQCgBf____8FA1ABqgULc29tZS1yZXEtaWTABQDJBQAFARTwP9IFCQkFC2QAAADYBQHgBQHwBd4C-gUECAAQAJAGAZgGAA..&s=08b1535744639c904684afe46e3c6c0e4786089f&test=1&referrer=prebid.org&pp=${AUCTION_PRICE}\\\"],\\\"jstracker\\\":\\\"\\\"}\",\"adid\":\"69595837\",\"adomain\":[\"appnexus.com\"],\"iurl\":\"http://nym1-ib.adnxs.com/cr?id=69595837\",\"cid\":\"958\",\"crid\":\"69595837\",\"cat\":[\"IAB20-3\"],\"ext\":{\"appnexus\":{\"brand_id\":1,\"brand_category_id\":1,\"auction_id\":5607483846416358664,\"bidder_id\":2,\"bid_ad_type\":3},\"origbidcpm\":1,\"origbidcur\":\"USD\"},\"wurl\":\"http://localhost:8080/event?t=win&b=928185755156387460&a=5001&ts=1000&bidder=appnexus&f=i&int=dmbjs\"}},{\"type\":\"json\",\"value\":{\"id\":\"880290288\",\"impid\":\"impId1\",\"price\":8.43,\"adm\":\"\",\"crid\":\"crid1\",\"w\":300,\"h\":250,\"ext\":{\"rp\":{\"targeting\":[{\"key\":\"rpfl_1001\",\"values\":[\"2_tier0100\"]}]},\"origbidcpm\":8.43},\"wurl\":\"http://localhost:8080/event?t=win&b=880290288&a=5001&ts=1000&bidder=rubicon&f=i&int=dmbjs\"}},{\"type\":\"xml\",\"value\":\"\",\"expiry\":120}]}", "responsebody": "{\"responses\":[{\"uuid\":\"91912e5b-dfa8-42bc-9c7e-df6ce0449c19\"},{\"uuid\":\"765e116a-5773-49d5-a648-0b97a9907a4e\"},{\"uuid\":\"117431c9-807a-41e1-82a7-dcd8f8875493\"},{\"uuid\":\"6cf69b42-96f5-4ba1-a984-a9b4d8ff21cf\"},{\"uuid\":\"c75130ed-bcdd-4821-ad91-90cf835615c5\"},{\"uuid\":\"683fe79f-6df7-4971-ac70-820e0486992d\"},{\"uuid\":\"4fe59ef5-6fb4-48c5-88b6-9870257fc49e\"},{\"uuid\":\"b2528f73-96ab-42ab-8f15-fbe6ed779a26\"}]}", "status": 200 } @@ -565,10 +577,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "5001" + "id": "5001", + "domain": "example.com" }, "ext": { "amp": 0 @@ -594,7 +607,7 @@ "data": [ { "ext": { - "taxonomyname": "Iab" + "segtax": 3 }, "segment": [ { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-cache-rubicon-appnexus-request.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-cache-rubicon-appnexus-request.json index 0dcf1e72cb3..0d5009c6739 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-cache-rubicon-appnexus-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-cache-rubicon-appnexus-request.json @@ -10,6 +10,9 @@ "crid": "crid2", "w": 300, "h": 600, + "ext": { + "origbidcpm": 4.26 + }, "wurl": "http://localhost:8080/event?t=win&b=466223845&a=5001&ts=1000&bidder=rubicon&f=i&int=dmbjs" } }, @@ -39,7 +42,9 @@ "bidder_id": 2, "bid_ad_type": 0, "ranking_price": 0.0 - } + }, + "origbidcpm": 5, + "origbidcur": "USD" } } }, @@ -67,7 +72,9 @@ "bidder_id": 2, "bid_ad_type": 0, "ranking_price": 0.0 - } + }, + "origbidcpm": 5.5, + "origbidcur": "USD" } } }, @@ -77,7 +84,7 @@ "id": "880290288", "impid": "impId1", "price": 8.43, - "adm": "", + "adm": "", "crid": "crid1", "w": 300, "h": 250, @@ -92,7 +99,8 @@ ] } ] - } + }, + "origbidcpm": 8.43 } } }, @@ -120,7 +128,9 @@ "auction_id": 5607483846416358664, "bidder_id": 2, "bid_ad_type": 3 - } + }, + "origbidcpm": 1, + "origbidcur": "USD" }, "wurl": "http://localhost:8080/event?t=win&b=928185755156387460&a=5001&ts=1000&bidder=appnexus&f=i&int=dmbjs" } @@ -132,6 +142,10 @@ "impid": "impStoredAuctionResponse", "crid": "crid1", "price": 0.9, + "ext": { + "origbidcpm": 0.9, + "origbidcur": "USD" + }, "wurl": "http://localhost:8080/event?t=win&b=a121a07f-1579-4465-bc5e-5c5b02a0c421&a=5001&ts=1000&bidder=appnexus&f=i&int=dmbjs" } }, @@ -142,6 +156,10 @@ "impid": "impStoredAuctionResponse", "crid": "crid1", "price": 0.8, + "ext": { + "origbidcpm": 0.8, + "origbidcur": "USD" + }, "wurl": "http://localhost:8080/event?t=win&b=f227a07f-1579-4465-bc5e-5c5b02a0c180&a=5001&ts=1000&bidder=rubicon&f=i&int=dmbjs" } }, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-rubicon-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-rubicon-bid-request-1.json index 29625aed927..72284cc0c98 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-rubicon-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-rubicon-bid-request-1.json @@ -48,12 +48,12 @@ "mint_version": "" } }, - "maxbids" : 1 + "maxbids": 1 } } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { "ext": { @@ -85,7 +85,7 @@ "data": [ { "ext": { - "taxonomyname": "Iab" + "segtax": 3 }, "segment": [ { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-rubicon-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-rubicon-bid-request-2.json index d5be79b89e5..c2eccfd734a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-rubicon-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-rubicon-bid-request-2.json @@ -32,12 +32,12 @@ "mint_version": "" } }, - "maxbids" : 1 + "maxbids": 1 } } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { "ext": { @@ -69,7 +69,7 @@ "data": [ { "ext": { - "taxonomyname": "Iab" + "segtax": 3 }, "segment": [ { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-appnexus-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-appnexus-bid-request-1.json index 65ecf50e440..25f8b3902f2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-appnexus-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-appnexus-bid-request-1.json @@ -32,10 +32,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "5001" + "id": "5001", + "domain": "example.com" }, "ext": { "amp": 0 @@ -115,7 +116,7 @@ } ], "auctiontimestamp": 1000, - "events" : { }, + "events": {}, "channel": { "name": "web" } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-auction-rubicon-appnexus-request.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-auction-rubicon-appnexus-request.json index 908e34d65ed..ce35462c0a7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-auction-rubicon-appnexus-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-auction-rubicon-appnexus-request.json @@ -142,7 +142,10 @@ "targetbiddercodeprefix": "rubN" }, { - "bidders": ["appnexus", "someBidder"], + "bidders": [ + "appnexus", + "someBidder" + ], "maxbids": 2 } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-auction-rubicon-appnexus-response.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-auction-rubicon-appnexus-response.json index ee6387c3c1c..15caae7a2c4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-auction-rubicon-appnexus-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-auction-rubicon-appnexus-response.json @@ -47,6 +47,7 @@ "imp": "{{ event.url }}t=imp&b=21521324&a=5001&ts=1000&bidder=rubicon&f=i&int=" } }, + "origbidcpm": 12.43, "bidder": { "rp": { "targeting": [ @@ -98,6 +99,7 @@ "imp": "{{ event.url }}t=imp&b=880290288&a=5001&ts=1000&bidder=rubicon&f=i&int=" } }, + "origbidcpm": 8.43, "bidder": { "rp": { "targeting": [ @@ -158,6 +160,8 @@ "imp": "{{ event.url }}t=imp&b=7706636740145184841&a=5001&ts=1000&bidder=appnexus&f=i&int=" } }, + "origbidcpm": 5.5, + "origbidcur": "USD", "bidder": { "appnexus": { "brand_id": 1, @@ -203,6 +207,8 @@ "imp": "{{ event.url }}t=imp&b=222214214214&a=5001&ts=1000&bidder=appnexus&f=i&int=" } }, + "origbidcpm": 2.0, + "origbidcur": "USD", "bidder": { "appnexus": { "brand_id": 1, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-cache-rubicon-appnexus-request.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-cache-rubicon-appnexus-request.json index e84906d0f2e..57715941820 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-cache-rubicon-appnexus-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-cache-rubicon-appnexus-request.json @@ -6,7 +6,7 @@ "id": "21521324", "impid": "impId1", "price": 12.43, - "adm": "", + "adm": "", "crid": "crid1", "w": 300, "h": 250, @@ -20,7 +20,8 @@ ] } ] - } + }, + "origbidcpm": 12.43 }, "wurl": "http://localhost:8080/event?t=win&b=21521324&a=5001&ts=1000&bidder=rubicon&f=i&int=" } @@ -46,7 +47,9 @@ "bidder_id": 2, "bid_ad_type": 1, "ranking_price": 0.0 - } + }, + "origbidcpm": 5.5, + "origbidcur": "USD" }, "wurl": "http://localhost:8080/event?t=win&b=7706636740145184841&a=5001&ts=1000&bidder=appnexus&f=i&int=" } @@ -57,7 +60,7 @@ "id": "880290288", "impid": "impId1", "price": 8.43, - "adm": "", + "adm": "", "crid": "crid1", "w": 300, "h": 250, @@ -71,7 +74,8 @@ ] } ] - } + }, + "origbidcpm": 8.43 }, "wurl": "http://localhost:8080/event?t=win&b=880290288&a=5001&ts=1000&bidder=rubicon&f=i&int=" } @@ -100,7 +104,9 @@ "auction_id": 5607483846416358664, "bidder_id": 2, "bid_ad_type": 1 - } + }, + "origbidcpm": 2, + "origbidcur": "USD" }, "wurl": "http://localhost:8080/event?t=win&b=222214214214&a=5001&ts=1000&bidder=appnexus&f=i&int=" } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-rubicon-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-rubicon-bid-request-1.json index 86ef210eb74..2837d7ddf34 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-rubicon-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus_multi_bid/test-rubicon-bid-request-1.json @@ -48,12 +48,12 @@ "mint_version": "" } }, - "maxbids" : 2 + "maxbids": 2 } } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { "ext": { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-auction-rubicon-request.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-auction-rubicon-request.json new file mode 100644 index 00000000000..1221267e675 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-auction-rubicon-request.json @@ -0,0 +1,57 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId001", + "video": { + "mimes": [ + "mimes" + ], + "w": 300, + "h": 250 + }, + "ext": { + "rubicon": { + "accountId": 2001, + "siteId": 3001, + "zoneId": 4001 + } + } + } + ], + "device": { + "ua": "testUa", + "ip": "193.168.244.1" + }, + "ext": { + "prebid": { + "bidadjustmentfactors": { + "mediatypes": { + "video": { + "rubicon": 0.9 + } + } + }, + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + } + }, + "cache": { + "bids": {} + }, + "auctiontimestamp": 1000 + } + }, + "regs": { + "ext": { + "gdpr": 0 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-auction-rubicon-response.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-auction-rubicon-response.json new file mode 100644 index 00000000000..64d0c8d1cee --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-auction-rubicon-response.json @@ -0,0 +1,59 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "id": "bid001", + "impid": "impId001", + "price": 2.997, + "adm": "adm001", + "adid": "adid001", + "cid": "cid001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "video", + "targeting": { + "hb_pb": "2.90", + "hb_size_rubicon": "300x250", + "hb_bidder_rubicon": "rubicon", + "hb_cache_path": "{{ cache.path }}", + "hb_size": "300x250", + "hb_cache_host_rubicon": "{{ cache.host }}", + "hb_cache_path_rubicon": "{{ cache.path }}", + "hb_cache_id_rubicon": "f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "hb_bidder": "rubicon", + "hb_cache_id": "f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "hb_pb_rubicon": "2.90", + "hb_cache_host": "{{ cache.host }}" + }, + "cache": { + "bids": { + "url": "{{ cache.resource_url }}f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" + } + } + }, + "origbidcpm": 3.33 + } + } + ], + "seat": "rubicon", + "group": 0 + } + ], + "cur": "USD", + "ext": { + "responsetimemillis": { + "rubicon": "{{ rubicon.response_time_ms }}", + "cache": "{{ cache.response_time_ms }}" + }, + "tmaxrequest": 2000, + "prebid": { + "auctiontimestamp": 1000 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-cache-rubicon-request.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-cache-rubicon-request.json new file mode 100644 index 00000000000..1a56724f9c0 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-cache-rubicon-request.json @@ -0,0 +1,21 @@ +{ + "puts": [ + { + "type": "json", + "value": { + "id": "bid001", + "impid": "impId001", + "price": 2.997, + "adm": "adm001", + "adid": "adid001", + "cid": "cid001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "origbidcpm": 3.33 + } + } + } + ] +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-cache-rubicon-response.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-cache-rubicon-response.json new file mode 100644 index 00000000000..93d0b8de2cd --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-cache-rubicon-response.json @@ -0,0 +1,7 @@ +{ + "responses": [ + { + "uuid": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-rubicon-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-rubicon-bid-request.json new file mode 100644 index 00000000000..95c16146e0e --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-rubicon-bid-request.json @@ -0,0 +1,65 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId001", + "video": { + "mimes": [ + "mimes" + ], + "w": 300, + "h": 250 + }, + "ext": { + "rp": { + "zone_id": 4001, + "target": { + "page": [ + "http://www.example.com" + ] + }, + "track": { + "mint": "", + "mint_version": "" + } + }, + "maxbids": 1 + } + } + ], + "site": { + "domain": "www.example.com", + "page": "http://www.example.com", + "publisher": { + "ext": { + "rp": { + "account_id": 2001 + } + } + }, + "ext": { + "amp": 0, + "rp": { + "site_id": 3001 + } + } + }, + "device": { + "ua": "testUa", + "ip": "193.168.244.1", + "ext": { + "rp": { + } + } + }, + "user": { + "buyeruid": "RUB-UID" + }, + "at": 1, + "tmax": 2000, + "regs": { + "ext": { + "gdpr": 0 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-rubicon-bid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-rubicon-bid-response.json new file mode 100644 index 00000000000..95a93284e04 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_core_functionality/test-rubicon-bid-response.json @@ -0,0 +1,20 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "id": "bid001", + "impid": "impId001", + "price": 3.33, + "adid": "adid001", + "crid": "crid001", + "cid": "cid001", + "adm": "adm001", + "h": 250, + "w": 300 + } + ] + } + ] +} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/openrtb2/sharethrough/test-auction-sharethrough-response.json b/src/test/resources/org/prebid/server/it/openrtb2/sharethrough/test-auction-sharethrough-response.json index b20ecd3bf0a..52d32d29299 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/sharethrough/test-auction-sharethrough-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/sharethrough/test-auction-sharethrough-response.json @@ -36,7 +36,9 @@ "cacheId": "a03927f1-86e1-48fb-9efc-da9104a44e39" } } - } + }, + "origbidcpm": 10, + "origbidcur": "USD" } } ], @@ -59,7 +61,7 @@ "cache": [ { "uri": "{{ cache.endpoint }}", - "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"bid\",\"impid\":\"bid\",\"price\":10,\"adm\":\"\\n\\t\\t
\\n\\t\\t\\n\\t\\t\\t\\n\",\"adid\":\"arid\",\"cid\":\"cmpKey\",\"crid\":\"creaKey\",\"w\":50,\"h\":50}}]}", + "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"bid\",\"impid\":\"bid\",\"price\":10,\"adm\":\"\\n\\t\\t
\\n\\t\\t\\n\\t\\t\\t\\n\",\"adid\":\"arid\",\"cid\":\"cmpKey\",\"crid\":\"creaKey\",\"w\":50,\"h\":50,\"ext\":{\"origbidcpm\":10,\"origbidcur\":\"USD\"}}}]}", "responsebody": "{\"responses\":[{\"uuid\":\"a03927f1-86e1-48fb-9efc-da9104a44e39\"}]}", "status": 200 } @@ -96,10 +98,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain" : "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/sharethrough/test-cache-sharethrough-request.json b/src/test/resources/org/prebid/server/it/openrtb2/sharethrough/test-cache-sharethrough-request.json index 73dc1156b71..c6eaf04633b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/sharethrough/test-cache-sharethrough-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/sharethrough/test-cache-sharethrough-request.json @@ -11,7 +11,11 @@ "cid": "cmpKey", "crid": "creaKey", "w": 50, - "h": 50 + "h": 50, + "ext": { + "origbidcpm": 10, + "origbidcur": "USD" + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/silvermob/test-auction-silvermob-response.json b/src/test/resources/org/prebid/server/it/openrtb2/silvermob/test-auction-silvermob-response.json index de2439c7f86..a598167bffc 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/silvermob/test-auction-silvermob-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/silvermob/test-auction-silvermob-response.json @@ -31,7 +31,8 @@ "cacheId": "3c0769d8-0dd9-465c-8bf3-f570605ba698" } } - } + }, + "origbidcpm": 0.01 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/silvermob/test-cache-silvermob-request.json b/src/test/resources/org/prebid/server/it/openrtb2/silvermob/test-cache-silvermob-request.json index ca8e3ab2f6a..383f37b4df9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/silvermob/test-cache-silvermob-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/silvermob/test-cache-silvermob-request.json @@ -8,7 +8,10 @@ "price": 0.01, "id": "testid", "impid": "testimpid", - "cid": "8048" + "cid": "8048", + "ext": { + "origbidcpm": 0.01 + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/silvermob/test-silvermob-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/silvermob/test-silvermob-bid-request.json index d713ab3ff08..5739115cea7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/silvermob/test-silvermob-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/silvermob/test-silvermob-bid-request.json @@ -17,10 +17,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smaato/test-auction-smaato-response.json b/src/test/resources/org/prebid/server/it/openrtb2/smaato/test-auction-smaato-response.json index e8bf61f24ac..e456ec3ba67 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smaato/test-auction-smaato-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smaato/test-auction-smaato-response.json @@ -31,7 +31,8 @@ "url": "{{ cache.resource_url }}f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 0.01 }, "id": "1", "impid": "impId001", @@ -53,4 +54,4 @@ }, "tmaxrequest": 3000 } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smaato/test-cache-smaato-request.json b/src/test/resources/org/prebid/server/it/openrtb2/smaato/test-cache-smaato-request.json index a8fced07cb3..babc951e8ea 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smaato/test-cache-smaato-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smaato/test-cache-smaato-request.json @@ -10,9 +10,10 @@ "cid": "test_cid", "crid": "test_banner_crid", "ext": { - "format": "BANNER" + "format": "BANNER", + "origbidcpm": 0.01 } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smaato/test-smaato-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/smaato/test-smaato-bid-request.json index 0f5f286397f..5c883eec1a2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smaato/test-smaato-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smaato/test-smaato-bid-request.json @@ -17,6 +17,7 @@ } ], "site": { + "domain" : "localhost", "page": "http://localhost:3000/server.html?pbjs_debug=true&endpoint=http://localhost:3000/bidder", "publisher": { "id": "11000" @@ -55,6 +56,6 @@ } }, "ext": { - "client": "prebid_server_0.1" + "client": "prebid_server_0.2" } } \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-response.json b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-response.json index 3eadc63eab9..a8937b3cfb9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-auction-smartadserver-response.json @@ -39,7 +39,8 @@ "cacheId": "78f9a6dd-d08c-4b80-ba0f-0159b9add9bf" } } - } + }, + "origbidcpm": 0.5 } } ], @@ -54,7 +55,7 @@ "cache": [ { "uri": "{{ cache.endpoint }}", - "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"7706636740145184841\",\"impid\":\"test-imp-banner-id\",\"price\":0.5,\"adm\":\"some-test-ad\",\"adid\":\"29681110\",\"adomain\":[\"advertsite.com\"],\"cid\":\"772\",\"crid\":\"29681110\",\"w\":1024,\"h\":576}}]}", + "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"7706636740145184841\",\"impid\":\"test-imp-banner-id\",\"price\":0.5,\"adm\":\"some-test-ad\",\"adid\":\"29681110\",\"adomain\":[\"advertsite.com\"],\"cid\":\"772\",\"crid\":\"29681110\",\"w\":1024,\"h\":576,\"ext\":{\"origbidcpm\":0.5}}}]}", "responsebody": "{\"responses\":[{\"uuid\":\"78f9a6dd-d08c-4b80-ba0f-0159b9add9bf\"}]}", "status": 200 } @@ -62,7 +63,7 @@ "smartadserver": [ { "uri": "{{ smartadserver.exchange_uri }}/api/bid?callerId=5", - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"test-imp-banner-id\",\"banner\":{\"format\":[{\"w\":300,\"h\":250}],\"w\":500,\"h\":400},\"ext\":{\"bidder\":{\"siteId\":1,\"pageId\":2,\"formatId\":3,\"networkId\":73}}}],\"site\":{\"publisher\":{\"id\":\"73\"}},\"device\":{\"ua\":\"userAgent\",\"dnt\":2,\"ip\":\"193.168.244.1\",\"pxratio\":4.2,\"language\":\"en\",\"ifa\":\"ifaId\"},\"user\":{\"buyeruid\":\"SA-UID\",\"ext\":{\"consent\":\"consentValue\"}},\"at\":1,\"tmax\":5000,\"cur\":[\"USD\"],\"source\":{\"fd\":1,\"tid\":\"tid\"},\"regs\":{\"ext\":{\"gdpr\":0}},\"ext\":{\"prebid\":{\"debug\":1,\"targeting\":{\"pricegranularity\":{\"precision\":2,\"ranges\":[{\"max\":20,\"increment\":0.1}]},\"includewinners\":true,\"includebidderkeys\":true},\"cache\":{\"bids\":{},\"vastxml\":{\"ttlseconds\":120}},\"auctiontimestamp\":1000,\"channel\":{\"name\":\"web\"}}}}", + "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"test-imp-banner-id\",\"banner\":{\"format\":[{\"w\":300,\"h\":250}],\"w\":500,\"h\":400},\"ext\":{\"bidder\":{\"siteId\":1,\"pageId\":2,\"formatId\":3,\"networkId\":73}}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"id\":\"73\",\"domain\":\"example.com\"},\"ext\":{\"amp\":0}},\"device\":{\"ua\":\"userAgent\",\"dnt\":2,\"ip\":\"193.168.244.1\",\"pxratio\":4.2,\"language\":\"en\",\"ifa\":\"ifaId\"},\"user\":{\"buyeruid\":\"SA-UID\",\"ext\":{\"consent\":\"consentValue\"}},\"at\":1,\"tmax\":5000,\"cur\":[\"USD\"],\"source\":{\"fd\":1,\"tid\":\"tid\"},\"regs\":{\"ext\":{\"gdpr\":0}},\"ext\":{\"prebid\":{\"debug\":1,\"targeting\":{\"pricegranularity\":{\"precision\":2,\"ranges\":[{\"max\":20,\"increment\":0.1}]},\"includewinners\":true,\"includebidderkeys\":true},\"cache\":{\"bids\":{},\"vastxml\":{\"ttlseconds\":120}},\"auctiontimestamp\":1000,\"channel\":{\"name\":\"web\"}}}}", "responsebody": "{\"id\":\"tid\",\"seatbid\":[{\"bid\":[{\"id\":\"7706636740145184841\",\"impid\":\"test-imp-banner-id\",\"price\":0.5,\"adid\":\"29681110\",\"adm\":\"some-test-ad\",\"adomain\":[\"advertsite.com\"],\"cid\":\"772\",\"crid\":\"29681110\",\"h\":576,\"w\":1024}]}]}", "status": 200 } @@ -98,10 +99,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-cache-smartadserver-request.json b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-cache-smartadserver-request.json index a97a73381ff..ecd360287a8 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-cache-smartadserver-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-cache-smartadserver-request.json @@ -8,11 +8,16 @@ "price": 0.500000, "adid": "29681110", "adm": "some-test-ad", - "adomain": ["advertsite.com"], + "adomain": [ + "advertsite.com" + ], "cid": "772", "crid": "29681110", "h": 576, - "w": 1024 + "w": 1024, + "ext": { + "origbidcpm": 0.500000 + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-request-1.json index d44e20c3b68..5f3ac7297c3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-request-1.json @@ -24,8 +24,14 @@ } ], "site": { + "domain": "www.example.com", + "page": "http://www.example.com", "publisher": { - "id": "73" + "id": "73", + "domain" : "example.com" + }, + "ext": { + "amp": 0 } }, "device": { @@ -37,7 +43,7 @@ "ifa": "ifaId" }, "user": { - "buyeruid" : "SA-UID", + "buyeruid": "SA-UID", "ext": { "consent": "consentValue" } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-response-1.json b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-response-1.json index 92517b36952..35da8708c10 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-response-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartadserver/test-smartadserver-bid-response-1.json @@ -9,7 +9,9 @@ "price": 0.500000, "adid": "29681110", "adm": "some-test-ad", - "adomain": ["advertsite.com"], + "adomain": [ + "advertsite.com" + ], "cid": "772", "crid": "29681110", "h": 576, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartrtb/test-auction-smartrtb-response.json b/src/test/resources/org/prebid/server/it/openrtb2/smartrtb/test-auction-smartrtb-response.json index 651a7c8f18f..eb8f673cacc 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartrtb/test-auction-smartrtb-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartrtb/test-auction-smartrtb-response.json @@ -29,7 +29,8 @@ "hb_pb_smartrtb": "0.00" }, "type": "banner" - } + }, + "origbidcpm": 0.01 }, "id": "1", "impid": "impId001", diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartrtb/test-cache-smartrtb-request.json b/src/test/resources/org/prebid/server/it/openrtb2/smartrtb/test-cache-smartrtb-request.json index 00cfdec611c..295b748894c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartrtb/test-cache-smartrtb-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartrtb/test-cache-smartrtb-request.json @@ -8,8 +8,11 @@ "crid": "test_banner_crid", "id": "1", "impid": "impId001", - "price": 0.01 + "price": 0.01, + "ext": { + "origbidcpm": 0.01 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartrtb/test-smartrtb-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/smartrtb/test-smartrtb-bid-request.json index e52187cc0b5..924b5fb44f0 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartrtb/test-smartrtb-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartrtb/test-smartrtb-bid-request.json @@ -97,7 +97,8 @@ }, "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" } }, "source": { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-auction-smartyads-request.json b/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-auction-smartyads-request.json index 1280fb16b76..f4520942e3a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-auction-smartyads-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-auction-smartyads-request.json @@ -28,7 +28,7 @@ } ], "device": { - "ua" : "userAgent", + "ua": "userAgent", "pxratio": 4.2, "dnt": 2, "language": "en", diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-auction-smartyads-response.json b/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-auction-smartyads-response.json index 10666bb7c54..606d8d72d88 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-auction-smartyads-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-auction-smartyads-response.json @@ -31,7 +31,8 @@ "cacheId": "3c0769d8-0dd9-465c-8bf3-f570605ba698" } } - } + }, + "origbidcpm": 0.01 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-cache-smartyads-request.json b/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-cache-smartyads-request.json index ca8e3ab2f6a..383f37b4df9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-cache-smartyads-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-cache-smartyads-request.json @@ -8,7 +8,10 @@ "price": 0.01, "id": "testid", "impid": "testimpid", - "cid": "8048" + "cid": "8048", + "ext": { + "origbidcpm": 0.01 + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-smartyads-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-smartyads-bid-request.json index f2d2eed193d..58f467a39aa 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-smartyads-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/smartyads/test-smartyads-bid-request.json @@ -21,10 +21,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-auction-somoaudience-response.json b/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-auction-somoaudience-response.json index 3f8b02be95b..4d0343d580a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-auction-somoaudience-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-auction-somoaudience-response.json @@ -34,7 +34,8 @@ "cacheId": "6da10965-53bf-453e-a890-ea94eeb00765" } } - } + }, + "origbidcpm": 8.43 } }, { @@ -68,7 +69,8 @@ "cacheId": "9ce56613-4f34-4b28-8a1e-69683ad26b99" } } - } + }, + "origbidcpm": 7.99 } }, { @@ -109,7 +111,8 @@ "cacheId": "8aa68c39-680d-46f5-ba83-fcd761d436fe" } } - } + }, + "origbidcpm": 9.99 } }, { @@ -148,7 +151,8 @@ "cacheId": "2bf317a1-d300-42df-97d5-8ae4a3fef9e3" } } - } + }, + "origbidcpm": 10.0 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-cache-matcher-somoaudience.json b/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-cache-matcher-somoaudience.json index 87f651fbebb..e58af3ee8d6 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-cache-matcher-somoaudience.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-cache-matcher-somoaudience.json @@ -1,7 +1,7 @@ { - "bidId01@8.43" : "6da10965-53bf-453e-a890-ea94eeb00765", - "bidId04@10" : "2bf317a1-d300-42df-97d5-8ae4a3fef9e3", - "bidId03@9.99" : "0bd56608-42fe-47f6-b2ec-bca5f3905dc5", - "bidId02@7.99" : "9ce56613-4f34-4b28-8a1e-69683ad26b99", - "adm18" : "8aa68c39-680d-46f5-ba83-fcd761d436fe" -} \ No newline at end of file + "bidId01@8.43": "6da10965-53bf-453e-a890-ea94eeb00765", + "bidId04@10": "2bf317a1-d300-42df-97d5-8ae4a3fef9e3", + "bidId03@9.99": "0bd56608-42fe-47f6-b2ec-bca5f3905dc5", + "bidId02@7.99": "9ce56613-4f34-4b28-8a1e-69683ad26b99", + "adm18": "8aa68c39-680d-46f5-ba83-fcd761d436fe" +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-cache-somoaudience-request.json b/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-cache-somoaudience-request.json index f7f2bbb35a8..c898e428eb5 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-cache-somoaudience-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-cache-somoaudience-request.json @@ -9,7 +9,10 @@ "adm": "adm16", "crid": "crid16", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 8.43 + } } }, { @@ -21,7 +24,10 @@ "adm": "adm17", "crid": "crid17", "w": 360, - "h": 240 + "h": 240, + "ext": { + "origbidcpm": 7.99 + } } }, { @@ -33,7 +39,10 @@ "adm": "adm18", "crid": "crid18", "w": 1024, - "h": 576 + "h": 576, + "ext": { + "origbidcpm": 9.99 + } } }, { @@ -52,7 +61,10 @@ "crid": "crid19", "cat": [ "IAB3-1" - ] + ], + "ext": { + "origbidcpm": 10 + } } }, { @@ -61,4 +73,4 @@ "expiry": 120 } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-somoaudience-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-somoaudience-bid-request-1.json index acc41e62f2b..321941dbea4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-somoaudience-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-somoaudience-bid-request-1.json @@ -27,10 +27,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-somoaudience-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-somoaudience-bid-request-2.json index 78dae5aebaf..940172df7cd 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-somoaudience-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-somoaudience-bid-request-2.json @@ -18,10 +18,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-somoaudience-bid-request-3.json b/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-somoaudience-bid-request-3.json index 1abac39190a..dcc561b5347 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-somoaudience-bid-request-3.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/somoaudience/test-somoaudience-bid-request-3.json @@ -11,10 +11,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-auction-sonobi-response.json b/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-auction-sonobi-response.json index 0d40a801f23..09004e0bc3f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-auction-sonobi-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-auction-sonobi-response.json @@ -34,7 +34,8 @@ "cacheId": "9092799c-93b0-4e11-a232-2c0151d5d275" } } - } + }, + "origbidcpm": 1.25 } }, { @@ -83,7 +84,8 @@ "cacheId": "99dc3357-34ac-4819-9f68-0820039a542f" } } - } + }, + "origbidcpm": 2.25 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-cache-sonobi-request.json b/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-cache-sonobi-request.json index 58471d39985..c393baa5ecf 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-cache-sonobi-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-cache-sonobi-request.json @@ -9,7 +9,10 @@ "adm": "adm001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 1.25 + } } }, { @@ -29,7 +32,10 @@ "IAB2" ], "w": 640, - "h": 480 + "h": 480, + "ext": { + "origbidcpm": 2.25 + } } }, { @@ -38,4 +44,4 @@ "expiry": 120 } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-sonobi-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-sonobi-bid-request-1.json index 51b5e0c2b3a..2f5fe7f23b3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-sonobi-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-sonobi-bid-request-1.json @@ -20,10 +20,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-sonobi-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-sonobi-bid-request-2.json index a4ac76b8a32..278817e7a03 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-sonobi-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/sonobi/test-sonobi-bid-request-2.json @@ -19,10 +19,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/sovrn/test-auction-sovrn-response.json b/src/test/resources/org/prebid/server/it/openrtb2/sovrn/test-auction-sovrn-response.json index f6fe198ca04..6edc56d1e7f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/sovrn/test-auction-sovrn-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/sovrn/test-auction-sovrn-response.json @@ -34,7 +34,8 @@ "cacheId": "1e6fb739-d0e7-4b7c-9b00-21aa40dc3301" } } - } + }, + "origbidcpm": 5.78 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/sovrn/test-cache-sovrn-request.json b/src/test/resources/org/prebid/server/it/openrtb2/sovrn/test-cache-sovrn-request.json index aba1be88992..4928606f4a5 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/sovrn/test-cache-sovrn-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/sovrn/test-cache-sovrn-request.json @@ -9,8 +9,11 @@ "adm": "adm 13", "crid": "crid13", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 5.78 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/sovrn/test-sovrn-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/sovrn/test-sovrn-bid-request-1.json index ae826e0b486..01f6505b8d1 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/sovrn/test-sovrn-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/sovrn/test-sovrn-bid-request-1.json @@ -22,10 +22,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/storedresponse/test-auction-response.json b/src/test/resources/org/prebid/server/it/openrtb2/storedresponse/test-auction-response.json index 3fe396f7cfe..ae3a07cbbe3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/storedresponse/test-auction-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/storedresponse/test-auction-response.json @@ -34,7 +34,8 @@ "cacheId": "474175c2-815f-4bde-90ad-935d2f6e1aa0" } } - } + }, + "origbidcpm": 0.8 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/storedresponse/test-cache-request.json b/src/test/resources/org/prebid/server/it/openrtb2/storedresponse/test-cache-request.json index fa0be1eef1e..4aa4ed8aad0 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/storedresponse/test-cache-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/storedresponse/test-cache-request.json @@ -9,8 +9,11 @@ "adm": "adm1", "crid": "crid1", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 0.8 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/synacormedia/test-auction-synacormedia-request.json b/src/test/resources/org/prebid/server/it/openrtb2/synacormedia/test-auction-synacormedia-request.json index 635962ae61b..447cfc8f5f6 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/synacormedia/test-auction-synacormedia-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/synacormedia/test-auction-synacormedia-request.json @@ -29,8 +29,8 @@ ] }, "ext": { - "synacormedia":{ - "seatId":"1987", + "synacormedia": { + "seatId": "1987", "tagId": "demo1" } } @@ -88,4 +88,4 @@ "gdpr": 0 } } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/synacormedia/test-auction-synacormedia-response.json b/src/test/resources/org/prebid/server/it/openrtb2/synacormedia/test-auction-synacormedia-response.json index d289c467330..95236342dcd 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/synacormedia/test-auction-synacormedia-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/synacormedia/test-auction-synacormedia-response.json @@ -36,7 +36,8 @@ "cacheId": "c1662cf6-f00a-4066-b71a-46d97abccc35" } } - } + }, + "origbidcpm": 7.77 } }, { @@ -82,7 +83,8 @@ "cacheId": "62019cff-d657-42fc-8366-16c34e1fd28c" } } - } + }, + "origbidcpm": 9.99 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/synacormedia/test-cache-synacormedia-request.json b/src/test/resources/org/prebid/server/it/openrtb2/synacormedia/test-cache-synacormedia-request.json index d22654a542b..bb6e149acf3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/synacormedia/test-cache-synacormedia-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/synacormedia/test-cache-synacormedia-request.json @@ -11,7 +11,10 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 7.77 + } } }, { @@ -24,10 +27,14 @@ "psacentral.org" ], "nurl": "https://example.com/nurl", + "adm": "prebid.org wrapper", "cid": "cid002", "crid": "crid002", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 9.99 + } } }, { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/synacormedia/test-synacormedia-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/synacormedia/test-synacormedia-bid-request.json index 5468f52bc99..64f08faf1e7 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/synacormedia/test-synacormedia-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/synacormedia/test-synacormedia-bid-request.json @@ -39,10 +39,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-auction-tappx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-auction-tappx-response.json index b8c423172e3..9398deec110 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-auction-tappx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-auction-tappx-response.json @@ -42,7 +42,8 @@ "cacheId": "9c0c4f2f-686f-4673-a00a-d8cae7e7a05d" } } - } + }, + "origbidcpm": 0.5 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-cache-tappx-request.json b/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-cache-tappx-request.json index 68da84fe2ec..7ee253bc6dc 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-cache-tappx-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-cache-tappx-request.json @@ -10,10 +10,17 @@ "crid": "19005", "adid": "19005", "adm": "", - "cat": ["IAB2"], - "adomain": ["test.com"], + "cat": [ + "IAB2" + ], + "adomain": [ + "test.com" + ], "h": 250, - "w": 300 + "w": 300, + "ext": { + "origbidcpm": 0.5 + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-tappx-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-tappx-bid-request.json index df98570852c..b530deffdd8 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-tappx-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-tappx-bid-request.json @@ -23,10 +23,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-tappx-bid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-tappx-bid-response.json index 6da4905c67c..efb74684748 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-tappx-bid-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/tappx/test-tappx-bid-response.json @@ -3,19 +3,25 @@ "seatbid": [ { "seat": "rtbhouse", - "bid": [{ - "id": "wehM-93KGr0_0_0", - "impid": "impId12", - "price": 0.5, - "cid": "3706", - "crid": "19005", - "adid": "19005", - "adm": "", - "cat": ["IAB2"], - "adomain": ["test.com"], - "h": 250, - "w": 300 - }] + "bid": [ + { + "id": "wehM-93KGr0_0_0", + "impid": "impId12", + "price": 0.5, + "cid": "3706", + "crid": "19005", + "adid": "19005", + "adm": "", + "cat": [ + "IAB2" + ], + "adomain": [ + "test.com" + ], + "h": 250, + "w": 300 + } + ] } ], "bidid": "bid01" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-auction-telaria-response.json b/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-auction-telaria-response.json index b68080d38b2..d6e713bc47f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-auction-telaria-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-auction-telaria-response.json @@ -40,6 +40,7 @@ } } }, + "origbidcpm": 0.01, "bidder": { "format": "VIDEO" } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-cache-telaria-request.json b/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-cache-telaria-request.json index 41b088f0620..1cdc865597d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-cache-telaria-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-cache-telaria-request.json @@ -8,13 +8,14 @@ "price": 0.01, "adm": "hi", "cid": "test_cid", - "exp" : 120, + "exp": 120, "crid": "test_video_crid", "ext": { - "format": "VIDEO" + "format": "VIDEO", + "origbidcpm": 0.01 } }, - "expiry" : 120 + "expiry": 120 }, { "type": "xml", @@ -22,4 +23,4 @@ "expiry": 120 } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-telaria-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-telaria-bid-request-1.json index f55efa396a0..4a3b1ef541a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-telaria-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-telaria-bid-request-1.json @@ -27,7 +27,8 @@ "domain": "example.com", "page": "http://www.example.com", "publisher": { - "id": "my-seatcode" + "id": "my-seatcode", + "domain" : "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-telaria-bid-response-1.json b/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-telaria-bid-response-1.json index 9b0a98f3625..568ccad766b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-telaria-bid-response-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/telaria/test-telaria-bid-response-1.json @@ -8,7 +8,7 @@ "crid": "test_video_crid", "cid": "test_cid", "impid": "impId002", - "exp" : 120, + "exp": 120, "id": "1", "price": 0.01, "ext": { @@ -18,4 +18,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/triplelift/test-auction-triplelift-response.json b/src/test/resources/org/prebid/server/it/openrtb2/triplelift/test-auction-triplelift-response.json index 70132708685..ad50cd1db40 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/triplelift/test-auction-triplelift-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/triplelift/test-auction-triplelift-response.json @@ -41,6 +41,8 @@ } } }, + "origbidcpm": 0.5, + "origbidcur": "USD", "bidder": { "triplelift_pb": { "format": 2 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/triplelift/test-cache-triplelift-request.json b/src/test/resources/org/prebid/server/it/openrtb2/triplelift/test-cache-triplelift-request.json index 23689d131c7..6d60392deae 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/triplelift/test-cache-triplelift-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/triplelift/test-cache-triplelift-request.json @@ -19,9 +19,11 @@ "ext": { "triplelift_pb": { "format": 2 - } + }, + "origbidcpm": 0.5, + "origbidcur": "USD" } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/triplelift/test-triplelift-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/triplelift/test-triplelift-bid-request.json index 493d9e71ecc..74db87ecdd5 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/triplelift/test-triplelift-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/triplelift/test-triplelift-bid-request.json @@ -20,10 +20,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-auction-triplelift-native-request.json b/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-auction-triplelift-native-request.json index bc3effc291b..36e5792674c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-auction-triplelift-native-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-auction-triplelift-native-request.json @@ -39,7 +39,6 @@ }, "ext": { "prebid": { - "debug": 1, "targeting": { "pricegranularity": { "precision": 2, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-auction-triplelift-native-response.json b/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-auction-triplelift-native-response.json index c41297924c0..9a14c1dd955 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-auction-triplelift-native-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-auction-triplelift-native-response.json @@ -40,7 +40,9 @@ "cacheId": "029e95ca-1a14-4e45-9669-8ad8d667de50" } } - } + }, + "origbidcpm": 0.5, + "origbidcur": "USD" } } ], @@ -50,111 +52,6 @@ ], "cur": "USD", "ext": { - "debug": { - "httpcalls": { - "cache": [ - { - "uri": "{{ cache.endpoint }}", - "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"7706636740145184841\",\"impid\":\"test-imp-id\",\"price\":0.5,\"adm\":\"some-test-ad\",\"adid\":\"29681110\",\"adomain\":[\"triplelift.com\"],\"iurl\":\"http://nym1-ib.adnxs.com/cr?id=29681110\",\"cid\":\"958\",\"crid\":\"29681110\",\"w\":300,\"h\":250}}]}", - "responsebody": "{\"responses\":[{\"uuid\":\"029e95ca-1a14-4e45-9669-8ad8d667de50\"}]}", - "status": 200 - } - ], - "triplelift_native": [ - { - "uri": "{{ triplelift_native.exchange_uri }}", - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"test-imp-id\",\"native\":{\"request\":\"{\\\"ver\\\":\\\"1.1\\\",\\\"context\\\":1,\\\"contextsubtype\\\":11,\\\"plcmttype\\\":4,\\\"plcmtcnt\\\":1,\\\"assets\\\":[{\\\"id\\\":0,\\\"required\\\":1,\\\"title\\\":{\\\"len\\\":500}}]}\"},\"tagid\":\"foo\",\"ext\":{\"bidder\":{\"inventoryCode\":\"foo\"}}}],\"site\":{\"domain\":\"example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"id\":\"test\"},\"ext\":{\"amp\":0}},\"device\":{\"ua\":\"userAgent\",\"dnt\":2,\"ip\":\"193.168.244.1\",\"pxratio\":4.2,\"language\":\"en\",\"ifa\":\"ifaId\"},\"user\":{\"buyeruid\":\"T\",\"ext\":{\"consent\":\"consentValue\"}},\"at\":1,\"tmax\":5000,\"cur\":[\"USD\"],\"source\":{\"fd\":1,\"tid\":\"tid\"},\"regs\":{\"ext\":{\"gdpr\":0}},\"ext\":{\"prebid\":{\"debug\":1,\"targeting\":{\"pricegranularity\":{\"precision\":2,\"ranges\":[{\"max\":20,\"increment\":0.1}]},\"includewinners\":true,\"includebidderkeys\":true},\"cache\":{\"bids\":{},\"vastxml\":{\"ttlseconds\":120}},\"auctiontimestamp\":1000,\"channel\":{\"name\":\"web\"}}}}", - "responsebody": "{\"id\":\"test-request-id\",\"seatbid\":[{\"seat\":\"958\",\"bid\":[{\"id\":\"7706636740145184841\",\"impid\":\"test-imp-id\",\"price\":0.5,\"adid\":\"29681110\",\"adm\":\"some-test-ad\",\"adomain\":[\"triplelift.com\"],\"iurl\":\"http://nym1-ib.adnxs.com/cr?id=29681110\",\"cid\":\"958\",\"crid\":\"29681110\",\"h\":250,\"w\":300}]}],\"bidid\":\"5778926625248726496\",\"cur\":\"USD\"}", - "status": 200 - } - ] - }, - "resolvedrequest": { - "id": "tid", - "imp": [ - { - "id": "test-imp-id", - "native": { - "request": "{\"ver\":\"1.1\",\"context\":1,\"contextsubtype\":11,\"plcmttype\":4,\"plcmtcnt\":1,\"assets\":[{\"id\":0,\"required\":1,\"title\":{\"len\":500}}]}" - }, - "ext": { - "prebid": { - "bidder": { - "triplelift_native": { - "inventoryCode": "foo" - } - } - } - } - } - ], - "site": { - "domain": "example.com", - "page": "http://www.example.com", - "publisher": { - "id": "test" - }, - "ext": { - "amp": 0 - } - }, - "device": { - "ua": "userAgent", - "dnt": 2, - "ip": "193.168.244.1", - "pxratio": 4.2, - "language": "en", - "ifa": "ifaId" - }, - "user": { - "ext": { - "consent": "consentValue" - } - }, - "at": 1, - "tmax": 5000, - "cur": [ - "USD" - ], - "source": { - "fd": 1, - "tid": "tid" - }, - "regs": { - "ext": { - "gdpr": 0 - } - }, - "ext": { - "prebid": { - "debug": 1, - "targeting": { - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "max": 20, - "increment": 0.1 - } - ] - }, - "includewinners": true, - "includebidderkeys": true - }, - "cache": { - "bids": {}, - "vastxml": { - "ttlseconds": 120 - } - }, - "auctiontimestamp": 1000, - "channel": { - "name": "web" - } - } - } - } - }, "responsetimemillis": { "triplelift_native": "{{ triplelift_native.response_time_ms }}", "cache": "{{ cache.response_time_ms }}" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-cache-triplelift-native-request.json b/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-cache-triplelift-native-request.json index d0168e8c2b9..a626a4aed9d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-cache-triplelift-native-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-cache-triplelift-native-request.json @@ -15,7 +15,11 @@ "cid": "958", "crid": "29681110", "h": 250, - "w": 300 + "w": 300, + "ext": { + "origbidcpm": 0.5, + "origbidcur": "USD" + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-triplelift-native-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-triplelift-native-bid-request.json index d4a22534d32..d8c0cf68b3d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-triplelift-native-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/tripleliftnative/test-triplelift-native-bid-request.json @@ -15,10 +15,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "test" + "id": "test", + "domain": "example.com" }, "ext": { "amp": 0 @@ -54,7 +55,6 @@ }, "ext": { "prebid": { - "debug": 1, "targeting": { "pricegranularity": { "precision": 2, @@ -80,4 +80,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-auction-ttx-request.json b/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-auction-ttx-request.json index ae2a214d8b4..548d95c6df0 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-auction-ttx-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-auction-ttx-request.json @@ -42,9 +42,6 @@ }, "ext": { "prebid": { - "bidadjustmentfactors": { - "33across": 0.7 - }, "targeting": { "pricegranularity": { "precision": 2, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-auction-ttx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-auction-ttx-response.json index ebd9b8f21ff..433ebf8628b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-auction-ttx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-auction-ttx-response.json @@ -34,7 +34,8 @@ "cacheId": "ab634778-1ad8-4851-8f8d-b8588885ec78" } } - } + }, + "origbidcpm": 1.25 } } ], @@ -53,4 +54,4 @@ }, "tmaxrequest": 5000 } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-cache-ttx-request.json b/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-cache-ttx-request.json index 14a96320420..8f3cf1133f3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-cache-ttx-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-cache-ttx-request.json @@ -9,8 +9,11 @@ "adm": "adm001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 1.25 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-ttx-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-ttx-bid-request-1.json index 183807bf649..b069432884a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-ttx-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-ttx-bid-request-1.json @@ -20,10 +20,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 @@ -59,9 +60,6 @@ }, "ext": { "prebid": { - "bidadjustmentfactors": { - "33across": 0.7 - }, "targeting": { "pricegranularity": { "precision": 2, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-ttx-bid-response-1.json b/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-ttx-bid-response-1.json index 89ec3dc2248..5cbb60b868c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-ttx-bid-response-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ttx/test-ttx-bid-response-1.json @@ -16,4 +16,4 @@ } ], "bidid": "bid001" -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ucfunnel/test-auction-ucfunnel-response.json b/src/test/resources/org/prebid/server/it/openrtb2/ucfunnel/test-auction-ucfunnel-response.json index b05053ea656..f673e84fbd1 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ucfunnel/test-auction-ucfunnel-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ucfunnel/test-auction-ucfunnel-response.json @@ -36,7 +36,8 @@ "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 3.33 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ucfunnel/test-cache-ucfunnel-request.json b/src/test/resources/org/prebid/server/it/openrtb2/ucfunnel/test-cache-ucfunnel-request.json index 60845624d51..424a76e0ac4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ucfunnel/test-cache-ucfunnel-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ucfunnel/test-cache-ucfunnel-request.json @@ -11,8 +11,11 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 3.33 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/ucfunnel/test-ucfunnel-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/ucfunnel/test-ucfunnel-bid-request.json index 62747e3cc7c..ca421c07033 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/ucfunnel/test-ucfunnel-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/ucfunnel/test-ucfunnel-bid-request.json @@ -20,10 +20,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-auction-unicorn-request.json b/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-auction-unicorn-request.json new file mode 100644 index 00000000000..4ebebc60f5b --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-auction-unicorn-request.json @@ -0,0 +1,63 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId001", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "unicorn": { + "placementId": "placementId", + "publisherId": 123, + "mediaId": "mediaTestId", + "accountId": 456 + } + } + } + ], + "device": { + "ua" : "userAgent", + "ifa": "ifaId", + "ip": "193.168.244.1" + }, + "site": { + "page": "awesomePage", + "publisher": { + "id": "publisherId" + } + }, + "source": { + "tid": "tidValue" + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + } + }, + "cache": { + "bids": {} + }, + "auctiontimestamp": 1000 + } + }, + "regs": { + "ext": { + "gdpr": 0 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-auction-unicorn-response.json b/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-auction-unicorn-response.json new file mode 100644 index 00000000000..6d3c35163e0 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-auction-unicorn-response.json @@ -0,0 +1,59 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "id": "bid001", + "impid": "impId001", + "price": 3.33, + "adm": "adm001", + "adid": "adid001", + "cid": "cid001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "banner", + "targeting": { + "hb_pb": "3.30", + "hb_size_unicorn": "300x250", + "hb_bidder_unicorn": "unicorn", + "hb_cache_path": "{{ cache.path }}", + "hb_size": "300x250", + "hb_cache_host_unicorn": "{{ cache.host }}", + "hb_cache_path_unicorn": "{{ cache.path }}", + "hb_cache_id_unicorn": "f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "hb_bidder": "unicorn", + "hb_cache_id": "f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "hb_pb_unicorn": "3.30", + "hb_cache_host": "{{ cache.host }}" + }, + "cache": { + "bids": { + "url": "{{ cache.resource_url }}f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" + } + } + }, + "origbidcpm" : 3.33 + } + } + ], + "seat": "unicorn", + "group": 0 + } + ], + "cur": "USD", + "ext": { + "responsetimemillis": { + "unicorn": "{{ unicorn.response_time_ms }}", + "cache": "{{ cache.response_time_ms }}" + }, + "prebid": { + "auctiontimestamp": 1000 + }, + "tmaxrequest": 5000 + } +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-cache-unicorn-request.json b/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-cache-unicorn-request.json new file mode 100644 index 00000000000..63d1e4fd66a --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-cache-unicorn-request.json @@ -0,0 +1,21 @@ +{ + "puts": [ + { + "type": "json", + "value": { + "id": "bid001", + "impid": "impId001", + "price": 3.33, + "adm": "adm001", + "adid": "adid001", + "cid": "cid001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "origbidcpm" : 3.33 + } + } + } + ] +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-cache-unicorn-response.json b/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-cache-unicorn-response.json new file mode 100644 index 00000000000..93d0b8de2cd --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-cache-unicorn-response.json @@ -0,0 +1,7 @@ +{ + "responses": [ + { + "uuid": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-unicorn-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-unicorn-bid-request.json new file mode 100644 index 00000000000..a5d9b9b0821 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-unicorn-bid-request.json @@ -0,0 +1,82 @@ +{ + "id": "tid", + "imp": [ + { + "id": "impId001", + "banner": { + "w": 300, + "h": 250 + }, + "tagid": "placementId", + "secure": 1, + "ext": { + "bidder": { + "placementId": "placementId", + "publisherId": 123, + "mediaId": "mediaTestId", + "accountId": 456 + } + } + } + ], + "site": { + "page": "awesomePage", + "publisher": { + "id": "publisherId" + }, + "ext": { + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "ip": "193.168.244.1", + "ifa": "ifaId" + }, + "user": { + "buyeruid": "UC-UID" + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "source": { + "tid": "tidValue", + "ext": { + "bidder": "unicorn", + "stype": "prebid_server_uncn" + } + }, + "regs": { + "ext": { + "gdpr": 0 + } + }, + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + }, + "includewinners": true, + "includebidderkeys": true + }, + "cache": { + "bids": {} + }, + "auctiontimestamp": 1000, + "channel": { + "name": "web" + } + }, + "accountId": 456 + } +} + diff --git a/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-unicorn-bid-response.json b/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-unicorn-bid-response.json new file mode 100644 index 00000000000..95a93284e04 --- /dev/null +++ b/src/test/resources/org/prebid/server/it/openrtb2/unicorn/test-unicorn-bid-response.json @@ -0,0 +1,20 @@ +{ + "id": "tid", + "seatbid": [ + { + "bid": [ + { + "id": "bid001", + "impid": "impId001", + "price": 3.33, + "adid": "adid001", + "crid": "crid001", + "cid": "cid001", + "adm": "adm001", + "h": 250, + "w": 300 + } + ] + } + ] +} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-auction-unruly-response.json b/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-auction-unruly-response.json index 42fef9c4241..ad5f6f01e23 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-auction-unruly-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-auction-unruly-response.json @@ -41,7 +41,8 @@ "cacheId": "54a3b0a5-e145-43cf-a1cc-1beaa8b29018" } } - } + }, + "origbidcpm": 1.25 } }, { @@ -82,7 +83,8 @@ "cacheId": "41c08fce-546f-4a57-a657-1158fd62af3d" } } - } + }, + "origbidcpm": 2.25 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-cache-unruly-request.json b/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-cache-unruly-request.json index 3bb021b79d7..3326b44919a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-cache-unruly-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-cache-unruly-request.json @@ -9,7 +9,10 @@ "adm": "adm001", "crid": "crid001", "w": 800, - "h": 600 + "h": 600, + "ext": { + "origbidcpm": 1.25 + } } }, { @@ -21,7 +24,10 @@ "adm": "adm002", "crid": "crid002", "w": 640, - "h": 480 + "h": 480, + "ext": { + "origbidcpm": 2.25 + } } }, { @@ -35,4 +41,4 @@ "expiry": 120 } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-unruly-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-unruly-bid-request-1.json index b3fcaf9705e..ee53968a614 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-unruly-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-unruly-bid-request-1.json @@ -19,10 +19,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-unruly-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-unruly-bid-request-2.json index 96889f14e2b..4828734b764 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-unruly-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/unruly/test-unruly-bid-request-2.json @@ -19,10 +19,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/valueimpression/test-auction-valueimpression-response.json b/src/test/resources/org/prebid/server/it/openrtb2/valueimpression/test-auction-valueimpression-response.json index 7344aec2c7e..f912c13d8eb 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/valueimpression/test-auction-valueimpression-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/valueimpression/test-auction-valueimpression-response.json @@ -36,7 +36,8 @@ "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 3.33 } }, { @@ -79,7 +80,8 @@ "cacheId": "44a52b06-b29f-4819-a05f-db36b9e7b8fc" } } - } + }, + "origbidcpm": 5.55 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/valueimpression/test-cache-valueimpression-request.json b/src/test/resources/org/prebid/server/it/openrtb2/valueimpression/test-cache-valueimpression-request.json index 883ffec2c36..53a307b9388 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/valueimpression/test-cache-valueimpression-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/valueimpression/test-cache-valueimpression-request.json @@ -11,7 +11,10 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 3.33 + } } }, { @@ -25,7 +28,10 @@ "cid": "cid002", "crid": "crid002", "w": 1024, - "h": 576 + "h": 576, + "ext": { + "origbidcpm": 5.55 + } } }, { @@ -34,4 +40,4 @@ "expiry": 120 } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/valueimpression/test-valueimpression-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/valueimpression/test-valueimpression-bid-request-1.json index a59a418916d..f7d01fb7585 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/valueimpression/test-valueimpression-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/valueimpression/test-valueimpression-bid-request-1.json @@ -38,10 +38,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/verizonmedia/test-auction-verizonmedia-response.json b/src/test/resources/org/prebid/server/it/openrtb2/verizonmedia/test-auction-verizonmedia-response.json index 920e42dc4e9..3e3e216ae5c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/verizonmedia/test-auction-verizonmedia-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/verizonmedia/test-auction-verizonmedia-response.json @@ -34,7 +34,8 @@ "cacheId": "3bdd45bf-b80e-4943-8445-32692ae5ff51" } } - } + }, + "origbidcpm": 1.25 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/verizonmedia/test-cache-verizonmedia-request.json b/src/test/resources/org/prebid/server/it/openrtb2/verizonmedia/test-cache-verizonmedia-request.json index 14a96320420..8f3cf1133f3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/verizonmedia/test-cache-verizonmedia-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/verizonmedia/test-cache-verizonmedia-request.json @@ -9,8 +9,11 @@ "adm": "adm001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 1.25 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/verizonmedia/test-verizonmedia-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/verizonmedia/test-verizonmedia-bid-request-1.json index 50ae26dd237..102d81cbc7e 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/verizonmedia/test-verizonmedia-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/verizonmedia/test-verizonmedia-bid-request-1.json @@ -24,10 +24,11 @@ ], "site": { "id": "dcn", - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/video/test-video-appnexus-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/video/test-video-appnexus-bid-request-1.json index b17816f4159..abf5074fb47 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/video/test-video-appnexus-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/video/test-video-appnexus-bid-request-1.json @@ -235,6 +235,9 @@ "site": { "domain": "prebid.com", "page": "https://prebid.com", + "publisher": { + "domain": "prebid.com" + }, "content": { "episode": 6, "title": "episodeName", diff --git a/src/test/resources/org/prebid/server/it/openrtb2/video/test-video-appnexus-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/video/test-video-appnexus-bid-request-2.json index 7fad685a3cd..cbeef385604 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/video/test-video-appnexus-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/video/test-video-appnexus-bid-request-2.json @@ -28,6 +28,9 @@ "site": { "domain": "prebid.com", "page": "https://prebid.com", + "publisher": { + "domain": "prebid.com" + }, "content": { "episode": 6, "title": "episodeName", diff --git a/src/test/resources/org/prebid/server/it/openrtb2/visx/test-auction-visx-response.json b/src/test/resources/org/prebid/server/it/openrtb2/visx/test-auction-visx-response.json index 4cca135f21c..0599f31ccb2 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/visx/test-auction-visx-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/visx/test-auction-visx-response.json @@ -37,7 +37,9 @@ "cacheId": "a5d3a873-d06e-4f2f-8556-120e05d62b28" } } - } + }, + "origbidcpm": 0.5, + "origbidcur": "USD" } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/visx/test-cache-visx-request.json b/src/test/resources/org/prebid/server/it/openrtb2/visx/test-cache-visx-request.json index 8ee5c82733f..8bbe6b2384a 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/visx/test-cache-visx-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/visx/test-cache-visx-request.json @@ -12,8 +12,12 @@ ], "crid": "11_222222", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 0.5, + "origbidcur": "USD" + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/visx/test-visx-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/visx/test-visx-bid-request.json index acd4d80c313..688a375dd13 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/visx/test-visx-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/visx/test-visx-bid-request.json @@ -27,10 +27,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/vrtcal/test-auction-vrtcal-response.json b/src/test/resources/org/prebid/server/it/openrtb2/vrtcal/test-auction-vrtcal-response.json index 36b4155213f..ee2fd363e65 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/vrtcal/test-auction-vrtcal-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/vrtcal/test-auction-vrtcal-response.json @@ -36,7 +36,8 @@ "cacheId": "6e2bfba0-8ff2-4ed8-8a2c-ce1a7ca4f599" } } - } + }, + "origbidcpm": 1.25 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/vrtcal/test-cache-vrtcal-request.json b/src/test/resources/org/prebid/server/it/openrtb2/vrtcal/test-cache-vrtcal-request.json index 14a96320420..8f3cf1133f3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/vrtcal/test-cache-vrtcal-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/vrtcal/test-cache-vrtcal-request.json @@ -9,8 +9,11 @@ "adm": "adm001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 1.25 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/yeahmobi/test-auction-yeahmobi-response.json b/src/test/resources/org/prebid/server/it/openrtb2/yeahmobi/test-auction-yeahmobi-response.json index b97993ef7d9..ac4f9440ffd 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/yeahmobi/test-auction-yeahmobi-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/yeahmobi/test-auction-yeahmobi-response.json @@ -34,7 +34,8 @@ "url": "{{ cache.resource_url }}f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 0.01 } } ], @@ -53,4 +54,4 @@ }, "tmaxrequest": 3000 } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/yeahmobi/test-cache-yeahmobi-request.json b/src/test/resources/org/prebid/server/it/openrtb2/yeahmobi/test-cache-yeahmobi-request.json index c6692479e4a..cdadbec00c4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/yeahmobi/test-cache-yeahmobi-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/yeahmobi/test-cache-yeahmobi-request.json @@ -10,9 +10,10 @@ "cid": "test_cid", "crid": "test_banner_crid", "ext": { - "format": "BANNER" + "format": "BANNER", + "origbidcpm": 0.01 } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/yeahmobi/test-yeahmobi-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/yeahmobi/test-yeahmobi-bid-request.json index b94c172d60b..ac6ff6eef59 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/yeahmobi/test-yeahmobi-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/yeahmobi/test-yeahmobi-bid-request.json @@ -27,7 +27,8 @@ "domain": "example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/yieldlab/test-auction-yieldlab-response.json b/src/test/resources/org/prebid/server/it/openrtb2/yieldlab/test-auction-yieldlab-response.json index 92eda441221..3f3621317e4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/yieldlab/test-auction-yieldlab-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/yieldlab/test-auction-yieldlab-response.json @@ -37,7 +37,9 @@ "cacheId": "ca2a4dd3-f974-4eff-be5c-986bf4e083ce" } } - } + }, + "origbidcpm": 2.01, + "origbidcur": "EUR" } } ], @@ -51,7 +53,7 @@ "httpcalls": { "cache": [ { - "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"12345\",\"impid\":\"impId001\",\"price\":2.29,\"adm\":\"\",\"crid\":\"12345123435\",\"dealid\":\"1234\",\"w\":400,\"h\":300}}]}", + "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"12345\",\"impid\":\"impId001\",\"price\":2.29,\"adm\":\"\",\"crid\":\"12345123435\",\"dealid\":\"1234\",\"w\":400,\"h\":300,\"ext\":{\"origbidcpm\":2.01,\"origbidcur\":\"EUR\"}}}]}", "responsebody": "{\"responses\":[{\"uuid\":\"ca2a4dd3-f974-4eff-be5c-986bf4e083ce\"}]}", "status": 200, "uri": "{{ cache.endpoint }}" @@ -151,6 +153,7 @@ } }, "site": { + "domain": "localhost", "ext": { "amp": 0 }, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/yieldlab/test-cache-yieldlab-request.json b/src/test/resources/org/prebid/server/it/openrtb2/yieldlab/test-cache-yieldlab-request.json index aeb6eb7cbc2..1f02a59c03b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/yieldlab/test-cache-yieldlab-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/yieldlab/test-cache-yieldlab-request.json @@ -10,8 +10,12 @@ "crid": "12345123435", "dealid": "1234", "w": 400, - "h": 300 + "h": 300, + "ext": { + "origbidcpm": 2.01, + "origbidcur": "EUR" + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/yieldmo/test-auction-yieldmo-response.json b/src/test/resources/org/prebid/server/it/openrtb2/yieldmo/test-auction-yieldmo-response.json index 36386f57789..bf4d467e11d 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/yieldmo/test-auction-yieldmo-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/yieldmo/test-auction-yieldmo-response.json @@ -36,7 +36,8 @@ "cacheId": "a5d3a873-d06e-4f2f-8556-120e05d62b28" } } - } + }, + "origbidcpm": 3.33 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/yieldmo/test-cache-yieldmo-request.json b/src/test/resources/org/prebid/server/it/openrtb2/yieldmo/test-cache-yieldmo-request.json index 60845624d51..424a76e0ac4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/yieldmo/test-cache-yieldmo-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/yieldmo/test-cache-yieldmo-request.json @@ -11,8 +11,11 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 3.33 + } } } ] -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/yieldmo/test-yieldmo-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/yieldmo/test-yieldmo-bid-request-1.json index 456dec57676..a1ef7a63797 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/yieldmo/test-yieldmo-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/yieldmo/test-yieldmo-bid-request-1.json @@ -17,10 +17,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/yieldone/test-auction-yieldone-response.json b/src/test/resources/org/prebid/server/it/openrtb2/yieldone/test-auction-yieldone-response.json index 0eebe0f049e..2288a229e67 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/yieldone/test-auction-yieldone-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/yieldone/test-auction-yieldone-response.json @@ -36,7 +36,8 @@ "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" } } - } + }, + "origbidcpm": 3.33 } } ], diff --git a/src/test/resources/org/prebid/server/it/openrtb2/yieldone/test-cache-yieldone-request.json b/src/test/resources/org/prebid/server/it/openrtb2/yieldone/test-cache-yieldone-request.json index 23ddbec96e5..424a76e0ac4 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/yieldone/test-cache-yieldone-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/yieldone/test-cache-yieldone-request.json @@ -11,7 +11,10 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 3.33 + } } } ] diff --git a/src/test/resources/org/prebid/server/it/openrtb2/yieldone/test-yieldone-bid-request.json b/src/test/resources/org/prebid/server/it/openrtb2/yieldone/test-yieldone-bid-request.json index 2dd1d05c05b..735c577995c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/yieldone/test-yieldone-bid-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/yieldone/test-yieldone-bid-request.json @@ -21,10 +21,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 diff --git a/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-auction-zeroclickfraud-request.json b/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-auction-zeroclickfraud-request.json index cf0d5e2ef9c..fba4b6cf08f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-auction-zeroclickfraud-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-auction-zeroclickfraud-request.json @@ -66,7 +66,6 @@ }, "ext": { "prebid": { - "debug": 1, "currency": { "rates": { "EUR": { @@ -107,4 +106,4 @@ "gdpr": 0 } } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-auction-zeroclickfraud-response.json b/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-auction-zeroclickfraud-response.json index 50684d8fff8..4e03d8c7c10 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-auction-zeroclickfraud-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-auction-zeroclickfraud-response.json @@ -46,7 +46,8 @@ "cacheId": "62019cff-d657-42fc-8366-16c34e1fd28c" } } - } + }, + "origbidcpm": 9.99 } }, { @@ -82,7 +83,8 @@ "cacheId": "c1662cf6-f00a-4066-b71a-46d97abccc35" } } - } + }, + "origbidcpm": 7.77 } } ], @@ -92,154 +94,6 @@ ], "cur": "USD", "ext": { - "debug": { - "httpcalls": { - "cache": [ - { - "uri": "{{ cache.endpoint }}", - "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"bid001\",\"impid\":\"impId001\",\"price\":7.77,\"adm\":\"adm001\",\"adid\":\"adid001\",\"cid\":\"cid001\",\"crid\":\"crid001\",\"w\":300,\"h\":250}},{\"type\":\"json\",\"value\":{\"id\":\"bid002\",\"impid\":\"impId002\",\"price\":9.99,\"nurl\":\"https://example.com/nurl\",\"adomain\":[\"psacentral.org\"],\"cid\":\"cid002\",\"crid\":\"crid002\",\"w\":300,\"h\":250}},{\"type\":\"xml\",\"value\":\"prebid.org wrapper\",\"expiry\":120}]}", - "responsebody": "{\"responses\":[{\"uuid\":\"c1662cf6-f00a-4066-b71a-46d97abccc35\"},{\"uuid\":\"dbaa191c-5a56-4655-85eb-da079f94e09f\"},{\"uuid\":\"62019cff-d657-42fc-8366-16c34e1fd28c\"}]}", - "status": 200 - } - ], - "zeroclickfraud": [ - { - "uri": "{{ zeroclickfraud.exchange_uri }}?sid=2", - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId002\",\"video\":{\"mimes\":[\"video/mp4\"],\"w\":300,\"h\":250,\"pos\":1},\"ext\":{\"bidder\":{\"host\":\"localhost:8090\",\"sourceId\":2}}}],\"site\":{\"domain\":\"example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"id\":\"publisherId\"},\"ext\":{\"amp\":0}},\"device\":{\"ua\":\"userAgent\",\"dnt\":2,\"ip\":\"193.168.244.1\",\"pxratio\":4.2,\"language\":\"en\",\"ifa\":\"ifaId\"},\"user\":{\"buyeruid\":\"ZF-UID\",\"ext\":{\"consent\":\"consentValue\"}},\"at\":1,\"tmax\":5000,\"cur\":[\"USD\"],\"source\":{\"fd\":1,\"tid\":\"tid\"},\"regs\":{\"ext\":{\"gdpr\":0}},\"ext\":{\"prebid\":{\"debug\":1,\"currency\":{\"rates\":{\"EUR\":{\"USD\":1.2406},\"USD\":{\"EUR\":0.811}}},\"targeting\":{\"pricegranularity\":{\"precision\":2,\"ranges\":[{\"max\":20,\"increment\":0.1}]},\"includewinners\":true,\"includebidderkeys\":true},\"cache\":{\"bids\":{},\"vastxml\":{\"ttlseconds\":120}},\"auctiontimestamp\":1000,\"channel\":{\"name\":\"web\"}}}}", - "responsebody": "{\"id\":\"tid\",\"seatbid\":[{\"bid\":[{\"id\":\"bid002\",\"impid\":\"impId002\",\"price\":9.99,\"crid\":\"crid002\",\"cid\":\"cid002\",\"adomain\":[\"psacentral.org\"],\"nurl\":\"https://example.com/nurl\",\"h\":250,\"w\":300}],\"seat\":\"zeroclickfraud\"}]}", - "status": 200 - }, - { - "uri": "{{ zeroclickfraud.exchange_uri }}?sid=1", - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId001\",\"banner\":{\"format\":[{\"w\":300,\"h\":250}]},\"ext\":{\"bidder\":{\"host\":\"localhost:8090\",\"sourceId\":1}}}],\"site\":{\"domain\":\"example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"id\":\"publisherId\"},\"ext\":{\"amp\":0}},\"device\":{\"ua\":\"userAgent\",\"dnt\":2,\"ip\":\"193.168.244.1\",\"pxratio\":4.2,\"language\":\"en\",\"ifa\":\"ifaId\"},\"user\":{\"buyeruid\":\"ZF-UID\",\"ext\":{\"consent\":\"consentValue\"}},\"at\":1,\"tmax\":5000,\"cur\":[\"USD\"],\"source\":{\"fd\":1,\"tid\":\"tid\"},\"regs\":{\"ext\":{\"gdpr\":0}},\"ext\":{\"prebid\":{\"debug\":1,\"currency\":{\"rates\":{\"EUR\":{\"USD\":1.2406},\"USD\":{\"EUR\":0.811}}},\"targeting\":{\"pricegranularity\":{\"precision\":2,\"ranges\":[{\"max\":20,\"increment\":0.1}]},\"includewinners\":true,\"includebidderkeys\":true},\"cache\":{\"bids\":{},\"vastxml\":{\"ttlseconds\":120}},\"auctiontimestamp\":1000,\"channel\":{\"name\":\"web\"}}}}", - "responsebody": "{\"id\":\"tid\",\"seatbid\":[{\"bid\":[{\"id\":\"bid001\",\"impid\":\"impId001\",\"price\":7.77,\"adid\":\"adid001\",\"crid\":\"crid001\",\"cid\":\"cid001\",\"adm\":\"adm001\",\"h\":250,\"w\":300}],\"seat\":\"zeroclickfraud\"}]}", - "status": 200 - } - ] - }, - "resolvedrequest": { - "id": "tid", - "imp": [ - { - "id": "impId001", - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "ext": { - "prebid": { - "bidder": { - "zeroclickfraud": { - "host": "localhost:8090", - "sourceId": 1 - } - } - } - } - }, - { - "id": "impId002", - "video": { - "mimes": [ - "video/mp4" - ], - "w": 300, - "h": 250, - "pos": 1 - }, - "ext": { - "prebid": { - "bidder": { - "zeroclickfraud": { - "host": "localhost:8090", - "sourceId": 2 - } - } - } - } - } - ], - "site": { - "domain": "example.com", - "page": "http://www.example.com", - "publisher": { - "id": "publisherId" - }, - "ext": { - "amp": 0 - } - }, - "device": { - "ua": "userAgent", - "dnt": 2, - "ip": "193.168.244.1", - "pxratio": 4.2, - "language": "en", - "ifa": "ifaId" - }, - "user": { - "ext": { - "consent": "consentValue" - } - }, - "at": 1, - "tmax": 5000, - "cur": [ - "USD" - ], - "source": { - "fd": 1, - "tid": "tid" - }, - "regs": { - "ext": { - "gdpr": 0 - } - }, - "ext": { - "prebid": { - "debug": 1, - "currency": { - "rates": { - "EUR": { - "USD": 1.2406 - }, - "USD": { - "EUR": 0.811 - } - } - }, - "targeting": { - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "max": 20, - "increment": 0.1 - } - ] - }, - "includewinners": true, - "includebidderkeys": true - }, - "cache": { - "bids": {}, - "vastxml": { - "ttlseconds": 120 - } - }, - "auctiontimestamp": 1000, - "channel": { - "name": "web" - } - } - } - } - }, "responsetimemillis": { "zeroclickfraud": "{{ zeroclickfraud.response_time_ms }}", "cache": "{{ cache.response_time_ms }}" diff --git a/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-cache-zeroclickfraud-request.json b/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-cache-zeroclickfraud-request.json index d22654a542b..bb6e149acf3 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-cache-zeroclickfraud-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-cache-zeroclickfraud-request.json @@ -11,7 +11,10 @@ "cid": "cid001", "crid": "crid001", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 7.77 + } } }, { @@ -24,10 +27,14 @@ "psacentral.org" ], "nurl": "https://example.com/nurl", + "adm": "prebid.org wrapper", "cid": "cid002", "crid": "crid002", "w": 300, - "h": 250 + "h": 250, + "ext": { + "origbidcpm": 9.99 + } } }, { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-zeroclickfraud-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-zeroclickfraud-bid-request-1.json index d578b675833..caa42460d1c 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-zeroclickfraud-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-zeroclickfraud-bid-request-1.json @@ -20,10 +20,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 @@ -59,7 +60,6 @@ }, "ext": { "prebid": { - "debug": 1, "currency": { "rates": { "EUR": { @@ -95,4 +95,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-zeroclickfraud-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-zeroclickfraud-bid-request-2.json index 871c2f75cd1..914ceabc8a6 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-zeroclickfraud-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/zeroclickfraud/test-zeroclickfraud-bid-request-2.json @@ -20,10 +20,11 @@ } ], "site": { - "domain": "example.com", + "domain": "www.example.com", "page": "http://www.example.com", "publisher": { - "id": "publisherId" + "id": "publisherId", + "domain": "example.com" }, "ext": { "amp": 0 @@ -59,7 +60,6 @@ }, "ext": { "prebid": { - "debug": 1, "currency": { "rates": { "EUR": { @@ -95,4 +95,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/test/resources/org/prebid/server/it/storedimps/test-rubicon-stored-video-cache-update.json b/src/test/resources/org/prebid/server/it/storedimps/test-rubicon-stored-video-cache-update.json index 2c07db85a8c..39002f2ebfc 100644 --- a/src/test/resources/org/prebid/server/it/storedimps/test-rubicon-stored-video-cache-update.json +++ b/src/test/resources/org/prebid/server/it/storedimps/test-rubicon-stored-video-cache-update.json @@ -13,7 +13,9 @@ "skipafter": 0, "skipmin": 0, "startdelay": 0, - "playbackmethod": [1] + "playbackmethod": [ + 1 + ] }, "ext": { "rubicon": { diff --git a/src/test/resources/org/prebid/server/it/storedimps/test-video-stored-imp-request-1.json b/src/test/resources/org/prebid/server/it/storedimps/test-video-stored-imp-request-1.json index ed4c508df98..3fd2300c22e 100644 --- a/src/test/resources/org/prebid/server/it/storedimps/test-video-stored-imp-request-1.json +++ b/src/test/resources/org/prebid/server/it/storedimps/test-video-stored-imp-request-1.json @@ -1 +1,7 @@ -{"ext": {"appnexus": {"placementId": 14997137}}} +{ + "ext": { + "appnexus": { + "placementId": 14997137 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/storedimps/test-video-stored-imp-request-2.json b/src/test/resources/org/prebid/server/it/storedimps/test-video-stored-imp-request-2.json index 920c894bca1..47ef883f74f 100644 --- a/src/test/resources/org/prebid/server/it/storedimps/test-video-stored-imp-request-2.json +++ b/src/test/resources/org/prebid/server/it/storedimps/test-video-stored-imp-request-2.json @@ -1 +1,7 @@ -{"ext": {"appnexus": {"placementId": 15016213}}} +{ + "ext": { + "appnexus": { + "placementId": 15016213 + } + } +} diff --git a/src/test/resources/org/prebid/server/it/test-application.properties b/src/test/resources/org/prebid/server/it/test-application.properties index c50e2539b66..7083e81afae 100644 --- a/src/test/resources/org/prebid/server/it/test-application.properties +++ b/src/test/resources/org/prebid/server/it/test-application.properties @@ -58,10 +58,15 @@ adapters.adtelligent.enabled=true adapters.adtelligent.endpoint=http://localhost:8090/adtelligent-exchange adapters.adtelligent.pbs-enforces-gdpr=true adapters.adtelligent.usersync.url=//adtelligent-usersync +adapters.adtelligent.aliases.mediafuse.enabled=true adapters.advangelists.enabled=true adapters.advangelists.endpoint=http://localhost:8090/advangelists-exchange?pubid={{PublisherID}} adapters.advangelists.pbs-enforces-gdpr=true adapters.advangelists.usersync.url=//advangelists-usersync +adapters.adyoulike.enabled=true +adapters.adyoulike.endpoint=http://localhost:8090/adyoulike-exchange +adapters.adyoulike.pbs-enforces-gdpr=true +adapters.adyoulike.usersync.url=//adyoulike-usersync adapters.aja.enabled=true adapters.aja.endpoint=http://localhost:8090/aja adapters.aja.pbs-enforces-gdpr=true @@ -74,6 +79,8 @@ adapters.appnexus.enabled=true adapters.appnexus.endpoint=http://localhost:8090/appnexus-exchange adapters.appnexus.pbs-enforces-gdpr=true adapters.appnexus.usersync.url=//usersync-url/getuid? +adapters.appnexus.aliases.districtm.enabled=true +adapters.appnexus.aliases.districtm.endpoint=http://localhost:8090/districtm-exchange adapters.applogy.enabled=true adapters.applogy.endpoint=http://localhost:8090/applogy-exchange adapters.applogy.pbs-enforces-gdpr=true @@ -83,10 +90,10 @@ adapters.avocet.endpoint=http://localhost:8090/avocet-exchange adapters.avocet.pbs-enforces-gdpr=true adapters.avocet.usersync.url=//avocet-usersync adapters.beachfront.enabled=true -adapters.beachfront.endpoint:http://localhost:8090/beachfront-exchange/banner -adapters.beachfront.video-endpoint:http://localhost:8090/beachfront-exchange/video?exchange_id= -adapters.beachfront.platform-id:142 -adapters.beachfront.pbs-enforces-gdpr:true +adapters.beachfront.endpoint=http://localhost:8090/beachfront-exchange/banner +adapters.beachfront.video-endpoint=http://localhost:8090/beachfront-exchange/video?exchange_id= +adapters.beachfront.platform-id=142 +adapters.beachfront.pbs-enforces-gdpr=true adapters.beachfront.usersync.url=//beachfront-usersync adapters.beintoo.enabled=true adapters.beintoo.endpoint=http://localhost:8090/beintoo-exchange @@ -117,6 +124,10 @@ adapters.datablocks.enabled=true adapters.datablocks.endpoint=http://{{Host}}/datablocks-exchange?sid={{SourceId}} adapters.datablocks.pbs-enforces-gdpr=true adapters.datablocks.usersync.url=//datablocks-usersync +adapters.decenterads.enabled=true +adapters.decenterads.endpoint=http://localhost:8090/decenterads-exchange +adapters.decenterads.pbs-enforces-gdpr=true +adapters.decenterads.usersync.url=//decenterads-usersync adapters.deepintent.enabled=true adapters.deepintent.endpoint=http://localhost:8090/deepintent-exchange adapters.deepintent.pbs-enforces-gdpr=true @@ -137,6 +148,10 @@ adapters.eplanning.enabled=true adapters.eplanning.endpoint=http://localhost:8090/eplanning-exchange adapters.eplanning.pbs-enforces-gdpr=true adapters.eplanning.usersync.url=//eplanning-usersync +adapters.epom.enabled=true +adapters.epom.endpoint=http://localhost:8090/epom-exchange +adapters.epom.pbs-enforces-gdpr=true +adapters.epom.usersync.url=//epom-usersync adapters.facebook.enabled=true adapters.facebook.endpoint=http://localhost:8090/audienceNetwork-exchange adapters.facebook.pbs-enforces-gdpr=true @@ -167,6 +182,10 @@ adapters.ix.enabled=true adapters.ix.endpoint=http://localhost:8090/ix-exchange adapters.ix.pbs-enforces-gdpr=true adapters.ix.usersync.url=//ix-usersync +adapters.jixie.enabled=true +adapters.jixie.endpoint=http://localhost:8090/jixie-exchange +adapters.jixie.pbs-enforces-gdpr=true +adapters.jixie.usersync.url=//jixie-usersync adapters.kidoz.enabled=true adapters.kidoz.endpoint=http://localhost:8090/kidoz-exchange adapters.kidoz.pbs-enforces-gdpr=true @@ -208,7 +227,7 @@ adapters.mgid.endpoint=http://localhost:8090/mgid-exchange/ adapters.mgid.pbs-enforces-gdpr=true adapters.mgid.usersync.url=//mgid-usersync adapters.mobfoxpb.enabled=true -adapters.mobfoxpb.endpoint=http://localhost:8090/mobfoxpb-exchange +adapters.mobfoxpb.endpoint=http://localhost:8090/mobfoxpb-exchange?c=__route__&m=__method__&key=__key__ adapters.mobfoxpb.pbs-enforces-gdpr=true adapters.mobfoxpb.usersync.url=//mobfoxpb-usersync adapters.mobilefuse.enabled=true @@ -227,6 +246,10 @@ adapters.nobid.enabled=true adapters.nobid.endpoint=http://localhost:8090/nobid-exchange?pubid= adapters.nobid.pbs-enforces-gdpr=true adapters.nobid.usersync.url=//nobid-usersync +adapters.onetag.enabled=true +adapters.onetag.endpoint=http://localhost:8090/onetag-exchange +adapters.onetag.pbs-enforces-gdpr=true +adapters.onetag.usersync.url=//onetag-usersync adapters.openx.enabled=true adapters.openx.endpoint=http://localhost:8090/openx-exchange adapters.openx.pbs-enforces-gdpr=true @@ -235,6 +258,14 @@ adapters.orbidder.enabled=true adapters.orbidder.endpoint=http://localhost:8090/orbidder-exchange adapters.orbidder.pbs-enforces-gdpr=true adapters.orbidder.usersync.url=//orbidder-usersync +adapters.outbrain.enabled=true +adapters.outbrain.endpoint=http://localhost:8090/outbrain-exchange +adapters.outbrain.pbs-enforces-gdpr=true +adapters.outbrain.usersync.url=//outbrain-usersync +adapters.pangle.enabled=true +adapters.pangle.endpoint=http://localhost:8090/pangle-exchange +adapters.pangle.pbs-enforces-gdpr=true +adapters.pangle.usersync.url=//pangle-usersync adapters.pubmatic.enabled=true adapters.pubmatic.endpoint=http://localhost:8090/pubmatic-exchange adapters.pubmatic.pbs-enforces-gdpr=true @@ -327,10 +358,15 @@ adapters.ttx.endpoint=http://localhost:8090/ttx-exchange adapters.ttx.partner-id=partner adapters.ttx.pbs-enforces-gdpr=true adapters.ttx.usersync.url=//ttx-usersync +adapters.ttx.aliases.33across.enabled=true adapters.ucfunnel.enabled=true adapters.ucfunnel.endpoint=http://localhost:8090/ucfunnel-exchange adapters.ucfunnel.pbs-enforces-gdpr=true adapters.ucfunnel.usersync.url=//ucfunnel-usersync +adapters.unicorn.enabled=true +adapters.unicorn.endpoint=http://localhost:8090/unicorn-exchange +adapters.unicorn.pbs-enforces-gdpr=true +adapters.unicorn.usersync.url=//unicorn-usersync adapters.between.enabled=true adapters.between.endpoint=http://localhost:8090/between-exchange?host={{Host}}&pubId={{PublisherId}} adapters.between.pbs-enforces-gdpr=true diff --git a/src/test/resources/org/prebid/server/validation/schema/invalid/rubicon.json b/src/test/resources/org/prebid/server/validation/schema/invalid/rubicon.json index 0079b4102c2..985d2d7592f 100644 --- a/src/test/resources/org/prebid/server/validation/schema/invalid/rubicon.json +++ b/src/test/resources/org/prebid/server/validation/schema/invalid/rubicon.json @@ -1 +1 @@ -} 12345 : } \ No newline at end of file +} 12345: } \ No newline at end of file From fe32b0493e6d9d55fc1621bbefe1e4f76b0b0946 Mon Sep 17 00:00:00 2001 From: albertmolinermrf Date: Mon, 13 Mar 2023 07:08:07 +0100 Subject: [PATCH 28/29] Dummy change to force a rebuild (#14) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c4f9d91d0fa..279af6acec6 100644 --- a/README.md +++ b/README.md @@ -108,3 +108,4 @@ and verify response status is `200 OK`. - [Code Style](docs/code-style.md) - [Code Review](docs/code-reviews.md) - [Versioning](docs/versioning.md) + From 42951341a7fb0918f00efa5523358da3f80aebab Mon Sep 17 00:00:00 2001 From: Fran Date: Tue, 21 Oct 2025 16:59:55 +0200 Subject: [PATCH 29/29] Update JDK --- build/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Dockerfile b/build/Dockerfile index 9fa747486d3..386c7e100b8 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -1,4 +1,4 @@ -FROM openjdk:8-jdk +FROM --platform=amd64 tomcat:8.5-jdk8-temurin-jammy ENV VERTICLE_FILE prebid-server.jar