I am trying to modify the http response in a filter and am getting the following exception
java.lang.IllegalStateException: WRITER at org.eclipse.jetty.server.Response.getOutputStream(Response.java:657) at javax.servlet.ServletResponseWrapper.getOutputStream(ServletResponseWrapper.java:142) at org.eclipse.jetty.servlets.ProxyServlet.service(ProxyServlet.java:414) at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:643) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1331) at com.cisco.vsx.node.proxy.http.RegexFilter.doFilter(RegexFilter.java:36)
I am using SelectChannelSelector and ProxyServlet.Transparent proxy.
Below is the snippet from test class
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
ProxyServlet.Transparent p1 = new ProxyServlet.Transparent("/proxy",
"www.cisco.com", 80);
ServletHolder servletHolder = new ServletHolder(p1);
context.addServlet(servletHolder, "/proxy/*");
context.addFilter(new FilterHolder(RegexFilter.class), "/*", null);
server.setHandler(context);
server.start();
server.join();
This is the code from filter class
PrintWriter out = response.getWriter();
CharResponseWrapper wrapper = new CharResponseWrapper((HttpServletResponse) response);
chain.doFilter(request, wrapper);
String html = wrapper.toString();
if (regex != null && response.getContentType() != null
&& response.getContentType().startsWith("text/html")) {
Matcher matcher = regex.matcher(html);
Map<Integer, Integer> matches = new LinkedHashMap<Integer, Integer>();
while (matcher.find()) {
int start = matcher.start(1);
System.out.println("START" + start);
int end = matcher.end(1);
System.out.println("END" + end);
matches.put(start, end - start);
}
StringBuffer sb = new StringBuffer();
int start = 0;
for (int startIndex : matches.keySet()) {
String str = html.substring(start, startIndex) + "/proxy/";
sb.append(str);
start = startIndex + matches.get(startIndex);
}
html = sb.toString();
}
response.setContentLength(html.getBytes().length);
out.write(html);
Not sure where stuff is going wrong.
Your Jetty Response can be in two (technically three) distinct modes. One is the writer mode, the other one is the streaming mode (and the third one is basically the undecided mode).
If you call getWriter()
on an 'undecided' response, you're putting it in writer mode, which can't be reversed. If something later tries to use this response in streaming mode (by calling getOutputStream()
) the Exception you see is thrown.
To fix this, don't use this response in writer mode and 'do your thing' on the OutputStream instead. If you were accessing the writer at a later point (after doChain), you'd get the inverse Exception
java.lang.IllegalStateException: STREAM
instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With