Skip to content

Commit 7a3fc81

Browse files
authored
Port Kueez: New Adapter (#3930)
1 parent 7037dba commit 7a3fc81

File tree

13 files changed

+620
-0
lines changed

13 files changed

+620
-0
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package org.prebid.server.bidder.kueezrtb;
2+
3+
import com.fasterxml.jackson.core.type.TypeReference;
4+
import com.iab.openrtb.request.BidRequest;
5+
import com.iab.openrtb.request.Imp;
6+
import com.iab.openrtb.response.Bid;
7+
import com.iab.openrtb.response.BidResponse;
8+
import com.iab.openrtb.response.SeatBid;
9+
import org.apache.commons.lang3.StringUtils;
10+
import org.prebid.server.bidder.Bidder;
11+
import org.prebid.server.bidder.model.BidderBid;
12+
import org.prebid.server.bidder.model.BidderCall;
13+
import org.prebid.server.bidder.model.BidderError;
14+
import org.prebid.server.bidder.model.HttpRequest;
15+
import org.prebid.server.bidder.model.Result;
16+
import org.prebid.server.exception.PreBidException;
17+
import org.prebid.server.json.DecodeException;
18+
import org.prebid.server.json.JacksonMapper;
19+
import org.prebid.server.proto.openrtb.ext.ExtPrebid;
20+
import org.prebid.server.proto.openrtb.ext.request.kueezrtb.KueezRtbImpExt;
21+
import org.prebid.server.proto.openrtb.ext.response.BidType;
22+
import org.prebid.server.util.BidderUtil;
23+
import org.prebid.server.util.HttpUtil;
24+
import org.springframework.util.CollectionUtils;
25+
26+
import java.util.ArrayList;
27+
import java.util.Collection;
28+
import java.util.Collections;
29+
import java.util.List;
30+
import java.util.Objects;
31+
32+
public class KueezRtbBidder implements Bidder<BidRequest> {
33+
34+
private static final TypeReference<ExtPrebid<?, KueezRtbImpExt>> TYPE_REFERENCE = new TypeReference<>() { };
35+
36+
private final String endpointUrl;
37+
private final JacksonMapper mapper;
38+
39+
public KueezRtbBidder(String endpointUrl, JacksonMapper mapper) {
40+
this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl));
41+
this.mapper = Objects.requireNonNull(mapper);
42+
}
43+
44+
@Override
45+
public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest bidRequest) {
46+
final List<HttpRequest<BidRequest>> requests = new ArrayList<>();
47+
final List<BidderError> errors = new ArrayList<>();
48+
49+
for (Imp imp : bidRequest.getImp()) {
50+
try {
51+
final KueezRtbImpExt impExt = parseImpExt(imp);
52+
requests.add(makeHttpRequest(bidRequest, imp, impExt));
53+
} catch (PreBidException e) {
54+
errors.add(BidderError.badInput(e.getMessage()));
55+
}
56+
}
57+
return Result.of(requests, errors);
58+
}
59+
60+
private KueezRtbImpExt parseImpExt(Imp imp) throws PreBidException {
61+
try {
62+
return mapper.mapper().convertValue(imp.getExt(), TYPE_REFERENCE).getBidder();
63+
} catch (IllegalArgumentException e) {
64+
throw new PreBidException(e.getMessage());
65+
}
66+
}
67+
68+
private HttpRequest<BidRequest> makeHttpRequest(BidRequest bidRequest, Imp imp, KueezRtbImpExt impExt) {
69+
final BidRequest modifiedBidRequest = bidRequest.toBuilder().imp(Collections.singletonList(imp)).build();
70+
final String uri = endpointUrl + HttpUtil.encodeUrl(StringUtils.defaultString(impExt.getConnectionId()).trim());
71+
72+
return BidderUtil.defaultRequest(modifiedBidRequest, uri, mapper);
73+
}
74+
75+
@Override
76+
public final Result<List<BidderBid>> makeBids(BidderCall<BidRequest> httpCall, BidRequest bidRequest) {
77+
final List<BidderError> errors = new ArrayList<>();
78+
try {
79+
final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class);
80+
return Result.of(extractBids(bidResponse, errors), errors);
81+
} catch (DecodeException | PreBidException e) {
82+
return Result.withError(BidderError.badServerResponse(e.getMessage()));
83+
}
84+
}
85+
86+
private static List<BidderBid> extractBids(BidResponse bidResponse, List<BidderError> errors) {
87+
if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) {
88+
return Collections.emptyList();
89+
}
90+
return bidResponse.getSeatbid().stream()
91+
.filter(Objects::nonNull)
92+
.map(SeatBid::getBid)
93+
.filter(Objects::nonNull)
94+
.flatMap(Collection::stream)
95+
.filter(Objects::nonNull)
96+
.map(bid -> makeBid(bid, bidResponse.getCur(), errors))
97+
.filter(Objects::nonNull)
98+
.toList();
99+
}
100+
101+
private static BidderBid makeBid(Bid bid, String currency, List<BidderError> errors) {
102+
try {
103+
final BidType mediaType = getMediaTypeForBid(bid);
104+
return BidderBid.of(bid, mediaType, currency);
105+
} catch (PreBidException e) {
106+
errors.add(BidderError.badServerResponse(e.getMessage()));
107+
return null;
108+
}
109+
}
110+
111+
private static BidType getMediaTypeForBid(Bid bid) {
112+
final Integer mType = bid.getMtype();
113+
return switch (mType) {
114+
case 1 -> BidType.banner;
115+
case 2 -> BidType.video;
116+
case null, default -> throw new PreBidException("Could not define bid type for imp: " + bid.getImpid());
117+
};
118+
}
119+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.prebid.server.proto.openrtb.ext.request.kueezrtb;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import lombok.Value;
5+
6+
@Value(staticConstructor = "of")
7+
public class KueezRtbImpExt {
8+
9+
@JsonProperty("cId")
10+
String connectionId;
11+
12+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package org.prebid.server.spring.config.bidder;
2+
3+
import org.prebid.server.bidder.BidderDeps;
4+
import org.prebid.server.bidder.kueezrtb.KueezRtbBidder;
5+
import org.prebid.server.json.JacksonMapper;
6+
import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties;
7+
import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler;
8+
import org.prebid.server.spring.config.bidder.util.UsersyncerCreator;
9+
import org.prebid.server.spring.env.YamlPropertySourceFactory;
10+
import org.springframework.beans.factory.annotation.Value;
11+
import org.springframework.boot.context.properties.ConfigurationProperties;
12+
import org.springframework.context.annotation.Bean;
13+
import org.springframework.context.annotation.Configuration;
14+
import org.springframework.context.annotation.PropertySource;
15+
16+
import jakarta.validation.constraints.NotBlank;
17+
18+
@Configuration
19+
@PropertySource(value = "classpath:/bidder-config/kueezrtb.yaml", factory = YamlPropertySourceFactory.class)
20+
public class KueezRtbConfiguration {
21+
22+
private static final String BIDDER_NAME = "kueezrtb";
23+
24+
@Bean("kueezrtbConfigurationProperties")
25+
@ConfigurationProperties("adapters.kueezrtb")
26+
BidderConfigurationProperties configurationProperties() {
27+
return new BidderConfigurationProperties();
28+
}
29+
30+
@Bean
31+
BidderDeps kueezrtbBidderDeps(BidderConfigurationProperties kueezrtbConfigurationProperties,
32+
@NotBlank @Value("${external-url}") String externalUrl,
33+
JacksonMapper mapper) {
34+
35+
return BidderDepsAssembler.forBidder(BIDDER_NAME)
36+
.withConfig(kueezrtbConfigurationProperties)
37+
.usersyncerCreator(UsersyncerCreator.create(externalUrl))
38+
.bidderCreator(config -> new KueezRtbBidder(config.getEndpoint(), mapper))
39+
.assemble();
40+
}
41+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
adapters:
2+
kueezrtb:
3+
endpoint: https://prebidsrvr.kueezrtb.com/openrtb/
4+
endpoint-compression: gzip
5+
meta-info:
6+
maintainer-email: [email protected]
7+
app-media-types:
8+
- banner
9+
- video
10+
site-media-types:
11+
- banner
12+
- video
13+
supported-vendors:
14+
vendor-id: 1165
15+
usersync:
16+
cookie-family-name: kueezrtb
17+
iframe:
18+
url: https://sync.kueezrtb.com/api/user/html/62ce79e7dd15099534ae5e04?pbs=true&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&redirect={{redirect_url}}&gpp={{gpp}}&gpp_sid={{gpp_sid}}
19+
support-cors: false
20+
uid-macro: '${userId}'
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-04/schema#",
3+
"title": "Kueez RTB Adapter Params",
4+
"description": "A schema which validates params accepted by the Kueez RTB adapter",
5+
"type": "object",
6+
"properties": {
7+
"cId": {
8+
"type": "string",
9+
"description": "The connection id.",
10+
"minLength": 1,
11+
"pattern": "^[a-zA-Z0-9_]+$"
12+
}
13+
},
14+
"required": [
15+
"cId"
16+
],
17+
"additionalProperties": false
18+
}

src/test/groovy/org/prebid/server/functional/model/response/biddersparams/BidderParams.groovy

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ class BidderParams {
1717
def appid
1818
def placementid
1919
def dependencies
20+
def additionalProperties
2021
}

0 commit comments

Comments
 (0)