Many times during testing there is a need to override interent data (IP, cookies, HTTP headers) to simulate different use cases.
Most of times I see code such as:
String ip = request.getRemoteAddr();
// for testing purposes
if ( configuredForTesting ) {
ip = getIpFromOtherSource();
}
There is an elegant way to overcome this clutter using javax.servlet.http.HttpServletRequestWrapper and servlet filters (javax.servlet.Filter), shown in the following classes:
import java.io.IOException;
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.HttpServletRequest;
public class QAFilter implements Filter {
public void init ( FilterConfig filterConfig ) throws ServletException {
}
public void doFilter ( ServletRequest request , ServletResponse response , FilterChain filterChain ) throws IOException, ServletException {
// wrap the request for QA
QARequestWrapper requestWrapper = new QARequestWrapper( (HttpServletRequest)request );
// pass the request/response on
filterChain.doFilter( requestWrapper, response );
}
public void destroy() {
}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class QARequestWrapper extends HttpServletRequestWrapper {
private String ip = null;
private List cookies = null;
private Map headers = null;
public QARequestWrapper ( HttpServletRequest request ) {
super ( request );
cookies = new ArrayList();
headers = new HashMap();
String ip = request.getParameter( "ip" );
if ( ip != null ) {
ip = ip.trim();
if ( ip.length() != 0 ) {
this.ip = ip;
}
}
String[] unparsedCookies = request.getParameterValues( "cookie" );
if ( unparsedCookies != null ) {
for ( int i = 0 ; i < unparsedCookies.length ; i++ ) {
String[] cookieDetails = unparsedCookies[i].split( "~!!~" );
Cookie cookie = new Cookie( cookieDetails[0], cookieDetails[1] );
cookies.add( cookie );
}
}
String[] unparsedHeaders = request.getParameterValues( "header" );
if ( unparsedHeaders != null ) {
for ( int i = 0 ; i < unparsedHeaders.length ; i++ ) {
String[] headerDetails = unparsedHeaders[i].split( "~!!~" );
String headerKey = headerDetails[0];
String headerValue = headerDetails[1];
List headerValueList = (List)headers.get( new IgnoreCaseString( headerKey ) );
if( headerValueList != null ) {
headerValueList.add( headerValue );
}
else {
List l = new ArrayList();
l.add( headerValue );
headers.put( new IgnoreCaseString( headerKey ), l );
}
}
}
}
public String getRemoteAddr() {
String out = null;
if ( ip != null ) {
out = ip;
}
else {
out = super.getRemoteAddr();
}
return out;
}
public Enumeration getHeaders ( String headerName ) {
Enumeration out = null;
if ( headers != null ) {
List headersFromUser = (List)headers.get( new IgnoreCaseString( headerName ) );
if ( headersFromUser != null ) {
out = Collections.enumeration( headersFromUser );
}
else {
out = super.getHeaders( headerName );
}
}
else {
out = super.getHeaders( headerName );
}
return out;
}
public String getHeader ( String headerName ) {
String out = null;
if ( headers != null ) {
List headersFromUser = (List)headers.get( new IgnoreCaseString( headerName ) );
if ( headersFromUser != null ) {
out = (String)headersFromUser.listIterator().next();
}
else {
out = super.getHeader( headerName );
}
}
else {
out = super.getHeader( headerName );
}
return out;
}
public Enumeration getHeaderNames() {
Enumeration out = null;
if ( headers != null && headers.size() > 0 ) {
HashSet actualKeySet = new HashSet( Collections.list( super.getHeaderNames() ) );
Set falseKeySet = headers.keySet();
List falseKeySetToString = new ArrayList( falseKeySet.size() );
for ( Iterator iter = falseKeySet.iterator ( ) ; iter.hasNext ( ) ; ) {
IgnoreCaseString header = (IgnoreCaseString)iter.next ( );
falseKeySetToString.add( header.toString() );
}
actualKeySet.removeAll( falseKeySetToString );
actualKeySet.addAll( falseKeySetToString );
out = Collections.enumeration( actualKeySet );
}
else {
out = super.getHeaderNames();
}
return out;
}
public Cookie[] getCookies() {
Cookie[] out = null;
if ( cookies != null && cookies.size() > 0 ) {
List cookiesList = new ArrayList( Arrays.asList( super.getCookies() ) );
for ( Iterator iterator = cookies.iterator() ; iterator.hasNext() ; ) {
Cookie userDefinedCookie = (Cookie)iterator.next();
for ( Iterator iter = cookiesList.iterator() ; iter.hasNext ( ) ; ) {
Cookie actualCookie = (Cookie)iter.next();
if ( actualCookie.getName().equals( userDefinedCookie.getName() ) ) {
cookiesList.remove( actualCookie );
break;
}
}
cookiesList.add( userDefinedCookie );
}
Cookie[] cookiesArray = new Cookie[ cookiesList.size() ];
cookiesList.toArray( cookiesArray );
out = cookiesArray;
}
else {
out = super.getCookies ( );
}
return out;
}
private static class IgnoreCaseString
{
private String string = null;
public IgnoreCaseString( String s ) {
string = s;
}
public boolean equals ( Object obj ) {
if ( ! ( obj instanceof IgnoreCaseString ) ) {
return false;
}
else {
return string.equalsIgnoreCase( ((IgnoreCaseString)obj).string );
}
}
public int hashCode() {
return string.toLowerCase().hashCode ( );
}
public String toString() {
return string;
}
}
}
Now configure your filter only on your QA environment deployment descriptor (web.xml):
qa_filter
QAFilter
qa_filter
/yourWebApp/someResource
The result: Now in your QA environment you can override internet data using HTTP parameters.