diff --git a/extra/pom.xml b/extra/pom.xml index 1a43c1b8ace..873ce0e65c3 100644 --- a/extra/pom.xml +++ b/extra/pom.xml @@ -39,9 +39,7 @@ 4.4 1.27.1 3.6.1 - 1.10.0 2.1 - 4.5.14 5.5.1 6.8.0 1.5.6 @@ -137,23 +135,6 @@ commons-math3 ${commons-math3.version} - - commons-validator - commons-validator - ${commons-validator.version} - - - - org.apache.httpcomponents - httpclient - ${httpclient.version} - - - commons-logging - commons-logging - - - com.github.seancfoley ipaddress diff --git a/pom.xml b/pom.xml index 8ef80350c78..86fa067ddfb 100644 --- a/pom.xml +++ b/pom.xml @@ -80,6 +80,10 @@ io.vertx vertx-auth-common + + io.vertx + vertx-uri-template + com.ongres.scram client @@ -110,14 +114,6 @@ org.apache.commons commons-math3 - - org.apache.httpcomponents - httpclient - - - commons-validator - commons-validator - com.github.seancfoley ipaddress diff --git a/src/main/java/org/prebid/server/auction/IpAddressHelper.java b/src/main/java/org/prebid/server/auction/IpAddressHelper.java index 523219fd511..36a2a3e61c5 100644 --- a/src/main/java/org/prebid/server/auction/IpAddressHelper.java +++ b/src/main/java/org/prebid/server/auction/IpAddressHelper.java @@ -5,17 +5,23 @@ import inet.ipaddr.IPAddressString; import inet.ipaddr.IPAddressStringParameters; import org.apache.commons.lang3.StringUtils; -import org.apache.http.conn.util.InetAddressUtils; import org.prebid.server.auction.model.IpAddress; import org.prebid.server.log.Logger; import org.prebid.server.log.LoggerFactory; import java.util.List; +import java.util.regex.Pattern; public class IpAddressHelper { private static final Logger logger = LoggerFactory.getLogger(IpAddressHelper.class); + private static final Pattern IP_V4_PATTERN = Pattern.compile(""" + ^\ + (?:[1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.\ + (?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){2}\ + (?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ + """); private static final IPAddressStringParameters IP_ADDRESS_VALIDATION_OPTIONS = IPAddressString.DEFAULT_VALIDATION_OPTIONS.toBuilder() .allowSingleSegment(false) @@ -73,7 +79,7 @@ public IpAddress toIpAddress(String ip) { } public String maskIpv4(String ip) { - if (StringUtils.isBlank(ip) || !InetAddressUtils.isIPv4Address(ip)) { + if (StringUtils.isBlank(ip) || !IP_V4_PATTERN.matcher(ip).matches()) { return ip; } diff --git a/src/main/java/org/prebid/server/bidder/adgeneration/AdgenerationBidder.java b/src/main/java/org/prebid/server/bidder/adgeneration/AdgenerationBidder.java index 22fc3dc5309..5898afae169 100644 --- a/src/main/java/org/prebid/server/bidder/adgeneration/AdgenerationBidder.java +++ b/src/main/java/org/prebid/server/bidder/adgeneration/AdgenerationBidder.java @@ -12,9 +12,9 @@ import com.iab.openrtb.response.Bid; import io.vertx.core.MultiMap; import io.vertx.core.http.HttpMethod; +import io.vertx.uritemplate.Variables; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.http.client.utils.URIBuilder; import org.prebid.server.bidder.Bidder; import org.prebid.server.bidder.adgeneration.model.AdgenerationResponse; import org.prebid.server.bidder.model.BidderBid; @@ -31,8 +31,9 @@ import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.util.HttpUtil; import org.prebid.server.util.ObjectUtil; +import org.prebid.server.util.uritemplate.UriTemplate; +import org.prebid.server.util.uritemplate.UriTemplateFactory; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -51,11 +52,12 @@ public class AdgenerationBidder implements Bidder { new TypeReference<>() { }; - private final String endpointUrl; + private final UriTemplate endpointTemplate; private final JacksonMapper mapper; public AdgenerationBidder(String endpointUrl, JacksonMapper mapper) { - this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.endpointTemplate = UriTemplateFactory.dynamicParams(endpointUrl); this.mapper = Objects.requireNonNull(mapper); } @@ -96,47 +98,40 @@ private ExtImpAdgeneration parseAndValidateImpExt(Imp imp) { } private String getUri(String adSize, String id, String currency, BidRequest bidRequest) { - final URIBuilder uriBuilder; - try { - uriBuilder = new URIBuilder(endpointUrl); - } catch (URISyntaxException e) { - throw new PreBidException("Invalid url: %s, error: %s".formatted(endpointUrl, e.getMessage())); - } - - uriBuilder - .addParameter("posall", "SSPLOC") - .addParameter("id", id) - .addParameter("hb", "true") - .addParameter("t", "json3") - .addParameter("currency", currency) - .addParameter("sdkname", "prebidserver") - .addParameter("adapterver", VERSION); - - addParameterIfNotEmpty(uriBuilder, "sizes", adSize); - addParameterIfNotEmpty(uriBuilder, "tp", ObjectUtil.getIfNotNull(bidRequest.getSite(), Site::getPage)); - addParameterIfNotEmpty(uriBuilder, "appbundle", ObjectUtil.getIfNotNull(bidRequest.getApp(), App::getBundle)); - addParameterIfNotEmpty(uriBuilder, "appname", ObjectUtil.getIfNotNull(bidRequest.getApp(), App::getName)); + final Variables variables = endpointTemplate.newVariables() + .set("posall", "SSPLOC") + .set("id", id) + .set("hb", "true") + .set("t", "json3") + .set("currency", currency) + .set("sdkname", "prebidserver") + .set("adapterver", VERSION); + + addParameterIfNotEmpty(variables, "sizes", adSize); + addParameterIfNotEmpty(variables, "tp", ObjectUtil.getIfNotNull(bidRequest.getSite(), Site::getPage)); + addParameterIfNotEmpty(variables, "appbundle", ObjectUtil.getIfNotNull(bidRequest.getApp(), App::getBundle)); + addParameterIfNotEmpty(variables, "appname", ObjectUtil.getIfNotNull(bidRequest.getApp(), App::getName)); addParameterIfNotEmpty( - uriBuilder, "transactionid", ObjectUtil.getIfNotNull(bidRequest.getSource(), Source::getTid)); + variables, "transactionid", ObjectUtil.getIfNotNull(bidRequest.getSource(), Source::getTid)); final Device device = bidRequest.getDevice(); final String deviceOs = device != null ? device.getOs() : null; if ("android".equals(deviceOs)) { - uriBuilder.addParameter("sdktype", "1"); - addParameterIfNotEmpty(uriBuilder, "advertising_id", device.getIfa()); + variables.set("sdktype", "1"); + addParameterIfNotEmpty(variables, "advertising_id", device.getIfa()); } else if ("ios".equals(deviceOs)) { - uriBuilder.addParameter("sdktype", "2"); - addParameterIfNotEmpty(uriBuilder, "idfa", device.getIfa()); + variables.set("sdktype", "2"); + addParameterIfNotEmpty(variables, "idfa", device.getIfa()); } else { - uriBuilder.addParameter("sdktype", "0"); + variables.set("sdktype", "0"); } - return uriBuilder.toString(); + return endpointTemplate.expandToString(variables); } - private static void addParameterIfNotEmpty(URIBuilder uriBuilder, String parameter, String value) { + private static void addParameterIfNotEmpty(Variables variables, String parameter, String value) { if (StringUtils.isNotEmpty(value)) { - uriBuilder.addParameter(parameter, value); + variables.set(parameter, value); } } diff --git a/src/main/java/org/prebid/server/bidder/adnuntius/AdnuntiusBidder.java b/src/main/java/org/prebid/server/bidder/adnuntius/AdnuntiusBidder.java index 127d02ae000..67ea8e599a3 100644 --- a/src/main/java/org/prebid/server/bidder/adnuntius/AdnuntiusBidder.java +++ b/src/main/java/org/prebid/server/bidder/adnuntius/AdnuntiusBidder.java @@ -17,12 +17,12 @@ import com.iab.openrtb.response.Bid; import io.vertx.core.MultiMap; import io.vertx.core.http.HttpMethod; +import io.vertx.uritemplate.Variables; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.http.client.utils.URIBuilder; import org.prebid.server.bidder.Bidder; import org.prebid.server.bidder.adnuntius.model.request.AdnuntiusMetaData; import org.prebid.server.bidder.adnuntius.model.request.AdnuntiusNativeRequest; @@ -58,9 +58,10 @@ import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; import org.prebid.server.util.ObjectUtil; +import org.prebid.server.util.uritemplate.UriTemplate; +import org.prebid.server.util.uritemplate.UriTemplateFactory; import java.math.BigDecimal; -import java.net.URISyntaxException; import java.time.Clock; import java.time.OffsetDateTime; import java.util.ArrayList; @@ -83,8 +84,8 @@ public class AdnuntiusBidder implements Bidder { private static final int BANNER_MTYPE = 1; private static final int NATIVE_MTYPE = 4; - private final String endpointUrl; - private final String euEndpoint; + private final UriTemplate endpointTemplate; + private final UriTemplate euEndpointTemplate; private final Clock clock; private final JacksonMapper mapper; @@ -93,8 +94,13 @@ public AdnuntiusBidder(String endpointUrl, Clock clock, JacksonMapper mapper) { - this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); - this.euEndpoint = euEndpoint == null ? null : HttpUtil.validateUrl(euEndpoint); + HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + if (euEndpoint != null) { + HttpUtil.validateUrl(euEndpoint); + } + + this.endpointTemplate = UriTemplateFactory.dynamicParams(endpointUrl); + this.euEndpointTemplate = euEndpoint != null ? UriTemplateFactory.dynamicParams(euEndpoint) : null; this.clock = Objects.requireNonNull(clock); this.mapper = Objects.requireNonNull(mapper); } @@ -261,35 +267,30 @@ private List> createHttpRequests( } private String makeEndpoint(BidRequest bidRequest, Boolean noCookies) { - try { - final String gdpr = extractGdpr(bidRequest.getRegs()); - final String url = StringUtils.isNotBlank(gdpr) ? euEndpoint : endpointUrl; - - if (url == null) { - throw new PreBidException("an EU endpoint is required but invalid"); - } + final String gdpr = extractGdpr(bidRequest.getRegs()); + final UriTemplate template = StringUtils.isNotBlank(gdpr) ? euEndpointTemplate : endpointTemplate; + if (template == null) { + throw new PreBidException("an EU endpoint is required but invalid"); + } - final URIBuilder uriBuilder = new URIBuilder(url) - .addParameter("format", "prebidServer") - .addParameter("tzo", getTimeZoneOffset()); + final Variables variables = template.newVariables(); + variables.set("format", "prebidServer"); + variables.set("tzo", getTimeZoneOffset()); - if (StringUtils.isNotEmpty(gdpr)) { - uriBuilder.addParameter("gdpr", gdpr); - } - - final String consent = extractConsent(bidRequest.getUser()); - if (StringUtils.isNotEmpty(consent)) { - uriBuilder.addParameter("consentString", consent); - } + if (StringUtils.isNotEmpty(gdpr)) { + variables.set("gdpr", gdpr); + } - if (noCookies || extractNoCookies(bidRequest.getDevice())) { - uriBuilder.addParameter("noCookies", "true"); - } + final String consent = extractConsent(bidRequest.getUser()); + if (StringUtils.isNotEmpty(consent)) { + variables.set("consentString", consent); + } - return uriBuilder.build().toString(); - } catch (URISyntaxException | IllegalArgumentException e) { - throw new PreBidException(e.getMessage()); + if (noCookies || extractNoCookies(bidRequest.getDevice())) { + variables.set("noCookies", "true"); } + + return template.expandToString(variables); } private String getTimeZoneOffset() { diff --git a/src/main/java/org/prebid/server/bidder/amx/AmxBidder.java b/src/main/java/org/prebid/server/bidder/amx/AmxBidder.java index f9d309a3495..02a65ab6d8d 100644 --- a/src/main/java/org/prebid/server/bidder/amx/AmxBidder.java +++ b/src/main/java/org/prebid/server/bidder/amx/AmxBidder.java @@ -13,7 +13,6 @@ import com.iab.openrtb.response.SeatBid; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.http.client.utils.URIBuilder; import org.prebid.server.bidder.Bidder; import org.prebid.server.bidder.amx.model.AmxBidExt; import org.prebid.server.bidder.model.BidderBid; @@ -31,8 +30,8 @@ import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidMeta; import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; +import org.prebid.server.util.uritemplate.UriTemplateFactory; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -52,20 +51,13 @@ public class AmxBidder implements Bidder { private final JacksonMapper mapper; public AmxBidder(String endpointUrl, JacksonMapper mapper) { - this.mapper = Objects.requireNonNull(mapper); this.endpointUrl = resolveEndpointUrl(endpointUrl); + this.mapper = Objects.requireNonNull(mapper); } private static String resolveEndpointUrl(String url) { - final URIBuilder uriBuilder; - try { - uriBuilder = new URIBuilder(HttpUtil.validateUrl(Objects.requireNonNull(url))); - } catch (URISyntaxException e) { - throw new IllegalArgumentException("Invalid url: %s, error: %s".formatted(url, e.getMessage())); - } - return uriBuilder - .addParameter(VERSION_PARAM, ADAPTER_VERSION) - .toString(); + HttpUtil.validateUrl(Objects.requireNonNull(url)); + return UriTemplateFactory.dynamicParams(url).expandToString(VERSION_PARAM, ADAPTER_VERSION); } @Override diff --git a/src/main/java/org/prebid/server/bidder/appnexus/AppnexusBidder.java b/src/main/java/org/prebid/server/bidder/appnexus/AppnexusBidder.java index 06a37460655..72a2617cf43 100644 --- a/src/main/java/org/prebid/server/bidder/appnexus/AppnexusBidder.java +++ b/src/main/java/org/prebid/server/bidder/appnexus/AppnexusBidder.java @@ -19,7 +19,6 @@ import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.http.client.utils.URIBuilder; import org.prebid.server.auction.model.Endpoint; import org.prebid.server.bidder.Bidder; import org.prebid.server.bidder.appnexus.proto.AppnexusBidExt; @@ -53,10 +52,11 @@ import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; import org.prebid.server.util.ObjectUtil; +import org.prebid.server.util.uritemplate.UriTemplate; +import org.prebid.server.util.uritemplate.UriTemplateFactory; import jakarta.validation.ValidationException; import java.math.BigDecimal; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -83,7 +83,7 @@ public class AppnexusBidder implements Bidder { new TypeReference<>() { }; - private final String endpointUrl; + private final UriTemplate endpointTemplate; private final Integer headerBiddingSource; private final Map iabCategories; private final JacksonMapper mapper; @@ -93,7 +93,8 @@ public AppnexusBidder(String endpointUrl, Map iabCategories, JacksonMapper mapper) { - this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.endpointTemplate = UriTemplateFactory.declaredParams(endpointUrl); this.headerBiddingSource = ObjectUtils.defaultIfNull(platformId, DEFAULT_PLATFORM_ID); this.iabCategories = ObjectUtils.defaultIfNull(iabCategories, Collections.emptyMap()); this.mapper = Objects.requireNonNull(mapper); @@ -307,13 +308,7 @@ private String readKeywordsFromArray(JsonNode keywords) { } private String makeUrl(String member) { - try { - return member != null - ? new URIBuilder(endpointUrl).addParameter("member_id", member).build().toString() - : endpointUrl; - } catch (URISyntaxException e) { - throw new PreBidException(e.getMessage()); - } + return endpointTemplate.expandToString("member_id", member); } private static String extractEndpointName(BidRequest bidRequest) { diff --git a/src/main/java/org/prebid/server/bidder/bluesea/BlueSeaBidder.java b/src/main/java/org/prebid/server/bidder/bluesea/BlueSeaBidder.java index 8c93ba9f73d..e0bd35f55dc 100644 --- a/src/main/java/org/prebid/server/bidder/bluesea/BlueSeaBidder.java +++ b/src/main/java/org/prebid/server/bidder/bluesea/BlueSeaBidder.java @@ -9,7 +9,6 @@ import com.iab.openrtb.response.BidResponse; import com.iab.openrtb.response.SeatBid; import org.apache.commons.collections4.CollectionUtils; -import org.apache.http.client.utils.URIBuilder; import org.prebid.server.bidder.Bidder; import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderCall; @@ -24,6 +23,8 @@ import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; +import org.prebid.server.util.uritemplate.UriTemplate; +import org.prebid.server.util.uritemplate.UriTemplateFactory; import java.net.URISyntaxException; import java.util.ArrayList; @@ -39,11 +40,12 @@ public class BlueSeaBidder implements Bidder { new TypeReference<>() { }; - private final String endpointUrl; + private final UriTemplate endpointTemplate; private final JacksonMapper mapper; public BlueSeaBidder(String endpointUrl, JacksonMapper mapper) { - this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.endpointTemplate = UriTemplateFactory.declaredParams(endpointUrl); this.mapper = Objects.requireNonNull(mapper); } @@ -78,17 +80,9 @@ private HttpRequest makeRequest(BidRequest bidRequest, ExtImpBlueSea } private String resolveUrl(ExtImpBlueSea extImpBlueSea) { - final URIBuilder uriBuilder; - try { - uriBuilder = new URIBuilder(endpointUrl); - } catch (URISyntaxException e) { - throw new PreBidException("Invalid url: %s, error: %s".formatted(endpointUrl, e.getMessage())); - } - - return uriBuilder - .addParameter("pubid", extImpBlueSea.getPubId()) - .addParameter("token", extImpBlueSea.getToken()) - .toString(); + return endpointTemplate.expandToString( + "pubid", extImpBlueSea.getPubId(), + "token", extImpBlueSea.getToken()); } @Override diff --git a/src/main/java/org/prebid/server/bidder/connatix/ConnatixBidder.java b/src/main/java/org/prebid/server/bidder/connatix/ConnatixBidder.java index aef2abcaf61..a90e4d4ba22 100644 --- a/src/main/java/org/prebid/server/bidder/connatix/ConnatixBidder.java +++ b/src/main/java/org/prebid/server/bidder/connatix/ConnatixBidder.java @@ -7,9 +7,9 @@ import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Device; -import com.iab.openrtb.request.User; import com.iab.openrtb.request.Format; import com.iab.openrtb.request.Imp; +import com.iab.openrtb.request.User; import com.iab.openrtb.response.Bid; import com.iab.openrtb.response.BidResponse; import com.iab.openrtb.response.SeatBid; @@ -17,7 +17,6 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.http.client.utils.URIBuilder; import org.prebid.server.bidder.Bidder; import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderCall; @@ -35,9 +34,10 @@ import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; +import org.prebid.server.util.uritemplate.UriTemplate; +import org.prebid.server.util.uritemplate.UriTemplateFactory; import java.math.BigDecimal; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -53,9 +53,8 @@ public class ConnatixBidder implements Bidder { private static final String BIDDER_CURRENCY = "USD"; private static final String FORMATTING = "%s-%s"; - private static final String GPID_KEY = "gpid"; - private final String endpointUrl; + private final UriTemplate endpointTemplate; private final JacksonMapper mapper; private final CurrencyConversionService currencyConversionService; @@ -64,7 +63,8 @@ public ConnatixBidder(String endpointUrl, CurrencyConversionService currencyConversionService, JacksonMapper mapper) { - this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.endpointTemplate = UriTemplateFactory.declaredParams(endpointUrl); this.currencyConversionService = Objects.requireNonNull(currencyConversionService); this.mapper = Objects.requireNonNull(mapper); } @@ -106,20 +106,8 @@ public Result>> makeHttpRequests(BidRequest request } private String getOptimalEndpointUrl(BidRequest request) { - final Optional dataCenterCode = getUserId(request).map(ConnatixBidder::getDataCenterCode); - - if (dataCenterCode.isEmpty()) { - return endpointUrl; - } - - try { - return new URIBuilder(endpointUrl) - .addParameter("dc", dataCenterCode.get()) - .build() - .toString(); - } catch (URISyntaxException e) { - throw new PreBidException(e.getMessage()); - } + final String dataCenterCode = getUserId(request).map(ConnatixBidder::getDataCenterCode).orElse(null); + return endpointTemplate.expandToString("dc", dataCenterCode); } private static Optional getUserId(BidRequest request) { diff --git a/src/main/java/org/prebid/server/bidder/dxkulture/DxKultureBidder.java b/src/main/java/org/prebid/server/bidder/dxkulture/DxKultureBidder.java index ad3c146795d..fc12578007d 100644 --- a/src/main/java/org/prebid/server/bidder/dxkulture/DxKultureBidder.java +++ b/src/main/java/org/prebid/server/bidder/dxkulture/DxKultureBidder.java @@ -10,7 +10,6 @@ import com.iab.openrtb.response.SeatBid; import io.vertx.core.MultiMap; import org.apache.commons.collections4.CollectionUtils; -import org.apache.http.client.utils.URIBuilder; import org.prebid.server.bidder.Bidder; import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderCall; @@ -26,8 +25,9 @@ import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; import org.prebid.server.util.ObjectUtil; +import org.prebid.server.util.uritemplate.UriTemplate; +import org.prebid.server.util.uritemplate.UriTemplateFactory; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -41,11 +41,12 @@ public class DxKultureBidder implements Bidder { }; private static final String X_OPENRTB_VERSION = "2.5"; - private final String endpointUrl; + private final UriTemplate endpointTemplate; private final JacksonMapper mapper; public DxKultureBidder(String endpointUrl, JacksonMapper mapper) { - this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.endpointTemplate = UriTemplateFactory.declaredParams(endpointUrl); this.mapper = Objects.requireNonNull(mapper); } @@ -78,18 +79,9 @@ private ExtImpDxKulture parseImpExt(Imp imp) { } private String getUri(ExtImpDxKulture extImpDxKulture) { - final URIBuilder uriBuilder; - try { - uriBuilder = new URIBuilder(endpointUrl); - } catch (URISyntaxException e) { - throw new PreBidException("Invalid url: %s, error: %s".formatted(endpointUrl, e.getMessage())); - } - - uriBuilder - .addParameter("publisher_id", extImpDxKulture.getPublisherId()) - .addParameter("placement_id", extImpDxKulture.getPlacementId()); - - return uriBuilder.toString(); + return endpointTemplate.expandToString( + "publisher_id", extImpDxKulture.getPublisherId(), + "placement_id", extImpDxKulture.getPlacementId()); } private static MultiMap resolveHeaders(BidRequest bidRequest) { diff --git a/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java b/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java index 99beb0538bf..ec6d6da5459 100644 --- a/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java +++ b/src/main/java/org/prebid/server/bidder/eplanning/EplanningBidder.java @@ -15,10 +15,10 @@ import com.iab.openrtb.response.Bid; import io.vertx.core.MultiMap; import io.vertx.core.http.HttpMethod; +import io.vertx.uritemplate.Variables; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.http.client.utils.URIBuilder; import org.prebid.server.bidder.Bidder; import org.prebid.server.bidder.eplanning.model.CleanStepName; import org.prebid.server.bidder.eplanning.model.HbResponse; @@ -37,10 +37,11 @@ import org.prebid.server.proto.openrtb.ext.request.eplanning.ExtImpEplanning; import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.util.HttpUtil; +import org.prebid.server.util.uritemplate.UriTemplate; +import org.prebid.server.util.uritemplate.UriTemplateFactory; import java.math.BigDecimal; import java.net.MalformedURLException; -import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; @@ -79,11 +80,12 @@ public class EplanningBidder implements Bidder { new TypeReference<>() { }; - private final String endpointUrl; + private final UriTemplate endpointTemplate; private final JacksonMapper mapper; public EplanningBidder(String endpointUrl, JacksonMapper mapper) { - this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.endpointTemplate = UriTemplateFactory.declaredParams(endpointUrl); this.mapper = Objects.requireNonNull(mapper); } @@ -232,56 +234,51 @@ private String resolveRequestUri(BidRequest request, List requestsString ? app.getBundle() : pageDomain; - final String uri = "%s/%s/%s/%s/%s".formatted(endpointUrl, clientId, DFP_CLIENT_ID, requestTarget, SEC); - - final URIBuilder uriBuilder; - try { - uriBuilder = new URIBuilder(uri); - } catch (URISyntaxException e) { - throw new PreBidException("Invalid url: %s, error: %s".formatted(uri, e.getMessage())); - } - - uriBuilder - .addParameter("r", "pbs") - .addParameter("ncb", "1"); + final Variables variables = endpointTemplate.newVariables() + .set("clientId", clientId) + .set("dfpClientId", DFP_CLIENT_ID) + .set("requestTarget", requestTarget) + .set("sec", SEC) + .set("r", "pbs") + .set("ncb", "1") + .set("e", String.join("+", requestsStrings)); if (app == null) { - uriBuilder.addParameter("ur", pageUrl); + variables.set("ur", pageUrl); } - uriBuilder.addParameter("e", String.join("+", requestsStrings)); final User user = request.getUser(); final String buyeruid = user != null ? user.getBuyeruid() : null; if (StringUtils.isNotBlank(buyeruid)) { - uriBuilder.addParameter("uid", buyeruid); + variables.set("uid", buyeruid); } final Device device = request.getDevice(); final String ip = device != null ? device.getIp() : null; if (StringUtils.isNotBlank(ip)) { - uriBuilder.addParameter("ip", ip); + variables.set("ip", ip); } if (app != null) { if (StringUtils.isNotBlank(app.getName())) { - uriBuilder.addParameter("appn", app.getName()); + variables.set("appn", app.getName()); } if (StringUtils.isNotBlank(app.getId())) { - uriBuilder.addParameter("appid", app.getId()); + variables.set("appid", app.getId()); } if (request.getDevice() != null && StringUtils.isNotBlank(request.getDevice().getIfa())) { - uriBuilder.addParameter("ifa", request.getDevice().getIfa()); + variables.set("ifa", request.getDevice().getIfa()); } - uriBuilder.addParameter("app", REQUEST_TARGET_INVENTORY); + variables.set("app", REQUEST_TARGET_INVENTORY); } String schain = getSchainParameter(request.getSource()); if (schain != null) { schain = schain.replace(" ", "%20"); - uriBuilder.addParameter("sch", schain); + variables.set("sch", schain); } - return uriBuilder.toString(); + return endpointTemplate.expandToString(variables); } private static URL parseUrl(String url) { diff --git a/src/main/java/org/prebid/server/bidder/flipp/FlippBidder.java b/src/main/java/org/prebid/server/bidder/flipp/FlippBidder.java index dedd8399f1b..67090b4140a 100644 --- a/src/main/java/org/prebid/server/bidder/flipp/FlippBidder.java +++ b/src/main/java/org/prebid/server/bidder/flipp/FlippBidder.java @@ -16,8 +16,6 @@ import io.vertx.core.http.HttpMethod; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.http.NameValuePair; -import org.apache.http.client.utils.URLEncodedUtils; import org.prebid.server.bidder.Bidder; import org.prebid.server.bidder.flipp.model.request.CampaignRequestBody; import org.prebid.server.bidder.flipp.model.request.CampaignRequestBodyUser; @@ -47,7 +45,6 @@ import org.prebid.server.util.HttpUtil; import org.prebid.server.util.ObjectUtil; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -57,6 +54,8 @@ import java.util.Optional; import java.util.Set; import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class FlippBidder implements Bidder { @@ -72,6 +71,7 @@ public class FlippBidder implements Bidder { private static final String EXT_REQUEST_TRANSMIT_EIDS = "transmitEids"; private static final int DEFAULT_STANDARD_HEIGHT = 2400; private static final int DEFAULT_COMPACT_HEIGHT = 600; + private static final Pattern CONTENT_CODE_PATTERN = Pattern.compile("[?&]flipp-content-code=([^&]+)"); private final String endpointUrl; private final JacksonMapper mapper; @@ -167,13 +167,16 @@ private static String resolveContentCode(Site site, ExtImpFlipp extImp) { final String pageUrl = Optional.ofNullable(site) .map(Site::getPage) .orElse(null); + if (StringUtils.isBlank(pageUrl)) { + return null; + } - return URLEncodedUtils.parse(pageUrl, StandardCharsets.UTF_8) - .stream() - .filter(nameValuePair -> nameValuePair.getName().contains("flipp-content-code")) - .map(NameValuePair::getValue) - .findFirst() - .orElse(null); + final Matcher matcher = CONTENT_CODE_PATTERN.matcher(pageUrl); + if (!matcher.matches()) { + return null; + } + + return matcher.group(0); } private static List resolveKeywords(BidRequest bidRequest) { diff --git a/src/main/java/org/prebid/server/bidder/nexx360/Nexx360Bidder.java b/src/main/java/org/prebid/server/bidder/nexx360/Nexx360Bidder.java index b4b643cc3eb..d2167ef3ad4 100644 --- a/src/main/java/org/prebid/server/bidder/nexx360/Nexx360Bidder.java +++ b/src/main/java/org/prebid/server/bidder/nexx360/Nexx360Bidder.java @@ -7,9 +7,9 @@ import com.iab.openrtb.response.Bid; import com.iab.openrtb.response.BidResponse; import com.iab.openrtb.response.SeatBid; +import io.vertx.uritemplate.Variables; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.http.client.utils.URIBuilder; import org.prebid.server.bidder.Bidder; import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderCall; @@ -25,9 +25,10 @@ import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; +import org.prebid.server.util.uritemplate.UriTemplate; +import org.prebid.server.util.uritemplate.UriTemplateFactory; import org.prebid.server.version.PrebidVersionProvider; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -41,12 +42,13 @@ public class Nexx360Bidder implements Bidder { }; private static final String BIDDER_NAME = "nexx360"; - private final String endpointUrl; + private final UriTemplate endpointTemplate; private final JacksonMapper mapper; private final PrebidVersionProvider prebidVersionProvider; public Nexx360Bidder(String endpointUrl, JacksonMapper mapper, PrebidVersionProvider prebidVersionProvider) { - this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.endpointTemplate = UriTemplateFactory.declaredParams(endpointUrl); this.mapper = Objects.requireNonNull(mapper); this.prebidVersionProvider = Objects.requireNonNull(prebidVersionProvider); } @@ -100,21 +102,15 @@ private BidRequest makeRequest(BidRequest request, List imps) { } private String makeUrl(String tagId, String placement) { - final URIBuilder uriBuilder; - try { - uriBuilder = new URIBuilder(endpointUrl); - } catch (URISyntaxException e) { - throw new PreBidException("Invalid url: %s, error: %s".formatted(endpointUrl, e.getMessage())); - } - + final Variables variables = endpointTemplate.newVariables(); if (StringUtils.isNotBlank(placement)) { - uriBuilder.addParameter("placement", placement); + variables.set("placement", placement); } if (StringUtils.isNotBlank(tagId)) { - uriBuilder.addParameter("tag_id", tagId); + variables.set("tag_id", tagId); } - return uriBuilder.toString(); + return endpointTemplate.expandToString(variables); } @Override diff --git a/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java b/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java index 150c37fd255..22aed8b6659 100644 --- a/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java +++ b/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java @@ -9,8 +9,6 @@ import com.iab.openrtb.response.BidResponse; import com.iab.openrtb.response.SeatBid; import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.http.client.utils.URIBuilder; import org.prebid.server.bidder.Bidder; import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderCall; @@ -25,9 +23,9 @@ import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; +import org.prebid.server.util.uritemplate.UriTemplate; +import org.prebid.server.util.uritemplate.UriTemplateFactory; -import java.net.URI; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -41,13 +39,15 @@ public class SmartadserverBidder implements Bidder { new TypeReference<>() { }; - private final String endpointUrl; - private final String secondaryEndpointUrl; + private final UriTemplate endpointTemplate; + private final UriTemplate secondaryEndpointTemplate; private final JacksonMapper mapper; public SmartadserverBidder(String endpointUrl, String secondaryEndpointUrl, JacksonMapper mapper) { - this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); - this.secondaryEndpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(secondaryEndpointUrl)); + HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + HttpUtil.validateUrl(Objects.requireNonNull(secondaryEndpointUrl)); + this.endpointTemplate = UriTemplateFactory.dynamicParams(endpointUrl); + this.secondaryEndpointTemplate = UriTemplateFactory.dynamicParams(secondaryEndpointUrl); this.mapper = Objects.requireNonNull(mapper); } @@ -120,21 +120,8 @@ private static Publisher modifyPublisher(Publisher publisher, Integer networkId) } private String makeUrl(boolean isProgrammaticGuaranteed) { - final String url = isProgrammaticGuaranteed ? secondaryEndpointUrl : endpointUrl; - try { - final URI uri = new URI(url); - final String path = isProgrammaticGuaranteed ? "/ortb" : "/api/bid"; - final URIBuilder uriBuilder = new URIBuilder(uri) - .setPath(StringUtils.removeEnd(uri.getPath(), "/") + path); - - if (!isProgrammaticGuaranteed) { - uriBuilder.addParameter("callerId", "5"); - } - - return uriBuilder.toString(); - } catch (URISyntaxException e) { - throw new PreBidException("Malformed URL: %s.".formatted(url)); - } + final UriTemplate template = isProgrammaticGuaranteed ? secondaryEndpointTemplate : endpointTemplate; + return template.expandToString("callerId", !isProgrammaticGuaranteed ? "5" : null); } @Override diff --git a/src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java b/src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java index 42c12a48d1c..43b32876680 100644 --- a/src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java +++ b/src/main/java/org/prebid/server/bidder/sparteo/SparteoBidder.java @@ -12,6 +12,7 @@ import com.iab.openrtb.response.Bid; import com.iab.openrtb.response.BidResponse; import com.iab.openrtb.response.SeatBid; +import io.vertx.uritemplate.Variables; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.prebid.server.bidder.Bidder; @@ -31,9 +32,9 @@ import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; import org.prebid.server.util.BidderUtil; import org.prebid.server.util.HttpUtil; -import org.apache.http.client.utils.URIBuilder; +import org.prebid.server.util.uritemplate.UriTemplate; +import org.prebid.server.util.uritemplate.UriTemplateFactory; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -46,13 +47,15 @@ public class SparteoBidder implements Bidder { private static final String UNKNOWN_VALUE = "unknown"; private static final TypeReference> TYPE_REFERENCE = - new TypeReference<>() { }; + new TypeReference<>() { + }; - private final String endpointUrl; + private final UriTemplate endpointTemplate; private final JacksonMapper mapper; public SparteoBidder(String endpointUrl, JacksonMapper mapper) { - this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.endpointTemplate = UriTemplateFactory.declaredParams(endpointUrl); this.mapper = Objects.requireNonNull(mapper); } @@ -222,24 +225,21 @@ private String resolveBundle(App app) { } private String resolveEndpoint(String siteDomain, String appDomain, String networkId, String bundle) { - try { - final URIBuilder uriBuilder = new URIBuilder(endpointUrl); - if (StringUtils.isNotBlank(networkId)) { - uriBuilder.addParameter("network_id", networkId); - } - if (StringUtils.isNotBlank(siteDomain)) { - uriBuilder.addParameter("site_domain", siteDomain); - } - if (StringUtils.isNotBlank(appDomain)) { - uriBuilder.addParameter("app_domain", appDomain); - } - if (StringUtils.isNotBlank(bundle)) { - uriBuilder.addParameter("bundle", bundle); - } - return uriBuilder.build().toString(); - } catch (URISyntaxException e) { - throw new PreBidException("Failed to build endpoint URL", e); + final Variables variables = endpointTemplate.newVariables(); + if (StringUtils.isNotBlank(networkId)) { + variables.set("network_id", networkId); + } + if (StringUtils.isNotBlank(siteDomain)) { + variables.set("site_domain", siteDomain); + } + if (StringUtils.isNotBlank(appDomain)) { + variables.set("app_domain", appDomain); } + if (StringUtils.isNotBlank(bundle)) { + variables.set("bundle", bundle); + } + + return endpointTemplate.expandToString(variables); } @Override diff --git a/src/main/java/org/prebid/server/bidder/videobyte/VideobyteBidder.java b/src/main/java/org/prebid/server/bidder/videobyte/VideobyteBidder.java index cdbac176521..b33ed6a3dfc 100644 --- a/src/main/java/org/prebid/server/bidder/videobyte/VideobyteBidder.java +++ b/src/main/java/org/prebid/server/bidder/videobyte/VideobyteBidder.java @@ -8,9 +8,9 @@ import com.iab.openrtb.response.SeatBid; import io.vertx.core.MultiMap; import io.vertx.core.http.HttpMethod; +import io.vertx.uritemplate.Variables; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.http.client.utils.URIBuilder; import org.prebid.server.bidder.Bidder; import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.bidder.model.BidderCall; @@ -24,8 +24,9 @@ import org.prebid.server.proto.openrtb.ext.request.videobyte.ExtImpVideobyte; import org.prebid.server.proto.openrtb.ext.response.BidType; import org.prebid.server.util.HttpUtil; +import org.prebid.server.util.uritemplate.UriTemplate; +import org.prebid.server.util.uritemplate.UriTemplateFactory; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -39,11 +40,12 @@ public class VideobyteBidder implements Bidder { new TypeReference<>() { }; - private final String endpointUrl; + private final UriTemplate endpointTemplate; private final JacksonMapper mapper; public VideobyteBidder(String endpointUrl, JacksonMapper mapper) { - this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.endpointTemplate = UriTemplateFactory.declaredParams(endpointUrl); this.mapper = Objects.requireNonNull(mapper); } @@ -86,25 +88,18 @@ private HttpRequest createRequest(BidRequest bidRequest, Imp imp, Ex } private String createUri(ExtImpVideobyte extImpVideobyte) { - final URIBuilder uriBuilder; - try { - uriBuilder = new URIBuilder(endpointUrl); - } catch (URISyntaxException e) { - throw new PreBidException(e.getMessage()); - } - - uriBuilder.addParameter("source", "pbs") - .addParameter("pid", extImpVideobyte.getPublisherId()); + final Variables variables = endpointTemplate.newVariables(); + variables.set("pid", extImpVideobyte.getPublisherId()); - addUriParameterIfNotEmpty(uriBuilder, "placementId", extImpVideobyte.getPlacementId()); - addUriParameterIfNotEmpty(uriBuilder, "nid", extImpVideobyte.getNetworkId()); + addParameterIfNotEmpty(variables, "placementId", extImpVideobyte.getPlacementId()); + addParameterIfNotEmpty(variables, "nid", extImpVideobyte.getNetworkId()); - return uriBuilder.toString(); + return endpointTemplate.expandToString(variables); } - private static void addUriParameterIfNotEmpty(URIBuilder uriBuilder, String parameter, String value) { + private static void addParameterIfNotEmpty(Variables variables, String parameter, String value) { if (StringUtils.isNotEmpty(value)) { - uriBuilder.addParameter(parameter, value); + variables.set(parameter, value); } } diff --git a/src/main/java/org/prebid/server/cache/CoreCacheService.java b/src/main/java/org/prebid/server/cache/CoreCacheService.java index 6b028eb9ae8..e1e146a9a03 100644 --- a/src/main/java/org/prebid/server/cache/CoreCacheService.java +++ b/src/main/java/org/prebid/server/cache/CoreCacheService.java @@ -9,7 +9,6 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.http.client.utils.URIBuilder; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.BidInfo; import org.prebid.server.auction.model.CachedDebugLog; diff --git a/src/main/java/org/prebid/server/floors/PriceFloorFetcher.java b/src/main/java/org/prebid/server/floors/PriceFloorFetcher.java index b1cc8c257b2..4db7d31d0e7 100644 --- a/src/main/java/org/prebid/server/floors/PriceFloorFetcher.java +++ b/src/main/java/org/prebid/server/floors/PriceFloorFetcher.java @@ -2,6 +2,7 @@ import com.github.benmanes.caffeine.cache.Caffeine; import io.netty.channel.ConnectTimeoutException; +import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.Future; import io.vertx.core.Vertx; import io.vertx.core.http.HttpHeaders; @@ -11,7 +12,6 @@ import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; -import org.apache.http.HttpStatus; import org.prebid.server.exception.PreBidException; import org.prebid.server.execution.timeout.TimeoutFactory; import org.prebid.server.floors.model.PriceFloorData; @@ -165,7 +165,7 @@ private ResponseCacheInfo parseFloorResponse(HttpClientResponse httpClientRespon AccountPriceFloorsFetchConfig fetchConfig) { final int statusCode = httpClientResponse.getStatusCode(); - if (statusCode != HttpStatus.SC_OK) { + if (statusCode != HttpResponseStatus.OK.code()) { throw new PreBidException("Failed to request, provider respond with status %s".formatted(statusCode)); } final String body = httpClientResponse.getBody(); diff --git a/src/main/java/org/prebid/server/handler/OptoutHandler.java b/src/main/java/org/prebid/server/handler/OptoutHandler.java index 5d9885c70ec..6011971649b 100644 --- a/src/main/java/org/prebid/server/handler/OptoutHandler.java +++ b/src/main/java/org/prebid/server/handler/OptoutHandler.java @@ -17,8 +17,6 @@ import org.prebid.server.vertx.verticles.server.HttpEndpoint; import org.prebid.server.vertx.verticles.server.application.ApplicationResource; -import java.net.MalformedURLException; -import java.net.URL; import java.util.List; import java.util.Objects; @@ -121,9 +119,8 @@ private static String getRequestParam(RoutingContext routingContext, String para public static String getOptoutRedirectUrl(String externalUrl) { try { - final URL url = new URL(externalUrl); - return new URL(url.toExternalForm() + "/static/optout.html").toString(); - } catch (MalformedURLException e) { + return HttpUtil.validateUrl(externalUrl + "/static/optout.html"); + } catch (IllegalArgumentException e) { throw new IllegalArgumentException("Could not get optout redirect url", e); } } diff --git a/src/main/java/org/prebid/server/settings/HttpApplicationSettings.java b/src/main/java/org/prebid/server/settings/HttpApplicationSettings.java index c0d899508c4..a74d9b2b35a 100644 --- a/src/main/java/org/prebid/server/settings/HttpApplicationSettings.java +++ b/src/main/java/org/prebid/server/settings/HttpApplicationSettings.java @@ -8,7 +8,6 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.http.client.utils.URIBuilder; import org.prebid.server.exception.PreBidException; import org.prebid.server.execution.timeout.Timeout; import org.prebid.server.json.DecodeException; @@ -95,10 +94,10 @@ public HttpApplicationSettings(boolean isRfc3986Compatible, JacksonMapper mapper) { this.isRfc3986Compatible = isRfc3986Compatible; - this.endpoint = HttpUtil.validateUrlSyntax(Objects.requireNonNull(endpoint)); - this.ampEndpoint = HttpUtil.validateUrlSyntax(Objects.requireNonNull(ampEndpoint)); - this.videoEndpoint = HttpUtil.validateUrlSyntax(Objects.requireNonNull(videoEndpoint)); - this.categoryEndpoint = HttpUtil.validateUrlSyntax(Objects.requireNonNull(categoryEndpoint)); + this.endpoint = HttpUtil.validateUrl(Objects.requireNonNull(endpoint)); + this.ampEndpoint = HttpUtil.validateUrl(Objects.requireNonNull(ampEndpoint)); + this.videoEndpoint = HttpUtil.validateUrl(Objects.requireNonNull(videoEndpoint)); + this.categoryEndpoint = HttpUtil.validateUrl(Objects.requireNonNull(categoryEndpoint)); this.httpClient = Objects.requireNonNull(httpClient); this.mapper = Objects.requireNonNull(mapper); } diff --git a/src/main/java/org/prebid/server/util/HttpUtil.java b/src/main/java/org/prebid/server/util/HttpUtil.java index e08a276c6fa..617dabbd3b3 100644 --- a/src/main/java/org/prebid/server/util/HttpUtil.java +++ b/src/main/java/org/prebid/server/util/HttpUtil.java @@ -8,7 +8,6 @@ import io.vertx.core.http.HttpServerResponse; import io.vertx.ext.web.RoutingContext; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.validator.routines.UrlValidator; import org.prebid.server.log.ConditionalLogger; import org.prebid.server.log.Logger; import org.prebid.server.log.LoggerFactory; @@ -16,6 +15,8 @@ import org.prebid.server.model.HttpRequestContext; import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import java.net.URLDecoder; import java.net.URLEncoder; @@ -28,9 +29,6 @@ import java.util.function.Consumer; import java.util.stream.Collectors; -/** - * This class consists of {@code static} utility methods for operating HTTP requests. - */ public final class HttpUtil { private static final Logger logger = LoggerFactory.getLogger(HttpUtil.class); @@ -85,52 +83,30 @@ public final class HttpUtil { public static final String MACROS_OPEN = "{{"; public static final String MACROS_CLOSE = "}}"; - private static final UrlValidator URL_VALIDAROR = UrlValidator.getInstance(); - private HttpUtil() { } - /** - * Checks the input string for using as URL. - */ - @Deprecated - public static String validateUrl(String url) { - if (containsMacrosses(url)) { - return url; - } - + public static URL parseUrl(String url) { try { - return new URL(url).toString(); - } catch (MalformedURLException e) { + return new URI(url).toURL(); + } catch (URISyntaxException | MalformedURLException e) { throw new IllegalArgumentException("URL supplied is not valid: " + url, e); } } - public static String validateUrlSyntax(String url) { - if (containsMacrosses(url) || URL_VALIDAROR.isValid(url)) { - return url; - } - - throw new IllegalArgumentException("URL supplied is not valid: " + url); + public static String validateUrl(String url) { + // TODO: check new macro + return !containsMacrosses(url) ? parseUrl(url).toString() : url; } - // TODO: We need our own way to work with url macrosses private static boolean containsMacrosses(String url) { return StringUtils.contains(url, MACROS_OPEN) && StringUtils.contains(url, MACROS_CLOSE); } - /** - * Returns encoded URL for the given value. - *

- * The result can be safety used as the query string. - */ public static String encodeUrl(String value) { return URLEncoder.encode(value, StandardCharsets.UTF_8); } - /** - * Returns decoded value if supplied is not null, otherwise returns null. - */ public static String decodeUrl(String value) { if (StringUtils.isBlank(value)) { return null; @@ -138,18 +114,12 @@ public static String decodeUrl(String value) { return URLDecoder.decode(value, StandardCharsets.UTF_8); } - /** - * Creates general headers for request. - */ public static MultiMap headers() { return MultiMap.caseInsensitiveMultiMap() .add(CONTENT_TYPE_HEADER, APPLICATION_JSON_CONTENT_TYPE) .add(ACCEPT_HEADER, HttpHeaderValues.APPLICATION_JSON); } - /** - * Creates header from name and value, when value is not null or empty string. - */ public static void addHeaderIfValueIsNotEmpty(MultiMap headers, CharSequence headerName, CharSequence headerValue) { if (StringUtils.isNotEmpty(headerValue)) { headers.add(headerName, headerValue); @@ -160,9 +130,10 @@ public static String getHostFromUrl(String url) { if (StringUtils.isBlank(url)) { return null; } + try { - return new URL(url).getHost(); - } catch (MalformedURLException e) { + return parseUrl(url).getHost(); + } catch (IllegalArgumentException e) { return null; } } diff --git a/src/main/java/org/prebid/server/util/uritemplate/DeclaredParamsUriTemplate.java b/src/main/java/org/prebid/server/util/uritemplate/DeclaredParamsUriTemplate.java new file mode 100644 index 00000000000..1d2b8ea15f1 --- /dev/null +++ b/src/main/java/org/prebid/server/util/uritemplate/DeclaredParamsUriTemplate.java @@ -0,0 +1,36 @@ +package org.prebid.server.util.uritemplate; + +import io.vertx.uritemplate.ExpandOptions; +import io.vertx.uritemplate.Variables; + +class DeclaredParamsUriTemplate implements UriTemplate { + + private static final ExpandOptions DEFAULT_OPTIONS = new ExpandOptions().setAllowVariableMiss(true); + + private final io.vertx.uritemplate.UriTemplate internal; + private final ExpandOptions defaultOptions; + + DeclaredParamsUriTemplate(String uri) { + this(uri, DEFAULT_OPTIONS); + } + + DeclaredParamsUriTemplate(String uri, ExpandOptions defaultOptions) { + this.internal = io.vertx.uritemplate.UriTemplate.of(uri); + this.defaultOptions = defaultOptions; + } + + @Override + public Variables newVariables() { + return Variables.variables(); + } + + @Override + public String expandToString(Variables variables) { + return expandToString(variables, defaultOptions); + } + + @Override + public String expandToString(Variables variables, ExpandOptions expandOptions) { + return internal.expandToString(variables, expandOptions); + } +} diff --git a/src/main/java/org/prebid/server/util/uritemplate/DynamicParamsUriTemplate.java b/src/main/java/org/prebid/server/util/uritemplate/DynamicParamsUriTemplate.java new file mode 100644 index 00000000000..b0e1f684253 --- /dev/null +++ b/src/main/java/org/prebid/server/util/uritemplate/DynamicParamsUriTemplate.java @@ -0,0 +1,67 @@ +package org.prebid.server.util.uritemplate; + +import io.vertx.core.json.JsonObject; +import io.vertx.uritemplate.ExpandOptions; +import io.vertx.uritemplate.Variables; +import io.vertx.uritemplate.impl.VariablesImpl; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class DynamicParamsUriTemplate extends DeclaredParamsUriTemplate implements UriTemplate { + + private static final ExpandOptions DEFAULT_OPTIONS = new ExpandOptions().setAllowVariableMiss(false); + private static final String DYNAMIC_QUERY_PARAM = "{?DYNAMIC_QUERY_PARAM*}"; + + + DynamicParamsUriTemplate(String uri) { + super(uri + DYNAMIC_QUERY_PARAM, DEFAULT_OPTIONS); + } + + @Override + public Variables newVariables() { + return new VariablesWithDynamicQueryParams(); + } + + private static class VariablesWithDynamicQueryParams extends VariablesImpl { + + private VariablesWithDynamicQueryParams() { + init(); + } + + private void init() { + super.set(DYNAMIC_QUERY_PARAM, new HashMap<>()); + } + + @Override + public Variables set(String name, String value) { + if (value != null) { + getMap(DYNAMIC_QUERY_PARAM).put(name, value); + } + return this; + } + + @Override + public Variables set(String name, List value) { + throw new UnsupportedOperationException(); + } + + @Override + public Variables set(String name, Map value) { + throw new UnsupportedOperationException(); + } + + @Override + public Variables addAll(JsonObject json) { + throw new UnsupportedOperationException(); + } + + @Override + public Variables clear() { + super.clear(); + init(); + return this; + } + } +} diff --git a/src/main/java/org/prebid/server/util/uritemplate/UriTemplate.java b/src/main/java/org/prebid/server/util/uritemplate/UriTemplate.java new file mode 100644 index 00000000000..914e2978c82 --- /dev/null +++ b/src/main/java/org/prebid/server/util/uritemplate/UriTemplate.java @@ -0,0 +1,30 @@ +package org.prebid.server.util.uritemplate; + +import io.vertx.uritemplate.Variables; + +public interface UriTemplate extends io.vertx.uritemplate.UriTemplate { + + Variables newVariables(); + + default String expandToString(String key, String value) { + return expandToString(newVariables().set(key, value)); + } + + default String expandToString(String key1, String value1, + String key2, String value2) { + + return expandToString(newVariables() + .set(key1, value1) + .set(key2, value2)); + } + + default String expandToString(String key1, String value1, + String key2, String value2, + String key3, String value3) { + + return expandToString(newVariables() + .set(key1, value1) + .set(key2, value2) + .set(key3, value3)); + } +} diff --git a/src/main/java/org/prebid/server/util/uritemplate/UriTemplateFactory.java b/src/main/java/org/prebid/server/util/uritemplate/UriTemplateFactory.java new file mode 100644 index 00000000000..0ace00d79a9 --- /dev/null +++ b/src/main/java/org/prebid/server/util/uritemplate/UriTemplateFactory.java @@ -0,0 +1,12 @@ +package org.prebid.server.util.uritemplate; + +public interface UriTemplateFactory { + + static UriTemplate declaredParams(String uri) { + return new DeclaredParamsUriTemplate(uri); + } + + static UriTemplate dynamicParams(String uri) { + return new DynamicParamsUriTemplate(uri); + } +} diff --git a/src/main/resources/bidder-config/appnexus.yaml b/src/main/resources/bidder-config/appnexus.yaml index 6928936bc5f..f815ccea8be 100644 --- a/src/main/resources/bidder-config/appnexus.yaml +++ b/src/main/resources/bidder-config/appnexus.yaml @@ -1,6 +1,6 @@ adapters: appnexus: - endpoint: http://ib.adnxs.com/openrtb2 + endpoint: http://ib.adnxs.com/openrtb2{?member_id} aliases: mediafuse: meta-info: diff --git a/src/main/resources/bidder-config/bluesea.yaml b/src/main/resources/bidder-config/bluesea.yaml index 23f6a7a702a..ef336ab244b 100644 --- a/src/main/resources/bidder-config/bluesea.yaml +++ b/src/main/resources/bidder-config/bluesea.yaml @@ -1,6 +1,6 @@ adapters: bluesea: - endpoint: https://bid.bluevoox.com/rtb/prebid + endpoint: https://bid.bluevoox.com/rtb/prebid{?pubid,token} endpoint-compression: gzip modifying-vast-xml-allowed: true meta-info: diff --git a/src/main/resources/bidder-config/connatix.yaml b/src/main/resources/bidder-config/connatix.yaml index 63e1aca65c1..1178ae81ee3 100644 --- a/src/main/resources/bidder-config/connatix.yaml +++ b/src/main/resources/bidder-config/connatix.yaml @@ -1,6 +1,6 @@ adapters: connatix: - endpoint: "https://capi.connatix.com/rtb/ortb" + endpoint: "https://capi.connatix.com/rtb/ortb{?dc}" endpoint-compression: gzip meta-info: maintainer-email: "pubsolutions@connatix.com" diff --git a/src/main/resources/bidder-config/dxkulture.yaml b/src/main/resources/bidder-config/dxkulture.yaml index 739b2ba00af..4dcc9e833f3 100644 --- a/src/main/resources/bidder-config/dxkulture.yaml +++ b/src/main/resources/bidder-config/dxkulture.yaml @@ -1,6 +1,6 @@ adapters: dxkulture: - endpoint: https://ads.dxkulture.com/pbs + endpoint: https://ads.dxkulture.com/pbs{?publisher_id,placement_id} meta-info: maintainer-email: devops@dxkulture.com app-media-types: diff --git a/src/main/resources/bidder-config/eplanning.yaml b/src/main/resources/bidder-config/eplanning.yaml index db89054080a..8811acd68a5 100644 --- a/src/main/resources/bidder-config/eplanning.yaml +++ b/src/main/resources/bidder-config/eplanning.yaml @@ -1,6 +1,6 @@ adapters: eplanning: - endpoint: http://rtb.e-planning.net/pbs/1 + endpoint: http://rtb.e-planning.net/pbs/1{/clientId,dfpClientId,requestTarget,sec}{?r,ncb,ur,e,uid,ip,appn,appid,ifa,app,sch} meta-info: maintainer-email: producto@e-planning.net app-media-types: diff --git a/src/main/resources/bidder-config/nexx360.yaml b/src/main/resources/bidder-config/nexx360.yaml index 7f3820e24d1..3deaee96d19 100644 --- a/src/main/resources/bidder-config/nexx360.yaml +++ b/src/main/resources/bidder-config/nexx360.yaml @@ -1,6 +1,6 @@ adapters: nexx360: - endpoint: http://fast.nexx360.io/prebid-server + endpoint: http://fast.nexx360.io/prebid-server{?placement,tag_id} endpoint-compression: gzip aliases: 1accord: ~ diff --git a/src/main/resources/bidder-config/smartadserver.yaml b/src/main/resources/bidder-config/smartadserver.yaml index 343bec392de..906e673d963 100644 --- a/src/main/resources/bidder-config/smartadserver.yaml +++ b/src/main/resources/bidder-config/smartadserver.yaml @@ -1,7 +1,7 @@ adapters: smartadserver: - endpoint: https://ssb-global.smartadserver.com - secondary-endpoint: https://prebid-global.smartadserver.com + endpoint: https://ssb-global.smartadserver.com/api/bid + secondary-endpoint: https://prebid-global.smartadserver.com/ortb endpoint-compression: gzip aliases: equativ: diff --git a/src/main/resources/bidder-config/sparteo.yaml b/src/main/resources/bidder-config/sparteo.yaml index 5dd9dd19b1d..cd91cf0f196 100644 --- a/src/main/resources/bidder-config/sparteo.yaml +++ b/src/main/resources/bidder-config/sparteo.yaml @@ -1,6 +1,6 @@ adapters: sparteo: - endpoint: https://bid.sparteo.com/s2s-auction + endpoint: https://bid.sparteo.com/s2s-auction{?network_id,site_domain,app_domain,bundle} meta-info: maintainer-email: prebid@sparteo.com app-media-types: diff --git a/src/main/resources/bidder-config/videobyte.yaml b/src/main/resources/bidder-config/videobyte.yaml index 9d4223748fa..0691b27a57c 100644 --- a/src/main/resources/bidder-config/videobyte.yaml +++ b/src/main/resources/bidder-config/videobyte.yaml @@ -1,6 +1,6 @@ adapters: videobyte: - endpoint: https://x.videobyte.com/ortbhb + endpoint: https://x.videobyte.com/ortbhb?source=pbs&pid={pid}{&placementId,nid} meta-info: maintainer-email: prebid@videobyte.com app-media-types: