XForwardedForCondition.java

package com.ziesemer.utils.web.addressFilter.conditions;

import java.net.InetAddress;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;

/**
 * @author Mark A. Ziesemer
 * 	<a href="http://www.ziesemer.com.">&lt;www.ziesemer.com&gt;</a>
 */
public class XForwardedForCondition implements ICondition{
	
	protected static final Pattern CHAIN_SPLIT = Pattern.compile("\\s*,\\s*");
	
	protected final int proxyIndex;
	protected final List<IAddressChecker> checkers;
	
	public XForwardedForCondition(final List<IAddressChecker> checkers, final int proxyIndex){
		this.proxyIndex = proxyIndex;
		this.checkers = checkers;
	}
	
	public boolean checkCondition(final ServletRequest sr) throws Exception{
		if(!(sr instanceof HttpServletRequest)){
			return false;
		}
		
		final HttpServletRequest hsr = (HttpServletRequest)sr;
		final String forward = hsr.getHeader("X-Forwarded-For");
		
		InetAddress ip = null;
		if(forward != null){
			final String[] chain = CHAIN_SPLIT.split(forward);
			if(chain.length - 1 > proxyIndex){
				return false;
			}
			ip = InetAddress.getByName(chain[chain.length - 1 - proxyIndex]);
		}
		
		for(final IAddressChecker checker : checkers){
			if(checker.matches(ip, null)){
				return true;
			}
		}
		return false;
	}
	
	public int getProxyIndex(){
		return proxyIndex;
	}
	
	/**
	 * <p>
	 * 	Returns a read-only view of the checkers checked against, primarily for unit testing.
	 * </p>
	 */
	public List<IAddressChecker> getCheckers(){
		return Collections.unmodifiableList(checkers);
	}
	
}