-
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
bb1f267
commit 11c143e
Showing
12 changed files
with
765 additions
and
0 deletions.
There are no files selected for viewing
134 changes: 134 additions & 0 deletions
134
src/main/java/org/prebid/server/bidder/pgamssp/PgamSspBidder.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,134 @@ | ||
package org.prebid.server.bidder.pgamssp; | ||
|
||
import com.fasterxml.jackson.core.type.TypeReference; | ||
import com.fasterxml.jackson.databind.node.ObjectNode; | ||
import com.iab.openrtb.request.BidRequest; | ||
import com.iab.openrtb.request.Imp; | ||
import com.iab.openrtb.response.Bid; | ||
import com.iab.openrtb.response.BidResponse; | ||
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.BidderCall; | ||
import org.prebid.server.bidder.model.BidderError; | ||
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.pgamssp.PgamSspImpExt; | ||
import org.prebid.server.proto.openrtb.ext.response.BidType; | ||
import org.prebid.server.util.HttpUtil; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.Optional; | ||
|
||
public class PgamSspBidder implements Bidder<BidRequest> { | ||
|
||
private static final TypeReference<ExtPrebid<?, PgamSspImpExt>> PGAMSSP_EXT_TYPE_REFERENCE = new TypeReference<>() { | ||
}; | ||
private static final String PUBLISHER_IMP_EXT_TYPE = "publisher"; | ||
private static final String NETWORK_IMP_EXT_TYPE = "network"; | ||
|
||
private final String endpointUrl; | ||
private final JacksonMapper mapper; | ||
|
||
public PgamSspBidder(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<HttpRequest<BidRequest>> httpRequests = new ArrayList<>(); | ||
|
||
for (Imp imp : request.getImp()) { | ||
try { | ||
final PgamSspImpExt impExt = parseImpExt(imp); | ||
final BidRequest modifiedBidRequest = makeRequest(request, imp, impExt); | ||
httpRequests.add(makeHttpRequest(modifiedBidRequest, imp.getId())); | ||
} catch (PreBidException e) { | ||
return Result.withError(BidderError.badInput(e.getMessage())); | ||
} | ||
} | ||
|
||
return Result.withValues(httpRequests); | ||
} | ||
|
||
private PgamSspImpExt parseImpExt(Imp imp) throws PreBidException { | ||
try { | ||
return mapper.mapper().convertValue(imp.getExt(), PGAMSSP_EXT_TYPE_REFERENCE).getBidder(); | ||
} catch (IllegalArgumentException e) { | ||
throw new PreBidException("Invalid ext. Imp.Id: " + imp.getId()); | ||
} | ||
} | ||
|
||
private BidRequest makeRequest(BidRequest request, Imp imp, PgamSspImpExt impExt) { | ||
final boolean hasPlacement = StringUtils.isNotBlank(impExt.getPlacementId()); | ||
final boolean hasEndpoint = !hasPlacement && StringUtils.isNotBlank(impExt.getEndpointId()); | ||
final PgamSspImpExt modifiedImpExt = PgamSspImpExt.builder() | ||
.placementId(hasPlacement ? impExt.getPlacementId() : null) | ||
.endpointId(hasEndpoint ? impExt.getEndpointId() : null) | ||
.type(hasPlacement ? PUBLISHER_IMP_EXT_TYPE : hasEndpoint ? NETWORK_IMP_EXT_TYPE : null) | ||
.build(); | ||
|
||
final ObjectNode ext = mapper.mapper().valueToTree(ExtPrebid.of(null, modifiedImpExt)); | ||
return request.toBuilder().imp(Collections.singletonList(imp.toBuilder().ext(ext).build())).build(); | ||
} | ||
|
||
private HttpRequest<BidRequest> makeHttpRequest(BidRequest bidRequest, String impId) { | ||
return HttpRequest.<BidRequest>builder() | ||
.method(HttpMethod.POST) | ||
.headers(HttpUtil.headers()) | ||
.impIds(Collections.singleton(impId)) | ||
.uri(endpointUrl) | ||
.body(mapper.encodeToBytes(bidRequest)) | ||
.payload(bidRequest) | ||
.build(); | ||
} | ||
|
||
@Override | ||
public Result<List<BidderBid>> makeBids(BidderCall<BidRequest> httpCall, BidRequest bidRequest) { | ||
try { | ||
final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class); | ||
return Result.withValues(extractBids(bidResponse)); | ||
} catch (DecodeException e) { | ||
return Result.withError(BidderError.badServerResponse("Bad Server Response")); | ||
} catch (PreBidException e) { | ||
return Result.withError(BidderError.badServerResponse(e.getMessage())); | ||
} | ||
} | ||
|
||
private List<BidderBid> extractBids(BidResponse bidResponse) { | ||
if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) { | ||
throw new PreBidException("Empty SeatBid array"); | ||
} | ||
|
||
return bidResponse.getSeatbid().stream() | ||
.flatMap(seatBid -> Optional.ofNullable(seatBid.getBid()).orElse(List.of()).stream()) | ||
.map(bid -> BidderBid.of(bid, getBidMediaType(bid), bidResponse.getCur())) | ||
.toList(); | ||
} | ||
|
||
private static BidType getBidMediaType(Bid bid) { | ||
final Integer markupType = bid.getMtype(); | ||
if (markupType == null) { | ||
throw new PreBidException("Missing MType for bid: " + bid.getId()); | ||
} | ||
|
||
return switch (markupType) { | ||
case 1 -> BidType.banner; | ||
case 2 -> BidType.video; | ||
case 3 -> BidType.audio; | ||
case 4 -> BidType.xNative; | ||
default -> throw new PreBidException( | ||
"Unable to fetch mediaType " + bid.getMtype() + " in multi-format: " + bid.getImpid()); | ||
}; | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/main/java/org/prebid/server/proto/openrtb/ext/request/pgamssp/PgamSspImpExt.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,19 @@ | ||
package org.prebid.server.proto.openrtb.ext.request.pgamssp; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import lombok.Builder; | ||
import lombok.Value; | ||
|
||
@Value | ||
@Builder | ||
public class PgamSspImpExt { | ||
|
||
String type; | ||
|
||
@JsonProperty("placementId") | ||
String placementId; | ||
|
||
@JsonProperty("endpointId") | ||
String endpointId; | ||
|
||
} |
41 changes: 41 additions & 0 deletions
41
src/main/java/org/prebid/server/spring/config/bidder/PgamSspConfiguration.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,41 @@ | ||
package org.prebid.server.spring.config.bidder; | ||
|
||
import org.prebid.server.bidder.BidderDeps; | ||
import org.prebid.server.bidder.pgamssp.PgamSspBidder; | ||
import org.prebid.server.json.JacksonMapper; | ||
import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; | ||
import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; | ||
import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; | ||
import org.prebid.server.spring.env.YamlPropertySourceFactory; | ||
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/pgamssp.yaml", factory = YamlPropertySourceFactory.class) | ||
public class PgamSspConfiguration { | ||
|
||
private static final String BIDDER_NAME = "pgamssp"; | ||
|
||
@Bean("pgamsspConfigurationProperties") | ||
@ConfigurationProperties("adapters.pgamssp") | ||
BidderConfigurationProperties configurationProperties() { | ||
return new BidderConfigurationProperties(); | ||
} | ||
|
||
@Bean | ||
BidderDeps pgamsspBidderDeps(BidderConfigurationProperties pgamsspConfigurationProperties, | ||
@NotBlank @Value("${external-url}") String externalUrl, | ||
JacksonMapper mapper) { | ||
|
||
return BidderDepsAssembler.forBidder(BIDDER_NAME) | ||
.withConfig(pgamsspConfigurationProperties) | ||
.usersyncerCreator(UsersyncerCreator.create(externalUrl)) | ||
.bidderCreator(config -> new PgamSspBidder(config.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,21 @@ | ||
adapters: | ||
pgamssp: | ||
endpoint: http://us-east.pgammedia.com/pserver | ||
meta-info: | ||
maintainer-email: info@pgammedia.com | ||
app-media-types: | ||
- banner | ||
- video | ||
- native | ||
site-media-types: | ||
- banner | ||
- video | ||
- native | ||
supported-vendors: | ||
vendor-id: 0 | ||
usersync: | ||
cookie-family-name: pgamssp | ||
redirect: | ||
url: https://cs.pgammedia.com/pserver?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}&r={{redirect_url}} | ||
support-cors: false | ||
uid-macro: '[UID]' |
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,23 @@ | ||
{ | ||
"$schema": "http://json-schema.org/draft-04/schema#", | ||
"title": "PgamSSP Adapter Params", | ||
"description": "A schema which validates params accepted by the PgamSSP adapter", | ||
"type": "object", | ||
|
||
"properties": { | ||
"placementId": { | ||
"type": "string", | ||
"minLength": 1, | ||
"description": "Placement ID" | ||
}, | ||
"endpointId": { | ||
"type": "string", | ||
"minLength": 1, | ||
"description": "Endpoint ID" | ||
} | ||
}, | ||
"oneOf": [ | ||
{ "required": ["placementId"] }, | ||
{ "required": ["endpointId"] } | ||
] | ||
} |
Oops, something went wrong.