-
Notifications
You must be signed in to change notification settings - Fork 224
Kobler: New adapter ported from Go #3684
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
8ea1419
Kobler: New adapter (#3667)
przemkaczmarek 3e4f05e
fix clean code
przemkaczmarek 858b5df
Merge branch 'master' into Kobler-New-Adapter-(#3667)
przemkaczmarek c3e11ce
fix bugs
przemkaczmarek 5ca450c
fix bugs
przemkaczmarek 7293b44
fix bugs
przemkaczmarek ac1eb72
fix comments
przemkaczmarek 9287f80
fix checkstyle
przemkaczmarek 857a308
fix yaml
przemkaczmarek c385084
fix comments
przemkaczmarek 3078b30
fix checkstyle
przemkaczmarek d64f134
fix comments
przemkaczmarek 68770b0
fix checkstyle
przemkaczmarek 4982cf4
fix comments
przemkaczmarek 3521a00
fix comments
przemkaczmarek 5ee2283
fix comments
przemkaczmarek a8b9c4b
fix tests
przemkaczmarek 0ea93c2
fix comments
przemkaczmarek 1ffdb23
fix comments
przemkaczmarek 733c5bc
fix comments
przemkaczmarek 0bcb6cf
fix comments
przemkaczmarek File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
190 changes: 190 additions & 0 deletions
190
src/main/java/org/prebid/server/bidder/kobler/KoblerBidder.java
This file contains hidden or 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,190 @@ | ||
| package org.prebid.server.bidder.kobler; | ||
|
|
||
| import com.fasterxml.jackson.core.JsonProcessingException; | ||
| import com.fasterxml.jackson.core.type.TypeReference; | ||
| import com.fasterxml.jackson.databind.JsonNode; | ||
| 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 com.iab.openrtb.response.SeatBid; | ||
| import org.apache.commons.collections4.CollectionUtils; | ||
| 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.Price; | ||
| import org.prebid.server.bidder.model.Result; | ||
| import org.prebid.server.currency.CurrencyConversionService; | ||
| 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.kobler.ExtImpKobler; | ||
| import org.prebid.server.proto.openrtb.ext.response.BidType; | ||
| import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid; | ||
| import org.prebid.server.util.BidderUtil; | ||
| import org.prebid.server.util.HttpUtil; | ||
|
|
||
| import java.math.BigDecimal; | ||
| import java.util.ArrayList; | ||
| import java.util.Collection; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
| import java.util.Objects; | ||
| import java.util.Optional; | ||
|
|
||
| public class KoblerBidder implements Bidder<BidRequest> { | ||
|
|
||
| private static final TypeReference<ExtPrebid<?, ExtImpKobler>> KOBLER_EXT_TYPE_REFERENCE = | ||
| new TypeReference<>() { | ||
| }; | ||
|
|
||
| private static final String DEFAULT_BID_CURRENCY = "USD"; | ||
| private static final String EXT_PREBID = "prebid"; | ||
|
|
||
| private final String endpointUrl; | ||
| private final String devEndpoint; | ||
| private final CurrencyConversionService currencyConversionService; | ||
| private final JacksonMapper mapper; | ||
|
|
||
| public KoblerBidder(String endpointUrl, | ||
| String devEndpoint, | ||
| CurrencyConversionService currencyConversionService, | ||
| JacksonMapper mapper) { | ||
|
|
||
| this.endpointUrl = HttpUtil.validateUrl(endpointUrl); | ||
| this.devEndpoint = Objects.requireNonNull(devEndpoint); | ||
| this.currencyConversionService = Objects.requireNonNull(currencyConversionService); | ||
| this.mapper = Objects.requireNonNull(mapper); | ||
| } | ||
|
|
||
| @Override | ||
| public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest bidRequest) { | ||
| final List<BidderError> errors = new ArrayList<>(); | ||
| final List<Imp> modifiedImps = new ArrayList<>(); | ||
|
|
||
| final List<Imp> imps = bidRequest.getImp(); | ||
| for (Imp imp : imps) { | ||
| try { | ||
| modifiedImps.add(modifyImp(bidRequest, imp)); | ||
| } catch (PreBidException e) { | ||
| errors.add(BidderError.badInput(e.getMessage())); | ||
przemkaczmarek marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return Result.withErrors(errors); | ||
| } | ||
| } | ||
|
|
||
| final BidRequest modifiedRequest = bidRequest.toBuilder() | ||
| .imp(modifiedImps) | ||
| .cur(normalizeCurrencies(bidRequest)) | ||
| .build(); | ||
|
|
||
| final String endpoint = isTest(imps.getFirst(), errors) ? devEndpoint : endpointUrl; | ||
|
|
||
| final HttpRequest<BidRequest> httpRequest = BidderUtil.defaultRequest(modifiedRequest, endpoint, mapper); | ||
| return Result.of(Collections.singletonList(httpRequest), errors); | ||
| } | ||
|
|
||
| private Imp modifyImp(BidRequest bidRequest, Imp imp) { | ||
| final Price resolvedBidFloor = resolveBidFloor(imp, bidRequest); | ||
|
|
||
| return imp.toBuilder() | ||
| .bidfloor(resolvedBidFloor.getValue()) | ||
| .bidfloorcur(resolvedBidFloor.getCurrency()) | ||
| .build(); | ||
| } | ||
|
|
||
| private Price resolveBidFloor(Imp imp, BidRequest bidRequest) { | ||
| final Price initialBidFloorPrice = Price.of(imp.getBidfloorcur(), imp.getBidfloor()); | ||
| return BidderUtil.shouldConvertBidFloor(initialBidFloorPrice, DEFAULT_BID_CURRENCY) | ||
| ? convertBidFloor(initialBidFloorPrice, bidRequest) | ||
| : initialBidFloorPrice; | ||
| } | ||
|
|
||
| private Price convertBidFloor(Price bidFloorPrice, BidRequest bidRequest) { | ||
| final BigDecimal convertedPrice = currencyConversionService.convertCurrency( | ||
| bidFloorPrice.getValue(), | ||
| bidRequest, | ||
| bidFloorPrice.getCurrency(), | ||
| DEFAULT_BID_CURRENCY); | ||
|
|
||
| return Price.of(DEFAULT_BID_CURRENCY, convertedPrice); | ||
| } | ||
|
|
||
| private List<String> normalizeCurrencies(BidRequest bidRequest) { | ||
| final List<String> currencies = bidRequest.getCur(); | ||
| if (currencies.contains(DEFAULT_BID_CURRENCY)) { | ||
| return currencies; | ||
| } | ||
|
|
||
| final List<String> newCurrencies = new ArrayList<>(currencies); | ||
| newCurrencies.add(DEFAULT_BID_CURRENCY); | ||
| return newCurrencies; | ||
| } | ||
|
|
||
| private boolean isTest(Imp imp, List<BidderError> errors) { | ||
| try { | ||
| return parseImpExt(imp).getTest(); | ||
| } catch (PreBidException e) { | ||
| errors.add(BidderError.badInput(e.getMessage())); | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| private ExtImpKobler parseImpExt(Imp imp) { | ||
| try { | ||
| return mapper.mapper().convertValue(imp.getExt(), KOBLER_EXT_TYPE_REFERENCE).getBidder(); | ||
| } catch (IllegalArgumentException e) { | ||
| throw new PreBidException(e.getMessage()); | ||
| } | ||
| } | ||
|
|
||
| @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(e.getMessage())); | ||
| } | ||
| } | ||
|
|
||
| private List<BidderBid> extractBids(BidResponse bidResponse) { | ||
| if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) { | ||
| return Collections.emptyList(); | ||
| } | ||
| return bidsFromResponse(bidResponse); | ||
| } | ||
|
|
||
| private List<BidderBid> bidsFromResponse(BidResponse bidResponse) { | ||
| return bidResponse.getSeatbid().stream() | ||
| .filter(Objects::nonNull) | ||
| .map(SeatBid::getBid) | ||
| .filter(Objects::nonNull) | ||
| .flatMap(Collection::stream) | ||
| .filter(Objects::nonNull) | ||
przemkaczmarek marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| .map(bid -> BidderBid.of(bid, getBidType(bid), bidResponse.getCur())) | ||
przemkaczmarek marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| .toList(); | ||
| } | ||
|
|
||
| private BidType getBidType(Bid bid) { | ||
| return Optional.ofNullable(bid.getExt()) | ||
| .map(ext -> ext.get(EXT_PREBID)) | ||
| .filter(JsonNode::isObject) | ||
| .map(ObjectNode.class::cast) | ||
CTMBNara marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| .filter(JsonNode::isObject) | ||
| .map(this::parseExtBidPrebid) | ||
| .map(ExtBidPrebid::getType) | ||
| .orElse(BidType.banner); | ||
| } | ||
|
|
||
| private ExtBidPrebid parseExtBidPrebid(ObjectNode prebid) { | ||
| try { | ||
| return mapper.mapper().treeToValue(prebid, ExtBidPrebid.class); | ||
| } catch (JsonProcessingException e) { | ||
| return null; | ||
| } | ||
| } | ||
| } | ||
9 changes: 9 additions & 0 deletions
9
src/main/java/org/prebid/server/proto/openrtb/ext/request/kobler/ExtImpKobler.java
This file contains hidden or 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,9 @@ | ||
| package org.prebid.server.proto.openrtb.ext.request.kobler; | ||
|
|
||
| import lombok.Value; | ||
|
|
||
| @Value(staticConstructor = "of") | ||
| public class ExtImpKobler { | ||
|
|
||
| Boolean test; | ||
| } |
62 changes: 62 additions & 0 deletions
62
src/main/java/org/prebid/server/spring/config/bidder/KoblerConfiguration.java
This file contains hidden or 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,62 @@ | ||
| package org.prebid.server.spring.config.bidder; | ||
|
|
||
| import lombok.Data; | ||
| import lombok.EqualsAndHashCode; | ||
| import lombok.NoArgsConstructor; | ||
| import org.prebid.server.bidder.BidderDeps; | ||
| import org.prebid.server.bidder.kobler.KoblerBidder; | ||
| import org.prebid.server.currency.CurrencyConversionService; | ||
| 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 org.springframework.validation.annotation.Validated; | ||
|
|
||
| import jakarta.validation.constraints.NotBlank; | ||
|
|
||
| @Configuration | ||
| @PropertySource(value = "classpath:/bidder-config/kobler.yaml", factory = YamlPropertySourceFactory.class) | ||
| public class KoblerConfiguration { | ||
|
|
||
| private static final String BIDDER_NAME = "kobler"; | ||
|
|
||
| @Bean("koblerConfigurationProperties") | ||
| @ConfigurationProperties("adapters.kobler") | ||
| KoblerConfigurationProperties configurationProperties() { | ||
| return new KoblerConfigurationProperties(); | ||
| } | ||
|
|
||
| @Bean | ||
| BidderDeps koblerBidderDeps(KoblerConfigurationProperties config, | ||
| CurrencyConversionService currencyConversionService, | ||
| @NotBlank @Value("${external-url}") String externalUrl, | ||
| JacksonMapper mapper) { | ||
|
|
||
| return BidderDepsAssembler.<KoblerConfigurationProperties>forBidder(BIDDER_NAME) | ||
| .withConfig(config) | ||
| .usersyncerCreator(UsersyncerCreator.create(externalUrl)) | ||
| .bidderCreator(cfg -> new KoblerBidder( | ||
| cfg.getEndpoint(), | ||
| cfg.getDevEndpoint(), | ||
| currencyConversionService, | ||
| mapper)) | ||
| .assemble(); | ||
|
|
||
| } | ||
|
|
||
| @Validated | ||
| @Data | ||
| @EqualsAndHashCode(callSuper = true) | ||
| @NoArgsConstructor | ||
| private static class KoblerConfigurationProperties extends BidderConfigurationProperties { | ||
|
|
||
| @NotBlank | ||
| private String devEndpoint; | ||
CTMBNara marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
This file contains hidden or 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,14 @@ | ||
| adapters: | ||
| kobler: | ||
| endpoint: "https://bid.essrtb.com/bid/prebid_server_rtb_call" | ||
przemkaczmarek marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| dev-endpoint: "https://bid-service.dev.essrtb.com/bid/prebid_server_rtb_call" | ||
| endpoint-compression: gzip | ||
| geoscope: | ||
| - NOR | ||
| - SWE | ||
| - DNK | ||
| meta-info: | ||
| maintainer-email: bidding-support@kobler.no | ||
| site-media-types: | ||
| - banner | ||
| vendor-id: 0 | ||
This file contains hidden or 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": "Kobler Adapter Params", | ||
| "description": "A schema which validates params accepted by the Kobler adapter", | ||
| "type": "object", | ||
|
|
||
| "properties": { | ||
| "test": { | ||
| "type": "boolean", | ||
| "description": "Whether the request is for testing only. When multiple ad units are submitted together, it is enough to set this parameter on the first one." | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.