Last active
December 28, 2020 13:10
-
-
Save ppkarwasz/925520383962ea37aa3025882f71640a to your computer and use it in GitHub Desktop.
An example how to register `ProxyServlet` instances during runtime.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package pl.copernik.servlet; | |
import java.io.IOException; | |
import java.util.Collections; | |
import java.util.Enumeration; | |
import java.util.Map.Entry; | |
import java.util.Objects; | |
import java.util.TreeMap; | |
import javax.servlet.ServletConfig; | |
import javax.servlet.ServletContext; | |
import javax.servlet.ServletException; | |
import javax.servlet.http.HttpServlet; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpServletRequestWrapper; | |
import javax.servlet.http.HttpServletResponse; | |
import org.mitre.dsmiley.httpproxy.ProxyServlet; | |
public class MetaProxyServlet extends HttpServlet { | |
private static final long serialVersionUID = 1L; | |
/** | |
* To configure a {@link ProxyServlet} without modifying its code. | |
*/ | |
private static class ProxyServletConfig implements ServletConfig { | |
private static final String P_TARGET_URI = "targetUri"; | |
private final String servletName; | |
private final ServletContext servletContext; | |
private final String targetUri; | |
public ProxyServletConfig(String servletName, ServletContext servletContext, String targetUri) { | |
this.servletName = servletName; | |
this.servletContext = servletContext; | |
this.targetUri = targetUri; | |
} | |
@Override | |
public String getServletName() { | |
return servletName; | |
} | |
@Override | |
public ServletContext getServletContext() { | |
return servletContext; | |
} | |
@Override | |
public String getInitParameter(String name) { | |
return P_TARGET_URI.equals(name) ? targetUri : null; | |
} | |
@Override | |
public Enumeration<String> getInitParameterNames() { | |
return Collections.enumeration(Collections.singleton(P_TARGET_URI)); | |
} | |
} | |
/** | |
* Serves to modify the pathInfo of the request. | |
*/ | |
private static class RewrittenServletRequest extends HttpServletRequestWrapper { | |
private final String pathInfo; | |
public RewrittenServletRequest(HttpServletRequest request, String pathInfo) { | |
super(request); | |
this.pathInfo = pathInfo; | |
} | |
@Override | |
public String getPathInfo() { | |
return pathInfo; | |
} | |
} | |
private TreeMap<String, ProxyServlet> proxyServlets = new TreeMap<>(); | |
/** | |
* Adds a reverse proxy between {@code pathPrefix} of this servlets namespace | |
* and {@code targetUri}. | |
* | |
* @param pathPrefix | |
* must start with '/' | |
* @param targetUri | |
* URI to be proxied | |
* @throws ServletException | |
*/ | |
public void addRedirect(String pathPrefix, String targetUri) throws ServletException { | |
Objects.requireNonNull(pathPrefix); | |
Objects.requireNonNull(targetUri); | |
final ProxyServlet servlet = new ProxyServlet(); | |
servlet.init(new ProxyServletConfig(pathPrefix, getServletContext(), targetUri)); | |
proxyServlets.put(pathPrefix, servlet); | |
} | |
@Override | |
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { | |
String pathInfo = req.getPathInfo(); | |
Entry<String, ProxyServlet> entry = proxyServlets.floorEntry(pathInfo); | |
// entry.getKey() precedes, but not necessarily is a prefix for pathInfo | |
if (entry != null && pathInfo.startsWith(entry.getKey())) { | |
String rewrittenPathInfo = pathInfo.substring(entry.getKey().length()); | |
entry.getValue()// | |
.service(new RewrittenServletRequest(req, rewrittenPathInfo), resp); | |
} else { | |
resp.sendError(HttpServletResponse.SC_NOT_FOUND); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment