[ https://issues.apache.org/jira/browse/WW-5496?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17906112#comment-17906112 ]
Günter Paul commented on WW-5496: --------------------------------- Filter-class {code:java} package de.guenterpaul.servlet;import jakarta.servlet.*; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger;import java.util.StringTokenizer; public class BlankFilter implements Filter { @Override public void init(FilterConfig pFilterConfig) { setTrimOnly(pFilterConfig.getInitParameter("trimOnly")); if (m_Logger.isDebugEnabled()) m_Logger.debug("init filter: " + this); } @Override public void doFilter(ServletRequest pServletRequest, ServletResponse pServletResponse, FilterChain pFilterChain) { HttpServletRequest lHttpServletRequest = (HttpServletRequest) pServletRequest; if (m_Logger.isInfoEnabled()) m_Logger.info("Start Blank-Filter >" + lHttpServletRequest.getRequestURI() + "< " + this); try { HttpServletResponse lHttpServletResponse = (HttpServletResponse) pServletResponse; StringResponseWrapper lResponseWrapper = new StringResponseWrapper(lHttpServletResponse); pFilterChain.doFilter(pServletRequest,lResponseWrapper); if (m_Logger.isDebugEnabled()) m_Logger.debug("ContentType >" + lResponseWrapper.getContentType() + "<"); if ( (lResponseWrapper.getContentType() != null) && (lResponseWrapper.getContentType().startsWith("text/html")) ) { if (m_Logger.isInfoEnabled()) { m_Logger.info("BlankFilter Text >" + lResponseWrapper.getContentType() + "< Size: " + lResponseWrapper.getBufferSize()); } StringBuilder lStringBuffer = new StringBuilder(); String lsResponse = lResponseWrapper.toString().trim(); if (m_Logger.isDebugEnabled()) { m_Logger.debug("Response >" + lsResponse + "<"); } lsResponse = lsResponse.replaceAll("\r\n", "\n"); StringTokenizer lStringTokenizer = new StringTokenizer(lsResponse, "\n"); while (lStringTokenizer.hasMoreTokens()) { String lsZeile = lStringTokenizer.nextToken().trim(); if (m_Logger.isDebugEnabled()) m_Logger.debug("Zeile >" + lsZeile + "<"); if (lsZeile.isEmpty() == false) { lStringBuffer.append(lsZeile.trim()); if (isTrimOnly() == true) { lStringBuffer.append("\r\n"); } } } if (m_Logger.isInfoEnabled()) m_Logger.info("Laenge Ausgabe: " + lStringBuffer.toString().length()); if (m_Logger.isDebugEnabled()) { m_Logger.debug(lStringBuffer); } lHttpServletResponse.setContentType(lResponseWrapper.getContentType()); lHttpServletResponse.setContentLength(lStringBuffer.toString().length()); lHttpServletResponse.getWriter().print(lStringBuffer); } else { m_Logger.debug("Standard Ausgabe: " + lResponseWrapper.getBufferSize()); if ( (lResponseWrapper.getBufferSize() > 0) && (lResponseWrapper.toString() != null) ) { pServletResponse.getOutputStream().write(lResponseWrapper.toString().getBytes()); } } if (m_Logger.isDebugEnabled()) { m_Logger.debug("Ende Request BlankFilter >" + lHttpServletRequest.getRequestURI() + "<"); } } catch (Exception ex) { m_Logger.error("Fehler: " + ex.getMessage(), ex); } if (m_Logger.isDebugEnabled()) m_Logger.debug("Ende Blank-Filter"); } @Override public void destroy() { if (m_Logger.isDebugEnabled()) m_Logger.debug("destroy filter"); } public boolean isTrimOnly() { return m_bTrimOnly; } public void setTrimOnly(boolean pbTrimOnly) { if (m_Logger.isDebugEnabled()) m_Logger.debug("B: TrimOnly: " + pbTrimOnly); this.m_bTrimOnly = pbTrimOnly; } public void setTrimOnly(String psTrimOnly) { boolean lbTrimOnly = isTrimOnly(); if ((psTrimOnly != null) && (psTrimOnly.isEmpty() == false) ) { if (psTrimOnly.toLowerCase().equals(Boolean.TRUE.toString())) { lbTrimOnly = true; } else if (psTrimOnly.toLowerCase().equals(Boolean.FALSE.toString())) { lbTrimOnly = false; } } if (m_Logger.isDebugEnabled()) m_Logger.debug("S: TrimOnly >" + psTrimOnly + "< : " + lbTrimOnly); setTrimOnly(lbTrimOnly); } @Override public String toString() { return "BlankFilter{" + "m_bTrimOnly=" + m_bTrimOnly + '}'; } private static final Logger m_Logger = LogManager.getLogger(BlankFilter.class.getName()); private boolean m_bTrimOnly = false; } {code} ResponseWrapper-class {code:java} package de.guenterpaul.servlet; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.WriteListener; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponseWrapper;import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter;public class StringResponseWrapper extends HttpServletResponseWrapper { private final ByteArrayOutputStream capture; private ServletOutputStream output; private PrintWriter writer; public StringResponseWrapper(HttpServletResponse response) { super(response); capture = new ByteArrayOutputStream(response.getBufferSize()); } @Override public ServletOutputStream getOutputStream() { if (writer != null) { throw new IllegalStateException("getWriter() has already been called on this response."); } if (output == null) { // inner class - lets the wrapper manipulate the response output = new ServletOutputStream() { @Override public boolean isReady() { return true; } @Override public void setWriteListener(WriteListener writeListener) { } @Override public void write(int b) { capture.write(b); } @Override public void flush() throws IOException { capture.flush(); } @Override public void close() throws IOException { capture.close(); } }; } return output; } @Override public PrintWriter getWriter() throws IOException { if (output != null) { throw new IllegalStateException("getOutputStream() has already been called on this response."); } if (writer == null) { writer = new PrintWriter(new OutputStreamWriter(capture, getCharacterEncoding())); } return writer; } @Override public void flushBuffer() throws IOException { super.flushBuffer(); if (writer != null) { writer.flush(); } else if (output != null) { output.flush(); } } public byte[] getCaptureAsBytes() throws IOException { flushBuffer(); if (writer != null) { writer.close(); } else if (output != null) { output.close(); } return capture.toByteArray(); } public String getCaptureAsString() throws IOException { return new String(getCaptureAsBytes(), getCharacterEncoding()); } @Override public String toString() { try { return getCaptureAsString(); } catch (IOException e) { return super.toString(); } } } {code} > Struts filter and HttpServletResponseWrapper > -------------------------------------------- > > Key: WW-5496 > URL: https://issues.apache.org/jira/browse/WW-5496 > Project: Struts 2 > Issue Type: Bug > Components: Core > Affects Versions: 7.0.0 > Reporter: Günter Paul > Priority: Minor > Fix For: 7.1.0 > > > I've been using a servlet filter for a long time. It removes spaces in the > lines (trim()) and line breaks (only for *.action requests). > The filter is installed in the web.xml before the struts filter. It works > very well so far, even with the current Struts 7.0.0-M10 version. > Until now I was using Tomcat 10. After switching to Tomcat 11, only blank > pages are displayed. > If I use a web-application without struts, the filter works fine. Only when > the Struts filter (StrutsPrepareAndExecuteFilter) is installed does the > output of the wrapper appear to no longer be included in the output stream. -- This message was sent by Atlassian Jira (v8.20.10#820010)