SlingFilter for injecting additional markup into response: IllegalStateException
Hi,
I'm trying to write a custom Sling Filter for injecting additional HTML markup into the response.
Original response:
<html> <head> ... </head> <body> ... </body> </html>
Response after custom filter:
<html> <head> ... <custom-tag> ... </custom-tag> </head> <body> ... </body> </html>
This is the filter I wrote using Sling Filters:
import java.io.CharArrayWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.sling.SlingFilter; import org.apache.felix.scr.annotations.sling.SlingFilterScope; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.day.cq.wcm.api.Page; @SlingFilter(generateComponent = false, generateService = true, order = -50001, scope = SlingFilterScope.REQUEST) @Component(immediate = true, metatype = false) public class TealiumFilter implements Filter { private Logger logger = LoggerFactory.getLogger(TealiumFilter.class); public void init(FilterConfig filterConfig) throws ServletException { } @Activate protected void activate(final Map<String, Object> props) { logger.warn("***** TEALIUM FILTER *****"); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request; Resource resource = slingRequest.getResource(); if(resource != null && !resource.getPath().contains("qfusion/")) { chain.doFilter(request, response); return; } Page page = resource.adaptTo(Page.class); CharResponseWrapper responseWrapper = new CharResponseWrapper((HttpServletResponse) response); chain.doFilter(request, responseWrapper); // Get writer must be called after chain.doFilter // otherwise request for non html resources (images, css, js, etc.) // results in an IllegalStateException PrintWriter out = response.getWriter(); String servletResponse = new String(responseWrapper.toString()); if(servletResponse != null && servletResponse.length() > 0 && // Servlet response must be non empty responseWrapper.getContentType().contains("text/html") && // Servlet response must be html page != null && // The resource the request points to must resolve to a CQ Page servletResponse.contains("<head>")) { // Servlet response must contain head tag logger.warn("**** APPLYING TEALIUM FILTER ****"); CharArrayWriter caw = new CharArrayWriter(); caw.write(servletResponse.substring(0, servletResponse.indexOf("</head>")-1)); //logger.warn("before manipulation: " + caw.toString()); caw.write("<meta name=\"og:title\" content=\"og:"+ page.getTitle() +"\" />"); caw.write(servletResponse.substring(servletResponse.indexOf("</head>")-1, servletResponse.length())); //logger.warn("after manipulation: " + caw.toString()); response.setContentLength(caw.toString().length()); out.write(caw.toString()); } else { out.write(servletResponse); } out.close(); } public void destroy() { } }The problem here is the line of code for getting the PrintWriter from the response. If I move this line of code *before* the call to chain.doFilter then I have an IllegalStateException for all the requests that do not point to an HTML resource (css, js, images, ...).
chain.doFilter(request, responseWrapper); // Get writer must be called after chain.doFilter // otherwise request for non html resources (images, css, js, etc.) // results in an IllegalStateException PrintWriter out = response.getWriter();
Why I have this exception only for non-html resources? Do you have any real example of implementation of Sling Filter that modifies the HTML response sent to the client?
Thank you in advance!
