diff --git a/src/main/java/io/github/danthe1st/httpsintercept/config/Config.java b/src/main/java/io/github/danthe1st/httpsintercept/config/Config.java index 4ffd564..8b81513 100644 --- a/src/main/java/io/github/danthe1st/httpsintercept/config/Config.java +++ b/src/main/java/io/github/danthe1st/httpsintercept/config/Config.java @@ -18,8 +18,7 @@ public record Config( HostMatcherConfig ignoredHosts, List preForwardRules, - List postForwardRules -) { + List postForwardRules) { public Config(@Nullable HostMatcherConfig ignoredHosts, @Nullable List preForwardRules, @Nullable List postForwardRules) { if(ignoredHosts == null){ @@ -38,7 +37,7 @@ public Config(@Nullable HostMatcherConfig ignoredHosts, @Nullable List(List.of(Map.entry(config.ignoredHosts(), new Object())), false); } - + private HostMatcher createMatcherFromRules(@UnderInitialization ServerHandlersInit this, List ruleList) { List> rules = new ArrayList<>(); for(T rule : ruleList){ diff --git a/src/main/java/io/github/danthe1st/httpsintercept/handler/http/HttpResponseContentAccessor.java b/src/main/java/io/github/danthe1st/httpsintercept/handler/http/HttpResponseContentAccessor.java index 6a65b13..1ce15f5 100644 --- a/src/main/java/io/github/danthe1st/httpsintercept/handler/http/HttpResponseContentAccessor.java +++ b/src/main/java/io/github/danthe1st/httpsintercept/handler/http/HttpResponseContentAccessor.java @@ -25,7 +25,7 @@ public String getAsString() { ensureBytesPresent(); return new String(bytes, StandardCharsets.UTF_8); } - + @EnsuresNonNull("bytes") private void ensureBytesPresent() { if(bytes == null){ diff --git a/src/main/java/io/github/danthe1st/httpsintercept/handler/http/IncomingHttpRequestHandler.java b/src/main/java/io/github/danthe1st/httpsintercept/handler/http/IncomingHttpRequestHandler.java index 952aa61..b02b587 100644 --- a/src/main/java/io/github/danthe1st/httpsintercept/handler/http/IncomingHttpRequestHandler.java +++ b/src/main/java/io/github/danthe1st/httpsintercept/handler/http/IncomingHttpRequestHandler.java @@ -85,16 +85,15 @@ private void forwardRequest(ChannelHandlerContext channelHandlerContext, FullHtt } } - // in case Netty caught an exception (e.g. the server is unreachable), // the client receives a 502 Bad Gateway response including the stack trace @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - LOG - .atError() - .addArgument(sniHandler::hostname) - .log("An exception occured trying to process a request to host '{}'", cause); - ctx.channel().close(); + LOG + .atError() + .addArgument(sniHandler::hostname) + .log("An exception occured trying to process a request to host '{}'", cause); + ctx.channel().close(); } private void writeException(Throwable cause, Channel channel) throws InterruptedException, IOException { diff --git a/src/main/java/io/github/danthe1st/httpsintercept/handler/http/ResponseHandler.java b/src/main/java/io/github/danthe1st/httpsintercept/handler/http/ResponseHandler.java index 1f6a83f..1fefb8e 100644 --- a/src/main/java/io/github/danthe1st/httpsintercept/handler/http/ResponseHandler.java +++ b/src/main/java/io/github/danthe1st/httpsintercept/handler/http/ResponseHandler.java @@ -40,7 +40,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception originalClientContext.channel().close(); ctx.channel().close(); } - + private void processRules(FullHttpResponse res) { HttpResponseContentAccessor contentAccessor = new HttpResponseContentAccessor(res); for(PostForwardRule rule : postForwardRules){ diff --git a/src/main/java/io/github/danthe1st/httpsintercept/handler/sni/CustomSniHandler.java b/src/main/java/io/github/danthe1st/httpsintercept/handler/sni/CustomSniHandler.java index aea9344..0d8b314 100644 --- a/src/main/java/io/github/danthe1st/httpsintercept/handler/sni/CustomSniHandler.java +++ b/src/main/java/io/github/danthe1st/httpsintercept/handler/sni/CustomSniHandler.java @@ -29,7 +29,7 @@ public CustomSniHandler(Mapping mapping, B this.clientBootstrapTemplate = clientBootstrapTemplate; ignoredHosts = ignoredHostMatcher; } - + @Override protected void replaceHandler(ChannelHandlerContext channelHandlerContext, String hostname, SslContext sslContext) throws Exception { ChannelPipeline pipeline = channelHandlerContext.pipeline(); @@ -39,7 +39,7 @@ protected void replaceHandler(ChannelHandlerContext channelHandlerContext, Strin boolean foundThis = false; - for(Iterator> it = pipeline.iterator();it.hasNext();) { + for(Iterator> it = pipeline.iterator(); it.hasNext();){ ChannelHandler handler = it.next().getValue(); if(foundThis){ it.remove(); diff --git a/src/main/java/io/github/danthe1st/httpsintercept/handler/sni/SNIHandlerMapping.java b/src/main/java/io/github/danthe1st/httpsintercept/handler/sni/SNIHandlerMapping.java index 13177a2..4ec0a69 100644 --- a/src/main/java/io/github/danthe1st/httpsintercept/handler/sni/SNIHandlerMapping.java +++ b/src/main/java/io/github/danthe1st/httpsintercept/handler/sni/SNIHandlerMapping.java @@ -39,7 +39,7 @@ public class SNIHandlerMapping implements Mapping { private final Map certificateCache = new ConcurrentHashMap<>(); private final KeyPair rootKeyPair; private final X509Certificate rootCert; - + private final KeyPair serverKeyPair; private SNIHandlerMapping() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException { @@ -87,7 +87,7 @@ public static SNIHandlerMapping createMapping() throws KeyStoreException, NoSuch Thread.startVirtualThread(mapping::runCleanupDaemon); return mapping; } - + private void runCleanupDaemon() { try{ while(true){// NOSONAR ended by potential InterruptedException (or more likely the virtual thread ending) @@ -101,7 +101,7 @@ private void runCleanupDaemon() { Thread.currentThread().interrupt(); } } - + @Override public SslContext map(String hostname) { LOG.debug("loadding certificate for hostname {}", hostname); diff --git a/src/main/java/io/github/danthe1st/httpsintercept/matcher/ConcatenatingIterator.java b/src/main/java/io/github/danthe1st/httpsintercept/matcher/ConcatenatingIterator.java new file mode 100644 index 0000000..234b3db --- /dev/null +++ b/src/main/java/io/github/danthe1st/httpsintercept/matcher/ConcatenatingIterator.java @@ -0,0 +1,29 @@ +package io.github.danthe1st.httpsintercept.matcher; + +import java.util.Collections; +import java.util.Iterator; +import java.util.Queue; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +final class ConcatenatingIterator<@NonNull T> extends IteratingIterator { + private final Queue> iterators; + private @Nullable Iterator current; + + ConcatenatingIterator(Queue> iterators) { + this.iterators = iterators; + current = iterators.poll(); + } + + @Override + protected Iterator findNextIterator() { + while(current != null && !current.hasNext()){ + current = iterators.poll(); + } + if(current == null){ + return Collections.emptyIterator(); + } + return current; + } +} \ No newline at end of file diff --git a/src/main/java/io/github/danthe1st/httpsintercept/matcher/FilterIterator.java b/src/main/java/io/github/danthe1st/httpsintercept/matcher/FilterIterator.java index 879cfda..1698a79 100644 --- a/src/main/java/io/github/danthe1st/httpsintercept/matcher/FilterIterator.java +++ b/src/main/java/io/github/danthe1st/httpsintercept/matcher/FilterIterator.java @@ -17,6 +17,7 @@ public FilterIterator(Iterator<@NonNull T> iterator, Predicate<@NonNull T> filte this.iterator = iterator; this.filter = filter; } + @Override @EnsuresNonNullIf(expression = "current", result = true) public boolean hasNext() { diff --git a/src/main/java/io/github/danthe1st/httpsintercept/matcher/HostMatcher.java b/src/main/java/io/github/danthe1st/httpsintercept/matcher/HostMatcher.java index 048c5d5..0d6c999 100644 --- a/src/main/java/io/github/danthe1st/httpsintercept/matcher/HostMatcher.java +++ b/src/main/java/io/github/danthe1st/httpsintercept/matcher/HostMatcher.java @@ -16,7 +16,6 @@ import io.github.danthe1st.httpsintercept.config.HostMatcherConfig; import org.checkerframework.checker.initialization.qual.UnderInitialization; import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; public final class HostMatcher<@NonNull T> { private final Map> exactHosts; @@ -48,9 +47,11 @@ public HostMatcher(List> configs, boole private void addToMap(@UnderInitialization HostMatcher this, Map> multimap, @NonNull T value, Set configValue, Function keyTransformer) { for(String host : configValue){ - multimap - .computeIfAbsent(keyTransformer.apply(host), h -> new ArrayList<@NonNull T>()) - .add(value); + multimap.merge( + keyTransformer.apply(host), + new ArrayList<>(), + (existing, emptyList) -> existing + ).add(value); } } @@ -71,24 +72,9 @@ private void addToMap(@UnderInitialization HostMatcher this, Map(hostRegexes, hostname)); iterators.add(wildcards.iterator()); - Iterator<@NonNull T> it = new IteratingIterator<@NonNull T>() { - private @Nullable Iterator<@NonNull T> current = iterators.poll(); - - @Override - protected Iterator<@NonNull T> findNextIterator() { - while(current != null && !current.hasNext()){ - current = iterators.poll(); - } - if(current == null){ - return Collections.emptyIterator(); - } - return current; - } - }; - - return distinctIterator(it); + return distinctIterator(new ConcatenatingIterator<>(iterators)); } - + private Iterator<@NonNull T> distinctIterator(Iterator<@NonNull T> it) { Set matchers = Collections.newSetFromMap(new IdentityHashMap<>()); return new FilterIterator<>(it, element -> { diff --git a/src/main/java/io/github/danthe1st/httpsintercept/matcher/HostPartIterator.java b/src/main/java/io/github/danthe1st/httpsintercept/matcher/HostPartIterator.java index 66b2840..d8e0e93 100644 --- a/src/main/java/io/github/danthe1st/httpsintercept/matcher/HostPartIterator.java +++ b/src/main/java/io/github/danthe1st/httpsintercept/matcher/HostPartIterator.java @@ -36,14 +36,14 @@ protected Iterator findNextIterator() { }while(nextIndex() != -1); return Collections.emptyIterator(); } - + private int nextIndex() { index = hostname.indexOf('.', index); if(index != -1){ index++; } if(index >= hostname.length()){ - index=-1; + index = -1; } return index; } diff --git a/src/main/java/io/github/danthe1st/httpsintercept/matcher/IteratingIterator.java b/src/main/java/io/github/danthe1st/httpsintercept/matcher/IteratingIterator.java index 482ce82..aefa9f3 100644 --- a/src/main/java/io/github/danthe1st/httpsintercept/matcher/IteratingIterator.java +++ b/src/main/java/io/github/danthe1st/httpsintercept/matcher/IteratingIterator.java @@ -10,7 +10,7 @@ abstract class IteratingIterator implements Iterator { public boolean hasNext() { return findNextIterator().hasNext(); } - + @Override public T next() { return findNextIterator().next(); 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 index c413138..4af9c6e 100644 --- a/src/main/java/io/github/danthe1st/httpsintercept/rules/post/HtmlBasedBlocker.java +++ b/src/main/java/io/github/danthe1st/httpsintercept/rules/post/HtmlBasedBlocker.java @@ -33,7 +33,7 @@ public HtmlBasedBlocker(HostMatcherConfig hostMatcher, if(status <= 0){ status = 500; } - if(responseContentType==null) { + if(responseContentType == null){ responseContentType = "text/html"; }