-
Notifications
You must be signed in to change notification settings - Fork 187
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
17d7e30
commit c6e31b0
Showing
14 changed files
with
880 additions
and
0 deletions.
There are no files selected for viewing
167 changes: 167 additions & 0 deletions
167
src/main/java/org/prebid/server/bidder/silvermob/SilvermobBidder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
package org.prebid.server.bidder.silvermob; | ||
|
||
import com.fasterxml.jackson.core.type.TypeReference; | ||
import com.iab.openrtb.request.BidRequest; | ||
import com.iab.openrtb.request.Device; | ||
import com.iab.openrtb.request.Imp; | ||
import com.iab.openrtb.response.BidResponse; | ||
import com.iab.openrtb.response.SeatBid; | ||
import io.vertx.core.MultiMap; | ||
import io.vertx.core.http.HttpMethod; | ||
import org.apache.commons.collections4.CollectionUtils; | ||
import org.apache.commons.lang3.StringUtils; | ||
import org.prebid.server.bidder.Bidder; | ||
import org.prebid.server.bidder.model.BidderBid; | ||
import org.prebid.server.bidder.model.BidderError; | ||
import org.prebid.server.bidder.model.HttpCall; | ||
import org.prebid.server.bidder.model.HttpRequest; | ||
import org.prebid.server.bidder.model.Result; | ||
import org.prebid.server.exception.PreBidException; | ||
import org.prebid.server.json.DecodeException; | ||
import org.prebid.server.json.JacksonMapper; | ||
import org.prebid.server.proto.openrtb.ext.ExtPrebid; | ||
import org.prebid.server.proto.openrtb.ext.request.silvermob.ExtImpSilvermob; | ||
import org.prebid.server.proto.openrtb.ext.response.BidType; | ||
import org.prebid.server.util.HttpUtil; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.stream.Collectors; | ||
|
||
/** | ||
* Silvermob {@link Bidder} implementation. | ||
*/ | ||
public class SilvermobBidder implements Bidder<BidRequest> { | ||
|
||
private static final TypeReference<ExtPrebid<?, ExtImpSilvermob>> SILVERMOB_EXT_TYPE_REFERENCE = | ||
new TypeReference<ExtPrebid<?, ExtImpSilvermob>>() { | ||
}; | ||
|
||
private static final String URL_HOST_MACRO = "{{Host}}"; | ||
private static final String URL_ZONE_ID_MACRO = "{{ZoneID}}"; | ||
|
||
private final String endpointUrl; | ||
private final JacksonMapper mapper; | ||
|
||
public SilvermobBidder(String endpointUrl, JacksonMapper mapper) { | ||
this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); | ||
this.mapper = Objects.requireNonNull(mapper); | ||
} | ||
|
||
@Override | ||
public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request) { | ||
final List<BidderError> errors = new ArrayList<>(); | ||
final List<HttpRequest<BidRequest>> requests = new ArrayList<>(); | ||
|
||
for (Imp imp : request.getImp()) { | ||
try { | ||
requests.add(createRequestForImp(imp, request)); | ||
} catch (PreBidException e) { | ||
errors.add(BidderError.badInput(e.getMessage())); | ||
} | ||
} | ||
|
||
return Result.of(requests, errors); | ||
} | ||
|
||
private HttpRequest<BidRequest> createRequestForImp(Imp imp, BidRequest request) { | ||
final ExtImpSilvermob extImp = parseImpExt(imp); | ||
|
||
final BidRequest outgoingRequest = request.toBuilder() | ||
.imp(Collections.singletonList(imp)) | ||
.build(); | ||
return HttpRequest.<BidRequest>builder() | ||
.method(HttpMethod.POST) | ||
.uri(resolveEndpoint(extImp)) | ||
.headers(resolveHeaders(request.getDevice())) | ||
.payload(outgoingRequest) | ||
.body(mapper.encode(outgoingRequest)) | ||
.build(); | ||
} | ||
|
||
private ExtImpSilvermob parseImpExt(Imp imp) { | ||
final ExtImpSilvermob extImp; | ||
try { | ||
extImp = mapper.mapper().convertValue(imp.getExt(), SILVERMOB_EXT_TYPE_REFERENCE).getBidder(); | ||
} catch (IllegalArgumentException e) { | ||
throw new PreBidException(String.format("error unmarshalling imp.ext.bidder: %s", e.getMessage())); | ||
} | ||
if (StringUtils.isBlank(extImp.getHost())) { | ||
throw new PreBidException("host is a required silvermob ext.imp param"); | ||
} | ||
|
||
if (StringUtils.isBlank(extImp.getZoneId())) { | ||
throw new PreBidException("zoneId is a required silvermob ext.imp param"); | ||
} | ||
return extImp; | ||
} | ||
|
||
private String resolveEndpoint(ExtImpSilvermob extImp) { | ||
return endpointUrl | ||
.replace(URL_HOST_MACRO, extImp.getHost()) | ||
.replace(URL_ZONE_ID_MACRO, HttpUtil.encodeUrl(extImp.getZoneId())); | ||
} | ||
|
||
private static MultiMap resolveHeaders(Device device) { | ||
final MultiMap headers = HttpUtil.headers() | ||
.add(HttpUtil.X_OPENRTB_VERSION_HEADER, "2.5"); | ||
|
||
if (device != null) { | ||
HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.USER_AGENT_HEADER, device.getUa()); | ||
HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.X_FORWARDED_FOR_HEADER, device.getIpv6()); | ||
HttpUtil.addHeaderIfValueIsNotEmpty(headers, HttpUtil.X_FORWARDED_FOR_HEADER, device.getIp()); | ||
} | ||
|
||
return headers; | ||
} | ||
|
||
@Override | ||
public Result<List<BidderBid>> makeBids(HttpCall<BidRequest> httpCall, BidRequest bidRequest) { | ||
try { | ||
return Result.of(extractBids(httpCall), Collections.emptyList()); | ||
} catch (DecodeException | PreBidException e) { | ||
return Result.withError(BidderError.badServerResponse(e.getMessage())); | ||
} | ||
} | ||
|
||
private List<BidderBid> extractBids(HttpCall<BidRequest> httpCall) { | ||
final BidResponse bidResponse; | ||
try { | ||
bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class); | ||
} catch (DecodeException e) { | ||
throw new PreBidException(String.format("Error unmarshalling server Response: %s", e.getMessage())); | ||
} | ||
if (bidResponse == null) { | ||
throw new PreBidException("Response in not present"); | ||
} | ||
if (CollectionUtils.isEmpty(bidResponse.getSeatbid())) { | ||
throw new PreBidException("Empty SeatBid array"); | ||
} | ||
return bidsFromResponse(bidResponse, httpCall.getRequest().getPayload()); | ||
} | ||
|
||
private static List<BidderBid> bidsFromResponse(BidResponse bidResponse, BidRequest bidRequest) { | ||
return bidResponse.getSeatbid().stream() | ||
.map(SeatBid::getBid) | ||
.flatMap(Collection::stream) | ||
.map(bid -> BidderBid.of(bid, getBidType(bid.getImpid(), bidRequest.getImp()), bidResponse.getCur())) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
private static BidType getBidType(String impId, List<Imp> imps) { | ||
for (Imp imp : imps) { | ||
if (imp.getId().equals(impId)) { | ||
if (imp.getVideo() != null) { | ||
return BidType.video; | ||
} | ||
if (imp.getXNative() != null) { | ||
return BidType.xNative; | ||
} | ||
} | ||
} | ||
return BidType.banner; | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
src/main/java/org/prebid/server/proto/openrtb/ext/request/silvermob/ExtImpSilvermob.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package org.prebid.server.proto.openrtb.ext.request.silvermob; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Value; | ||
|
||
/** | ||
* Defines the contract for bidRequest.imp[i].ext.silvermob | ||
*/ | ||
@AllArgsConstructor(staticName = "of") | ||
@Value | ||
public class ExtImpSilvermob { | ||
|
||
@JsonProperty("zoneid") | ||
String zoneId; | ||
|
||
String host; | ||
} |
56 changes: 56 additions & 0 deletions
56
src/main/java/org/prebid/server/spring/config/bidder/SilvermobConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package org.prebid.server.spring.config.bidder; | ||
|
||
import org.prebid.server.bidder.BidderDeps; | ||
import org.prebid.server.bidder.silvermob.SilvermobBidder; | ||
import org.prebid.server.json.JacksonMapper; | ||
import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; | ||
import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; | ||
import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; | ||
import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; | ||
import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; | ||
import org.prebid.server.spring.env.YamlPropertySourceFactory; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.beans.factory.annotation.Qualifier; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.context.annotation.PropertySource; | ||
|
||
import javax.validation.constraints.NotBlank; | ||
|
||
@Configuration | ||
@PropertySource(value = "classpath:/bidder-config/silvermob.yaml", factory = YamlPropertySourceFactory.class) | ||
public class SilvermobConfiguration { | ||
|
||
private static final String BIDDER_NAME = "silvermob"; | ||
|
||
@Value("${external-url}") | ||
@NotBlank | ||
private String externalUrl; | ||
|
||
@Autowired | ||
private JacksonMapper mapper; | ||
|
||
@Autowired | ||
@Qualifier("silvermobConfigurationProperties") | ||
private BidderConfigurationProperties configProperties; | ||
|
||
@Bean("silvermobConfigurationProperties") | ||
@ConfigurationProperties("adapters.silvermob") | ||
BidderConfigurationProperties configurationProperties() { | ||
return new BidderConfigurationProperties(); | ||
} | ||
|
||
@Bean | ||
BidderDeps silvermobBidderDeps() { | ||
final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); | ||
|
||
return BidderDepsAssembler.forBidder(BIDDER_NAME) | ||
.withConfig(configProperties) | ||
.bidderInfo(BidderInfoCreator.create(configProperties)) | ||
.usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) | ||
.bidderCreator(() -> new SilvermobBidder(configProperties.getEndpoint(), mapper)) | ||
.assemble(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
adapters: | ||
silvermob: | ||
enabled: false | ||
endpoint: http://{{Host}}.silvermob.com/marketplace/api/dsp/bid/{{ZoneID}} | ||
pbs-enforces-gdpr: true | ||
pbs-enforces-ccpa: true | ||
modifying-vast-xml-allowed: true | ||
deprecated-names: | ||
aliases: | ||
meta-info: | ||
maintainer-email: [email protected] | ||
app-media-types: | ||
- banner | ||
- video | ||
- native | ||
site-media-types: | ||
supported-vendors: | ||
vendor-id: 0 | ||
usersync: | ||
url: | ||
redirect-url: | ||
cookie-family-name: silvermob | ||
type: redirect | ||
support-cors: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"$schema": "http://json-schema.org/draft-04/schema#", | ||
"title": "SilverMob Adapter Params", | ||
"description": "A schema which validates params accepted by the SilverMob adapter", | ||
"type": "object", | ||
"properties": { | ||
"zoneid": { | ||
"type": "string", | ||
"description": "Zone ID" | ||
}, | ||
"host": { | ||
"type": "string", | ||
"description": "Host" | ||
} | ||
}, | ||
"required": ["zoneid", "host"] | ||
} |
Oops, something went wrong.