diff --git a/docs/bidders/appnexus.md b/docs/bidders/appnexus.md index 7cd126fda71..2868740d234 100644 --- a/docs/bidders/appnexus.md +++ b/docs/bidders/appnexus.md @@ -15,7 +15,7 @@ The AppNexus endpoint expects `imp.displaymanagerver` to be populated for mobile requests, however not all SDKs will populate this field. If the `imp.displaymanagerver` field is not supplied for an `imp`, but `request.app.ext.prebid.source` and `request.app.ext.prebid.version` are supplied, the adapter will fill in a value for -`diplaymanagerver`. It will concatonate the two `app` fields as `-` to fill in +`diplaymanagerver`. It will concatenate the two `app` fields as `-` to fill in the empty `displaymanagerver` before sending the request to AppNexus. ## Test Request diff --git a/docs/config-app.md b/docs/config-app.md index ccf54647aa6..865ac90601d 100644 --- a/docs/config-app.md +++ b/docs/config-app.md @@ -358,11 +358,11 @@ If not defined in config all other Health Checkers would be disabled and endpoin - `gdpr.special-features.sfN.vendor-exceptions[]` - bidder names that will be treated opposite to `sfN.enforce` value. - `gdpr.purpose-one-treatment-interpretation` - option that allows to skip the Purpose one enforcement workflow. - `gdpr.vendorlist.default-timeout-ms` - default operation timeout for obtaining new vendor list. -- `gdpr.vendorlist.vN.http-endpoint-template` - template string for vendor list url, where `{VERSION}` is used as version number placeholder. -- `gdpr.vendorlist.vN.refresh-missing-list-period-ms` - time to wait between attempts to fetch vendor list version that previously was reported to be missing by origin. Default `3600000` (one hour). -- `gdpr.vendorlist.vN.fallback-vendor-list-path` - location on the file system of the fallback vendor list that will be used in place of missing vendor list versions. Optional. -- `gdpr.vendorlist.vN.deprecated` - Flag to show is this vendor list is deprecated or not. -- `gdpr.vendorlist.vN.cache-dir` - directory for local storage cache for vendor list. Should be with `WRITE` permissions for user application run from. +- `gdpr.vendorlist.v2.http-endpoint-template` - template string for vendor list url version 2. +- `gdpr.vendorlist.v2.refresh-missing-list-period-ms` - time to wait between attempts to fetch vendor list version that previously was reported to be missing by origin. Default `3600000` (one hour). +- `gdpr.vendorlist.v2.fallback-vendor-list-path` - location on the file system of the fallback vendor list that will be used in place of missing vendor list versions. Optional. +- `gdpr.vendorlist.v2.deprecated` - Flag to show is this vendor list is deprecated or not. +- `gdpr.vendorlist.v2.cache-dir` - directory for local storage cache for vendor list. Should be with `WRITE` permissions for user application run from. ## CCPA - `ccpa.enforce` - if equals to `true` enforces to check ccpa policy, otherwise ignore ccpa verification. diff --git a/pom.xml b/pom.xml index 277a6c1f655..9b63949ae1d 100644 --- a/pom.xml +++ b/pom.xml @@ -321,6 +321,12 @@ ${wiremock.version} test + + com.iabtcf + iabtcf-encoder + ${iabtcf.version} + test + org.eclipse.jetty jetty-server diff --git a/sample/prebid-config.yaml b/sample/prebid-config.yaml index 2a80c48effe..e7bed758cf9 100644 --- a/sample/prebid-config.yaml +++ b/sample/prebid-config.yaml @@ -19,7 +19,5 @@ settings: stored-responses-dir: gdpr: vendorlist: - v1: - cache-dir: /var/tmp/vendor1 v2: cache-dir: /var/tmp/vendor2 diff --git a/src/main/java/org/prebid/server/metric/Metrics.java b/src/main/java/org/prebid/server/metric/Metrics.java index 3c3cf9ef8bc..43a7dfc4a78 100644 --- a/src/main/java/org/prebid/server/metric/Metrics.java +++ b/src/main/java/org/prebid/server/metric/Metrics.java @@ -373,12 +373,12 @@ public void updatePrivacyTcfInvalidMetric() { } public void updatePrivacyTcfRequestsMetric(int version) { - final UpdatableMetrics versionMetrics = version == 2 ? privacy().tcf().v2() : privacy().tcf().v1(); + final UpdatableMetrics versionMetrics = privacy().tcf().fromVersion(version); versionMetrics.incCounter(MetricName.requests); } public void updatePrivacyTcfGeoMetric(int version, Boolean inEea) { - final UpdatableMetrics versionMetrics = version == 2 ? privacy().tcf().v2() : privacy().tcf().v1(); + final UpdatableMetrics versionMetrics = privacy().tcf().fromVersion(version); final MetricName metricName = inEea == null ? MetricName.unknown_geo @@ -405,8 +405,7 @@ public void updatePrivacyTcfVendorListFallbackMetric(int version) { private void updatePrivacyTcfVendorListMetric(int version, MetricName metricName) { final TcfMetrics tcfMetrics = privacy().tcf(); - final TcfMetrics.TcfVersionMetrics tcfVersionMetrics = version == 2 ? tcfMetrics.v2() : tcfMetrics.v1(); - tcfVersionMetrics.vendorList().incCounter(metricName); + tcfMetrics.fromVersion(version).vendorList().incCounter(metricName); } public void updateConnectionAcceptErrors() { diff --git a/src/main/java/org/prebid/server/metric/TcfMetrics.java b/src/main/java/org/prebid/server/metric/TcfMetrics.java index 1bd01b43bba..b29416f061e 100644 --- a/src/main/java/org/prebid/server/metric/TcfMetrics.java +++ b/src/main/java/org/prebid/server/metric/TcfMetrics.java @@ -1,6 +1,7 @@ package org.prebid.server.metric; import com.codahale.metrics.MetricRegistry; +import org.prebid.server.exception.PreBidException; import java.util.Objects; import java.util.function.Function; @@ -10,6 +11,9 @@ */ class TcfMetrics extends UpdatableMetrics { + private static final int TCF_V1_VERSION = 1; + private static final int TCF_V2_VERSION = 2; + private final TcfVersionMetrics tcfVersion1Metrics; private final TcfVersionMetrics tcfVersion2Metrics; @@ -23,12 +27,15 @@ class TcfMetrics extends UpdatableMetrics { tcfVersion2Metrics = new TcfVersionMetrics(metricRegistry, counterType, createTcfPrefix(prefix), "v2"); } - TcfVersionMetrics v1() { - return tcfVersion1Metrics; - } - - TcfVersionMetrics v2() { - return tcfVersion2Metrics; + TcfVersionMetrics fromVersion(int version) { + switch (version) { + case TCF_V1_VERSION: + return tcfVersion1Metrics; + case TCF_V2_VERSION: + return tcfVersion2Metrics; + default: + throw new PreBidException(String.format("Unknown tcf version %s", version)); + } } private static String createTcfPrefix(String prefix) { diff --git a/src/main/java/org/prebid/server/privacy/gdpr/GdprService.java b/src/main/java/org/prebid/server/privacy/gdpr/GdprService.java deleted file mode 100644 index e75e2d6bf6a..00000000000 --- a/src/main/java/org/prebid/server/privacy/gdpr/GdprService.java +++ /dev/null @@ -1,181 +0,0 @@ -package org.prebid.server.privacy.gdpr; - -import com.iab.gdpr.consent.VendorConsent; -import com.iab.gdpr.consent.VendorConsentDecoder; -import com.iab.gdpr.exception.VendorConsentParseException; -import io.vertx.core.Future; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import org.apache.commons.lang3.StringUtils; -import org.prebid.server.exception.InvalidRequestException; -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.PurposeCode; -import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorListV1; -import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV1; - -import java.util.Collection; -import java.util.EnumSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * Service provides GDPR support. - *

- * For more information about GDPR, see https://gdpr.iab.com site. - */ -public class GdprService { - - private static final Logger logger = LoggerFactory.getLogger(GdprService.class); - - private final VendorListService vendorListService; - - public GdprService(VendorListService vendorListService) { - this.vendorListService = Objects.requireNonNull(vendorListService); - } - - /** - * Determines what is allowed and what is not (in terms of TCF v1.1 implementation aka GDPR) for each vendor - * taking into account user consent string (version 1.1). - * - * @param vendorIds to examine in consent string and vendor list - * @param vendorConsentString user consent string - * @return collection of {@link VendorPermission}s indicating what vendor is allowed to do - */ - public Future> resultFor(Set vendorIds, String vendorConsentString) { - - final VendorConsent vendorConsent = vendorConsentFrom(vendorConsentString); - if (vendorConsent == null) { - // consent string is broken - return Future.succeededFuture(vendorIds.stream() - .map(GdprService::toRestrictedVendorPermission) - .collect(Collectors.toList())); - } - - return vendorListService.forVersion(vendorConsent.getVendorListVersion()) - .compose(vendorListMapping -> toResult(vendorListMapping, vendorIds, vendorConsent), - ignoredFailed -> toFallbackResult(vendorIds)); - } - - /** - * Parses consent string to {@link VendorConsent} model. Returns null if: - *

- * - consent string is missing - *

- * - parsing of consent string is failed - */ - private VendorConsent vendorConsentFrom(String vendorConsentString) { - if (StringUtils.isEmpty(vendorConsentString)) { - return null; - } - try { - return VendorConsentDecoder.fromBase64String(vendorConsentString); - } catch (IllegalArgumentException | IllegalStateException e) { - logger.info("Parsing consent string failed with error: {0}", e.getMessage()); - return null; - } - } - - /** - * Processes {@link VendorListService} response and returns GDPR result for every vendor ID. - */ - private static Future> toResult(Map vendorListMapping, - Set vendorIds, - VendorConsent vendorConsent) { - - final Set allowedPurposeIds = getAllowedPurposeIdsFromConsent(vendorConsent); - final List vendorPermissions = vendorIds.stream() - .map(vendorId -> toVendorPermission(vendorId, vendorListMapping, vendorConsent, allowedPurposeIds)) - .collect(Collectors.toList()); - return Future.succeededFuture(vendorPermissions); - } - - /** - * Retrieves allowed purpose ids from consent string. Throws {@link InvalidRequestException} in case of - * gdpr sdk throws {@link ArrayIndexOutOfBoundsException} when consent string is not valid. - */ - private static Set getAllowedPurposeIdsFromConsent(VendorConsent vendorConsent) { - try { - return vendorConsent.getAllowedPurposeIds(); - } catch (ArrayIndexOutOfBoundsException e) { - throw new InvalidRequestException( - "Error when retrieving allowed purpose ids in a reason of invalid consent string"); - } - } - - private static VendorPermission toVendorPermission(Integer vendorId, - Map vendorListMapping, - VendorConsent vendorConsent, - Set allowedPurposeIds) { - - // confirm that there is consent for vendor and it has entry in vendor list - if (!isVendorAllowed(vendorConsent, vendorId) || !vendorListMapping.containsKey(vendorId)) { - return toRestrictedVendorPermission(vendorId); - } - - final VendorV1 vendorListEntry = vendorListMapping.get(vendorId); - - // confirm purposes - final EnumSet claimedPurposes = vendorListEntry.combinedPurposes(); - final boolean claimedPurposesAllowed = isClaimedPurposesAllowed(claimedPurposes, allowedPurposeIds); - final boolean purposeOneClaimedAndAllowed = isPurposeOneClaimedAndAllowed(claimedPurposes, allowedPurposeIds); - - return VendorPermission.of(vendorId, null, toAction(claimedPurposesAllowed, purposeOneClaimedAndAllowed)); - } - - private static VendorPermission toRestrictedVendorPermission(Integer vendorId) { - return VendorPermission.of(vendorId, null, allDenied()); - } - - /** - * Checks if vendorId is in list of allowed vendors in consent string. Throws {@link InvalidRequestException} - * in case of gdpr sdk throws exception when consent string is not valid. - */ - private static boolean isVendorAllowed(VendorConsent vendorConsent, Integer vendorId) { - try { - return vendorConsent.isVendorAllowed(vendorId); - } catch (ArrayIndexOutOfBoundsException | VendorConsentParseException e) { - throw new InvalidRequestException( - "Error when checking if vendor is allowed in a reason of invalid consent string"); - } - } - - private static boolean isClaimedPurposesAllowed(EnumSet claimedPurposeCodes, - Set allowedPurposeIds) { - return claimedPurposeCodes.stream().allMatch(o -> allowedPurposeIds.contains(o.code())); - } - - private static boolean isPurposeOneClaimedAndAllowed( - EnumSet claimedPurposeCodes, Set allowedPurposeIds) { - - return claimedPurposeCodes.contains(PurposeCode.ONE) && allowedPurposeIds.contains(PurposeCode.ONE.code()); - } - - private static PrivacyEnforcementAction allDenied() { - return toAction(false, false); - } - - private static PrivacyEnforcementAction toAction(boolean allowPrivateInfo, boolean allowUserSync) { - return PrivacyEnforcementAction.builder() - .removeUserIds(!allowPrivateInfo) - .maskGeo(!allowPrivateInfo) - .maskDeviceIp(!allowPrivateInfo) - .maskDeviceInfo(!allowPrivateInfo) - .blockAnalyticsReport(false) - .blockBidderRequest(false) - .blockPixelSync(!allowUserSync) - .build(); - } - - private static Future> toFallbackResult(Set vendorIds) { - final List vendorPermissions = vendorIds.stream() - .filter(Objects::nonNull) - .map(GdprService::toRestrictedVendorPermission) - .collect(Collectors.toList()); - return Future.succeededFuture(vendorPermissions); - } -} 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 56c78ebc2c2..edd3a85ce61 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/TcfDefinerService.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/TcfDefinerService.java @@ -28,7 +28,6 @@ import org.prebid.server.settings.model.GdprConfig; import java.util.Collection; -import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -54,7 +53,6 @@ public class TcfDefinerService { private final boolean gdprEnabled; private final String gdprDefaultValue; private final boolean consentStringMeansInScope; - private final GdprService gdprService; private final Tcf2Service tcf2Service; private final Set eeaCountries; private final GeoLocationService geoLocationService; @@ -64,7 +62,6 @@ public class TcfDefinerService { public TcfDefinerService(GdprConfig gdprConfig, Set eeaCountries, - GdprService gdprService, Tcf2Service tcf2Service, GeoLocationService geoLocationService, BidderCatalog bidderCatalog, @@ -75,7 +72,6 @@ public TcfDefinerService(GdprConfig gdprConfig, this.gdprDefaultValue = gdprConfig != null ? gdprConfig.getDefaultValue() : null; this.consentStringMeansInScope = gdprConfig != null && BooleanUtils.isTrue(gdprConfig.getConsentStringMeansInScope()); - this.gdprService = Objects.requireNonNull(gdprService); this.tcf2Service = Objects.requireNonNull(tcf2Service); this.eeaCountries = Objects.requireNonNull(eeaCountries); this.geoLocationService = geoLocationService; @@ -120,9 +116,7 @@ public Future> resultForVendorIds(Set vendorIds, T return resultForInternal( tcfContext, country -> createAllowAllTcfResponse(vendorIds, country), - (consentString, country) -> tcf2Service.permissionsFor(vendorIds, consentString) - .map(vendorPermissions -> createVendorIdTcfResponse(vendorPermissions, country)), - (consentString, country) -> gdprService.resultFor(vendorIds, consentString) + (tcfConsent, country) -> tcf2Service.permissionsFor(vendorIds, tcfConsent) .map(vendorPermissions -> createVendorIdTcfResponse(vendorPermissions, country))); } @@ -133,11 +127,9 @@ public Future> resultForBidderNames(Set bidderNames, return resultForInternal( tcfContext, country -> createAllowAllTcfResponse(bidderNames, country), - (consentString, country) -> - tcf2Service.permissionsFor(bidderNames, vendorIdResolver, consentString, accountGdprConfig) - .map(vendorPermissions -> createBidderNameTcfResponse(vendorPermissions, country)), - (consentString, country) -> - bidderNameResultFromGdpr(bidderNames, vendorIdResolver, consentString, country)); + (tcfConsent, country) -> + tcf2Service.permissionsFor(bidderNames, vendorIdResolver, tcfConsent, accountGdprConfig) + .map(vendorPermissions -> createBidderNameTcfResponse(vendorPermissions, country))); } public Future> resultForBidderNames( @@ -149,8 +141,7 @@ public Future> resultForBidderNames( private Future> resultForInternal( TcfContext tcfContext, Function>> allowAllTcfResponseCreator, - BiFunction>> tcf2Strategy, - BiFunction>> gdprStrategy) { + BiFunction>> tcf2Strategy) { final GeoInfo geoInfo = tcfContext.getGeoInfo(); final String country = geoInfo != null ? geoInfo.getCountry() : null; @@ -159,11 +150,7 @@ private Future> resultForInternal( return allowAllTcfResponseCreator.apply(country); } - final TCString consent = tcfContext.getConsent(); - - return consent.getVersion() == 2 - ? tcf2Strategy.apply(consent, country) - : gdprStrategy.apply(tcfContext.getConsentString(), country); + return tcf2Strategy.apply(tcfContext.getConsent(), country); } private boolean isGdprEnabled(AccountGdprConfig accountGdprConfig, MetricName requestType) { @@ -343,56 +330,6 @@ private static TcfResponse createBidderNameTcfResponse( country); } - private Future> bidderNameResultFromGdpr( - Set bidderNames, VendorIdResolver vendorIdResolver, String consentString, String country) { - - final Map bidderToVendorId = resolveBidderToVendorId(bidderNames, vendorIdResolver); - final Set vendorIds = bidderToVendorId.values().stream() - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - - return gdprService.resultFor(vendorIds, consentString) - .map(vendorPermissions -> gdprResponseToTcfResponse(vendorPermissions, bidderToVendorId, country)); - } - - private static Map resolveBidderToVendorId( - Set bidderNames, VendorIdResolver vendorIdResolver) { - - final Map bidderToVendorId = new HashMap<>(); - bidderNames.forEach(bidderName -> bidderToVendorId.put(bidderName, vendorIdResolver.resolve(bidderName))); - return bidderToVendorId; - } - - private static TcfResponse gdprResponseToTcfResponse(Collection vendorPermissions, - Map bidderToVendorId, - String country) { - - final Map bidderNameToAction = new HashMap<>(); - - final Map> vendorIdToBidders = bidderToVendorId.entrySet().stream() - .filter(entry -> entry.getValue() != null) - .collect(Collectors.groupingBy( - Map.Entry::getValue, - Collectors.mapping(Map.Entry::getKey, Collectors.toSet()))); - - for (final VendorPermission vendorPermission : vendorPermissions) { - final Integer vendorId = vendorPermission.getVendorId(); - - if (vendorIdToBidders.containsKey(vendorId)) { - final PrivacyEnforcementAction action = vendorPermission.getPrivacyEnforcementAction(); - vendorIdToBidders.get(vendorId).forEach(bidderName -> bidderNameToAction.put(bidderName, action)); - } - } - - // process bidders whose vendorIds weren't resolved - bidderToVendorId.entrySet().stream() - .filter(entry -> entry.getValue() == null) - .map(Map.Entry::getKey) - .forEach(bidder -> bidderNameToAction.put(bidder, restrictAllButAnalyticsAndAuction())); - - return TcfResponse.of(true, bidderNameToAction, country); - } - private static Map allowAll(Collection identifiers) { return identifiers.stream() .collect(Collectors.toMap(Function.identity(), ignored -> PrivacyEnforcementAction.allowAll())); @@ -421,6 +358,12 @@ private TCString parseConsentString(String consentString, RequestLogInfo request final int version = tcString.getVersion(); metrics.updatePrivacyTcfRequestsMetric(version); + // disable TCF1 support + if (version == 1) { + logWarn(consentString, "TCF version 1 is deprecated and treated as corrupted TCF version 2", + requestLogInfo); + return TCStringEmpty.create(); + } return tcString; } @@ -481,16 +424,4 @@ public static boolean isConsentStringValid(String consentString) { return false; } } - - private static PrivacyEnforcementAction restrictAllButAnalyticsAndAuction() { - return PrivacyEnforcementAction.builder() - .removeUserIds(true) - .maskGeo(true) - .maskDeviceIp(true) - .maskDeviceInfo(true) - .blockAnalyticsReport(false) - .blockBidderRequest(false) - .blockPixelSync(true) - .build(); - } } diff --git a/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV1.java b/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV1.java deleted file mode 100644 index 27c7e834800..00000000000 --- a/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV1.java +++ /dev/null @@ -1,94 +0,0 @@ -package org.prebid.server.privacy.gdpr.vendorlist; - -import io.vertx.core.Vertx; -import io.vertx.core.file.FileSystem; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import org.apache.commons.collections4.CollectionUtils; -import org.prebid.server.bidder.BidderCatalog; -import org.prebid.server.exception.PreBidException; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.metric.Metrics; -import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorListV1; -import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV1; -import org.prebid.server.vertx.http.HttpClient; - -import java.io.IOException; -import java.util.Collection; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -public class VendorListServiceV1 extends VendorListService { - - private static final Logger logger = LoggerFactory.getLogger(VendorListServiceV1.class); - - private static final int TCF_VERSION = 1; - - public VendorListServiceV1(String cacheDir, - String endpointTemplate, - int defaultTimeoutMs, - long refreshMissingListPeriodMs, - boolean deprecated, - Integer gdprHostVendorId, - String fallbackVendorListPath, - BidderCatalog bidderCatalog, - Vertx vertx, - FileSystem fileSystem, - HttpClient httpClient, - Metrics metrics, - JacksonMapper mapper) { - - super( - cacheDir, - endpointTemplate, - defaultTimeoutMs, - refreshMissingListPeriodMs, - deprecated, - gdprHostVendorId, - fallbackVendorListPath, - bidderCatalog, - vertx, - fileSystem, - httpClient, - metrics, - mapper); - } - - protected VendorListV1 toVendorList(String content) { - try { - return mapper.mapper().readValue(content, VendorListV1.class); - } catch (IOException e) { - final String message = String.format("Cannot parse vendor list from: %s", content); - - logger.error(message, e); - throw new PreBidException(message, e); - } - } - - protected Map filterVendorIdToVendors(VendorListV1 vendorList) { - return vendorList.getVendors().stream() - .filter(vendor -> knownVendorIds.contains(vendor.getId())) // optimize cache to use only known vendors - .collect(Collectors.toMap(VendorV1::getId, Function.identity())); - } - - protected boolean isValid(VendorListV1 vendorList) { - return vendorList.getVendorListVersion() != null - && vendorList.getLastUpdated() != null - && CollectionUtils.isNotEmpty(vendorList.getVendors()) - && isValidVendors(vendorList.getVendors()); - } - - @Override - protected int getTcfVersion() { - return TCF_VERSION; - } - - private static boolean isValidVendors(Collection vendors) { - return vendors.stream() - .allMatch(vendor -> vendor != null - && vendor.getId() != null - && vendor.getPurposeIds() != null - && vendor.getLegIntPurposeIds() != null); - } -} diff --git a/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/VendorListV1.java b/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/VendorListV1.java deleted file mode 100644 index 270fd6c8b2c..00000000000 --- a/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/VendorListV1.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.prebid.server.privacy.gdpr.vendorlist.proto; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; -import lombok.Value; - -import java.util.Date; -import java.util.List; - -@AllArgsConstructor(staticName = "of") -@Value -public class VendorListV1 { - - @JsonProperty("vendorListVersion") - Integer vendorListVersion; - - @JsonProperty("lastUpdated") - Date lastUpdated; - - List vendors; -} 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 deleted file mode 100644 index f87b262298c..00000000000 --- a/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/proto/VendorV1.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.prebid.server.privacy.gdpr.vendorlist.proto; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Value; - -import java.util.EnumSet; - -@Value(staticConstructor = "of") -public class VendorV1 { - - Integer id; - - @JsonProperty("purposeIds") - EnumSet purposeIds; - - @JsonProperty("legIntPurposeIds") - EnumSet legIntPurposeIds; - - public EnumSet combinedPurposes() { - final EnumSet combinedPurposes = EnumSet.noneOf(PurposeCode.class); - if (purposeIds != null) { - combinedPurposes.addAll(purposeIds); - } - if (legIntPurposeIds != null) { - combinedPurposes.addAll(legIntPurposeIds); - } - - return combinedPurposes; - } -} diff --git a/src/main/java/org/prebid/server/spring/config/PrivacyServiceConfiguration.java b/src/main/java/org/prebid/server/spring/config/PrivacyServiceConfiguration.java index 996313afceb..f38787a5f0c 100644 --- a/src/main/java/org/prebid/server/spring/config/PrivacyServiceConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/PrivacyServiceConfiguration.java @@ -7,7 +7,6 @@ import org.prebid.server.geolocation.GeoLocationService; import org.prebid.server.json.JacksonMapper; import org.prebid.server.metric.Metrics; -import org.prebid.server.privacy.gdpr.GdprService; import org.prebid.server.privacy.gdpr.Tcf2Service; import org.prebid.server.privacy.gdpr.TcfDefinerService; import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.PurposeEightStrategy; @@ -27,7 +26,6 @@ import org.prebid.server.privacy.gdpr.tcfstrategies.purpose.typestrategies.PurposeTwoBasicEnforcePurposeStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.specialfeature.SpecialFeaturesOneStrategy; import org.prebid.server.privacy.gdpr.tcfstrategies.specialfeature.SpecialFeaturesStrategy; -import org.prebid.server.privacy.gdpr.vendorlist.VendorListServiceV1; import org.prebid.server.privacy.gdpr.vendorlist.VendorListServiceV2; import org.prebid.server.settings.model.GdprConfig; import org.prebid.server.settings.model.Purpose; @@ -49,38 +47,6 @@ @Configuration public class PrivacyServiceConfiguration { - @Bean - VendorListServiceV1 vendorListServiceV1( - @Value("${gdpr.vendorlist.v1.cache-dir}") String cacheDir, - @Value("${gdpr.vendorlist.v1.http-endpoint-template}") String endpointTemplate, - @Value("${gdpr.vendorlist.default-timeout-ms}") int defaultTimeoutMs, - @Value("${gdpr.vendorlist.v1.refresh-missing-list-period-ms}") int refreshMissingListPeriodMs, - @Value("${gdpr.host-vendor-id:#{null}}") Integer hostVendorId, - @Value("${gdpr.vendorlist.v1.fallback-vendor-list-path:#{null}}") String fallbackVendorListPath, - @Value("${gdpr.vendorlist.v1.deprecated}") boolean deprecated, - BidderCatalog bidderCatalog, - Vertx vertx, - FileSystem fileSystem, - HttpClient httpClient, - Metrics metrics, - JacksonMapper mapper) { - - return new VendorListServiceV1( - cacheDir, - endpointTemplate, - defaultTimeoutMs, - refreshMissingListPeriodMs, - deprecated, - hostVendorId, - fallbackVendorListPath, - bidderCatalog, - vertx, - fileSystem, - httpClient, - metrics, - mapper); - } - @Bean VendorListServiceV2 vendorListServiceV2( @Value("${gdpr.vendorlist.v2.cache-dir}") String cacheDir, @@ -113,11 +79,6 @@ VendorListServiceV2 vendorListServiceV2( mapper); } - @Bean - GdprService gdprService(VendorListServiceV1 vendorListServiceV1) { - return new GdprService(vendorListServiceV1); - } - @Bean Tcf2Service tcf2Service(GdprConfig gdprConfig, List purposeStrategies, @@ -133,7 +94,6 @@ Tcf2Service tcf2Service(GdprConfig gdprConfig, TcfDefinerService tcfDefinerService( GdprConfig gdprConfig, @Value("${gdpr.eea-countries}") String eeaCountriesAsString, - GdprService gdprService, Tcf2Service tcf2Service, @Autowired(required = false) GeoLocationService geoLocationService, BidderCatalog bidderCatalog, @@ -145,7 +105,6 @@ TcfDefinerService tcfDefinerService( return new TcfDefinerService( gdprConfig, eeaCountries, - gdprService, tcf2Service, geoLocationService, bidderCatalog, diff --git a/src/test/java/org/prebid/server/it/ApplicationTest.java b/src/test/java/org/prebid/server/it/ApplicationTest.java index 3281895b93c..a8e2d2f9a32 100644 --- a/src/test/java/org/prebid/server/it/ApplicationTest.java +++ b/src/test/java/org/prebid/server/it/ApplicationTest.java @@ -4,9 +4,8 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; -import com.iab.gdpr.consent.VendorConsentEncoder; -import com.iab.gdpr.consent.implementation.v1.VendorConsentBuilder; -import com.iab.gdpr.consent.range.StartEndRangeEntry; +import com.iabtcf.encoder.TCStringEncoder; +import com.iabtcf.utils.BitSetIntIterable; import io.restassured.builder.RequestSpecBuilder; import io.restassured.builder.ResponseSpecBuilder; import io.restassured.config.ObjectMapperConfig; @@ -41,7 +40,6 @@ 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; @@ -348,16 +346,14 @@ public void staticShouldReturnHttp200Ok() { @Test public void cookieSyncShouldReturnBidderStatusWithExpectedUsersyncInfo() { // given - final String gdprConsent = VendorConsentEncoder.toBase64String(new VendorConsentBuilder() - .withConsentRecordCreatedOn(Instant.now()) - .withConsentRecordLastUpdatedOn(Instant.now()) - .withConsentLanguage("en") - .withVendorListVersion(79) - .withRangeEntries(singletonList(new StartEndRangeEntry(1, 100))) - .withMaxVendorId(100) - .withBitField(new HashSet<>(asList(1, 32, 52))) - .withAllowedPurposeIds(new HashSet<>(asList(1, 3))) - .build()); + final String gdprConsent = TCStringEncoder.newBuilder() + .version(2) + .consentLanguage("EN") + .vendorListVersion(52) + .tcfPolicyVersion(2) + .addPurposesConsent(BitSetIntIterable.from(1)) + .addVendorConsent(BitSetIntIterable.from(1, 32, 52)) + .encode(); // when final CookieSyncResponse cookieSyncResponse = given(SPEC) @@ -420,7 +416,7 @@ public void setuidShouldUpdateRubiconUidInUidCookie() throws IOException { .queryParam("bidder", RUBICON) .queryParam("uid", "updatedUid") .queryParam("gdpr", "1") - .queryParam("gdpr_consent", "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA") + .queryParam("gdpr_consent", "CPBCKiyPBCKiyAAAAAENA0CAAIAAAAAAACiQAaQAwAAgAgABoAAAAAA") .when() .get("/setuid") .then() diff --git a/src/test/java/org/prebid/server/metric/MetricsTest.java b/src/test/java/org/prebid/server/metric/MetricsTest.java index 908dbe8adc6..a2b4a629b0e 100644 --- a/src/test/java/org/prebid/server/metric/MetricsTest.java +++ b/src/test/java/org/prebid/server/metric/MetricsTest.java @@ -691,12 +691,13 @@ public void privacyTcfShouldReturnSameMetricsOnSuccessiveCalls() { @Test public void privacyTcfVersionShouldReturnSameMetricsOnSuccessiveCalls() { - assertThat(metrics.privacy().tcf().v1()).isSameAs(metrics.privacy().tcf().v1()); + assertThat(metrics.privacy().tcf().fromVersion(1)).isSameAs(metrics.privacy().tcf().fromVersion(1)); } @Test public void privacyTcfVersionVendorListShouldReturnSameMetricsOnSuccessiveCalls() { - assertThat(metrics.privacy().tcf().v2().vendorList()).isSameAs(metrics.privacy().tcf().v2().vendorList()); + assertThat(metrics.privacy().tcf().fromVersion(2).vendorList()) + .isSameAs(metrics.privacy().tcf().fromVersion(2).vendorList()); } @Test diff --git a/src/test/java/org/prebid/server/privacy/gdpr/GdprServiceTest.java b/src/test/java/org/prebid/server/privacy/gdpr/GdprServiceTest.java deleted file mode 100644 index 3f87c79664f..00000000000 --- a/src/test/java/org/prebid/server/privacy/gdpr/GdprServiceTest.java +++ /dev/null @@ -1,191 +0,0 @@ -package org.prebid.server.privacy.gdpr; - -import io.vertx.core.Future; -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.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.VendorListV1; -import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV1; - -import java.util.EnumSet; - -import static java.util.Collections.emptyMap; -import static java.util.Collections.singleton; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -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.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 { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private VendorListService vendorListService; - - private GdprService gdprService; - - @Before - public void setUp() { - gdprService = new GdprService(vendorListService); - } - - @Test - public void shouldReturnAllDeniedWhenNoConsentParam() { - assertThat(gdprService.resultFor(singleton(1), null)) - .succeededWith(singletonList(VendorPermission.of(1, null, denyAll()))); - } - - @Test - public void shouldReturnAllDeniedWhenConsentParamIsInvalid() { - assertThat(gdprService.resultFor(singleton(1), "invalid-consent")) - .succeededWith(singletonList(VendorPermission.of(1, null, denyAll()))); - } - - @Test - public void shouldReturnAllDeniedWhenVendorListIsNotFetchedYet() { - // given - given(vendorListService.forVersion(anyInt())).willReturn(Future.failedFuture("Not fetched yet")); - - // when and then - assertThat(gdprService.resultFor(singleton(9), "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA")) - .succeededWith(singletonList(VendorPermission.of(9, null, denyAll()))); - } - - @Test - public void shouldReturnAllDeniedWhenVendorIsNotAllowed() { - // given - given(vendorListService.forVersion(anyInt())).willReturn(Future.succeededFuture(emptyMap())); - - // when and then - assertThat(gdprService.resultFor(singleton(9), "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA")) - .succeededWith(singletonList(VendorPermission.of(9, null, denyAll()))); - } - - @Test - public void shouldReturnAllDeniedWhenVendorIsNotInVendorList() { - // given - given(vendorListService.forVersion(anyInt())).willReturn(Future.succeededFuture(emptyMap())); - - // when and then - assertThat(gdprService.resultFor(singleton(1), "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA")) - .succeededWith(singletonList(VendorPermission.of(1, null, denyAll()))); - } - - @Test - public void shouldReturnAllDeniedWhenAllClaimedPurposesAreNotAllowed() { - // given - given(vendorListService.forVersion(anyInt())).willReturn(Future.succeededFuture( - singletonMap(1, VendorV1.of(1, EnumSet.of(FOUR), EnumSet.of(FIVE))))); - - // when and then - assertThat(gdprService.resultFor(singleton(1), "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA")) - .succeededWith(singletonList(VendorPermission.of(1, null, denyAll()))); - } - - @Test - public void shouldReturnPrivateInfoAllowedUserSyncDeniedWhenAllClaimedPurposesAreAllowed() { - // given - given(vendorListService.forVersion(anyInt())).willReturn(Future.succeededFuture( - singletonMap(1, VendorV1.of(1, EnumSet.of(TWO), EnumSet.of(THREE))))); - - // when and then - assertThat(gdprService.resultFor(singleton(1), "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA")) - .succeededWith(singletonList(VendorPermission.of(1, null, action(true, false)))); - } - - @Test - public void shouldReturnAllAllowedWhenAllClaimedPurposesAreAllowedIncludingPurposeOne() { - // given - given(vendorListService.forVersion(anyInt())).willReturn(Future.succeededFuture( - singletonMap(1, VendorV1.of(1, EnumSet.of(ONE), EnumSet.of(TWO))))); - - // when and then - assertThat(gdprService.resultFor(singleton(1), "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA")) - .succeededWith(singletonList(VendorPermission.of(1, null, action(true, true)))); - } - - @Test - public void shouldReturnPrivateInfoDeniedUserSyncAllowedWhenNotAllClaimedPurposesAreAllowedButPurposeOneIs() { - // given - given(vendorListService.forVersion(anyInt())).willReturn(Future.succeededFuture( - singletonMap(1, VendorV1.of(1, EnumSet.of(ONE), EnumSet.of(FOUR))))); - - // when and then - assertThat(gdprService.resultFor(singleton(1), "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA")) - .succeededWith(singletonList(VendorPermission.of(1, null, action(false, true)))); - } - - @Test - public void shouldReturnUserSyncDeniedWhenPurposeOneIsAllowedButNotClaimed() { - // given - given(vendorListService.forVersion(anyInt())).willReturn(Future.succeededFuture( - singletonMap(1, VendorV1.of(1, EnumSet.of(TWO), EnumSet.of(THREE))))); - - // when and then - assertThat(gdprService.resultFor(singleton(1), "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA")) - .succeededWith(singletonList(VendorPermission.of(1, null, action(true, false)))); - } - - @Test - public void shouldReturnFailedFutureWhenGettingAllowedPurposesFails() { - // given - given(vendorListService.forVersion(anyInt())).willReturn(Future.succeededFuture(emptyMap())); - - // when and then - assertThat(gdprService.resultFor(singleton(1), "BONciguONcjGKADACHENAOLS1r")) - .isFailed() - .hasMessage("Error when retrieving allowed purpose ids in a reason of invalid consent string"); - } - - @Test - public void shouldReturnFailedFutureWhenGettingIfVendorAllowedFails() { - // given - given(vendorListService.forVersion(anyInt())).willReturn(Future.succeededFuture(emptyMap())); - - // when and then - assertThat(gdprService.resultFor(singleton(1), "BOSbaBZOSbaBoABABBENBcoAAAAgSABgBAA")) - .isFailed() - .hasMessage("Error when checking if vendor is allowed in a reason of invalid consent string"); - } - - @Test - public void shouldReturnAllDeniedWhenVendorListServiceFailed() { - // given - given(vendorListService.forVersion(anyInt())).willReturn(Future.failedFuture("error")); - - // when and then - assertThat(gdprService.resultFor(singleton(1), "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA")) - .succeededWith(singletonList(VendorPermission.of(1, null, denyAll()))); - } - - private static PrivacyEnforcementAction denyAll() { - return action(false, false); - } - - private static PrivacyEnforcementAction action(boolean allowPrivateInfo, boolean allowUserSync) { - return PrivacyEnforcementAction.builder() - .removeUserIds(!allowPrivateInfo) - .maskGeo(!allowPrivateInfo) - .maskDeviceIp(!allowPrivateInfo) - .maskDeviceInfo(!allowPrivateInfo) - .blockAnalyticsReport(false) - .blockBidderRequest(false) - .blockPixelSync(!allowUserSync) - .build(); - } -} 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 f8c1d7aab64..cdfd0b8f614 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/TcfDefinerServiceTest.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/TcfDefinerServiceTest.java @@ -57,8 +57,6 @@ public class TcfDefinerServiceTest { @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); - @Mock - private GdprService gdprService; @Mock private Tcf2Service tcf2Service; @Mock @@ -88,7 +86,6 @@ public void setUp() { tcfDefinerService = new TcfDefinerService( gdprConfig, singleton(EEA_COUNTRY), - gdprService, tcf2Service, geoLocationService, bidderCatalog, @@ -103,7 +100,6 @@ public void resolveTcfContextShouldReturnContextWhenGdprIsDisabled() { tcfDefinerService = new TcfDefinerService( gdprConfig, singleton(EEA_COUNTRY), - gdprService, tcf2Service, geoLocationService, bidderCatalog, @@ -182,7 +178,6 @@ public void resolveTcfContextShouldCheckServiceConfigValueWhenRequestTypeIsUnkno tcfDefinerService = new TcfDefinerService( gdprConfig, singleton(EEA_COUNTRY), - gdprService, tcf2Service, geoLocationService, bidderCatalog, @@ -205,7 +200,7 @@ public void resolveTcfContextShouldCheckServiceConfigValueWhenRequestTypeIsUnkno } @Test - public void resolveTcfContextShouldConsiderPresenceOfConsentStringAsInScope() { + public void resolveTcfContextShouldConsiderTcfVersionOneAsCorruptedVersionTwo() { // given final GdprConfig gdprConfig = GdprConfig.builder() .enabled(true) @@ -215,7 +210,6 @@ public void resolveTcfContextShouldConsiderPresenceOfConsentStringAsInScope() { tcfDefinerService = new TcfDefinerService( gdprConfig, singleton(EEA_COUNTRY), - gdprService, tcf2Service, geoLocationService, bidderCatalog, @@ -228,6 +222,34 @@ public void resolveTcfContextShouldConsiderPresenceOfConsentStringAsInScope() { final Future result = tcfDefinerService.resolveTcfContext( Privacy.of(null, vendorConsent, null, null), null, null, MetricName.setuid, null, null); + // then + assertThat(result).isSucceeded(); + assertThat(result.result().getConsent()).isInstanceOf(TCStringEmpty.class); + } + + @Test + public void resolveTcfContextShouldConsiderPresenceOfConsentStringAsInScope() { + // given + final GdprConfig gdprConfig = GdprConfig.builder() + .enabled(true) + .consentStringMeansInScope(true) + .build(); + + tcfDefinerService = new TcfDefinerService( + gdprConfig, + singleton(EEA_COUNTRY), + tcf2Service, + geoLocationService, + bidderCatalog, + ipAddressHelper, + metrics); + + final String vendorConsent = "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA"; + + // when + final Future result = tcfDefinerService.resolveTcfContext( + Privacy.of(null, vendorConsent, null, null), null, null, null, null, null); + // then assertThat(result).isSucceeded(); assertThat(result.result()).extracting( @@ -237,12 +259,13 @@ public void resolveTcfContextShouldConsiderPresenceOfConsentStringAsInScope() { TcfContext::getGeoInfo, TcfContext::getInEea, TcfContext::getIpAddress) - .containsExactly("1", "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA", true, null, null, null); + .containsExactly("1", "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", + true, null, null, null); assertThat(result.result().getConsent()).isNotNull(); verifyZeroInteractions(geoLocationService); - verify(metrics).updatePrivacyTcfRequestsMetric(1); - verify(metrics).updatePrivacyTcfGeoMetric(1, null); + verify(metrics).updatePrivacyTcfRequestsMetric(2); + verify(metrics).updatePrivacyTcfGeoMetric(2, null); } @Test @@ -307,7 +330,6 @@ public void resolveTcfContextShouldConsultDefaultValueWhenGeoLookupFailed() { tcfDefinerService = new TcfDefinerService( gdprConfig, singleton(EEA_COUNTRY), - gdprService, tcf2Service, geoLocationService, bidderCatalog, @@ -343,7 +365,6 @@ public void resolveTcfContextShouldConsultDefaultValueAndSkipGeoLookupWhenIpIsNu tcfDefinerService = new TcfDefinerService( gdprConfig, singleton(EEA_COUNTRY), - gdprService, tcf2Service, geoLocationService, bidderCatalog, @@ -373,7 +394,8 @@ public void resolveTcfContextShouldConsultDefaultValueAndSkipGeoLookupWhenIpIsNu public void resolveTcfContextShouldReturnTcfContextWithConsentValidAsTrue() { // when final Future result = tcfDefinerService.resolveTcfContext( - Privacy.of("1", "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA", null, null), null, null, MetricName.setuid, null, + Privacy.of("1", "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", + null, null), null, null, MetricName.setuid, null, null); // then @@ -382,7 +404,7 @@ public void resolveTcfContextShouldReturnTcfContextWithConsentValidAsTrue() { TcfContext::getGdpr, TcfContext::getConsentString, TcfContext::getIsConsentValid) - .containsExactly("1", "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA", true); + .containsExactly("1", "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", true); } @Test @@ -447,7 +469,6 @@ public void resultForVendorIdsShouldAllowAllWhenGdprIsZero() { assertThat(result).succeededWith( TcfResponse.of(false, singletonMap(1, PrivacyEnforcementAction.allowAll()), null)); - verifyZeroInteractions(gdprService); verifyZeroInteractions(tcf2Service); } @@ -464,7 +485,6 @@ public void resultForVendorIdsShouldReturnRestrictAllWhenConsentIsMissing() { // then verify(tcf2Service).permissionsFor(any(), argThat(arg -> arg.getClass() == TCStringEmpty.class)); - verifyZeroInteractions(gdprService); } @Test @@ -477,79 +497,6 @@ public void resultForBidderNamesShouldReturnAllowAllWhenGdprIsZero() { assertThat(result).succeededWith( TcfResponse.of(false, singletonMap("b1", PrivacyEnforcementAction.allowAll()), null)); - verifyZeroInteractions(tcf2Service); - verifyZeroInteractions(gdprService); - } - - @Test - public void resultForVendorIdsShouldReturnTcfResponseFromGdprServiceWhenConsentStringIsFirstVersion() { - // given - given(gdprService.resultFor(anySet(), anyString())) - .willReturn(Future.succeededFuture(asList( - VendorPermission.of(1, null, PrivacyEnforcementAction.allowAll()), - VendorPermission.of(2, null, PrivacyEnforcementAction.restrictAll())))); - - final String consentString = "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA"; - - // when - final Future> result = tcfDefinerService.resultForVendorIds( - new HashSet<>(asList(1, 2)), - TcfContext.builder() - .gdpr("1") - .consentString(consentString) - .consent(TCString.decode(consentString)) - .build()); - - // then - final HashMap expectedVendorIdToPrivacyMap = new HashMap<>(); - expectedVendorIdToPrivacyMap.put(1, PrivacyEnforcementAction.allowAll()); - expectedVendorIdToPrivacyMap.put(2, PrivacyEnforcementAction.restrictAll()); - assertThat(result).succeededWith(TcfResponse.of(true, expectedVendorIdToPrivacyMap, null)); - - verifyZeroInteractions(tcf2Service); - } - - @Test - public void resultForBidderNamesShouldReturnTcfResponseFromGdprServiceWhenConsentStringIsFirstVersion() { - // given - given(gdprService.resultFor(anySet(), anyString())) - .willReturn(Future.succeededFuture(asList( - VendorPermission.of(1, null, PrivacyEnforcementAction.allowAll()), - VendorPermission.of(2, null, PrivacyEnforcementAction.allowAll())))); - - given(bidderCatalog.isActive(eq("b1"))).willReturn(true); - given(bidderCatalog.isActive(eq("b2"))).willReturn(true); - given(bidderCatalog.isActive(eq("b3"))).willReturn(false); - given(bidderCatalog.vendorIdByName(eq("b1"))).willReturn(1); - given(bidderCatalog.vendorIdByName(eq("b2"))).willReturn(2); - - final String consentString = "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA"; - - // when - final Future> result = tcfDefinerService.resultForBidderNames( - new HashSet<>(asList("b1", "b2", "b3")), - TcfContext.builder() - .gdpr("1") - .consentString(consentString) - .consent(TCString.decode(consentString)) - .build(), - null); - - // then - final HashMap expectedBidderNameToPrivacyMap = new HashMap<>(); - expectedBidderNameToPrivacyMap.put("b1", PrivacyEnforcementAction.allowAll()); - expectedBidderNameToPrivacyMap.put("b2", PrivacyEnforcementAction.allowAll()); - expectedBidderNameToPrivacyMap.put("b3", PrivacyEnforcementAction.builder() - .removeUserIds(true) - .maskGeo(true) - .maskDeviceIp(true) - .maskDeviceInfo(true) - .blockAnalyticsReport(false) - .blockBidderRequest(false) - .blockPixelSync(true) - .build()); - assertThat(result).succeededWith(TcfResponse.of(true, expectedBidderNameToPrivacyMap, null)); - verifyZeroInteractions(tcf2Service); } @@ -573,8 +520,6 @@ public void resultForVendorIdsShouldReturnTcfResponseFromTcf2ServiceWhenConsentS expectedVendorIdToPrivacyMap.put(1, PrivacyEnforcementAction.allowAll()); expectedVendorIdToPrivacyMap.put(2, PrivacyEnforcementAction.allowAll()); assertThat(result).succeededWith(TcfResponse.of(true, expectedVendorIdToPrivacyMap, null)); - - verifyZeroInteractions(gdprService); } @Test @@ -601,13 +546,12 @@ public void resultForBidderNamesShouldReturnTcfResponseFromTcf2ServiceWhenConsen expectedBidderNameToPrivacyMap.put("b1", PrivacyEnforcementAction.allowAll()); expectedBidderNameToPrivacyMap.put("b2", PrivacyEnforcementAction.allowAll()); assertThat(result).succeededWith(TcfResponse.of(true, expectedBidderNameToPrivacyMap, null)); - - verifyZeroInteractions(gdprService); } @Test public void isConsentStringValidShouldReturnTrueWhenStringIsValid() { - assertThat(TcfDefinerService.isConsentStringValid("BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA")).isTrue(); + assertThat(TcfDefinerService.isConsentStringValid("CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA")) + .isTrue(); } @Test 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 deleted file mode 100644 index 7a2dee7d416..00000000000 --- a/src/test/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV1Test.java +++ /dev/null @@ -1,579 +0,0 @@ -package org.prebid.server.privacy.gdpr.vendorlist; - -import com.fasterxml.jackson.core.JsonProcessingException; -import io.vertx.core.Future; -import io.vertx.core.Handler; -import io.vertx.core.Vertx; -import io.vertx.core.buffer.Buffer; -import io.vertx.core.file.FileSystem; -import org.apache.commons.lang3.StringUtils; -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.mockito.stubbing.Answer; -import org.prebid.server.VertxTest; -import org.prebid.server.bidder.BidderCatalog; -import org.prebid.server.exception.PreBidException; -import org.prebid.server.metric.Metrics; -import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorListV1; -import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV1; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; - -import java.io.File; -import java.util.Date; -import java.util.EnumSet; -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.assertj.core.api.Assertions.assertThatThrownBy; -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; -import static org.prebid.server.assertion.FutureAssertion.assertThat; -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 { - - private static final String CACHE_DIR = "/cache/dir"; - private static final long REFRESH_MISSING_LIST_PERIOD_MS = 3600000L; - private static final String FALLBACK_VENDOR_LIST_PATH = "fallback.json"; - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private Vertx vertx; - @Mock - private FileSystem fileSystem; - @Mock - private HttpClient httpClient; - @Mock - private Metrics metrics; - @Mock - private BidderCatalog bidderCatalog; - - private VendorListService vendorListService; - - @Before - public void setUp() throws JsonProcessingException { - given(fileSystem.existsBlocking(anyString())).willReturn(false); // always create cache dir - - given(bidderCatalog.knownVendorIds()).willReturn(singleton(52)); - - given(fileSystem.readFileBlocking(eq(FALLBACK_VENDOR_LIST_PATH))) - .willReturn(Buffer.buffer(mapper.writeValueAsString(givenVendorList()))); - - vendorListService = new VendorListServiceV1( - CACHE_DIR, - "http://vendorlist/{VERSION}", - 0, - REFRESH_MISSING_LIST_PERIOD_MS, - false, - null, - FALLBACK_VENDOR_LIST_PATH, - bidderCatalog, - vertx, - fileSystem, - httpClient, - metrics, - jacksonMapper); - } - - // Creation related tests - - @Test - public void creationShouldFailIfCannotCreateCacheDir() { - // given - given(fileSystem.mkdirsBlocking(anyString())).willThrow(new RuntimeException("dir creation error")); - - // then - assertThatThrownBy( - () -> new VendorListServiceV1( - CACHE_DIR, - "http://vendorlist/%s", - 0, - REFRESH_MISSING_LIST_PERIOD_MS, - false, - null, - FALLBACK_VENDOR_LIST_PATH, - bidderCatalog, - vertx, - fileSystem, - httpClient, - metrics, - jacksonMapper)) - .hasMessage("dir creation error"); - } - - @Test - public void shouldStartUsingFallbackVersionIfDeprecatedIsTrue() { - // given - vendorListService = new VendorListServiceV1( - CACHE_DIR, - "http://vendorlist/{VERSION}", - 0, - REFRESH_MISSING_LIST_PERIOD_MS, - true, - null, - FALLBACK_VENDOR_LIST_PATH, - bidderCatalog, - vertx, - fileSystem, - httpClient, - metrics, - jacksonMapper); - - // when - final Future> future = vendorListService.forVersion(1); - - // then - verifyZeroInteractions(httpClient); - assertThat(future).succeededWith(singletonMap(52, VendorV1.of(52, EnumSet.of(ONE), EnumSet.of(TWO)))); - } - - @Test - public void shouldThrowExceptionIfVersionIsDeprecatedAndNoFallbackPresent() { - // then - assertThatThrownBy(() -> vendorListService = new VendorListServiceV1( - CACHE_DIR, - "http://vendorlist/{VERSION}", - 0, - REFRESH_MISSING_LIST_PERIOD_MS, - true, - null, - null, - bidderCatalog, - vertx, - fileSystem, - httpClient, - metrics, - jacksonMapper)) - .isInstanceOf(PreBidException.class) - .hasMessage("No fallback vendorList for deprecated version present"); - } - - @Test - public void creationShouldFailIfCannotReadFiles() { - // given - given(fileSystem.readDirBlocking(anyString())).willThrow(new RuntimeException("read error")); - - // then - assertThatThrownBy( - () -> new VendorListServiceV1( - CACHE_DIR, - "http://vendorlist/%s", - 0, - REFRESH_MISSING_LIST_PERIOD_MS, - false, - null, - FALLBACK_VENDOR_LIST_PATH, - bidderCatalog, - vertx, - fileSystem, - httpClient, - metrics, - jacksonMapper)) - .isInstanceOf(RuntimeException.class) - .hasMessage("read error"); - } - - @Test - public void creationShouldFailIfCannotReadAtLeastOneVendorListFile() { - // given - given(fileSystem.readDirBlocking(anyString())).willReturn(singletonList("1.json")); - given(fileSystem.readFileBlocking(anyString())).willThrow(new RuntimeException("read error")); - - // then - assertThatThrownBy( - () -> new VendorListServiceV1( - CACHE_DIR, - "http://vendorlist/%s", - 0, - REFRESH_MISSING_LIST_PERIOD_MS, - false, - null, - FALLBACK_VENDOR_LIST_PATH, - bidderCatalog, - vertx, - fileSystem, - httpClient, - metrics, - jacksonMapper)) - .isInstanceOf(RuntimeException.class) - .hasMessage("read error"); - } - - @Test - public void creationShouldFailIfAtLeastOneVendorListFileCannotBeParsed() { - // given - given(fileSystem.readDirBlocking(anyString())).willReturn(singletonList("1.json")); - given(fileSystem.readFileBlocking(anyString())).willReturn(Buffer.buffer("invalid")); - - // then - assertThatThrownBy( - () -> new VendorListServiceV1( - CACHE_DIR, - "http://vendorlist/%s", - 0, - REFRESH_MISSING_LIST_PERIOD_MS, - false, - null, - FALLBACK_VENDOR_LIST_PATH, - bidderCatalog, - vertx, - fileSystem, - httpClient, - metrics, - jacksonMapper)) - .isInstanceOf(PreBidException.class) - .hasMessage("Cannot parse vendor list from: invalid"); - } - - // Http related tests - - @Test - public void shouldPerformHttpRequestWithExpectedQueryIfVendorListNotFound() { - // given - givenHttpClientReturnsResponse(200, null); - - // when - vendorListService.forVersion(1); - - // then - verify(httpClient).get(eq("http://vendorlist/1"), anyLong()); - } - - @Test - public void shouldNotAskToSaveFileIfReadingHttpResponseFails() { - // given - givenHttpClientProducesException(new RuntimeException("Response exception")); - - // when - vendorListService.forVersion(1); - - // then - verify(httpClient).get(anyString(), anyLong()); - verify(fileSystem, never()).writeFile(any(), any(), any()); - } - - @Test - public void shouldNotAskToSaveFileIfResponseCodeIsNot200() { - // given - givenHttpClientReturnsResponse(503, null); - - // when - vendorListService.forVersion(1); - - // then - verify(httpClient).get(anyString(), anyLong()); - verify(fileSystem, never()).writeFile(any(), any(), any()); - } - - @Test - public void shouldNotAskToSaveFileIfResponseBodyCouldNotBeParsed() { - // given - givenHttpClientReturnsResponse(200, "response"); - - // when - vendorListService.forVersion(1); - - // then - verify(httpClient).get(anyString(), anyLong()); - verify(fileSystem, never()).writeFile(any(), any(), any()); - } - - @Test - public void shouldNotAskToSaveFileIfFetchedVendorListHasInvalidVendorListVersion() throws JsonProcessingException { - // given - final VendorListV1 vendorList = VendorListV1.of(null, null, null); - givenHttpClientReturnsResponse(200, mapper.writeValueAsString(vendorList)); - - // when - vendorListService.forVersion(1); - - // then - verify(httpClient).get(anyString(), anyLong()); - verify(fileSystem, never()).writeFile(any(), any(), any()); - } - - @Test - public void shouldNotAskToSaveFileIfFetchedVendorListHasInvalidLastUpdated() throws JsonProcessingException { - // given - final VendorListV1 vendorList = VendorListV1.of(1, null, null); - givenHttpClientReturnsResponse(200, mapper.writeValueAsString(vendorList)); - - // when - vendorListService.forVersion(1); - - // then - verify(httpClient).get(anyString(), anyLong()); - verify(fileSystem, never()).writeFile(any(), any(), any()); - } - - @Test - public void shouldNotAskToSaveFileIfFetchedVendorListHasNoVendors() throws JsonProcessingException { - // given - final VendorListV1 vendorList = VendorListV1.of(1, new Date(), null); - givenHttpClientReturnsResponse(200, mapper.writeValueAsString(vendorList)); - - // when - vendorListService.forVersion(1); - - // then - verify(httpClient).get(anyString(), anyLong()); - verify(fileSystem, never()).writeFile(any(), any(), any()); - } - - @Test - public void shouldNotAskToSaveFileIfFetchedVendorListHasEmptyVendors() throws JsonProcessingException { - // given - final VendorListV1 vendorList = VendorListV1.of(1, new Date(), emptyList()); - givenHttpClientReturnsResponse(200, mapper.writeValueAsString(vendorList)); - - // when - vendorListService.forVersion(1); - - // then - verify(httpClient).get(anyString(), anyLong()); - verify(fileSystem, never()).writeFile(any(), any(), any()); - } - - @Test - public void shouldNotAskToSaveFileIfFetchedVendorListHasAtLeastOneInvalidVendor() throws JsonProcessingException { - // given - final VendorListV1 vendorList = VendorListV1.of(1, new Date(), singletonList(VendorV1.of(null, null, null))); - givenHttpClientReturnsResponse(200, mapper.writeValueAsString(vendorList)); - - // when - vendorListService.forVersion(1); - - // then - verify(httpClient).get(anyString(), anyLong()); - verify(fileSystem, never()).writeFile(any(), any(), any()); - } - - // File system related tests - - @Test - public void shouldSaveFileWithExpectedPathAndContentIfVendorListNotFound() throws JsonProcessingException { - // given - final String vendorListAsString = mapper.writeValueAsString(givenVendorList()); - givenHttpClientReturnsResponse(200, vendorListAsString); - // generate file path to avoid conflicts with path separators in different OS - final String filePath = new File("/cache/dir/1.json").getPath(); - - // when - vendorListService.forVersion(1); - - // then - verify(fileSystem).writeFile(eq(filePath), eq(Buffer.buffer(vendorListAsString)), any()); - } - - // In-memory cache related tests - - @Test - public void shouldFailIfVendorListIsBelowOrZero() { - // given - givenHttpClientProducesException(new RuntimeException()); - - // when - final Future result1 = vendorListService.forVersion(0); - final Future result2 = vendorListService.forVersion(-2); - - // then - assertThat(result1).isFailed().hasMessage("TCF 1 vendor list for version 0 not valid."); - assertThat(result2).isFailed().hasMessage("TCF 1 vendor list for version -2 not valid."); - } - - @Test - public void shouldFailIfVendorListNotFound() { - // given - givenHttpClientProducesException(new RuntimeException()); - - // when - final Future> future = vendorListService.forVersion(1); - - // then - assertThat(future).isFailed().hasMessage("TCF 1 vendor list for version 1 not fetched yet, try again later."); - } - - @Test - public void shouldReturnVendorListFromCache() throws JsonProcessingException { - // given - givenHttpClientReturnsResponse(200, mapper.writeValueAsString(givenVendorList())); - - given(fileSystem.writeFile(anyString(), any(), any())) - .willAnswer(withSelfAndPassObjectToHandler(Future.succeededFuture())); - - // when - vendorListService.forVersion(1); // populate cache - final Future> result = vendorListService.forVersion(1); - - // then - assertThat(result).succeededWith(singletonMap(52, VendorV1.of(52, EnumSet.of(ONE), EnumSet.of(TWO)))); - } - - @Test - public void shouldKeepPurposesOnlyForKnownVendors() throws JsonProcessingException { - // given - final VendorListV1 vendorList = VendorListV1.of(1, new Date(), - asList( - VendorV1.of(52, EnumSet.of(ONE), EnumSet.of(TWO)), - VendorV1.of(42, EnumSet.of(ONE), EnumSet.of(TWO)))); - givenHttpClientReturnsResponse(200, mapper.writeValueAsString(vendorList)); - - given(fileSystem.writeFile(anyString(), any(), any())) - .willAnswer(withSelfAndPassObjectToHandler(Future.succeededFuture())); - - // when - vendorListService.forVersion(1); // populate cache - final Future> future = vendorListService.forVersion(1); - - // then - assertThat(future).succeededWith(singletonMap(52, VendorV1.of(52, EnumSet.of(ONE), EnumSet.of(TWO)))); - } - - @Test - public void shouldReturnFallbackIfVendorListNotFound() { - // given - givenHttpClientReturnsResponse(404, StringUtils.EMPTY); - - // when - - // first call triggers http request that results in 404 - final Future> future1 = vendorListService.forVersion(1); - // second call yields fallback vendor list - final Future> future2 = vendorListService.forVersion(1); - - // then - assertThat(future1).isFailed(); - assertThat(future2).succeededWith(singletonMap(52, VendorV1.of(52, EnumSet.of(ONE), EnumSet.of(TWO)))); - } - - @Test - public void shouldReturnFallbackIfServerUnavailable() { - // given - givenHttpClientReturnsResponse(503, StringUtils.EMPTY); - - // when - - // first call triggers http request that results in 503 - final Future> future1 = vendorListService.forVersion(1); - // second call yields fallback vendor list - final Future> future2 = vendorListService.forVersion(1); - - // then - assertThat(future1).isFailed(); - assertThat(future2).succeededWith(singletonMap(52, VendorV1.of(52, EnumSet.of(ONE), EnumSet.of(TWO)))); - } - - // Metrics tests - - @Test - public void shouldIncrementVendorListMissingMetric() { - // given - givenHttpClientReturnsResponse(200, null); - - // when - vendorListService.forVersion(1); - - // then - verify(metrics).updatePrivacyTcfVendorListMissingMetric(eq(1)); - } - - @Test - public void shouldIncrementVendorListErrorMetricWhenFileIsNotDownloaded() { - // given - givenHttpClientReturnsResponse(503, null); - - // when - vendorListService.forVersion(1); - - // then - verify(metrics).updatePrivacyTcfVendorListErrorMetric(eq(1)); - } - - @Test - public void shouldIncrementVendorListErrorMetricWhenFileIsNotSaved() throws JsonProcessingException { - // given - givenHttpClientReturnsResponse(200, mapper.writeValueAsString(givenVendorList())); - - given(fileSystem.writeFile(anyString(), any(), any())) - .willAnswer(withSelfAndPassObjectToHandler(Future.failedFuture("error"))); - - // when - vendorListService.forVersion(1); - - // then - verify(metrics).updatePrivacyTcfVendorListErrorMetric(eq(1)); - } - - @Test - public void shouldIncrementVendorListOkMetric() throws JsonProcessingException { - // given - givenHttpClientReturnsResponse(200, mapper.writeValueAsString(givenVendorList())); - - given(fileSystem.writeFile(anyString(), any(), any())) - .willAnswer(withSelfAndPassObjectToHandler(Future.succeededFuture())); - - // when - vendorListService.forVersion(1); - - // then - verify(metrics).updatePrivacyTcfVendorListOkMetric(eq(1)); - } - - @Test - public void shouldIncrementVendorListFallbackMetric() { - // given - givenHttpClientReturnsResponse(404, StringUtils.EMPTY); - - // when - - // first call triggers http request that results in 404 - vendorListService.forVersion(1); - // second call yields fallback vendor list - vendorListService.forVersion(1); - - // then - verify(metrics).updatePrivacyTcfVendorListFallbackMetric(eq(1)); - } - - private static VendorListV1 givenVendorList() { - final VendorV1 vendor = VendorV1.of(52, EnumSet.of(ONE), EnumSet.of(TWO)); - return VendorListV1.of(1, new Date(), singletonList(vendor)); - } - - private void givenHttpClientReturnsResponse(int statusCode, String response) { - given(httpClient.get(anyString(), anyLong())) - .willReturn(Future.succeededFuture(HttpClientResponse.of(statusCode, null, response))); - } - - private void givenHttpClientProducesException(Throwable throwable) { - given(httpClient.get(anyString(), anyLong())) - .willReturn(Future.failedFuture(throwable)); - } - - @SuppressWarnings("unchecked") - private static Answer withSelfAndPassObjectToHandler(T obj) { - return inv -> { - // invoking handler right away passing mock to it - ((Handler) inv.getArgument(2)).handle(obj); - return inv.getMock(); - }; - } -} diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-appnexus-bid-request-1.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-appnexus-bid-request-1.json index f7d8749a221..ac196a990b9 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-appnexus-bid-request-1.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-appnexus-bid-request-1.json @@ -57,6 +57,7 @@ "ip": "80.215.195.0", "pxratio": 4.2, "language": "en", + "ifa": "ifaId", "ext": { "prebid": { "interstitial": { @@ -67,6 +68,7 @@ } }, "user": { + "buyeruid": "12345", "data": [ { "ext": { @@ -83,7 +85,38 @@ } ], "ext": { - "consent": "BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA" + "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", + "eids": [ + { + "source": "adserver.org", + "uids": [ + { + "id": "cd96870f-f53d-4986-a08e-cd1612fb13b0", + "ext": { + "rtiPartner": "TDID" + } + } + ] + }, + { + "source": "liveintent.com", + "uids": [ + { + "id": "efcf3a33-2eaf-4d6b-bf11-a411f134278c" + } + ], + "ext": { + "segments": [ + "999", + "888" + ] + } + }, + { + "source": "pubcid", + "id": "29cfaea8-a429-48fc-9537-8a19a8eb4f0d" + } + ] } }, "at": 1, @@ -108,21 +141,20 @@ "ext": { "prebid": { "debug": 1, + "aliases": { + "appnexusAlias": "appnexus" + }, "currency": { "rates": { "EUR": { "USD": 1.2406 }, "USD": { - "EUR": 0.8110 + "EUR": 0.811 } }, "usepbsrates": false }, - "aliases": { - "appnexusAlias": "appnexus" - }, - "events": {}, "targeting": { "pricegranularity": { "precision": 2, @@ -137,11 +169,13 @@ "includebidderkeys": true }, "cache": { - "bids": {}, + "bids": { + }, "vastxml": { "ttlseconds": 120 } }, + "events": {}, "auctiontimestamp": 1000, "integration": "dmbjs", "channel": { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-appnexus-bid-request-2.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-appnexus-bid-request-2.json index 0f7512a4189..655598bbe7b 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-appnexus-bid-request-2.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-appnexus-bid-request-2.json @@ -45,6 +45,7 @@ "ip": "80.215.195.0", "pxratio": 4.2, "language": "en", + "ifa": "ifaId", "ext": { "prebid": { "interstitial": { @@ -55,6 +56,7 @@ } }, "user": { + "buyeruid": "12345", "data": [ { "ext": { @@ -71,7 +73,38 @@ } ], "ext": { - "consent": "BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA" + "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", + "eids": [ + { + "source": "adserver.org", + "uids": [ + { + "id": "cd96870f-f53d-4986-a08e-cd1612fb13b0", + "ext": { + "rtiPartner": "TDID" + } + } + ] + }, + { + "source": "liveintent.com", + "uids": [ + { + "id": "efcf3a33-2eaf-4d6b-bf11-a411f134278c" + } + ], + "ext": { + "segments": [ + "999", + "888" + ] + } + }, + { + "source": "pubcid", + "id": "29cfaea8-a429-48fc-9537-8a19a8eb4f0d" + } + ] } }, "at": 1, @@ -96,21 +129,20 @@ "ext": { "prebid": { "debug": 1, + "aliases": { + "appnexusAlias": "appnexus" + }, "currency": { "rates": { "EUR": { "USD": 1.2406 }, "USD": { - "EUR": 0.8110 + "EUR": 0.811 } }, "usepbsrates": false }, - "aliases": { - "appnexusAlias": "appnexus" - }, - "events": {}, "targeting": { "pricegranularity": { "precision": 2, @@ -125,11 +157,13 @@ "includebidderkeys": true }, "cache": { - "bids": {}, + "bids": { + }, "vastxml": { "ttlseconds": 120 } }, + "events": {}, "auctiontimestamp": 1000, "integration": "dmbjs", "channel": { diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-auction-rubicon-appnexus-request.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-auction-rubicon-appnexus-request.json index 63a4c70700a..0284cfbdab0 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-auction-rubicon-appnexus-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-auction-rubicon-appnexus-request.json @@ -174,7 +174,7 @@ "device": { "pxratio": 4.2, "dnt": 2, - "ip": "80.215.195.122", + "ip": "80.215.195.0", "language": "en", "ifa": "ifaId", "ext": { @@ -287,7 +287,7 @@ } ], "ext": { - "consent": "BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA", + "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", "eids": [ { "source": "adserver.org", diff --git a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-auction-rubicon-appnexus-response.json b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-auction-rubicon-appnexus-response.json index 4b7a9679ebf..852a951a2b1 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-auction-rubicon-appnexus-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/rubicon_appnexus/test-auction-rubicon-appnexus-response.json @@ -6,16 +6,16 @@ { "id": "a121a07f-1579-4465-bc5e-5c5b02a0c421", "impid": "impStoredAuctionResponse", - "crid": "crid1", "price": 0.9, + "crid": "crid1", "ext": { "prebid": { "type": "banner", "targeting": { "hb_pb": "0.90", "hb_pb_appnexus": "0.90", - "hb_cache_path": "/cache", - "hb_cache_path_appnexus": "/cache", + "hb_cache_path": "{{ cache.path }}", + "hb_cache_path_appnexus": "{{ cache.path }}", "hb_bidder_appnexus": "appnexus", "hb_bidder": "appnexus", "hb_cache_id": "765e116a-5773-49d5-a648-0b97a9907a4e", @@ -56,28 +56,28 @@ "prebid": { "type": "banner", "targeting": { - "hb_pb": "5.50", "hb_pb_appnexus": "5.50", + "hb_cache_path_appnexus": "{{ cache.path }}", + "hb_cache_id": "117431c9-807a-41e1-82a7-dcd8f8875493", + "hb_cache_host_appnexus": "{{ cache.host }}", + "hb_cache_id_appnexus": "117431c9-807a-41e1-82a7-dcd8f8875493", + "hb_pb": "5.50", + "hb_cache_path": "{{ cache.path }}", "hb_size": "300x250", "hb_bidder_appnexus": "appnexus", "hb_bidder": "appnexus", - "hb_cache_id": "117431c9-807a-41e1-82a7-dcd8f8875493", - "hb_size_appnexus": "300x250", - "hb_cache_id_appnexus": "117431c9-807a-41e1-82a7-dcd8f8875493", "hb_cache_host": "{{ cache.host }}", - "hb_cache_host_appnexus": "{{ cache.host }}", - "hb_cache_path": "{{ cache.path }}", - "hb_cache_path_appnexus": "{{ cache.path }}" - }, - "events": { - "win": "{{ event.url }}t=win&b=7706636740145184841&a=5001&ts=1000&bidder=appnexus&f=i&int=dmbjs", - "imp": "{{ event.url }}t=imp&b=7706636740145184841&a=5001&ts=1000&bidder=appnexus&f=i&int=dmbjs" + "hb_size_appnexus": "300x250" }, "cache": { "bids": { "url": "{{ cache.resource_url }}117431c9-807a-41e1-82a7-dcd8f8875493", "cacheId": "117431c9-807a-41e1-82a7-dcd8f8875493" } + }, + "events": { + "win": "{{ event.url }}t=win&b=7706636740145184841&a=5001&ts=1000&bidder=appnexus&f=i&int=dmbjs", + "imp": "{{ event.url }}t=imp&b=7706636740145184841&a=5001&ts=1000&bidder=appnexus&f=i&int=dmbjs" } }, "bidder": { @@ -114,24 +114,24 @@ "targeting": { "hb_pb": "1.00", "hb_pb_appnexus": "1.00", + "hb_cache_path": "{{ cache.path }}", + "hb_cache_path_appnexus": "{{ cache.path }}", "hb_bidder_appnexus": "appnexus", "hb_bidder": "appnexus", "hb_cache_id": "6cf69b42-96f5-4ba1-a984-a9b4d8ff21cf", - "hb_cache_id_appnexus": "6cf69b42-96f5-4ba1-a984-a9b4d8ff21cf", "hb_cache_host": "{{ cache.host }}", "hb_cache_host_appnexus": "{{ cache.host }}", - "hb_cache_path": "{{ cache.path }}", - "hb_cache_path_appnexus": "{{ cache.path }}" - }, - "events": { - "win": "{{ event.url }}t=win&b=928185755156387460&a=5001&ts=1000&bidder=appnexus&f=i&int=dmbjs", - "imp": "{{ event.url }}t=imp&b=928185755156387460&a=5001&ts=1000&bidder=appnexus&f=i&int=dmbjs" + "hb_cache_id_appnexus": "6cf69b42-96f5-4ba1-a984-a9b4d8ff21cf" }, "cache": { "bids": { "url": "{{ cache.resource_url }}6cf69b42-96f5-4ba1-a984-a9b4d8ff21cf", "cacheId": "6cf69b42-96f5-4ba1-a984-a9b4d8ff21cf" } + }, + "events": { + "win": "{{ event.url }}t=win&b=928185755156387460&a=5001&ts=1000&bidder=appnexus&f=i&int=dmbjs", + "imp": "{{ event.url }}t=imp&b=928185755156387460&a=5001&ts=1000&bidder=appnexus&f=i&int=dmbjs" } }, "bidder": { @@ -151,70 +151,13 @@ "seat": "appnexus", "group": 0 }, - { - "bid": [ - { - "id": "7706636740145184840", - "impid": "impId3", - "price": 5.00, - "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": { - "prebid": { - "type": "banner", - "targeting": { - "hb_bidder_appnexusAlias": "appnexusAlias", - "hb_pb_appnexusAlias": "5.00", - "hb_size_appnexusAlias": "300x250", - "hb_cache_id_appnexusAlias": "91912e5b-dfa8-42bc-9c7e-df6ce0449c19", - "hb_cache_host_appnexusAlias": "{{ cache.host }}", - "hb_cache_path_appnexusAlias": "{{ cache.path }}" - }, - "events": { - "win": "{{ event.url }}t=win&b=7706636740145184840&a=5001&ts=1000&bidder=appnexusAlias&f=i&int=dmbjs", - "imp": "{{ event.url }}t=imp&b=7706636740145184840&a=5001&ts=1000&bidder=appnexusAlias&f=i&int=dmbjs" - }, - "cache": { - "bids": { - "url": "{{ cache_resource_url }}91912e5b-dfa8-42bc-9c7e-df6ce0449c19", - "cacheId": "91912e5b-dfa8-42bc-9c7e-df6ce0449c19" - } - } - }, - "bidder": { - "appnexus": { - "brand_id": 350, - "brand_category_id": 350, - "auction_id": 8189378542222915031, - "bidder_id": 2, - "bid_ad_type": 0, - "ranking_price": 0.0 - } - }, - "origbidcpm": 5.00, - "origbidcur": "USD" - } - } - ], - "seat": "appnexusAlias", - "group": 0 - }, { "bid": [ { "id": "f227a07f-1579-4465-bc5e-5c5b02a0c180", "impid": "impStoredAuctionResponse", - "crid": "crid1", "price": 0.8, + "crid": "crid1", "ext": { "prebid": { "type": "banner", @@ -253,34 +196,34 @@ "prebid": { "type": "video", "targeting": { + "hb_size_rubicon": "300x250", + "hb_cache_id": "683fe79f-6df7-4971-ac70-820e0486992d", + "hb_cache_path_rubicon": "{{ cache.path }}", + "hb_cache_host_rubicon": "{{ cache.host }}", "hb_pb": "8.40", "hb_pb_rubicon": "8.40", "hb_cache_id_rubicon": "683fe79f-6df7-4971-ac70-820e0486992d", + "hb_cache_path": "{{ cache.path }}", + "hb_uuid": "b2528f73-96ab-42ab-8f15-fbe6ed779a26", "hb_size": "300x250", - "hb_size_rubicon": "300x250", + "hb_uuid_rubicon": "b2528f73-96ab-42ab-8f15-fbe6ed779a26", "hb_bidder": "rubicon", "hb_bidder_rubicon": "rubicon", - "hb_cache_id": "683fe79f-6df7-4971-ac70-820e0486992d", - "hb_uuid_rubicon": "b2528f73-96ab-42ab-8f15-fbe6ed779a26", - "hb_uuid": "b2528f73-96ab-42ab-8f15-fbe6ed779a26", - "hb_cache_host": "{{ cache.host }}", - "hb_cache_host_rubicon": "{{ cache.host }}", - "hb_cache_path": "{{ cache.path }}", - "hb_cache_path_rubicon": "{{ cache.path }}" - }, - "events": { - "win": "{{ event.url }}t=win&b=880290288&a=5001&ts=1000&bidder=rubicon&f=i&int=dmbjs", - "imp": "{{ event.url }}t=imp&b=880290288&a=5001&ts=1000&bidder=rubicon&f=i&int=dmbjs" + "hb_cache_host": "{{ cache.host }}" }, "cache": { - "vastXml": { - "url": "{{ cache.resource_url }}b2528f73-96ab-42ab-8f15-fbe6ed779a26", - "cacheId": "b2528f73-96ab-42ab-8f15-fbe6ed779a26" - }, "bids": { "url": "{{ cache.resource_url }}683fe79f-6df7-4971-ac70-820e0486992d", "cacheId": "683fe79f-6df7-4971-ac70-820e0486992d" + }, + "vastXml": { + "url": "{{ cache.resource_url }}b2528f73-96ab-42ab-8f15-fbe6ed779a26", + "cacheId": "b2528f73-96ab-42ab-8f15-fbe6ed779a26" } + }, + "events": { + "win": "{{ event.url }}t=win&b=880290288&a=5001&ts=1000&bidder=rubicon&f=i&int=dmbjs", + "imp": "{{ event.url }}t=imp&b=880290288&a=5001&ts=1000&bidder=rubicon&f=i&int=dmbjs" } }, "bidder": { @@ -310,28 +253,28 @@ "prebid": { "type": "banner", "targeting": { + "hb_size_rubicon": "300x600", + "hb_cache_id": "4fe59ef5-6fb4-48c5-88b6-9870257fc49e", + "hb_cache_path_rubicon": "{{ cache.path }}", + "hb_cache_host_rubicon": "{{ cache.host }}", "hb_pb": "4.20", "hb_pb_rubicon": "4.20", "hb_cache_id_rubicon": "4fe59ef5-6fb4-48c5-88b6-9870257fc49e", + "hb_cache_path": "{{ cache.path }}", "hb_size": "300x600", - "hb_size_rubicon": "300x600", "hb_bidder": "rubicon", "hb_bidder_rubicon": "rubicon", - "hb_cache_id": "4fe59ef5-6fb4-48c5-88b6-9870257fc49e", - "hb_cache_host": "{{ cache.host }}", - "hb_cache_host_rubicon": "{{ cache.host }}", - "hb_cache_path": "{{ cache.path }}", - "hb_cache_path_rubicon": "{{ cache.path }}" - }, - "events": { - "win": "{{ event.url }}t=win&b=466223845&a=5001&ts=1000&bidder=rubicon&f=i&int=dmbjs", - "imp": "{{ event.url }}t=imp&b=466223845&a=5001&ts=1000&bidder=rubicon&f=i&int=dmbjs" + "hb_cache_host": "{{ cache.host }}" }, "cache": { "bids": { "url": "{{ cache.resource_url }}4fe59ef5-6fb4-48c5-88b6-9870257fc49e", "cacheId": "4fe59ef5-6fb4-48c5-88b6-9870257fc49e" } + }, + "events": { + "win": "{{ event.url }}t=win&b=466223845&a=5001&ts=1000&bidder=rubicon&f=i&int=dmbjs", + "imp": "{{ event.url }}t=imp&b=466223845&a=5001&ts=1000&bidder=rubicon&f=i&int=dmbjs" } }, "origbidcpm": 4.26 @@ -340,47 +283,104 @@ ], "seat": "rubicon", "group": 0 + }, + { + "bid": [ + { + "id": "7706636740145184840", + "impid": "impId3", + "price": 5.0, + "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": { + "prebid": { + "type": "banner", + "targeting": { + "hb_bidder_appnexusAlias": "appnexusAlias", + "hb_pb_appnexusAlias": "5.00", + "hb_size_appnexusAlias": "300x250", + "hb_cache_path_appnexusAlias": "{{ cache.path }}", + "hb_cache_host_appnexusAlias": "{{ cache.host }}", + "hb_cache_id_appnexusAlias": "91912e5b-dfa8-42bc-9c7e-df6ce0449c19" + }, + "cache": { + "bids": { + "url": "{{ cache.resource_url }}91912e5b-dfa8-42bc-9c7e-df6ce0449c19", + "cacheId": "91912e5b-dfa8-42bc-9c7e-df6ce0449c19" + } + }, + "events": { + "win": "{{ event.url }}t=win&b=7706636740145184840&a=5001&ts=1000&bidder=appnexusAlias&f=i&int=dmbjs", + "imp": "{{ event.url }}t=imp&b=7706636740145184840&a=5001&ts=1000&bidder=appnexusAlias&f=i&int=dmbjs" + } + }, + "bidder": { + "appnexus": { + "brand_id": 350, + "brand_category_id": 350, + "auction_id": 8189378542222915031, + "bidder_id": 2, + "bid_ad_type": 0, + "ranking_price": 0.0 + } + }, + "origbidcpm": 5.0, + "origbidcur": "USD" + } + } + ], + "seat": "appnexusAlias", + "group": 0 } ], "cur": "USD", "ext": { "debug": { "httpcalls": { - "appnexus": [ - { - "uri": "{{ appnexus.exchange_uri }}?member_id=103", - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId3\",\"banner\":{\"format\":[{\"w\":300,\"h\":250},{\"w\":300,\"h\":600}],\"w\":300,\"h\":250,\"pos\":3},\"tagid\":\"abc\",\"bidfloor\":1.0,\"ext\":{\"appnexus\":{\"keywords\":\"foo=bar,foo=baz\",\"traffic_source_code\":\"trafficSource\"}}},{\"id\":\"impId131\",\"native\":{\"request\":\"{\\\"ver\\\":\\\"1.1\\\",\\\"context\\\":1,\\\"contextsubtype\\\":11,\\\"plcmttype\\\":4,\\\"plcmtcnt\\\":1,\\\"assets\\\":[{\\\"id\\\":0,\\\"required\\\":1,\\\"title\\\":{\\\"len\\\":500}},{\\\"id\\\":1,\\\"required\\\":1,\\\"img\\\":{\\\"type\\\":3,\\\"wmin\\\":1,\\\"hmin\\\":1}},{\\\"id\\\":2,\\\"required\\\":0,\\\"data\\\":{\\\"type\\\":4,\\\"len\\\":200}},{\\\"id\\\":3,\\\"required\\\":0,\\\"data\\\":{\\\"type\\\":2,\\\"len\\\":15000}},{\\\"id\\\":4,\\\"required\\\":0,\\\"data\\\":{\\\"len\\\":40}},{\\\"id\\\":5,\\\"required\\\":0,\\\"data\\\":{\\\"type\\\":11}}]}\",\"ver\":\"1.1\"},\"ext\":{\"appnexus\":{\"placement_id\":9880618}}}],\"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\":\"958\",\"bid\":[{\"id\":\"7706636740145184841\",\"impid\":\"impId3\",\"price\":5.5,\"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,\"ext\":{\"appnexus\":{\"brand_id\":1,\"auction_id\":8189378542222915032,\"bidder_id\":2,\"bid_ad_type\":0,\"ranking_price\":0.0}}},{\"id\":\"928185755156387460\",\"impid\":\"impId131\",\"price\":1.0,\"adid\":\"69595837\",\"adm\":\"{\\\"assets\\\":[{\\\"id\\\":0,\\\"title\\\":{\\\"text\\\":\\\"This is an example Prebid Native creative\\\"}},{\\\"id\\\":1,\\\"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\\\":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\\\":\\\"\\\"}\",\"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 - } - ], - "appnexusAlias": [ + "cache": [ { - "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\":\"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\"}", + "uri": "{{ cache.endpoint }}", + "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"466223845\",\"impid\":\"impId2\",\"price\":4.26,\"adm\":\"adm2\",\"crid\":\"crid2\",\"w\":300,\"h\":600,\"ext\":{\"origbidcpm\":4.26},\"wurl\":\"{{ event.url }}t=win&b=466223845&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\",\"ext\":{\"origbidcpm\":0.8,\"origbidcur\":\"USD\"},\"wurl\":\"{{ event.url }}t=win&b=f227a07f-1579-4465-bc5e-5c5b02a0c180&a=5001&ts=1000&bidder=rubicon&f=i&int=dmbjs\"}},{\"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\":\"{{ event.url }}t=win&b=7706636740145184840&a=5001&ts=1000&bidder=appnexusAlias&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\":\"{{ event.url }}t=win&b=7706636740145184841&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\":\"{{ event.url }}t=win&b=880290288&a=5001&ts=1000&bidder=rubicon&f=i&int=dmbjs\"}},{\"type\":\"json\",\"value\":{\"id\":\"928185755156387460\",\"impid\":\"impId131\",\"price\":1,\"adm\":\"{\\\"assets\\\":[{\\\"id\\\":0,\\\"title\\\":{\\\"text\\\":\\\"This is an example Prebid Native creative\\\"}},{\\\"id\\\":1,\\\"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\\\":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\":\"{{ event.url }}t=win&b=928185755156387460&a=5001&ts=1000&bidder=appnexus&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\":\"{{ event.url }}t=win&b=a121a07f-1579-4465-bc5e-5c5b02a0c421&a=5001&ts=1000&bidder=appnexus&f=i&int=dmbjs\"}},{\"type\":\"xml\",\"value\":\"\",\"expiry\":120}]}", + "responsebody": "{\"responses\":[{\"uuid\":\"4fe59ef5-6fb4-48c5-88b6-9870257fc49e\"},{\"uuid\":\"c75130ed-bcdd-4821-ad91-90cf835615c5\"},{\"uuid\":\"91912e5b-dfa8-42bc-9c7e-df6ce0449c19\"},{\"uuid\":\"117431c9-807a-41e1-82a7-dcd8f8875493\"},{\"uuid\":\"683fe79f-6df7-4971-ac70-820e0486992d\"},{\"uuid\":\"6cf69b42-96f5-4ba1-a984-a9b4d8ff21cf\"},{\"uuid\":\"765e116a-5773-49d5-a648-0b97a9907a4e\"},{\"uuid\":\"b2528f73-96ab-42ab-8f15-fbe6ed779a26\"}]}", "status": 200 } ], "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\":\"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}]}", + "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\",\"ifa\":\"ifaId\",\"ext\":{\"rp\":{\"pixelratio\":4.2}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"data\":[{\"segment\":[{\"id\":\"segmentId1\"},{\"id\":\"segmentId2\"}],\"ext\":{\"segtax\":3}}],\"ext\":{\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"eids\":[{\"source\":\"adserver.org\",\"uids\":[{\"id\":\"cd96870f-f53d-4986-a08e-cd1612fb13b0\",\"ext\":{\"rtiPartner\":\"TDID\"}}]},{\"source\":\"liveintent.com\",\"uids\":[{\"id\":\"efcf3a33-2eaf-4d6b-bf11-a411f134278c\"}],\"ext\":{\"segments\":[\"999\",\"888\"]}},{\"source\":\"pubcid\",\"id\":\"29cfaea8-a429-48fc-9537-8a19a8eb4f0d\"}],\"tpid\":[{\"source\":\"tdid\",\"uid\":\"cd96870f-f53d-4986-a08e-cd1612fb13b0\"},{\"source\":\"liveintent.com\",\"uid\":\"efcf3a33-2eaf-4d6b-bf11-a411f134278c\"}],\"rp\":{\"target\":{\"LIseg\":[\"999\",\"888\"],\"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 }, { "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\":\"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}]}", + "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\",\"ifa\":\"ifaId\",\"ext\":{\"rp\":{\"pixelratio\":4.2}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"data\":[{\"segment\":[{\"id\":\"segmentId1\"},{\"id\":\"segmentId2\"}],\"ext\":{\"segtax\":3}}],\"ext\":{\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"eids\":[{\"source\":\"adserver.org\",\"uids\":[{\"id\":\"cd96870f-f53d-4986-a08e-cd1612fb13b0\",\"ext\":{\"rtiPartner\":\"TDID\"}}]},{\"source\":\"liveintent.com\",\"uids\":[{\"id\":\"efcf3a33-2eaf-4d6b-bf11-a411f134278c\"}],\"ext\":{\"segments\":[\"999\",\"888\"]}},{\"source\":\"pubcid\",\"id\":\"29cfaea8-a429-48fc-9537-8a19a8eb4f0d\"}],\"tpid\":[{\"source\":\"tdid\",\"uid\":\"cd96870f-f53d-4986-a08e-cd1612fb13b0\"},{\"source\":\"liveintent.com\",\"uid\":\"efcf3a33-2eaf-4d6b-bf11-a411f134278c\"}],\"rp\":{\"target\":{\"ucat\":[\"new\"],\"search\":[\"iphone\"],\"LIseg\":[\"999\",\"888\"],\"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 } ], - "cache": [ + "appnexus": [ { - "uri": "{{ cache.endpoint }}", - "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"928185755156387460\",\"impid\":\"impId131\",\"price\":1,\"adm\":\"{\\\"assets\\\":[{\\\"id\\\":0,\\\"title\\\":{\\\"text\\\":\\\"This is an example Prebid Native creative\\\"}},{\\\"id\\\":1,\\\"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\\\":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\":\"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\":\"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\":\"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\":\"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\":\"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\":\"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\"}]}", + "uri": "{{ appnexus.exchange_uri }}?member_id=103", + "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId3\",\"banner\":{\"format\":[{\"w\":300,\"h\":250},{\"w\":300,\"h\":600}],\"w\":300,\"h\":250,\"pos\":3},\"tagid\":\"abc\",\"bidfloor\":1.0,\"ext\":{\"appnexus\":{\"keywords\":\"foo=bar,foo=baz\",\"traffic_source_code\":\"trafficSource\"}}},{\"id\":\"impId131\",\"native\":{\"request\":\"{\\\"ver\\\":\\\"1.1\\\",\\\"context\\\":1,\\\"contextsubtype\\\":11,\\\"plcmttype\\\":4,\\\"plcmtcnt\\\":1,\\\"assets\\\":[{\\\"id\\\":0,\\\"required\\\":1,\\\"title\\\":{\\\"len\\\":500}},{\\\"id\\\":1,\\\"required\\\":1,\\\"img\\\":{\\\"type\\\":3,\\\"wmin\\\":1,\\\"hmin\\\":1}},{\\\"id\\\":2,\\\"required\\\":0,\\\"data\\\":{\\\"type\\\":4,\\\"len\\\":200}},{\\\"id\\\":3,\\\"required\\\":0,\\\"data\\\":{\\\"type\\\":2,\\\"len\\\":15000}},{\\\"id\\\":4,\\\"required\\\":0,\\\"data\\\":{\\\"len\\\":40}},{\\\"id\\\":5,\\\"required\\\":0,\\\"data\\\":{\\\"type\\\":11}}]}\",\"ver\":\"1.1\"},\"ext\":{\"appnexus\":{\"placement_id\":9880618}}}],\"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\",\"ifa\":\"ifaId\",\"ext\":{\"prebid\":{\"interstitial\":{\"minwidthperc\":50,\"minheightperc\":60}}}},\"user\":{\"buyeruid\":\"12345\",\"data\":[{\"segment\":[{\"id\":\"segmentId1\"},{\"id\":\"segmentId2\"}],\"ext\":{\"segtax\":3}}],\"ext\":{\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"eids\":[{\"source\":\"adserver.org\",\"uids\":[{\"id\":\"cd96870f-f53d-4986-a08e-cd1612fb13b0\",\"ext\":{\"rtiPartner\":\"TDID\"}}]},{\"source\":\"liveintent.com\",\"uids\":[{\"id\":\"efcf3a33-2eaf-4d6b-bf11-a411f134278c\"}],\"ext\":{\"segments\":[\"999\",\"888\"]}},{\"source\":\"pubcid\",\"id\":\"29cfaea8-a429-48fc-9537-8a19a8eb4f0d\"}]}},\"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\":\"958\",\"bid\":[{\"id\":\"7706636740145184841\",\"impid\":\"impId3\",\"price\":5.5,\"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,\"ext\":{\"appnexus\":{\"brand_id\":1,\"auction_id\":8189378542222915032,\"bidder_id\":2,\"bid_ad_type\":0,\"ranking_price\":0.0}}},{\"id\":\"928185755156387460\",\"impid\":\"impId131\",\"price\":1.0,\"adid\":\"69595837\",\"adm\":\"{\\\"assets\\\":[{\\\"id\\\":0,\\\"title\\\":{\\\"text\\\":\\\"This is an example Prebid Native creative\\\"}},{\\\"id\\\":1,\\\"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\\\":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\\\":\\\"\\\"}\",\"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 + } + ], + "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\":\"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\",\"ifa\":\"ifaId\",\"ext\":{\"prebid\":{\"interstitial\":{\"minwidthperc\":50,\"minheightperc\":60}}}},\"user\":{\"buyeruid\":\"12345\",\"data\":[{\"segment\":[{\"id\":\"segmentId1\"},{\"id\":\"segmentId2\"}],\"ext\":{\"segtax\":3}}],\"ext\":{\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"eids\":[{\"source\":\"adserver.org\",\"uids\":[{\"id\":\"cd96870f-f53d-4986-a08e-cd1612fb13b0\",\"ext\":{\"rtiPartner\":\"TDID\"}}]},{\"source\":\"liveintent.com\",\"uids\":[{\"id\":\"efcf3a33-2eaf-4d6b-bf11-a411f134278c\"}],\"ext\":{\"segments\":[\"999\",\"888\"]}},{\"source\":\"pubcid\",\"id\":\"29cfaea8-a429-48fc-9537-8a19a8eb4f0d\"}]}},\"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 } ] @@ -458,15 +458,15 @@ }, "ext": { "prebid": { + "storedrequest": { + "id": "test-rubicon-stored-request-2" + }, "bidder": { "rubicon": { "accountId": 5001, "siteId": 6001, "zoneId": 7001 } - }, - "storedrequest": { - "id": "test-rubicon-stored-request-2" } } } @@ -590,7 +590,7 @@ "device": { "ua": "userAgent", "dnt": 2, - "ip": "80.215.195.122", + "ip": "80.215.195.0", "pxratio": 4.2, "language": "en", "ifa": "ifaId", @@ -606,9 +606,6 @@ "user": { "data": [ { - "ext": { - "segtax": 3 - }, "segment": [ { "id": "segmentId1" @@ -616,11 +613,14 @@ { "id": "segmentId2" } - ] + ], + "ext": { + "segtax": 3 + } } ], "ext": { - "consent": "BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA", + "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", "eids": [ { "source": "adserver.org", @@ -671,6 +671,9 @@ "ext": { "prebid": { "debug": 1, + "aliases": { + "appnexusAlias": "appnexus" + }, "currency": { "rates": { "EUR": { @@ -682,10 +685,6 @@ }, "usepbsrates": false }, - "aliases": { - "appnexusAlias": "appnexus" - }, - "events": {}, "targeting": { "pricegranularity": { "precision": 2, @@ -705,6 +704,7 @@ "ttlseconds": 120 } }, + "events": {}, "schains": [ { "bidders": [ @@ -731,13 +731,13 @@ } } ], + "auctiontimestamp": 1000, "bidders": { "rubicon": { "integration": "dmbjs" } }, "integration": "dmbjs", - "auctiontimestamp": 1000, "channel": { "name": "web" } @@ -759,9 +759,9 @@ "rubicon": "{{ rubicon.response_time_ms }}", "cache": "{{ cache.response_time_ms }}" }, + "tmaxrequest": 5000, "prebid": { "auctiontimestamp": 1000 - }, - "tmaxrequest": 5000 + } } } 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 72284cc0c98..14cd5a61109 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 @@ -23,10 +23,10 @@ "ext": { "skip": 5, "skipdelay": 1, - "videotype": "rewarded", "rp": { "size_id": 15 - } + }, + "videotype": "rewarded" } }, "ext": { @@ -63,10 +63,10 @@ } }, "ext": { + "amp": 0, "rp": { "site_id": 3001 - }, - "amp": 0 + } } }, "device": { @@ -75,6 +75,7 @@ "ip": "80.215.195.0", "pxratio": 4.2, "language": "en", + "ifa": "ifaId", "ext": { "rp": { "pixelratio": 4.2 @@ -97,8 +98,50 @@ ] } ], + "buyeruid": "J5VLCWQP-26-CWFT", "ext": { - "consent": "BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA", + "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", + "eids": [ + { + "source": "adserver.org", + "uids": [ + { + "id": "cd96870f-f53d-4986-a08e-cd1612fb13b0", + "ext": { + "rtiPartner": "TDID" + } + } + ] + }, + { + "source": "liveintent.com", + "uids": [ + { + "id": "efcf3a33-2eaf-4d6b-bf11-a411f134278c" + } + ], + "ext": { + "segments": [ + "999", + "888" + ] + } + }, + { + "source": "pubcid", + "id": "29cfaea8-a429-48fc-9537-8a19a8eb4f0d" + } + ], + "tpid": [ + { + "source": "tdid", + "uid": "cd96870f-f53d-4986-a08e-cd1612fb13b0" + }, + { + "source": "liveintent.com", + "uid": "efcf3a33-2eaf-4d6b-bf11-a411f134278c" + } + ], "rp": { "target": { "ucat": [ @@ -107,6 +150,10 @@ "search": [ "iphone" ], + "LIseg": [ + "999", + "888" + ], "iab": [ "segmentId1", "segmentId2" 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 c2eccfd734a..aec0186f4ab 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 @@ -47,10 +47,10 @@ } }, "ext": { + "amp": 0, "rp": { "site_id": 6001 - }, - "amp": 0 + } } }, "device": { @@ -59,6 +59,7 @@ "ip": "80.215.195.0", "pxratio": 4.2, "language": "en", + "ifa": "ifaId", "ext": { "rp": { "pixelratio": 4.2 @@ -66,6 +67,7 @@ } }, "user": { + "buyeruid": "J5VLCWQP-26-CWFT", "data": [ { "ext": { @@ -82,9 +84,54 @@ } ], "ext": { - "consent": "BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA", + "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", + "eids": [ + { + "source": "adserver.org", + "uids": [ + { + "id": "cd96870f-f53d-4986-a08e-cd1612fb13b0", + "ext": { + "rtiPartner": "TDID" + } + } + ] + }, + { + "source": "liveintent.com", + "uids": [ + { + "id": "efcf3a33-2eaf-4d6b-bf11-a411f134278c" + } + ], + "ext": { + "segments": [ + "999", + "888" + ] + } + }, + { + "source": "pubcid", + "id": "29cfaea8-a429-48fc-9537-8a19a8eb4f0d" + } + ], + "tpid": [ + { + "source": "tdid", + "uid": "cd96870f-f53d-4986-a08e-cd1612fb13b0" + }, + { + "source": "liveintent.com", + "uid": "efcf3a33-2eaf-4d6b-bf11-a411f134278c" + } + ], "rp": { "target": { + "LIseg": [ + "999", + "888" + ], "iab": [ "segmentId1", "segmentId2" 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 25f8b3902f2..daf61f3032d 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 @@ -48,6 +48,7 @@ "ip": "80.215.195.0", "pxratio": 4.2, "language": "en", + "ifa": "ifaId", "ext": { "prebid": { "interstitial": { @@ -58,8 +59,9 @@ } }, "user": { + "buyeruid" : "12345", "ext": { - "consent": "BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA" + "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA" } }, "at": 1, @@ -85,7 +87,7 @@ "USD": 1.2406 }, "USD": { - "EUR": 0.8110 + "EUR": 0.811 } }, "usepbsrates": false @@ -104,11 +106,17 @@ "includebidderkeys": true }, "cache": { - "bids": {}, + "bids": { + }, "vastxml": { "ttlseconds": 120 } }, + "events": {}, + "auctiontimestamp": 1000, + "channel": { + "name": "web" + }, "multibid": [ { "bidder": "appnexus", 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 ce35462c0a7..2305a408e71 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 @@ -154,7 +154,7 @@ }, "user": { "ext": { - "consent": "BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA" + "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA" } }, "regs": { 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 2837d7ddf34..db331af2373 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 @@ -23,10 +23,10 @@ "ext": { "skip": 5, "skipdelay": 1, - "videotype": "rewarded", "rp": { "size_id": 15 - } + }, + "videotype": "rewarded" } }, "ext": { @@ -63,10 +63,10 @@ } }, "ext": { + "amp": 0, "rp": { "site_id": 3001 - }, - "amp": 0 + } } }, "device": { @@ -75,6 +75,7 @@ "ip": "80.215.195.0", "pxratio": 4.2, "language": "en", + "ifa": "ifaId", "ext": { "rp": { "pixelratio": 4.2 @@ -82,8 +83,9 @@ } }, "user": { + "buyeruid": "J5VLCWQP-26-CWFT", "ext": { - "consent": "BOEFEAyOEFEAyAHABDENAIgAAAB9vABAASA", + "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", "rp": { "target": { "ucat": [ @@ -107,4 +109,4 @@ "us_privacy": "1YNN" } } -} +} \ No newline at end of file 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 abf5074fb47..60943b6c2a0 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 @@ -254,7 +254,7 @@ "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.13 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2", "dnt": 33, "lmt": 44, - "ip": "123.145.167.10", + "ip": "123.145.167.0", "devicetype": 1, "os": "mac os", "h": 480, @@ -273,7 +273,7 @@ "gender": "F", "keywords": "Hotels, Travelling", "ext": { - "consent": "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA" + "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA" } }, "at": 1, 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 cbeef385604..3d839649d46 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 @@ -47,7 +47,7 @@ "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.13 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2", "dnt": 33, "lmt": 44, - "ip": "123.145.167.10", + "ip": "123.145.167.0", "devicetype": 1, "os": "mac os", "h": 480, @@ -66,7 +66,7 @@ "gender": "F", "keywords": "Hotels, Travelling", "ext": { - "consent": "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA" + "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA" } }, "at": 1, diff --git a/src/test/resources/org/prebid/server/it/openrtb2/video/test-video-appnexus-request.json b/src/test/resources/org/prebid/server/it/openrtb2/video/test-video-appnexus-request.json index f1d90701038..6dd7ce977f0 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/video/test-video-appnexus-request.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/video/test-video-appnexus-request.json @@ -24,7 +24,7 @@ }, "user": { "ext": { - "consent": "BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA" + "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA" }, "yob": 1991, "gender": "F",