Files
emo-grab/src/main/java/quant/rich/emoney/patch/okhttp/PatchOkHttpRule.java
Doghole d56ec783a3 修改代理 IP 获取设置,新增 GeoLite 本地归属地查询,修正 devtools 配置导致 ByteBuddy 重定义方法类
ClassLoader 不一致,进一步导致重定义方法内无法获取到自定义规则的问题
2025-05-15 01:35:53 +08:00

163 lines
5.2 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);
}
}
}