2012-11-28 50 views
6

我想修改過濾HTTP響應,並正在以下例外碼頭過濾器修改響應 - java.lang.IllegalStateException:作家

java.lang.IllegalStateException:作家在 組織.eclipse.jetty.server.Response.getOutputStream(Response.java:657) 在 javax.servlet.ServletResponseWrapper.getOutputStream(ServletResponseWrapper.java:142) 在 org.eclipse.jetty.servlets.ProxyServlet.service(ProxyServlet的.java:414) at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.jav一:643) 在 org.eclipse.jetty.servlet.ServletHandler $ CachedChain.doFilter(ServletHandler.java:1331) 在 com.cisco.vsx.node.proxy.http.RegexFilter.doFilter(RegexFilter.java: 36)

我正在使用SelectChannelSelector和ProxyServlet.Transparent代理。

下面是測試類

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(); 

的片斷這是過濾器類的代碼

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); 

不知道哪裏的東西是怎麼了。

回答

11

您的碼頭響應可以在兩個(技術上三個)不同的模式。一個是作家模式,另一個是流模式(第三個基本上是未定模式)。

如果您對'未定'響應調用getWriter(),那麼您將其置於Writer模式,這是無法逆轉的。如果稍後嘗試在流式傳輸模式下使用此響應(通過調用getOutputStream()),則會引發您看到的異常。

爲了解決這個問題,請不要在Writer模式下使用此響應,而是在OutputStream上「做你的事」。如果你在稍後的點(doChain後)訪問作家,你會得到相反的異常

java.lang.IllegalStateException:STREAM

代替。