Skip to content

Instantly share code, notes, and snippets.

@qb20nh
Last active January 14, 2022 09:29
Show Gist options
  • Save qb20nh/e4e8b87cf15f14cbaa6fe779c0b87d60 to your computer and use it in GitHub Desktop.
Save qb20nh/e4e8b87cf15f14cbaa6fe779c0b87d60 to your computer and use it in GitHub Desktop.
Intercept Redirect
package kr.co.benew.iddle_admin.servlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.UnaryOperator;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import kr.co.benew.util.Values;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
public class HttpRedirectInterceptor extends HttpServletResponseWrapper {
public enum InterceptionReplacementRule {
APPLY_FIRST,
APPLY_ALL,
APPLY_LAST,
}
private @Setter InterceptionReplacementRule replacementRule = InterceptionReplacementRule.APPLY_FIRST;
public static interface Matcher extends BiFunction<String, String, Boolean> {
}
@AllArgsConstructor
@RequiredArgsConstructor
public enum InterceptionMatchRule {
STARTS_WITH("NOT_STARTS_WITH", (a, b) -> a.startsWith(b)),
INCLUDES("NOT_INCLUDES", (a, b) -> a.contains(b)),
ENDS_WITH("NOT_ENDS_WITH", (a, b) -> a.endsWith(b)),
MATCHES("NOT_MATCHES", (a, b) -> a.matches(b)),
EQUALS("NOT_EQUALS", (a, b) -> a.equals(b)),
EQUALS_IGNORE_CASE("NOT_EQUALS_IGNORE_CASE", (a, b) -> a.equalsIgnoreCase(b)),
EMPTY("NOT_EMPTY", (a, b) -> a != null && a.isEmpty()),
NOT_STARTS_WITH("STARTS_WITH"),
NOT_INCLUDES("INCLUDES"),
NOT_ENDS_WITH("ENDS_WITH"),
NOT_MATCHES("MATCHES"),
NOT_EQUALS("EQUALS"),
NOT_EQUALS_IGNORE_CASE("EQUALS_IGNORE_CASE"),
NOT_EMPTY("EMPTY");
@NonNull private final String opposite;
private Matcher matcher;
public InterceptionMatchRule not() {
return InterceptionMatchRule.valueOf(opposite);
}
public Matcher getMatcher() {
return Values.firstNonNull(matcher, (a, b) -> !not().getMatcher().apply(a, b));
}
}
public static interface Replacer extends UnaryOperator<String> {
}
@RequiredArgsConstructor
@AllArgsConstructor
@Getter
public static class InterceptionRule {
@NonNull private InterceptionMatchRule type;
@NonNull private String pattern;
private @Setter Replacer replacer;
public boolean matches(@NonNull String self) {
Boolean bool = type.getMatcher().apply(self, pattern);
return Boolean.TRUE.equals(bool);
}
@SuppressWarnings("unused")
public String replace(@NonNull String self) {
return replace(self, this.replacer);
}
public String replace(@NonNull String self, @NonNull Replacer replacer) {
return Values.firstNonNull(replacer, this.replacer, s->s).apply(self);
}
@SuppressWarnings("unused")
public String matchAndReplace(@NonNull String self, Replacer replacer) {
if (matches(self)) {
return replace(self, replacer);
}
return self;
}
}
private List<InterceptionRule> rules = new ArrayList<>();
public HttpRedirectInterceptor addRule(@NonNull InterceptionRule rule) {
rules.add(rule);
return this;
}
public void setRules(@NonNull List<InterceptionRule> rules) {
this.rules = rules;
}
public HttpRedirectInterceptor(HttpServletResponse response) {
super(response);
}
public HttpRedirectInterceptor(ServletResponse response) {
this((HttpServletResponse) response);
}
@Override
public void sendRedirect(String location) throws IOException {
InterceptionRule firstMatch = null;
InterceptionRule lastMatch = null;
for (InterceptionRule rule : rules) {
if (firstMatch != null) break;
if (rule.matches(location)) {
switch (replacementRule) {
case APPLY_FIRST:
firstMatch = rule;
location = rule.replace(location);
break;
case APPLY_ALL:
location = rule.replace(location);
break;
case APPLY_LAST:
lastMatch = rule;
break;
default:
break;
}
}
}
if (lastMatch != null) {
location = lastMatch.replace(location);
}
super.sendRedirect(location);
}
}
package kr.co.benew.iddle_admin.servlet.filter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import kr.co.benew.iddle_admin.servlet.HttpRedirectInterceptor;
import kr.co.benew.iddle_admin.servlet.HttpRedirectInterceptor.InterceptionMatchRule;
import kr.co.benew.iddle_admin.servlet.HttpRedirectInterceptor.InterceptionRule;
@WebFilter("/*")
public class RedirectRewriteFilter implements Filter {
List<InterceptionRule> rules;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
rules = new ArrayList<>();
rules.add(new InterceptionRule(InterceptionMatchRule.STARTS_WITH, "https://", s -> "http"+s.substring(5)));
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpRedirectInterceptor wrapped = new HttpRedirectInterceptor(response);
wrapped.setRules(rules);
chain.doFilter(request, wrapped);
}
@Override
public void destroy() {
rules.clear();
rules = null;
}
}
@qb20nh
Copy link
Author

qb20nh commented Jan 14, 2022

Updated to fix rules not being applied

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment