Skip to content

Instantly share code, notes, and snippets.

@magicsih
Created March 19, 2019 01:03
Show Gist options
  • Save magicsih/cd9fa8b96e58fa7a8f977c82ad7a8d5f to your computer and use it in GitHub Desktop.
Save magicsih/cd9fa8b96e58fa7a8f977c82ad7a8d5f to your computer and use it in GitHub Desktop.
HttpProxyServer with Jetty 9.
public class CustomProxyServlet extends ProxyServlet {
private final Map<String, FilterableHost> filterMap;
public CustomProxyServlet() {
this.filterMap = new HashMap<>();
}
public CustomProxyServlet referHostFilterByUrl(String fromUrl, String toUrl) {
if(filterMap.containsKey(fromUrl)) {
filterMap.put(toUrl, filterMap.get(fromUrl));
return this;
} else {
throw new IllegalStateException("can't find " + fromUrl + " in filterMap. you should put hostFilter for " + fromUrl + " first");
}
}
public CustomProxyServlet addHostFilter(String url, FilterableHost filter) {
if(filterMap.containsKey(url) == false) {
filterMap.put(url, filter);
return this;
} else{
throw new IllegalStateException("host url " + url + " already exists");
}
}
@Override
protected void service(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
URL url = new URL(request.getRequestURL().toString()); // Extract host from URL
if(filterMap.containsKey(url.getHost())) {
final FilterableHost filterableHost = filterMap.get(url.getHost());
if(filterableHost.canHandle(url)) {
final AsyncContext asyncContext = request.startAsync();
// We do not timeout the continuation, but the proxy request
asyncContext.setTimeout(0);
filterableHost.process(request, response);
asyncContext.complete();
}
} else {
super.service(request, response);
}
}
@Override
protected Response.Listener newProxyResponseListener(HttpServletRequest request, HttpServletResponse response)
{
return new CustomProxyServletProxyResponseListener(request, response);
}
protected class CustomProxyServletProxyResponseListener extends Response.Listener.Adapter
{
private final HttpServletRequest request;
private final HttpServletResponse response;
protected CustomProxyServletProxyResponseListener(HttpServletRequest request, HttpServletResponse response)
{
this.request = request;
this.response = response;
}
@Override
public void onBegin(Response proxyResponse)
{
response.setStatus(proxyResponse.getStatus());
}
@Override
public void onHeaders(Response proxyResponse)
{
onServerResponseHeaders(request, response, proxyResponse);
}
@Override
public void onContent(final Response proxyResponse, ByteBuffer content, final Callback callback)
{
byte[] buffer;
int offset;
int length = content.remaining();
if (content.hasArray())
{
buffer = content.array();
offset = content.arrayOffset();
}
else
{
buffer = new byte[length];
content.get(buffer);
offset = 0;
}
onResponseContent(request, response, proxyResponse, buffer, offset, length, new Callback.Nested(callback)
{
@Override
public void failed(Throwable x)
{
super.failed(x);
proxyResponse.abort(x);
}
});
}
@Override
public void onComplete(Result result)
{
if (result.isSucceeded())
onProxyResponseSuccess(request, response, result.getResponse());
else
onProxyResponseFailure(request, response, result.getResponse(), result.getFailure());
}
}
}
public class DefaultFilterableHost implements FilterableHost {
@Override
public boolean canHandle(URL url) {
return url.getPath().endsWith("/somepath");
}
@Override
public void process(HttpServletRequest request, HttpServletResponse response) {
response.setStatus(HttpStatus.OK_200);
response.addHeader(HttpHeader.CONNECTION.asString(), HttpHeaderValue.KEEP_ALIVE.asString());
response.addHeader(HttpHeader.TRANSFER_ENCODING.asString(), HttpHeaderValue.CHUNKED.asString());
response.getOutputStream().write("some your revised response");
return response;
}
}
public interface FilterableHost {
boolean canHandle(URL url);
void process(final HttpServletRequest request, final HttpServletResponse response);
}
Server server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(8080);
server.addConnector(connector);
ConnectHandler proxy = new ConnectHandler();
server.setHandler(proxy);
CustomProxyServlet customProxyServlet = new CustomProxyServlet();
customProxyServlet.addHostFilter("maybe.somewhere.com", new DefaultFilterableHost()).referHostFilterByUrl("maybe.somewhere.com", "mightbe.somewhere.com");
// Setup proxy servlet
ServletContextHandler context = new ServletContextHandler(proxy, "/", ServletContextHandler.SESSIONS);
ServletHolder proxyServlet = new ServletHolder(customProxyServlet);
proxyServlet.setInitParameter("maxThreads", "10");
context.addServlet(proxyServlet, "/*");
server.start();
server.join();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment