163 lines
5.2 KiB
Java
163 lines
5.2 KiB
Java
package quant.rich.emoney.patch.okhttp;
|
||
|
||
import java.util.*;
|
||
import java.util.function.*;
|
||
import java.util.regex.Pattern;
|
||
|
||
import org.slf4j.Logger;
|
||
import org.slf4j.LoggerFactory;
|
||
|
||
import quant.rich.emoney.patch.okhttp.PatchOkHttp.HeaderInterceptor;
|
||
|
||
public class PatchOkHttpRule {
|
||
private final Predicate<RequestContext> condition;
|
||
private final List<HeaderAction> actions;
|
||
|
||
public PatchOkHttpRule(Predicate<RequestContext> condition, List<HeaderAction> actions) {
|
||
this.condition = condition;
|
||
this.actions = actions;
|
||
}
|
||
|
||
public boolean matches(RequestContext ctx) {
|
||
return condition.test(ctx);
|
||
}
|
||
|
||
public void apply(RequestContext ctx, String currentHeader, Consumer<String> overrideSetter) {
|
||
for (HeaderAction action : actions) {
|
||
action.apply(ctx, currentHeader, overrideSetter);
|
||
}
|
||
}
|
||
|
||
@FunctionalInterface
|
||
public interface HeaderAction {
|
||
void apply(RequestContext ctx, String currentHeader, Consumer<String> overrideValueSetter);
|
||
}
|
||
|
||
/**
|
||
* 起始语句,创建一个 Builder
|
||
* @return
|
||
*/
|
||
public static Builder when() {
|
||
return new Builder(ctx -> true);
|
||
}
|
||
|
||
public static class Builder {
|
||
public static final Logger log = LoggerFactory.getLogger(HeaderInterceptor.class);
|
||
private Predicate<RequestContext> condition;
|
||
private final List<HeaderAction> actions = new ArrayList<>();
|
||
|
||
public Builder(Predicate<RequestContext> initial) {
|
||
this.condition = initial;
|
||
}
|
||
|
||
public Builder hasHeaderPair(String name, String value) {
|
||
return and(ctx -> value.equals(ctx.headers.get(name)));
|
||
}
|
||
|
||
public Builder hasHeaderName(String name) {
|
||
return and(ctx -> ctx.headers.containsKey(name));
|
||
}
|
||
|
||
public Builder hasNotHeaderName(String name) {
|
||
return not(r -> r.and(ctx -> ctx.headers.containsKey(name)));
|
||
}
|
||
|
||
public Builder hasHeaderValueMatch(String name, String regex) {
|
||
Pattern pattern = Pattern.compile(regex);
|
||
return and(ctx -> {
|
||
String val = ctx.headers.get(name);
|
||
return val != null && pattern.matcher(val).matches();
|
||
});
|
||
}
|
||
|
||
public Builder hostEndsWith(String suffix) {
|
||
return and(ctx -> ctx.host != null && ctx.host.endsWith(suffix));
|
||
}
|
||
|
||
public Builder hostContains(String keyword) {
|
||
return and(ctx -> ctx.host != null && ctx.host.contains(keyword));
|
||
}
|
||
|
||
/**
|
||
*
|
||
* @param pattern
|
||
* @return
|
||
*/
|
||
public Builder hostMatches(String pattern) {
|
||
return and(ctx -> ctx.host != null && Pattern.matches(pattern, ctx.host));
|
||
}
|
||
|
||
public Builder isHttp() {
|
||
return and(ctx -> ctx.scheme.equalsIgnoreCase("http"));
|
||
}
|
||
|
||
public Builder isHttps() {
|
||
return and(ctx -> ctx.scheme.equalsIgnoreCase("https"));
|
||
}
|
||
|
||
/**
|
||
* 接收一个 not 条件<br>
|
||
* 例:Rule.when().not(r -> r.isHttps()).build()
|
||
*
|
||
* @param block
|
||
* @return
|
||
*/
|
||
public Builder not(Consumer<Builder> block) {
|
||
Builder sub = new Builder(ctx -> true); // starts with true
|
||
block.accept(sub);
|
||
this.condition = this.condition
|
||
.and(sub.condition.negate());
|
||
return this;
|
||
}
|
||
|
||
public Builder or(Consumer<Builder> block) {
|
||
Builder sub = new Builder(ctx -> true);
|
||
block.accept(sub);
|
||
this.condition = this.condition.or(sub.condition);
|
||
return this;
|
||
}
|
||
|
||
public Builder or(Builder other) {
|
||
this.condition = this.condition.or(other.condition);
|
||
return this;
|
||
}
|
||
|
||
public Builder or(PatchOkHttpRule rule) {
|
||
this.condition = this.condition.or(rule::matches);
|
||
return this;
|
||
}
|
||
|
||
public Builder and() {
|
||
return this;
|
||
}
|
||
|
||
public Builder and(Predicate<RequestContext> other) {
|
||
this.condition = this.condition.and(other);
|
||
return this;
|
||
}
|
||
|
||
public Builder then() {
|
||
return this;
|
||
}
|
||
|
||
public Builder setHeader(String name, String value) {
|
||
actions.add((ctx, curr, setter) -> ctx.headers.put(name, value));
|
||
return this;
|
||
}
|
||
|
||
public Builder overrideIf(String headerName, String value) {
|
||
actions.add((ctx, curr, setter) -> {
|
||
if (curr.equalsIgnoreCase(headerName)) {
|
||
log.debug("matches and applying - host: {}, currHeader {}, targetHeader {}, value: {}, classLoader: {}", ctx.host, curr, headerName,
|
||
value, this.getClass().getClassLoader());
|
||
setter.accept(value);
|
||
}
|
||
});
|
||
return this;
|
||
}
|
||
|
||
public PatchOkHttpRule build() {
|
||
return new PatchOkHttpRule(condition, actions);
|
||
}
|
||
}
|
||
} |