findNextIterator() {
if(hostParts.containsKey(hostPart)){
current = hostParts.get(hostPart).iterator();
if(current.hasNext()){
+ nextIndex();
return current;
}
}
- }while((index = hostname.indexOf('.', index) + 1) != 0 && index < hostname.length());
+ }while(nextIndex() != 0 && index < hostname.length());
return Collections.emptyIterator();
}
+
+ private int nextIndex() {
+ return index = hostname.indexOf('.', index) + 1;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/io/github/danthe1st/httpsintercept/rules/PostForwardRule.java b/src/main/java/io/github/danthe1st/httpsintercept/rules/PostForwardRule.java
new file mode 100644
index 0000000..4b1f383
--- /dev/null
+++ b/src/main/java/io/github/danthe1st/httpsintercept/rules/PostForwardRule.java
@@ -0,0 +1,16 @@
+package io.github.danthe1st.httpsintercept.rules;
+
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import io.github.danthe1st.httpsintercept.handler.http.HttpResponseContentAccessor;
+import io.github.danthe1st.httpsintercept.rules.post.HtmlBasedBlocker;
+import io.netty.channel.Channel;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.FullHttpResponse;
+
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
+@JsonSubTypes({ @Type(name = "htmlBasedBlock", value = HtmlBasedBlocker.class) })
+public interface PostForwardRule extends ProcessingRule {
+ boolean processRequest(FullHttpRequest fullHttpRequest, FullHttpResponse response, HttpResponseContentAccessor responseContentAccessor, Channel channel);
+}
diff --git a/src/main/java/io/github/danthe1st/httpsintercept/rules/PreForwardRule.java b/src/main/java/io/github/danthe1st/httpsintercept/rules/PreForwardRule.java
index 04a6077..4a72166 100644
--- a/src/main/java/io/github/danthe1st/httpsintercept/rules/PreForwardRule.java
+++ b/src/main/java/io/github/danthe1st/httpsintercept/rules/PreForwardRule.java
@@ -3,11 +3,12 @@
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import io.github.danthe1st.httpsintercept.rules.pre.SetRequestHeaderRule;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.FullHttpRequest;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
-@JsonSubTypes({ @Type(name = "addHeader", value = SetHeaderRule.class) })
+@JsonSubTypes({ @Type(name = "addHeader", value = SetRequestHeaderRule.class) })
public interface PreForwardRule extends ProcessingRule {
boolean processRequest(FullHttpRequest fullHttpRequest, Channel channel);
}
diff --git a/src/main/java/io/github/danthe1st/httpsintercept/rules/post/HtmlBasedBlocker.java b/src/main/java/io/github/danthe1st/httpsintercept/rules/post/HtmlBasedBlocker.java
new file mode 100644
index 0000000..fcf0005
--- /dev/null
+++ b/src/main/java/io/github/danthe1st/httpsintercept/rules/post/HtmlBasedBlocker.java
@@ -0,0 +1,96 @@
+package io.github.danthe1st.httpsintercept.rules.post;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.regex.Pattern;
+
+import io.github.danthe1st.httpsintercept.config.HostMatcherConfig;
+import io.github.danthe1st.httpsintercept.handler.http.HttpResponseContentAccessor;
+import io.github.danthe1st.httpsintercept.rules.PostForwardRule;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
+import io.netty.handler.codec.http.DefaultFullHttpResponse;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.FullHttpResponse;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import io.netty.handler.codec.http.HttpVersion;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+
+public record HtmlBasedBlocker(
+ HostMatcherConfig hostMatcher,
+ String selector, Pattern matcher,
+ int status, String responseContentType, String responsePath)
+ implements PostForwardRule {
+
+ public HtmlBasedBlocker(HostMatcherConfig hostMatcher,
+ String selector, Pattern matcher,
+ int status, String responseContentType,
+ String responsePath) {
+ if(status <= 0){
+ status = 500;
+ }
+ if(responseContentType==null) {
+ responseContentType = "text/html";
+ }
+
+ this.hostMatcher = hostMatcher;
+ this.selector = selector;
+ this.matcher = matcher;
+ this.status = status;
+ this.responseContentType = responseContentType;
+ this.responsePath = responsePath;
+ }
+
+ @Override
+ public boolean processRequest(FullHttpRequest fullHttpRequest, FullHttpResponse response, HttpResponseContentAccessor responseContentAccessor, Channel channel) {
+ String contentType = response.headers().get("Content-Type");
+ if(contentType.startsWith("text/html")){
+ String html = responseContentAccessor.getAsString();
+ Document doc = Jsoup.parse(html);
+ for(Element element : doc.select(selector)){
+ if(matcher.matcher(element.html()).matches()){
+ FullHttpResponse newResponse;
+ try{
+ newResponse = new DefaultFullHttpResponse(
+ HttpVersion.HTTP_1_1,
+ HttpResponseStatus.valueOf(status),
+ Unpooled.copiedBuffer(getResponseBytes())
+ );
+ newResponse.headers().add("Content-Type", contentType);
+ }catch(IOException e){
+ throw new UncheckedIOException(e);
+ }
+ channel.writeAndFlush(newResponse);
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private byte[] getResponseBytes() throws IOException {
+ if(responsePath == null){
+ return """
+
+
+
+ Blocked
+
+
+ Content has been blocked!
+
+ HTTPs-intercept blocked this response.
+
+
+
+ """.getBytes();
+ }
+ return Files.readAllBytes(Path.of(responsePath));
+ }
+
+}
diff --git a/src/main/java/io/github/danthe1st/httpsintercept/rules/SetHeaderRule.java b/src/main/java/io/github/danthe1st/httpsintercept/rules/pre/SetRequestHeaderRule.java
similarity index 66%
rename from src/main/java/io/github/danthe1st/httpsintercept/rules/SetHeaderRule.java
rename to src/main/java/io/github/danthe1st/httpsintercept/rules/pre/SetRequestHeaderRule.java
index abbcf2f..e41f867 100644
--- a/src/main/java/io/github/danthe1st/httpsintercept/rules/SetHeaderRule.java
+++ b/src/main/java/io/github/danthe1st/httpsintercept/rules/pre/SetRequestHeaderRule.java
@@ -1,18 +1,19 @@
-package io.github.danthe1st.httpsintercept.rules;
+package io.github.danthe1st.httpsintercept.rules.pre;
import java.util.Map;
import io.github.danthe1st.httpsintercept.config.HostMatcherConfig;
+import io.github.danthe1st.httpsintercept.rules.PreForwardRule;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.FullHttpRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public record SetHeaderRule(HostMatcherConfig hostMatcher,
+public record SetRequestHeaderRule(HostMatcherConfig hostMatcher,
Map headers)
implements PreForwardRule {
- private static final Logger LOG = LoggerFactory.getLogger(SetHeaderRule.class);
+ private static final Logger LOG = LoggerFactory.getLogger(SetRequestHeaderRule.class);
@Override
public boolean processRequest(FullHttpRequest fullHttpRequest, Channel channel) {