Skip to content

Commit 756fd50

Browse files
committed
RFC 3986 compatibility as optional for HttpApplicationSettings
1 parent 67042e5 commit 756fd50

4 files changed

Lines changed: 148 additions & 49 deletions

File tree

docs/config-app.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ For HTTP data source available next options:
346346
- `settings.http.amp-endpoint` - the url to fetch AMP stored requests.
347347
- `settings.http.video-endpoint` - the url to fetch video stored requests.
348348
- `settings.http.category-endpoint` - the url to fetch categories for long form video.
349+
- `settings.http.rfc3986-compatible` - if equals to `true` the url will be build according to RFC 3986, `false` by default
349350

350351
For account processing rules available next options:
351352
- `settings.enforce-valid-account` - if equals to `true` then request without account id will be rejected with 401.

src/main/java/org/prebid/server/settings/HttpApplicationSettings.java

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.apache.commons.collections4.CollectionUtils;
99
import org.apache.commons.collections4.MapUtils;
1010
import org.apache.commons.lang3.StringUtils;
11+
import org.apache.http.client.utils.URIBuilder;
1112
import org.prebid.server.exception.PreBidException;
1213
import org.prebid.server.execution.timeout.Timeout;
1314
import org.prebid.server.json.DecodeException;
@@ -25,6 +26,7 @@
2526
import org.prebid.server.vertx.httpclient.HttpClient;
2627
import org.prebid.server.vertx.httpclient.model.HttpClientResponse;
2728

29+
import java.net.URISyntaxException;
2830
import java.util.ArrayList;
2931
import java.util.Collections;
3032
import java.util.HashMap;
@@ -44,10 +46,14 @@
4446
* In order to enable caching and reduce latency for read operations {@link HttpApplicationSettings}
4547
* can be decorated by {@link CachingApplicationSettings}.
4648
* <p>
47-
* Expected the endpoint to satisfy the following API:
49+
* Expected the endpoint to satisfy the following API (URL is encoded):
4850
* <p>
4951
* GET {endpoint}?request-ids=["req1","req2"]&imp-ids=["imp1","imp2","imp3"]
5052
* <p>
53+
* or settings.http.rfc3986-compatible is set to true
54+
* <p>
55+
* * GET {endpoint}?request-id=req1&request-id=req2&imp-id=imp1&imp-id=imp2&imp-id=imp3
56+
* * <p>
5157
* This endpoint should return a payload like:
5258
* <pre>
5359
* {
@@ -76,15 +82,23 @@ public class HttpApplicationSettings implements ApplicationSettings {
7682
private final String categoryEndpoint;
7783
private final HttpClient httpClient;
7884
private final JacksonMapper mapper;
85+
private final boolean isRfc3986Compatible;
86+
87+
public HttpApplicationSettings(HttpClient httpClient,
88+
JacksonMapper mapper,
89+
String endpoint,
90+
String ampEndpoint,
91+
String videoEndpoint,
92+
String categoryEndpoint,
93+
boolean isRfc3986Compatible) {
7994

80-
public HttpApplicationSettings(HttpClient httpClient, JacksonMapper mapper, String endpoint, String ampEndpoint,
81-
String videoEndpoint, String categoryEndpoint) {
8295
this.httpClient = Objects.requireNonNull(httpClient);
8396
this.mapper = Objects.requireNonNull(mapper);
8497
this.endpoint = HttpUtil.validateUrl(Objects.requireNonNull(endpoint));
8598
this.ampEndpoint = HttpUtil.validateUrl(Objects.requireNonNull(ampEndpoint));
8699
this.videoEndpoint = HttpUtil.validateUrl(Objects.requireNonNull(videoEndpoint));
87100
this.categoryEndpoint = HttpUtil.validateUrl(Objects.requireNonNull(categoryEndpoint));
101+
this.isRfc3986Compatible = isRfc3986Compatible;
88102
}
89103

90104
@Override
@@ -111,15 +125,20 @@ private Future<Set<Account>> fetchAccountsByIds(Set<String> accountIds, Timeout
111125
.recover(Future::failedFuture);
112126
}
113127

114-
private static String accountsRequestUrlFrom(String endpoint, Set<String> accountIds) {
115-
final StringBuilder url = new StringBuilder(endpoint);
116-
url.append(endpoint.contains("?") ? "&" : "?");
117-
118-
if (!accountIds.isEmpty()) {
119-
url.append("account-ids=[\"").append(joinIds(accountIds)).append("\"]");
128+
private String accountsRequestUrlFrom(String endpoint, Set<String> accountIds) {
129+
try {
130+
final URIBuilder uriBuilder = new URIBuilder(endpoint);
131+
if (!accountIds.isEmpty()) {
132+
if (isRfc3986Compatible) {
133+
accountIds.forEach(accountId -> uriBuilder.addParameter("account-id", accountId));
134+
} else {
135+
uriBuilder.addParameter("account-ids", "[\"%s\"]".formatted(joinIds(accountIds)));
136+
}
137+
}
138+
return uriBuilder.build().toString();
139+
} catch (URISyntaxException e) {
140+
throw new PreBidException("URL %s has bad syntax".formatted(endpoint));
120141
}
121-
122-
return url.toString();
123142
}
124143

125144
private Future<Set<Account>> processAccountsResponse(HttpClientResponse response, Set<String> accountIds) {
@@ -165,9 +184,6 @@ public Future<StoredDataResult> getAmpStoredData(String accountId, Set<String> r
165184
return fetchStoredData(ampEndpoint, requestIds, Collections.emptySet(), timeout);
166185
}
167186

168-
/**
169-
* Not supported and returns failed result.
170-
*/
171187
@Override
172188
public Future<StoredDataResult> getVideoStoredData(String accountId, Set<String> requestIds, Set<String> impIds,
173189
Timeout timeout) {
@@ -240,22 +256,27 @@ private Future<StoredDataResult> fetchStoredData(String endpoint, Set<String> re
240256
.recover(exception -> failStoredDataResponse(exception, requestIds, impIds));
241257
}
242258

243-
private static String storeRequestUrlFrom(String endpoint, Set<String> requestIds, Set<String> impIds) {
244-
final StringBuilder url = new StringBuilder(endpoint);
245-
url.append(endpoint.contains("?") ? "&" : "?");
246-
247-
if (!requestIds.isEmpty()) {
248-
url.append("request-ids=[\"").append(joinIds(requestIds)).append("\"]");
249-
}
250-
251-
if (!impIds.isEmpty()) {
259+
private String storeRequestUrlFrom(String endpoint, Set<String> requestIds, Set<String> impIds) {
260+
try {
261+
final URIBuilder uriBuilder = new URIBuilder(endpoint);
252262
if (!requestIds.isEmpty()) {
253-
url.append("&");
263+
if (isRfc3986Compatible) {
264+
requestIds.forEach(requestId -> uriBuilder.addParameter("request-id", requestId));
265+
} else {
266+
uriBuilder.addParameter("request-ids", "[\"%s\"]".formatted(joinIds(requestIds)));
267+
}
268+
}
269+
if (!impIds.isEmpty()) {
270+
if (isRfc3986Compatible) {
271+
impIds.forEach(impId -> uriBuilder.addParameter("imp-id", impId));
272+
} else {
273+
uriBuilder.addParameter("imp-ids", "[\"%s\"]".formatted(joinIds(impIds)));
274+
}
254275
}
255-
url.append("imp-ids=[\"").append(joinIds(impIds)).append("\"]");
276+
return uriBuilder.build().toString();
277+
} catch (URISyntaxException e) {
278+
throw new PreBidException("URL %s has bad syntax".formatted(endpoint));
256279
}
257-
258-
return url.toString();
259280
}
260281

261282
private static String joinIds(Set<String> ids) {

src/main/java/org/prebid/server/spring/config/SettingsConfiguration.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,17 @@ HttpApplicationSettings httpApplicationSettings(
122122
@Value("${settings.http.endpoint}") String endpoint,
123123
@Value("${settings.http.amp-endpoint}") String ampEndpoint,
124124
@Value("${settings.http.video-endpoint}") String videoEndpoint,
125-
@Value("${settings.http.category-endpoint}") String categoryEndpoint) {
125+
@Value("${settings.http.category-endpoint}") String categoryEndpoint,
126+
@Value("${settings.http.rfc3986-compatible:false}") boolean isRfc3986Compatible) {
126127

127-
return new HttpApplicationSettings(httpClient, mapper, endpoint, ampEndpoint, videoEndpoint,
128-
categoryEndpoint);
128+
return new HttpApplicationSettings(
129+
httpClient,
130+
mapper,
131+
endpoint,
132+
ampEndpoint,
133+
videoEndpoint,
134+
categoryEndpoint,
135+
isRfc3986Compatible);
129136
}
130137
}
131138

0 commit comments

Comments
 (0)