On Sun, Oct 4, 2015 at 2:03 PM, Michael Greco <mike.james.gr...@gmail.com>
wrote:

> First time post here.
>
> Using :
> Tomcat 8.0.26
> JDK1.8.0 update 51
> Apache MyFaces 2.2.8.
> Maven build of webapp war file
> Chrome  45.0.2454.101 m 64 bit
> Windows 7 64 bit
>
> Trying to rewrite the entire request body in a filter using a http request
> wrapper.  Not entirely sure if this is the right approach or even possible
> but researching similar examples it seems this approach should work.
> Created a simple test case with a one page test app, expecting the
> index.xhtml page's text value of  "Welcome" to be replaced with the text
> "NEW TEXT HERE" found in the filter code, but I only get "Welcome" back
> when the page is rendered in the browser.
>
> Below is what I have in the index page, the filter and the web.xml and the
> pom.xml.  The reason I can see is that the getInputStream() or getReader()
> calls are never called by the FacesServlet in the extended
> HttpServletRequestWrapper.  I did override the getParameter function to put
> some simple debug output in there to ensure the wrapped request was
> actually used, so I know it's definitely getting into this class but not
> calling the methods that would return it the new body content.
>
> I even tried to re-read the entire request in the getParametersMap() from
> examples I found on the web, but this didn't seen to do the job either.  It
> seems that the request body is somehow cached somewhere / somehow and not
> changable?
>
> Thanks in advance for any insight on this.
>
> index page code (index.xhtml) :
>
> ---------------------------------------------------------------------------------
> <!DOCTYPE html>
> <html lang="en"
>   xmlns="http://www.w3.org/1999/xhtml";
>   xmlns:jsf="http://xmlns.jcp.org/jsf";
>   xmlns:h="http://xmlns.jcp.org/jsf/html";>
> <head jsf:id="head">
> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
> <title>Test Webapp</title>
> </head>
> <body jsf:id="body">
>     <div><h1>Welcome</h1></div>
> </body>
> </html>
>
> Filter code :
> --------------------------------------------------------------------------
> package com.testwebapp.reqrewrite.filter;
>
> import java.io.BufferedReader;
> import java.io.ByteArrayInputStream;
> import java.io.IOException;
> import java.io.InputStreamReader;
>
> import javax.servlet.Filter;
> import javax.servlet.FilterChain;
> import javax.servlet.FilterConfig;
> import javax.servlet.ReadListener;
> import javax.servlet.ServletException;
> import javax.servlet.ServletInputStream;
> import javax.servlet.ServletRequest;
> import javax.servlet.ServletResponse;
> import javax.servlet.http.HttpServletRequest;
> import javax.servlet.http.HttpServletRequestWrapper;
>
> public class RewriteBodyTestFilter implements Filter {
>
> public void init(FilterConfig filterConfig) throws ServletException {
> return;
> }
>
> public void doFilter(ServletRequest request, ServletResponse response,
> FilterChain chain)
> throws IOException, ServletException {
> String newReqBody = new String("<div><h1>NEW TEXT HERE</h1></div>");
> HttpServletRequest req = (HttpServletRequest)request;
> RewriteBodyRequestWrapper rewriteBodyRequestWrapper = new
> RewriteBodyRequestWrapper(req, newReqBody);
> chain.doFilter(rewriteBodyRequestWrapper, response);
> }
>
> public void destroy() {
> return;
> }
> class RewriteBodyRequestWrapper extends HttpServletRequestWrapper {
>
> private byte[] buffer;
>
> public RewriteBodyRequestWrapper(HttpServletRequest req, String reqBody)
> throws IOException {
> super(req);
> System.out.println("entering RewriteBodyRequestWrapper() constructor");
> this.buffer = reqBody.getBytes();
> }
>
> @Override
> public ServletInputStream getInputStream() {
> System.out.println("entering
> RewriteBodyRequestWrapper().getInputStream()");
> try {
> ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
> BufferedServletInputStream bsis = new BufferedServletInputStream(bais);
> return bsis;
> } catch (Exception ex) {
> ex.printStackTrace();
> throw new RuntimeException(ex);
> }
> }
>
> @Override
> public BufferedReader getReader() {
> System.out.println("entering RewriteBodyRequestWrapper().getReader()");
> InputStreamReader isr = new InputStreamReader(getInputStream());
> return new BufferedReader(isr);
> }
>
> }
> class BufferedServletInputStream extends ServletInputStream  {
>
> ByteArrayInputStream bais;
>
> public BufferedServletInputStream(ByteArrayInputStream bais) {
> this.bais = bais;
> }
>
> @Override
> public int available() {
> return bais.available();
> }
>
> @Override
> public boolean isFinished() {
> return bais.available() == 0;
> }
>
> @Override
> public boolean isReady() {
> return true;
> }
>
> @Override
> public void setReadListener(ReadListener readListener) {
> return;
> }
>
> @Override
> public int read() {
> return bais.read();
> }
>
> @Override
> public int read(byte[] buf) {
> return this.read(buf, 0, buf.length);
> }
>
> @Override
> public int read(byte[] buf, int off, int len) {
> return bais.read(buf, off, len);
> }
>
> }
> }
>
> web.xml code:
>
> --------------------------------------------------------------------------------------------------
> <?xml version="1.0" encoding="ISO-8859-1"?>
> <web-app xmlns="http://java.sun.com/xml/ns/j2ee"; xmlns:xsi="
> http://www.w3.org/2001/XMLSchema-instance";
> xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
> http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd";
> metadata-complete="true" version="3.0">
>
> <display-name>Test Webapp Req Rewrite</display-name>
>
> <!-- Change to "Production" when you are ready to deploy -->
> <context-param>
> <param-name>javax.faces.PROJECT_STAGE</param-name>
> <param-value>Development</param-value>
> </context-param>
>
> <!-- JSF mapping -->
> <servlet>
> <servlet-name>FacesServlet</servlet-name>
> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
> <load-on-startup>1</load-on-startup>
> </servlet>
>
> <!-- Map these files with JSF -->
> <servlet-mapping>
> <servlet-name>FacesServlet</servlet-name>
> <url-pattern>/faces/*</url-pattern>
> </servlet-mapping>
>
> <!-- Session timeout -->
> <session-config>
> <session-timeout>30</session-timeout>
> </session-config>
>
> <!-- Welcome page -->
> <welcome-file-list>
> <welcome-file>faces/index.xhtml</welcome-file>
> </welcome-file-list>
>
> <!-- Filters -->
> <filter>
> <filter-name>RewriteBodyTestFilter</filter-name>
> <filter-class>com.testwebapp.reqrewrite.filter.RewriteBodyTestFilter
> </filter-class>
> </filter>
>
> <!-- Filter mappings / chain ordering -->
> <filter-mapping>
> <filter-name>RewriteBodyTestFilter</filter-name>
> <servlet-name>FacesServlet</servlet-name>
> <dispatcher>REQUEST</dispatcher>
> <dispatcher>FORWARD</dispatcher>
> </filter-mapping>
>
> </web-app>
>
> pom.xml :
>
> -------------------------------------------------------------------------------------
> <project xmlns="http://maven.apache.org/POM/4.0.0"; xmlns:xsi="
> http://www.w3.org/2001/XMLSchema-instance";
>   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
> http://maven.apache.org/maven-v4_0_0.xsd";>
>   <modelVersion>4.0.0</modelVersion>
>   <groupId>com.testwebapp.reqrewrite</groupId>
>   <artifactId>reqrewrite</artifactId>
>   <packaging>war</packaging>
>   <version>1.0-SNAPSHOT</version>
>   <name>reqrewrite Maven Webapp</name>
>   <url>http://maven.apache.org</url>
> <dependencies>
> <dependency>
> <groupId>javax.servlet</groupId>
> <artifactId>javax.servlet-api</artifactId>
> <version>3.1.0</version>
> <scope>provided</scope>
> </dependency>
> <dependency>
> <groupId>org.apache.myfaces.core</groupId>
> <artifactId>myfaces-api</artifactId>
> <version>2.2.8</version>
> </dependency>
> <dependency>
> <groupId>org.apache.myfaces.core</groupId>
> <artifactId>myfaces-impl</artifactId>
> <version>2.2.8</version>
> </dependency>
> </dependencies>
>   <build>
>     <finalName>reqrewrite</finalName>
>   </build>
> </project>
>
>
> I think I might know what is going on now.  A specific
HttpServletRequestWrapper superclass method is being invoked first
(something other than getInputStream() and getReader()) and my overridden
methods getInputStream() and getReader() of my subclass are not being
invoked because of this, which leaves me to having to figure out this first
method invoked in the FacesServlet execution path that later invokes
getInputStream() and getReader() and then override this as well?  I really
think it would be a bad idea for me to try to implement/override more of
the container's request object methods beyond what I've done already.  Is
there another design pattern here that I can utilize to get around this
issue?  I would assume this issue probably varies from container to
container depending on how the server implements the seeded request classes.
(Sorry for the Top Post, and not sure if this next identical response will
be Bottom Post until I try, using Gmail web client)

Thanks
Mike

Reply via email to