diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java index bcc13aa3cdd..2fced56d1a8 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java @@ -151,6 +151,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co private long _idleTimeout = 30000; private String _defaultProtocol; private ConnectionFactory _defaultConnectionFactory; + private String _name; /** @@ -524,11 +525,29 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co return _scheduler; } + @Override + public String getName() + { + return _name; + } + + /* ------------------------------------------------------------ */ + /** + * Set a connector name. A context may be configured with + * virtual hosts in the form "@contextname" and will only serve + * requests from the named connector, + * @param name A connector name. + */ + public void setName(String name) + { + _name=name; + } + @Override public String toString() { return String.format("%s@%x{%s}", - getClass().getSimpleName(), + _name==null?getClass().getSimpleName():_name, hashCode(), getDefaultProtocol()); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java index 3454c7869ec..6866e5e49a1 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java @@ -24,6 +24,7 @@ import java.util.concurrent.Executor; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.component.Graceful; @@ -90,4 +91,15 @@ public interface Connector extends LifeCycle, Graceful * @return immutable collection of connected endpoints */ public Collection getConnectedEndPoints(); + + + /* ------------------------------------------------------------ */ + /** + * Get the connector name if set. + *

A {@link ContextHandler} may be configured with + * virtual hosts in the form "@connectorName" and will only serve + * requests from the named connector. + * @return The connector name or null. + */ + public String getName(); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 4d15352b28d..3d5fad459cb 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -65,6 +65,7 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.server.ClassLoaderDump; +import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Dispatcher; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HandlerContainer; @@ -280,7 +281,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu * * @param vhosts * Array of virtual hosts that this context responds to. A null host name or null/empty array means any hostname is acceptable. Host names may be - * String representation of IP addresses. Host names may start with '*.' to wildcard one level of names. + * String representation of IP addresses. Host names may start with '*.' to wildcard one level of names. Hosts may start with '@', in which case they + * will match the {@link Connector#getName()} for the request. */ public void setVirtualHosts(String[] vhosts) { @@ -872,18 +874,29 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu boolean match = false; - for (int i = 0; !match && i < _vhosts.length; i++) + loop: for (String contextVhost:_vhosts) { - String contextVhost = _vhosts[i]; - if (contextVhost == null) + if (contextVhost == null || contextVhost.length()==0) continue; - if (contextVhost.startsWith("*.")) + char c=contextVhost.charAt(0); + switch (c) { - // wildcard only at the beginning, and only for one additional subdomain level - match = contextVhost.regionMatches(true,2,vhost,vhost.indexOf(".") + 1,contextVhost.length() - 2); + case '*': + if (contextVhost.startsWith("*.")) + // wildcard only at the beginning, and only for one additional subdomain level + match = contextVhost.regionMatches(true,2,vhost,vhost.indexOf(".") + 1,contextVhost.length() - 2); + break; + case '@': + String name=baseRequest.getHttpChannel().getConnector().getName(); + match=name!=null && contextVhost.length()==name.length()+1 && contextVhost.endsWith(name); + break; + default: + match = contextVhost.equalsIgnoreCase(vhost); } - else - match = contextVhost.equalsIgnoreCase(vhost); + + if (match) + break loop; + } if (!match) return false; diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java index b8fe723dec0..f9d07f47b83 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java @@ -118,6 +118,79 @@ public class ContextHandlerTest } } + + + @Test + public void testNamedConnector() throws Exception + { + Server server = new Server(); + LocalConnector connector = new LocalConnector(server); + LocalConnector connectorN = new LocalConnector(server); + connectorN.setName("name"); + server.setConnectors(new Connector[] { connector, connectorN }); + + 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[]{ "@name" }); + + 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); + + server.start(); + try + { + connector.getResponses("GET / HTTP/1.0\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.0\n" + "Host: localhost\n\n"); + assertFalse(handlerA.isHandled()); + assertFalse(handlerB.isHandled()); + assertTrue(handlerC.isHandled()); + handlerA.reset(); + handlerB.reset(); + handlerC.reset(); + + connectorN.getResponses("GET / HTTP/1.0\n" + "Host: www.example.com.\n\n"); + assertTrue(handlerA.isHandled()); + assertFalse(handlerB.isHandled()); + assertFalse(handlerC.isHandled()); + handlerA.reset(); + handlerB.reset(); + handlerC.reset(); + + connectorN.getResponses("GET / HTTP/1.0\n" + "Host: localhost\n\n"); + assertFalse(handlerA.isHandled()); + assertTrue(handlerB.isHandled()); + assertFalse(handlerC.isHandled()); + handlerA.reset(); + handlerB.reset(); + handlerC.reset(); + + } + finally + { + server.stop(); + } + + } @Test public void testContextGetContext() throws Exception