Skip to content

Commit 9200613

Browse files
New BoldwinRapid Adapter (#4285)
1 parent edc2453 commit 9200613

File tree

12 files changed

+720
-0
lines changed

12 files changed

+720
-0
lines changed
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package org.prebid.server.bidder.boldwinrapid;
2+
3+
import com.fasterxml.jackson.core.type.TypeReference;
4+
import com.iab.openrtb.request.BidRequest;
5+
import com.iab.openrtb.request.Device;
6+
import com.iab.openrtb.request.Imp;
7+
import com.iab.openrtb.response.Bid;
8+
import com.iab.openrtb.response.BidResponse;
9+
import com.iab.openrtb.response.SeatBid;
10+
import io.vertx.core.MultiMap;
11+
import org.apache.commons.collections4.CollectionUtils;
12+
import org.apache.commons.lang3.StringUtils;
13+
import org.prebid.server.bidder.Bidder;
14+
import org.prebid.server.bidder.model.BidderBid;
15+
import org.prebid.server.bidder.model.BidderCall;
16+
import org.prebid.server.bidder.model.BidderError;
17+
import org.prebid.server.bidder.model.HttpRequest;
18+
import org.prebid.server.bidder.model.Result;
19+
import org.prebid.server.exception.PreBidException;
20+
import org.prebid.server.json.DecodeException;
21+
import org.prebid.server.json.JacksonMapper;
22+
import org.prebid.server.proto.openrtb.ext.ExtPrebid;
23+
import org.prebid.server.proto.openrtb.ext.request.boldwinrapid.ExtImpBoldwinRapid;
24+
import org.prebid.server.proto.openrtb.ext.response.BidType;
25+
import org.prebid.server.util.BidderUtil;
26+
import org.prebid.server.util.HttpUtil;
27+
28+
import java.util.ArrayList;
29+
import java.util.Collection;
30+
import java.util.Collections;
31+
import java.util.List;
32+
import java.util.Objects;
33+
34+
public class BoldwinRapidBidder implements Bidder<BidRequest> {
35+
36+
private static final TypeReference<ExtPrebid<?, ExtImpBoldwinRapid>> BOLDWIN_EXT_TYPE_REFERENCE =
37+
new TypeReference<>() {
38+
};
39+
private static final String PUBLISHER_ID_MACRO = "{{PublisherID}}";
40+
private static final String PLACEMENT_ID_MACRO = "{{PlacementID}}";
41+
private static final String HOST_HEADER_VALUE = "rtb.beardfleet.com";
42+
43+
private final String endpointUrl;
44+
private final JacksonMapper mapper;
45+
46+
public BoldwinRapidBidder(String endpointUrl, JacksonMapper mapper) {
47+
this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl));
48+
this.mapper = Objects.requireNonNull(mapper);
49+
}
50+
51+
@Override
52+
public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request) {
53+
final List<HttpRequest<BidRequest>> httpRequests = new ArrayList<>();
54+
final List<BidderError> errors = new ArrayList<>();
55+
final MultiMap headers = makeHeaders(request.getDevice());
56+
57+
for (Imp imp : request.getImp()) {
58+
try {
59+
final ExtImpBoldwinRapid extImp = parseImpExt(imp);
60+
final String resolvedEndpoint = resolveEndpoint(extImp);
61+
final BidRequest outgoingRequest = request.toBuilder()
62+
.imp(Collections.singletonList(imp))
63+
.build();
64+
65+
httpRequests.add(BidderUtil.defaultRequest(outgoingRequest, headers, resolvedEndpoint, mapper));
66+
} catch (PreBidException e) {
67+
errors.add(BidderError.badInput(e.getMessage()));
68+
}
69+
}
70+
71+
return Result.of(httpRequests, errors);
72+
}
73+
74+
private ExtImpBoldwinRapid parseImpExt(Imp imp) {
75+
try {
76+
return mapper.mapper().convertValue(imp.getExt(), BOLDWIN_EXT_TYPE_REFERENCE).getBidder();
77+
} catch (IllegalArgumentException e) {
78+
throw new PreBidException("Error parsing imp.ext: " + e.getMessage());
79+
}
80+
}
81+
82+
private String resolveEndpoint(ExtImpBoldwinRapid extImp) {
83+
return endpointUrl
84+
.replace(PUBLISHER_ID_MACRO, HttpUtil.encodeUrl(StringUtils.defaultString(extImp.getPid())))
85+
.replace(PLACEMENT_ID_MACRO, HttpUtil.encodeUrl(StringUtils.defaultString(extImp.getTid())));
86+
}
87+
88+
private static MultiMap makeHeaders(Device device) {
89+
final MultiMap headers = HttpUtil.headers()
90+
.set(HttpUtil.X_OPENRTB_VERSION_HEADER, "2.5")
91+
.set("Host", HOST_HEADER_VALUE);
92+
93+
if (device != null) {
94+
HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.USER_AGENT_HEADER, device.getUa());
95+
HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.X_FORWARDED_FOR_HEADER, device.getIp());
96+
HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.X_FORWARDED_FOR_HEADER, device.getIpv6());
97+
HttpUtil.addHeaderIfValueIsNotEmpty(headers, "IP", device.getIp());
98+
}
99+
100+
return headers;
101+
}
102+
103+
@Override
104+
public Result<List<BidderBid>> makeBids(BidderCall<BidRequest> httpCall, BidRequest bidRequest) {
105+
try {
106+
final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class);
107+
return Result.withValues(extractBids(bidResponse));
108+
} catch (DecodeException | PreBidException e) {
109+
return Result.withError(BidderError.badServerResponse(e.getMessage()));
110+
}
111+
}
112+
113+
private static List<BidderBid> extractBids(BidResponse bidResponse) {
114+
if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) {
115+
return Collections.emptyList();
116+
}
117+
return bidsFromResponse(bidResponse);
118+
}
119+
120+
private static List<BidderBid> bidsFromResponse(BidResponse bidResponse) {
121+
return bidResponse.getSeatbid().stream()
122+
.filter(Objects::nonNull)
123+
.map(SeatBid::getBid)
124+
.filter(Objects::nonNull)
125+
.flatMap(Collection::stream)
126+
.filter(Objects::nonNull)
127+
.map(bid -> BidderBid.of(bid, getBidType(bid), bidResponse.getCur()))
128+
.toList();
129+
}
130+
131+
private static BidType getBidType(Bid bid) {
132+
return switch (bid.getMtype()) {
133+
case 1 -> BidType.banner;
134+
case 2 -> BidType.video;
135+
case 4 -> BidType.xNative;
136+
case null, default -> throw new PreBidException(
137+
"Unable to fetch mediaType in multi-format: " + bid.getImpid());
138+
};
139+
}
140+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.prebid.server.proto.openrtb.ext.request.boldwinrapid;
2+
3+
import lombok.Value;
4+
5+
@Value(staticConstructor = "of")
6+
public class ExtImpBoldwinRapid {
7+
8+
String pid;
9+
10+
String tid;
11+
}
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.boldwinrapid.BoldwinRapidBidder;
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/boldwinrapid.yaml", factory = YamlPropertySourceFactory.class)
20+
public class BoldwinRapidConfiguration {
21+
22+
private static final String BIDDER_NAME = "boldwin_rapid";
23+
24+
@Bean("boldwinRapidConfigurationProperties")
25+
@ConfigurationProperties("adapters.boldwinrapid")
26+
BidderConfigurationProperties configurationProperties() {
27+
return new BidderConfigurationProperties();
28+
}
29+
30+
@Bean
31+
BidderDeps boldwinrapidBidderDeps(BidderConfigurationProperties boldwinRapidConfigurationProperties,
32+
@NotBlank @Value("${external-url}") String externalUrl,
33+
JacksonMapper mapper) {
34+
35+
return BidderDepsAssembler.forBidder(BIDDER_NAME)
36+
.withConfig(boldwinRapidConfigurationProperties)
37+
.usersyncerCreator(UsersyncerCreator.create(externalUrl))
38+
.bidderCreator(config -> new BoldwinRapidBidder(config.getEndpoint(), mapper))
39+
.assemble();
40+
}
41+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
adapters:
2+
boldwin_rapid:
3+
endpoint: https://rtb.beardfleet.com/auction/bid?pid={{PublisherID}}&tid={{PlacementID}}
4+
meta-info:
5+
maintainer-email: info@bold-win.com
6+
app-media-types:
7+
- banner
8+
- video
9+
- native
10+
supported-vendors:
11+
vendor-id: 0
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-04/schema#",
3+
"title": "Boldwin-Rapid Adapter Params",
4+
"description": "A schema which validates params accepted by the Boldwin-rapid adapter",
5+
"type": "object",
6+
"properties": {
7+
"pid": {
8+
"type": "string",
9+
"minLength": 1,
10+
"description": "Publisher ID"
11+
},
12+
"tid": {
13+
"type": "string",
14+
"minLength": 1,
15+
"description": "Placement ID"
16+
}
17+
},
18+
"required": [
19+
"pid",
20+
"tid"
21+
]
22+
}

0 commit comments

Comments
 (0)