Index: src/test/java/org/mortbay/jetty/handler/ContextHandlerTest.java =================================================================== --- src/test/java/org/mortbay/jetty/handler/ContextHandlerTest.java (revision 2132) +++ src/test/java/org/mortbay/jetty/handler/ContextHandlerTest.java (working copy) @@ -25,7 +25,16 @@ import junit.framework.TestCase; import org.mortbay.resource.Resource; +import org.mortbay.jetty.Server; +import org.mortbay.jetty.LocalConnector; +import org.mortbay.jetty.Connector; +import org.mortbay.jetty.Request; +import org.mortbay.jetty.HttpConnection; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletException; + /** * @version $Revision$ */ @@ -71,4 +80,87 @@ return root; } + + public void testVirtualHostNormalization() + throws Exception + { + Server server = new Server(); + LocalConnector connector = new LocalConnector(); + server.setConnectors(new Connector[] {connector}); + + ContextHandler contextA = new ContextHandler("/"); + contextA.setVirtualHosts(new String[] {"www.example.com"}); + IsHandledHandler handlerA = new IsHandledHandler(); + contextA.setHandler(handlerA); + + + ContextHandler contextB = new ContextHandler("/"); + IsHandledHandler handlerB = new IsHandledHandler(); + contextB.setHandler(handlerB); + contextB.setVirtualHosts(new String[] {"www.example2.com."}); + + ContextHandler contextC = new ContextHandler("/"); + IsHandledHandler handlerC = new IsHandledHandler(); + contextC.setHandler(handlerC); + + HandlerCollection c = new HandlerCollection(); + + c.addHandler(contextA); + c.addHandler(contextB); + c.addHandler(contextC); + + + server.setHandler(c); + + try + { + server.start(); + connector.getResponses("GET / HTTP/1.1\n" + + "Host: www.example.com.\n\n"); + + assertTrue(handlerA.isHandled()); + assertFalse(handlerB.isHandled()); + assertFalse(handlerC.isHandled()); + + handlerA.reset(); + handlerB.reset(); + handlerC.reset(); + + connector.getResponses("GET / HTTP/1.1\n" + + "Host: www.example2.com\n\n"); + + assertFalse(handlerA.isHandled()); + assertTrue(handlerB.isHandled()); + assertFalse(handlerC.isHandled()); + + + } + finally + { + server.stop(); + } + + + } + + public static final class IsHandledHandler extends AbstractHandler { + private boolean handled; + + public boolean isHandled() { + return handled; + } + + public void handle(String s, HttpServletRequest request, HttpServletResponse response, int i) throws IOException, + ServletException + { + Request base_request = (request instanceof Request) ? (Request) request : HttpConnection.getCurrentConnection().getRequest(); + base_request.setHandled(true); + this.handled = true; + } + + public void reset() + { + handled = false; + } + } } Index: src/main/java/org/mortbay/jetty/handler/ContextHandler.java =================================================================== --- src/main/java/org/mortbay/jetty/handler/ContextHandler.java (revision 2132) +++ src/main/java/org/mortbay/jetty/handler/ContextHandler.java (working copy) @@ -15,36 +15,6 @@ package org.mortbay.jetty.handler; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.EventListener; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - -import javax.servlet.RequestDispatcher; -import javax.servlet.Servlet; -import javax.servlet.ServletContext; -import javax.servlet.ServletContextAttributeEvent; -import javax.servlet.ServletContextAttributeListener; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.ServletException; -import javax.servlet.ServletRequestAttributeListener; -import javax.servlet.ServletRequestEvent; -import javax.servlet.ServletRequestListener; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import org.mortbay.io.Buffer; import org.mortbay.jetty.Handler; import org.mortbay.jetty.HandlerContainer; @@ -63,6 +33,35 @@ import org.mortbay.util.Loader; import org.mortbay.util.URIUtil; +import javax.servlet.RequestDispatcher; +import javax.servlet.Servlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletContextAttributeEvent; +import javax.servlet.ServletContextAttributeListener; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.ServletException; +import javax.servlet.ServletRequestAttributeListener; +import javax.servlet.ServletRequestEvent; +import javax.servlet.ServletRequestListener; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.EventListener; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + /* ------------------------------------------------------------ */ /** ContextHandler. * @@ -222,9 +221,20 @@ * null host name or null/empty array means any hostname is acceptable. * Host names may String representation of IP addresses. */ - public void setVirtualHosts(String[] vhosts) + public void setVirtualHosts( String[] vhosts ) { - _vhosts=vhosts; + if ( vhosts == null ) + { + _vhosts = vhosts; + } else { + _vhosts = new String[vhosts.length]; + for ( int i = 0; i < vhosts.length; i++ ) + { + _vhosts[i] = normalizeHostname( vhosts[i]); + + } + } + } /* ------------------------------------------------------------ */ @@ -610,7 +620,8 @@ // Check the vhosts if (_vhosts!=null && _vhosts.length>0) { - String vhost=request.getServerName(); + String vhost = normalizeHostname( request.getServerName()); + boolean match=false; // TODO non-linear lookup @@ -1451,6 +1462,20 @@ } + private String normalizeHostname( String host ) + { + if ( host == null ) + { + return null; + } + else if ( host.endsWith( "." ) ) + { + return host.substring( 0, host.length() -1); + } else { + return host; + } + } + }