forked from prebid/prebid-server-java
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Vrtcal bidder implementation (prebid#390)
- Loading branch information
1 parent
2c16de6
commit 69c9577
Showing
14 changed files
with
729 additions
and
0 deletions.
There are no files selected for viewing
19 changes: 19 additions & 0 deletions
19
src/main/java/org/prebid/server/bidder/vrtcal/VrtcalBidder.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.bidder.vrtcal; | ||
|
||
import com.iab.openrtb.request.Imp; | ||
import org.prebid.server.bidder.OpenrtbBidder; | ||
import org.prebid.server.proto.openrtb.ext.request.vrtcal.ExtImpVrtcal; | ||
import org.prebid.server.proto.openrtb.ext.response.BidType; | ||
|
||
import java.util.List; | ||
|
||
public class VrtcalBidder extends OpenrtbBidder<ExtImpVrtcal> { | ||
public VrtcalBidder(String endpointUrl) { | ||
super(endpointUrl, RequestCreationStrategy.SINGLE_REQUEST, ExtImpVrtcal.class); | ||
} | ||
|
||
@Override | ||
protected BidType getBidType(String impId, List<Imp> imps) { | ||
return BidType.banner; | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
src/main/java/org/prebid/server/proto/openrtb/ext/request/vrtcal/ExtImpVrtcal.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,16 @@ | ||
package org.prebid.server.proto.openrtb.ext.request.vrtcal; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Value; | ||
|
||
/** | ||
* Defines the contract for bidRequest.imp[i].ext.Vrtcal | ||
*/ | ||
@AllArgsConstructor(staticName = "of") | ||
@Value | ||
public class ExtImpVrtcal { | ||
|
||
@JsonProperty("Just_an_unused_vrtcal_param") | ||
String justAnUnusedVrtcalParam; | ||
} |
49 changes: 49 additions & 0 deletions
49
src/main/java/org/prebid/server/spring/config/bidder/VrtcalConfiguration.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,49 @@ | ||
package org.prebid.server.spring.config.bidder; | ||
|
||
import org.prebid.server.bidder.BidderDeps; | ||
import org.prebid.server.bidder.vrtcal.VrtcalBidder; | ||
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.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/vrtcal.yaml", factory = YamlPropertySourceFactory.class) | ||
public class VrtcalConfiguration { | ||
|
||
private static final String BIDDER_NAME = "vrtcal"; | ||
|
||
@Value("${external-url}") | ||
@NotBlank | ||
private String externalUrl; | ||
|
||
@Autowired | ||
@Qualifier("vrtcalConfigurationProperties") | ||
private BidderConfigurationProperties configProperties; | ||
|
||
@Bean("vrtcalConfigurationProperties") | ||
@ConfigurationProperties("adapters.vrtcal") | ||
BidderConfigurationProperties configurationProperties() { | ||
return new BidderConfigurationProperties(); | ||
} | ||
|
||
@Bean | ||
BidderDeps vrtcalBidderDeps() { | ||
return BidderDepsAssembler.forBidder(BIDDER_NAME) | ||
.withConfig(configProperties) | ||
.bidderInfo(BidderInfoCreator.create(configProperties)) | ||
.usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) | ||
.bidderCreator(() -> new VrtcalBidder(configProperties.getEndpoint())) | ||
.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,20 @@ | ||
adapters: | ||
vrtcal: | ||
enabled: false | ||
endpoint: http://rtb.vrtcal.com/bidder_prebid.vap?ssp=1804 | ||
pbs-enforces-gdpr: true | ||
deprecated-names: | ||
aliases: | ||
meta-info: | ||
maintainer-email: [email protected] | ||
app-media-types: | ||
- banner | ||
site-media-types: | ||
supported-vendors: | ||
vendor-id: 0 | ||
usersync: | ||
url: | ||
redirect-url: | ||
cookie-family-name: vrtcal | ||
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,13 @@ | ||
{ | ||
"$schema": "http://json-schema.org/draft-04/schema#", | ||
"title": "Vrtcal Adapter Params", | ||
"description": "A schema which validates params accepted by the Vrtcal adapter", | ||
"type": "object", | ||
"properties": { | ||
"just_an_unused_vrtcal_param": { | ||
"type": "string", | ||
"description": "We only have this param as the prebid server crashes without at least 1 custom param; Not set to required to achieve parameter-less custom functionality" | ||
} | ||
}, | ||
"required": [] | ||
} |
163 changes: 163 additions & 0 deletions
163
src/test/java/org/prebid/server/bidder/vrtcal/VrtcalBidderTest.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,163 @@ | ||
package org.prebid.server.bidder.vrtcal; | ||
|
||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
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 com.iab.openrtb.response.SeatBid; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
import org.prebid.server.VertxTest; | ||
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.HttpResponse; | ||
import org.prebid.server.bidder.model.Result; | ||
import org.prebid.server.proto.openrtb.ext.ExtPrebid; | ||
import org.prebid.server.proto.openrtb.ext.request.vrtcal.ExtImpVrtcal; | ||
|
||
import java.util.List; | ||
import java.util.function.Function; | ||
|
||
import static java.util.Collections.emptyMap; | ||
import static java.util.Collections.singletonList; | ||
import static java.util.function.Function.identity; | ||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; | ||
import static org.prebid.server.proto.openrtb.ext.response.BidType.banner; | ||
|
||
public class VrtcalBidderTest extends VertxTest { | ||
|
||
private static final String ENDPOINT_URL = "https://test.endpoint.com"; | ||
|
||
private VrtcalBidder vrtcalBidder; | ||
|
||
@Before | ||
public void setUp() { | ||
vrtcalBidder = new VrtcalBidder(ENDPOINT_URL); | ||
} | ||
|
||
@Test | ||
public void creationShouldFailOnInvalidEndpointUrl() { | ||
assertThatIllegalArgumentException().isThrownBy(() -> new VrtcalBidder("invalid_url")); | ||
} | ||
|
||
@Test | ||
public void makeHttpRequestsShouldReturnErrorIfImpExtCouldNotBeParsed() { | ||
// given | ||
final BidRequest bidRequest = BidRequest.builder() | ||
.imp(singletonList(Imp.builder() | ||
.ext(mapper.valueToTree(ExtPrebid.of(null, mapper.createArrayNode()))).build())) | ||
.build(); | ||
|
||
// when | ||
final Result<List<HttpRequest<BidRequest>>> result = vrtcalBidder.makeHttpRequests(bidRequest); | ||
|
||
// then | ||
assertThat(result.getErrors()).hasSize(1); | ||
assertThat(result.getErrors().get(0).getMessage()).startsWith("Cannot deserialize instance"); | ||
assertThat(result.getValue()).isEmpty(); | ||
} | ||
|
||
@Test | ||
public void makeHttpRequestsShouldNotModifyIncomingRequest() { | ||
// given | ||
final BidRequest bidRequest = BidRequest.builder() | ||
.imp(singletonList(Imp.builder() | ||
.ext(mapper.valueToTree(ExtPrebid.of(null, | ||
ExtImpVrtcal.of("JustAnUnusedVrtcalParam")))) | ||
.build())) | ||
.id("request_id") | ||
.build(); | ||
|
||
// when | ||
final Result<List<HttpRequest<BidRequest>>> result = vrtcalBidder.makeHttpRequests(bidRequest); | ||
|
||
// then | ||
assertThat(result.getErrors()).isEmpty(); | ||
assertThat(result.getValue()).hasSize(1) | ||
.extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) | ||
.containsOnly(bidRequest); | ||
} | ||
|
||
@Test | ||
public void makeBidsShouldReturnErrorIfResponseBodyCouldNotBeParsed() { | ||
// given | ||
final HttpCall<BidRequest> httpCall = givenHttpCall(null, "invalid"); | ||
|
||
// when | ||
final Result<List<BidderBid>> result = vrtcalBidder.makeBids(httpCall, null); | ||
|
||
// then | ||
assertThat(result.getErrors()).hasSize(1); | ||
assertThat(result.getErrors().get(0).getMessage()).startsWith("Failed to decode: Unrecognized token"); | ||
assertThat(result.getErrors().get(0).getType()).isEqualTo(BidderError.Type.bad_server_response); | ||
assertThat(result.getValue()).isEmpty(); | ||
} | ||
|
||
@Test | ||
public void makeBidsShouldReturnEmptyListIfBidResponseIsNull() throws JsonProcessingException { | ||
// given | ||
final HttpCall<BidRequest> httpCall = givenHttpCall(null, | ||
mapper.writeValueAsString(null)); | ||
|
||
// when | ||
final Result<List<BidderBid>> result = vrtcalBidder.makeBids(httpCall, null); | ||
|
||
// then | ||
assertThat(result.getErrors()).isEmpty(); | ||
assertThat(result.getValue()).isEmpty(); | ||
} | ||
|
||
@Test | ||
public void makeBidsShouldReturnEmptyListIfBidResponseSeatBidIsNull() throws JsonProcessingException { | ||
// given | ||
final HttpCall<BidRequest> httpCall = givenHttpCall(null, | ||
mapper.writeValueAsString(BidResponse.builder().build())); | ||
|
||
// when | ||
final Result<List<BidderBid>> result = vrtcalBidder.makeBids(httpCall, null); | ||
|
||
// then | ||
assertThat(result.getErrors()).isEmpty(); | ||
assertThat(result.getValue()).isEmpty(); | ||
} | ||
|
||
@Test | ||
public void makeBidsShouldAlwaysReturnBannerBid() throws JsonProcessingException { | ||
// given | ||
final HttpCall<BidRequest> httpCall = givenHttpCall( | ||
BidRequest.builder().imp(singletonList(Imp.builder().build())).build(), | ||
mapper.writeValueAsString(givenBidResponse(identity()))); | ||
|
||
// when | ||
final Result<List<BidderBid>> result = vrtcalBidder.makeBids(httpCall, null); | ||
|
||
// then | ||
assertThat(result.getErrors()).isEmpty(); | ||
assertThat(result.getValue()) | ||
.containsOnly(BidderBid.of(Bid.builder().build(), banner, "USD")); | ||
} | ||
|
||
@Test | ||
public void extractTargetingShouldReturnEmptyMap() { | ||
assertThat(vrtcalBidder.extractTargeting(mapper.createObjectNode())).isEqualTo(emptyMap()); | ||
} | ||
|
||
private static BidResponse givenBidResponse(Function<Bid.BidBuilder, Bid.BidBuilder> bidCustomizer) { | ||
return BidResponse.builder() | ||
.seatbid(singletonList(SeatBid.builder() | ||
.bid(singletonList(bidCustomizer.apply(Bid.builder()).build())) | ||
.build())) | ||
.build(); | ||
} | ||
|
||
private static HttpCall<BidRequest> givenHttpCall(BidRequest bidRequest, String body) { | ||
return HttpCall.success( | ||
HttpRequest.<BidRequest>builder().payload(bidRequest).build(), | ||
HttpResponse.of(200, null, body), | ||
null); | ||
} | ||
} |
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,54 @@ | ||
package org.prebid.server.it; | ||
|
||
import io.restassured.response.Response; | ||
import org.json.JSONException; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
import org.skyscreamer.jsonassert.JSONAssert; | ||
import org.skyscreamer.jsonassert.JSONCompareMode; | ||
import org.springframework.test.context.junit4.SpringRunner; | ||
|
||
import java.io.IOException; | ||
|
||
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; | ||
import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; | ||
import static com.github.tomakehurst.wiremock.client.WireMock.post; | ||
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; | ||
import static io.restassured.RestAssured.given; | ||
import static java.util.Collections.singletonList; | ||
|
||
@RunWith(SpringRunner.class) | ||
public class VrtcalTest extends IntegrationTest { | ||
|
||
@Test | ||
public void openrtb2AuctionShouldRespondWithBidsFromVrtcal() throws IOException, JSONException { | ||
// given | ||
// Vrtcal bid response for imp 001 | ||
wireMockRule.stubFor(post(urlPathEqualTo("/vrtcal-exchange")) | ||
.withRequestBody(equalToJson(jsonFrom("openrtb2/vrtcal/test-vrtcal-bid-request-1.json"))) | ||
.willReturn(aResponse().withBody(jsonFrom("openrtb2/vrtcal/test-vrtcal-bid-response-1.json")))); | ||
|
||
// pre-bid cache | ||
wireMockRule.stubFor(post(urlPathEqualTo("/cache")) | ||
.withRequestBody(equalToJson(jsonFrom("openrtb2/vrtcal/test-cache-vrtcal-request.json"))) | ||
.willReturn(aResponse().withBody(jsonFrom("openrtb2/vrtcal/test-cache-vrtcal-response.json")))); | ||
|
||
// when | ||
final Response response = given(spec) | ||
.header("Referer", "http://www.example.com") | ||
.header("X-Forwarded-For", "192.168.244.1") | ||
.header("User-Agent", "userAgent") | ||
.header("Origin", "http://www.example.com") | ||
// this uids cookie value stands for {"uids":{"vrtcal":"VR-UID"}} | ||
.cookie("uids", "eyJ1aWRzIjp7InZydGNhbCI6IlZSLVVJRCJ9fQ==") | ||
.body(jsonFrom("openrtb2/vrtcal/test-auction-vrtcal-request.json")) | ||
.post("/openrtb2/auction"); | ||
|
||
// then | ||
final String expectedAuctionResponse = openrtbAuctionResponseFrom( | ||
"openrtb2/vrtcal/test-auction-vrtcal-response.json", | ||
response, singletonList("vrtcal")); | ||
|
||
JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), JSONCompareMode.NON_EXTENSIBLE); | ||
} | ||
} |
Oops, something went wrong.