Skip to content

Commit

Permalink
Module: Request correction (#3526)
Browse files Browse the repository at this point in the history
  • Loading branch information
And1sS authored Nov 13, 2024
1 parent 6af31f5 commit d714f28
Show file tree
Hide file tree
Showing 35 changed files with 1,633 additions and 3 deletions.
5 changes: 5 additions & 0 deletions extra/bundle/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@
<artifactId>greenbids-real-time-data</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.prebid.server.hooks.modules</groupId>
<artifactId>pb-request-correction</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>

<build>
Expand Down
15 changes: 15 additions & 0 deletions extra/modules/pb-request-correction/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.prebid.server.hooks.modules</groupId>
<artifactId>all-modules</artifactId>
<version>3.15.0-SNAPSHOT</version>
</parent>

<artifactId>pb-request-correction</artifactId>

<name>pb-request-correction</name>
<description>Request correction module</description>
</project>
1 change: 1 addition & 0 deletions extra/modules/pb-request-correction/src/lombok.config
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lombok.anyConstructor.addConstructorProperties = true
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.prebid.server.hooks.modules.pb.request.correction.core;

import com.iab.openrtb.request.BidRequest;
import org.prebid.server.hooks.modules.pb.request.correction.core.config.model.Config;
import org.prebid.server.hooks.modules.pb.request.correction.core.correction.Correction;
import org.prebid.server.hooks.modules.pb.request.correction.core.correction.CorrectionProducer;

import java.util.List;
import java.util.Objects;

public class RequestCorrectionProvider {

private final List<CorrectionProducer> correctionProducers;

public RequestCorrectionProvider(List<CorrectionProducer> correctionProducers) {
this.correctionProducers = Objects.requireNonNull(correctionProducers);
}

public List<Correction> corrections(Config config, BidRequest bidRequest) {
return correctionProducers.stream()
.filter(correctionProducer -> correctionProducer.shouldProduce(config, bidRequest))
.map(correctionProducer -> correctionProducer.produce(config))
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.prebid.server.hooks.modules.pb.request.correction.core.config.model;

import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Builder;
import lombok.Value;

@Value
@Builder
public class Config {

boolean enabled;

@JsonAlias("pbsdkAndroidInstlRemove")
@JsonProperty("pbsdk-android-instl-remove")
boolean interstitialCorrectionEnabled;

@JsonAlias("pbsdkUaCleanup")
@JsonProperty("pbsdk-ua-cleanup")
boolean userAgentCorrectionEnabled;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.prebid.server.hooks.modules.pb.request.correction.core.correction;

import com.iab.openrtb.request.BidRequest;
import org.prebid.server.hooks.modules.pb.request.correction.core.config.model.Config;

public interface Correction {

BidRequest apply(BidRequest bidRequest);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.prebid.server.hooks.modules.pb.request.correction.core.correction;

import com.iab.openrtb.request.BidRequest;
import org.prebid.server.hooks.modules.pb.request.correction.core.config.model.Config;

public interface CorrectionProducer {

boolean shouldProduce(Config config, BidRequest bidRequest);

Correction produce(Config config);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.prebid.server.hooks.modules.pb.request.correction.core.correction.interstitial;

import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Imp;
import org.prebid.server.hooks.modules.pb.request.correction.core.correction.Correction;

public class InterstitialCorrection implements Correction {

@Override
public BidRequest apply(BidRequest bidRequest) {
return bidRequest.toBuilder()
.imp(bidRequest.getImp().stream()
.map(InterstitialCorrection::removeInterstitial)
.toList())
.build();
}

private static Imp removeInterstitial(Imp imp) {
final Integer interstitial = imp.getInstl();
return interstitial != null && interstitial == 1
? imp.toBuilder().instl(null).build()
: imp;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package org.prebid.server.hooks.modules.pb.request.correction.core.correction.interstitial;

import com.iab.openrtb.request.App;
import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Imp;
import org.apache.commons.lang3.StringUtils;
import org.prebid.server.hooks.modules.pb.request.correction.core.config.model.Config;
import org.prebid.server.hooks.modules.pb.request.correction.core.correction.Correction;
import org.prebid.server.hooks.modules.pb.request.correction.core.correction.CorrectionProducer;
import org.prebid.server.hooks.modules.pb.request.correction.core.util.VersionUtil;
import org.prebid.server.proto.openrtb.ext.request.ExtApp;
import org.prebid.server.proto.openrtb.ext.request.ExtAppPrebid;

import java.util.List;
import java.util.Optional;

public class InterstitialCorrectionProducer implements CorrectionProducer {

private static final InterstitialCorrection CORRECTION_INSTANCE = new InterstitialCorrection();

private static final String PREBID_MOBILE = "prebid-mobile";
private static final String ANDROID = "android";

private static final int MAX_VERSION_MAJOR = 2;
private static final int MAX_VERSION_MINOR = 2;
private static final int MAX_VERSION_PATCH = 3;

@Override
public boolean shouldProduce(Config config, BidRequest bidRequest) {
final App app = bidRequest.getApp();
return config.isInterstitialCorrectionEnabled()
&& hasInterstitialToRemove(bidRequest.getImp())
&& isPrebidMobile(app)
&& isAndroid(app)
&& isApplicableVersion(app);
}

private static boolean hasInterstitialToRemove(List<Imp> imps) {
for (Imp imp : imps) {
final Integer interstitial = imp.getInstl();
if (interstitial != null && interstitial == 1) {
return true;
}
}

return false;
}

private static boolean isPrebidMobile(App app) {
final String source = Optional.ofNullable(app)
.map(App::getExt)
.map(ExtApp::getPrebid)
.map(ExtAppPrebid::getSource)
.orElse(null);

return StringUtils.equalsIgnoreCase(source, PREBID_MOBILE);
}

private static boolean isAndroid(App app) {
return StringUtils.containsIgnoreCase(app.getBundle(), ANDROID);
}

private static boolean isApplicableVersion(App app) {
return Optional.ofNullable(app)
.map(App::getExt)
.map(ExtApp::getPrebid)
.map(ExtAppPrebid::getVersion)
.map(InterstitialCorrectionProducer::checkVersion)
.orElse(false);
}

private static boolean checkVersion(String version) {
return VersionUtil.isVersionLessThan(version, MAX_VERSION_MAJOR, MAX_VERSION_MINOR, MAX_VERSION_PATCH);
}

@Override
public Correction produce(Config config) {
return CORRECTION_INSTANCE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.prebid.server.hooks.modules.pb.request.correction.core.correction.useragent;

import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Device;
import org.prebid.server.hooks.modules.pb.request.correction.core.correction.Correction;

import java.util.regex.Pattern;

public class UserAgentCorrection implements Correction {

private static final Pattern USER_AGENT_PATTERN = Pattern.compile("PrebidMobile/[0-9][^ ]*");

@Override
public BidRequest apply(BidRequest bidRequest) {
return bidRequest.toBuilder()
.device(correctDevice(bidRequest.getDevice()))
.build();
}

private static Device correctDevice(Device device) {
return device.toBuilder()
.ua(USER_AGENT_PATTERN.matcher(device.getUa()).replaceAll(""))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package org.prebid.server.hooks.modules.pb.request.correction.core.correction.useragent;

import com.iab.openrtb.request.App;
import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Device;
import org.apache.commons.lang3.StringUtils;
import org.prebid.server.hooks.modules.pb.request.correction.core.config.model.Config;
import org.prebid.server.hooks.modules.pb.request.correction.core.correction.Correction;
import org.prebid.server.hooks.modules.pb.request.correction.core.correction.CorrectionProducer;
import org.prebid.server.hooks.modules.pb.request.correction.core.util.VersionUtil;
import org.prebid.server.proto.openrtb.ext.request.ExtApp;
import org.prebid.server.proto.openrtb.ext.request.ExtAppPrebid;

import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class UserAgentCorrectionProducer implements CorrectionProducer {

private static final UserAgentCorrection CORRECTION_INSTANCE = new UserAgentCorrection();

private static final String PREBID_MOBILE = "prebid-mobile";
private static final Pattern USER_AGENT_PATTERN = Pattern.compile(".*PrebidMobile/[0-9]+[^ ]*.*");


private static final int MAX_VERSION_MAJOR = 2;
private static final int MAX_VERSION_MINOR = 1;
private static final int MAX_VERSION_PATCH = 6;

@Override
public boolean shouldProduce(Config config, BidRequest bidRequest) {
final App app = bidRequest.getApp();
return config.isUserAgentCorrectionEnabled()
&& isPrebidMobile(app)
&& isApplicableVersion(app)
&& isApplicableDevice(bidRequest.getDevice());
}

private static boolean isPrebidMobile(App app) {
final String source = Optional.ofNullable(app)
.map(App::getExt)
.map(ExtApp::getPrebid)
.map(ExtAppPrebid::getSource)
.orElse(null);

return StringUtils.equalsIgnoreCase(source, PREBID_MOBILE);
}

private static boolean isApplicableVersion(App app) {
return Optional.ofNullable(app)
.map(App::getExt)
.map(ExtApp::getPrebid)
.map(ExtAppPrebid::getVersion)
.map(UserAgentCorrectionProducer::checkVersion)
.orElse(false);
}

private static boolean checkVersion(String version) {
return VersionUtil.isVersionLessThan(version, MAX_VERSION_MAJOR, MAX_VERSION_MINOR, MAX_VERSION_PATCH);
}

private static boolean isApplicableDevice(Device device) {
return Optional.ofNullable(device)
.map(Device::getUa)
.filter(StringUtils::isNotEmpty)
.map(USER_AGENT_PATTERN::matcher)
.map(Matcher::matches)
.orElse(false);
}


@Override
public Correction produce(Config config) {
return CORRECTION_INSTANCE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.prebid.server.hooks.modules.pb.request.correction.core.util;

public class VersionUtil {

public static boolean isVersionLessThan(String versionAsString, int major, int minor, int patch) {
return compareVersion(versionAsString, major, minor, patch) < 0;
}

private static int compareVersion(String versionAsString, int major, int minor, int patch) {
final String[] version = versionAsString.split("\\.");

final int parsedMajor = getAtAsIntOrDefault(version, 0, -1);
final int parsedMinor = getAtAsIntOrDefault(version, 1, 0);
final int parsedPatch = getAtAsIntOrDefault(version, 2, 0);

int diff = parsedMajor >= 0 ? parsedMajor - major : 1;
diff = diff == 0 ? parsedMinor - minor : diff;
diff = diff == 0 ? parsedPatch - patch : diff;

return diff;
}

private static int getAtAsIntOrDefault(String[] array, int index, int defaultValue) {
return array.length > index ? intOrDefault(array[index], defaultValue) : defaultValue;
}

private static int intOrDefault(String intAsString, int defaultValue) {
try {
final int parsed = Integer.parseInt(intAsString);
return parsed >= 0 ? parsed : defaultValue;
} catch (NumberFormatException e) {
return defaultValue;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.prebid.server.hooks.modules.pb.request.correction.spring.config;

import org.prebid.server.hooks.modules.pb.request.correction.core.RequestCorrectionProvider;
import org.prebid.server.hooks.modules.pb.request.correction.core.correction.CorrectionProducer;
import org.prebid.server.hooks.modules.pb.request.correction.core.correction.interstitial.InterstitialCorrectionProducer;
import org.prebid.server.hooks.modules.pb.request.correction.core.correction.useragent.UserAgentCorrectionProducer;
import org.prebid.server.hooks.modules.pb.request.correction.v1.RequestCorrectionModule;
import org.prebid.server.json.ObjectMapperProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

@Configuration
@ConditionalOnProperty(prefix = "hooks." + RequestCorrectionModule.CODE, name = "enabled", havingValue = "true")
public class RequestCorrectionModuleConfiguration {

@Bean
InterstitialCorrectionProducer interstitialCorrectionProducer() {
return new InterstitialCorrectionProducer();
}

@Bean
UserAgentCorrectionProducer userAgentCorrectionProducer() {
return new UserAgentCorrectionProducer();
}

@Bean
RequestCorrectionProvider requestCorrectionProvider(List<CorrectionProducer> correctionProducers) {
return new RequestCorrectionProvider(correctionProducers);
}

@Bean
RequestCorrectionModule requestCorrectionModule(RequestCorrectionProvider requestCorrectionProvider) {
return new RequestCorrectionModule(requestCorrectionProvider, ObjectMapperProvider.mapper());
}
}
Loading

0 comments on commit d714f28

Please sign in to comment.