Jetty-12 : Fixing ContextHandlerCollectionTest (#8322)
* Fixing ContextHandlerCollectionTest * Disabling array Indentation checkstyle + Doesn't play nice with Java 17 new switch/case usages.
This commit is contained in:
parent
68ddee69af
commit
b241446e66
|
@ -77,9 +77,11 @@
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
<!-- Indentation Rules -->
|
<!-- Indentation Rules -->
|
||||||
|
<!-- Disabled: does not support Java 17 new switch/case
|
||||||
<module name="Indentation">
|
<module name="Indentation">
|
||||||
<property name="arrayInitIndent" value="8"/>
|
<property name="arrayInitIndent" value="8"/>
|
||||||
</module>
|
</module>
|
||||||
|
-->
|
||||||
|
|
||||||
<!-- Interface Type Parameter Name -->
|
<!-- Interface Type Parameter Name -->
|
||||||
<module name="InterfaceTypeParameterName">
|
<module name="InterfaceTypeParameterName">
|
||||||
|
|
|
@ -253,14 +253,14 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace
|
||||||
* representation of IP addresses. Host names may start with '*.' to wildcard one level of names. Hosts and wildcard hosts may be followed with
|
* representation of IP addresses. Host names may start with '*.' to wildcard one level of names. Hosts and wildcard hosts may be followed with
|
||||||
* '@connectorname', in which case they will match only if the the {@link Connector#getName()} for the request also matches. If an entry is just
|
* '@connectorname', in which case they will match only if the the {@link Connector#getName()} for the request also matches. If an entry is just
|
||||||
* '@connectorname' it will match any host if that connector was used. Note - In previous versions if one or more connectorname only entries existed
|
* '@connectorname' it will match any host if that connector was used. Note - In previous versions if one or more connectorname only entries existed
|
||||||
* and non of the connectors matched the handler would not match regardless of any hostname entries. If there is one or more connectorname only
|
* and none of the connectors matched the handler would not match regardless of any hostname entries. If there is one or more connectorname only
|
||||||
* entries and one or more host only entries but no hostname and connector entries we assume the old behavior and will log a warning. The warning
|
* entries and one or more host only entries but no hostname and connector entries we assume the old behavior and will log a warning. The warning
|
||||||
* can be removed by removing the host entries that were previously being ignored, or modifying to include a hostname and connectorname entry.
|
* can be removed by removing the host entries that were previously being ignored, or modifying to include a hostname and connectorname entry.
|
||||||
*/
|
*/
|
||||||
@ManagedAttribute(value = "Virtual hosts accepted by the context", readonly = true)
|
@ManagedAttribute(value = "Virtual hosts accepted by the context", readonly = true)
|
||||||
public List<String> getVirtualHosts()
|
public List<String> getVirtualHosts()
|
||||||
{
|
{
|
||||||
return _vhosts.stream().map(VHost::getVHost).collect(Collectors.toList());
|
return _vhosts.stream().map(VHost::getName).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -536,9 +536,7 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace
|
||||||
if (_vhosts.isEmpty())
|
if (_vhosts.isEmpty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// TODO is this correct?
|
String host = normalizeHostname(request.getHttpURI().getHost());
|
||||||
String host = request.getHttpURI().getHost();
|
|
||||||
|
|
||||||
String connectorName = request.getConnectionMetaData().getConnector().getName();
|
String connectorName = request.getConnectionMetaData().getConnector().getName();
|
||||||
|
|
||||||
for (VHost vhost : _vhosts)
|
for (VHost vhost : _vhosts)
|
||||||
|
@ -750,11 +748,21 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace
|
||||||
b.append('{');
|
b.append('{');
|
||||||
if (getDisplayName() != null)
|
if (getDisplayName() != null)
|
||||||
b.append(getDisplayName()).append(',');
|
b.append(getDisplayName()).append(',');
|
||||||
b.append(getContextPath()).append(',').append(getResourceBase()).append(',').append(isAvailable());
|
b.append(getContextPath());
|
||||||
|
b.append(",b=").append(getResourceBase());
|
||||||
|
b.append(",a=").append(_availability.get());
|
||||||
|
|
||||||
for (String vh : vhosts)
|
if (!vhosts.isEmpty())
|
||||||
{
|
{
|
||||||
b.append(',').append(vh);
|
b.append(",vh=[");
|
||||||
|
b.append(String.join(",", vhosts));
|
||||||
|
b.append(']');
|
||||||
|
}
|
||||||
|
Handler nestedHandler = getHandler();
|
||||||
|
if (nestedHandler != null)
|
||||||
|
{
|
||||||
|
b.append(",h=");
|
||||||
|
b.append(nestedHandler);
|
||||||
}
|
}
|
||||||
b.append('}');
|
b.append('}');
|
||||||
|
|
||||||
|
@ -1040,5 +1048,23 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace
|
||||||
{
|
{
|
||||||
return _vHost;
|
return _vHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getName()
|
||||||
|
{
|
||||||
|
if (_vConnector != null)
|
||||||
|
return '@' + _vConnector;
|
||||||
|
else
|
||||||
|
return _vHost;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "VHost{" +
|
||||||
|
"_vHost='" + _vHost + '\'' +
|
||||||
|
", _wild=" + _wild +
|
||||||
|
", _vConnector='" + _vConnector + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
package org.eclipse.jetty.server.handler;
|
package org.eclipse.jetty.server.handler;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -248,7 +247,7 @@ public class ContextHandlerCollection extends Handler.Collection
|
||||||
private static final class Branch
|
private static final class Branch
|
||||||
{
|
{
|
||||||
private final Handler _handler;
|
private final Handler _handler;
|
||||||
private final ContextHandler[] _contexts;
|
private final List<ContextHandler> _contexts;
|
||||||
|
|
||||||
Branch(Handler handler)
|
Branch(Handler handler)
|
||||||
{
|
{
|
||||||
|
@ -256,16 +255,15 @@ public class ContextHandlerCollection extends Handler.Collection
|
||||||
|
|
||||||
if (handler instanceof ContextHandler)
|
if (handler instanceof ContextHandler)
|
||||||
{
|
{
|
||||||
_contexts = new ContextHandler[]{(ContextHandler)handler};
|
_contexts = List.of((ContextHandler)handler);
|
||||||
}
|
}
|
||||||
else if (handler instanceof Handler.Container)
|
else if (handler instanceof Handler.Container)
|
||||||
{
|
{
|
||||||
List<ContextHandler> contexts = ((Handler.Container)handler).getDescendants(ContextHandler.class);
|
List<ContextHandler> contexts = ((Handler.Container)handler).getDescendants(ContextHandler.class);
|
||||||
_contexts = new ContextHandler[contexts.size()];
|
_contexts = new ArrayList<>(contexts);
|
||||||
System.arraycopy(contexts, 0, _contexts, 0, contexts.size());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_contexts = new ContextHandler[0];
|
_contexts = List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<String> getContextPaths()
|
Set<String> getContextPaths()
|
||||||
|
@ -288,7 +286,7 @@ public class ContextHandlerCollection extends Handler.Collection
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ContextHandler[] getContextHandlers()
|
List<ContextHandler> getContextHandlers()
|
||||||
{
|
{
|
||||||
return _contexts;
|
return _contexts;
|
||||||
}
|
}
|
||||||
|
@ -301,7 +299,7 @@ public class ContextHandlerCollection extends Handler.Collection
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return String.format("{%s,%s}", _handler, Arrays.asList(_contexts));
|
return String.format("{%s,%s}", _handler, _contexts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,59 +13,106 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.server.handler;
|
package org.eclipse.jetty.server.handler;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.HttpStatus;
|
||||||
|
import org.eclipse.jetty.http.HttpTester;
|
||||||
|
import org.eclipse.jetty.server.Connector;
|
||||||
|
import org.eclipse.jetty.server.Handler;
|
||||||
|
import org.eclipse.jetty.server.LocalConnector;
|
||||||
|
import org.eclipse.jetty.server.Request;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.util.BufferUtil;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.TestInfo;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.endsWith;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
|
import static org.hamcrest.Matchers.startsWith;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
public class ContextHandlerCollectionTest
|
public class ContextHandlerCollectionTest
|
||||||
{
|
{
|
||||||
/* TODO
|
public static Stream<Arguments> virtualHostCases()
|
||||||
@Test
|
{
|
||||||
public void testVirtualHosts() throws Exception
|
return Stream.of(
|
||||||
|
Arguments.of(0, "www.example.com.", "/ctx", "-", HttpStatus.MOVED_PERMANENTLY_301),
|
||||||
|
Arguments.of(0, "www.example.com.", "/ctx/", "A", HttpStatus.OK_200),
|
||||||
|
Arguments.of(0, "www.example.com.", "/ctx/info", "A", HttpStatus.OK_200),
|
||||||
|
Arguments.of(0, "www.example.com", "/ctx/info", "A", HttpStatus.OK_200),
|
||||||
|
Arguments.of(0, "alias.example.com", "/ctx/info", "A", HttpStatus.OK_200),
|
||||||
|
Arguments.of(1, "www.example.com.", "/ctx/info", "A", HttpStatus.OK_200),
|
||||||
|
Arguments.of(1, "www.example.com", "/ctx/info", "A", HttpStatus.OK_200),
|
||||||
|
Arguments.of(1, "alias.example.com", "/ctx/info", "A", HttpStatus.OK_200),
|
||||||
|
|
||||||
|
Arguments.of(1, "www.other.com", "/ctx", "-", HttpStatus.MOVED_PERMANENTLY_301),
|
||||||
|
Arguments.of(1, "www.other.com", "/ctx/", "B", HttpStatus.OK_200),
|
||||||
|
Arguments.of(1, "www.other.com", "/ctx/info", "B", HttpStatus.OK_200),
|
||||||
|
Arguments.of(0, "www.other.com", "/ctx/info", "C", HttpStatus.OK_200),
|
||||||
|
|
||||||
|
Arguments.of(0, "www.example.com", "/ctxinfo", "D", HttpStatus.OK_200),
|
||||||
|
Arguments.of(1, "unknown.com", "/unknown", "D", HttpStatus.OK_200),
|
||||||
|
|
||||||
|
Arguments.of(0, "alias.example.com", "/ctx/foo/info", "E", HttpStatus.OK_200),
|
||||||
|
Arguments.of(0, "alias.example.com", "/ctxlong/info", "F", HttpStatus.OK_200)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("virtualHostCases")
|
||||||
|
public void testVirtualHosts(int useConnectorNum, String host, String uri, String handlerRef, int expectedStatus, TestInfo testInfo) throws Exception
|
||||||
{
|
{
|
||||||
Server server = new Server();
|
Server server = new Server();
|
||||||
LocalConnector connector0 = new LocalConnector(server);
|
LocalConnector connector0 = new LocalConnector(server);
|
||||||
LocalConnector connector1 = new LocalConnector(server);
|
LocalConnector connector1 = new LocalConnector(server);
|
||||||
connector1.setName("connector1");
|
connector1.setName("connector1");
|
||||||
|
|
||||||
server.setConnectors(new Connector[]
|
server.addConnector(connector0);
|
||||||
{connector0, connector1});
|
server.addConnector(connector1);
|
||||||
|
|
||||||
ContextHandler contextA = new ContextHandler("/ctx");
|
ContextHandler contextA = new ContextHandler("/ctx");
|
||||||
contextA.setVirtualHosts(new String[]
|
contextA.setVirtualHosts(List.of("www.example.com", "alias.example.com"));
|
||||||
{"www.example.com", "alias.example.com"});
|
contextA.setHandler(new IsHandledHandler("A"));
|
||||||
IsHandledHandler handlerA = new IsHandledHandler("A");
|
|
||||||
contextA.setHandler(handlerA);
|
|
||||||
contextA.setAllowNullPathInfo(true);
|
|
||||||
|
|
||||||
ContextHandler contextB = new ContextHandler("/ctx");
|
ContextHandler contextB = new ContextHandler("/ctx");
|
||||||
IsHandledHandler handlerB = new IsHandledHandler("B");
|
contextB.setHandler(new IsHandledHandler("B"));
|
||||||
contextB.setHandler(handlerB);
|
contextB.setVirtualHosts(List.of("*.other.com@connector1"));
|
||||||
contextB.setVirtualHosts(new String[]
|
|
||||||
{"*.other.com", "@connector1"});
|
|
||||||
|
|
||||||
ContextHandler contextC = new ContextHandler("/ctx");
|
ContextHandler contextC = new ContextHandler("/ctx");
|
||||||
IsHandledHandler handlerC = new IsHandledHandler("C");
|
contextC.setHandler(new IsHandledHandler("C"));
|
||||||
contextC.setHandler(handlerC);
|
|
||||||
|
|
||||||
ContextHandler contextD = new ContextHandler("/");
|
ContextHandler contextD = new ContextHandler("/");
|
||||||
IsHandledHandler handlerD = new IsHandledHandler("D");
|
contextD.setHandler(new IsHandledHandler("D"));
|
||||||
contextD.setHandler(handlerD);
|
|
||||||
|
|
||||||
ContextHandler contextE = new ContextHandler("/ctx/foo");
|
ContextHandler contextE = new ContextHandler("/ctx/foo");
|
||||||
IsHandledHandler handlerE = new IsHandledHandler("E");
|
contextE.setHandler(new IsHandledHandler("E"));
|
||||||
contextE.setHandler(handlerE);
|
|
||||||
|
|
||||||
ContextHandler contextF = new ContextHandler("/ctxlong");
|
ContextHandler contextF = new ContextHandler("/ctxlong");
|
||||||
IsHandledHandler handlerF = new IsHandledHandler("F");
|
contextF.setHandler(new IsHandledHandler("F"));
|
||||||
contextF.setHandler(handlerF);
|
|
||||||
|
|
||||||
ContextHandlerCollection c = new ContextHandlerCollection();
|
ContextHandlerCollection c = new ContextHandlerCollection();
|
||||||
c.addHandler(contextA);
|
c.addHandler(contextA);
|
||||||
c.addHandler(contextB);
|
c.addHandler(contextB);
|
||||||
c.addHandler(contextC);
|
c.addHandler(contextC);
|
||||||
|
|
||||||
HandlerList list = new HandlerList();
|
Handler.Collection handlers = new Handler.Collection();
|
||||||
list.addHandler(contextE);
|
handlers.addHandler(contextE);
|
||||||
list.addHandler(contextF);
|
handlers.addHandler(contextF);
|
||||||
list.addHandler(contextD);
|
handlers.addHandler(contextD);
|
||||||
c.addHandler(list);
|
c.addHandler(handlers);
|
||||||
|
|
||||||
server.setHandler(c);
|
server.setHandler(c);
|
||||||
|
|
||||||
|
@ -73,58 +120,29 @@ public class ContextHandlerCollectionTest
|
||||||
{
|
{
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
Object[][] tests = new Object[][]{
|
LocalConnector connector = switch (useConnectorNum)
|
||||||
{connector0, "www.example.com.", "/ctx", handlerA},
|
{
|
||||||
{connector0, "www.example.com.", "/ctx/", handlerA},
|
case 0 -> connector0;
|
||||||
{connector0, "www.example.com.", "/ctx/info", handlerA},
|
case 1 -> connector1;
|
||||||
{connector0, "www.example.com", "/ctx/info", handlerA},
|
default -> fail("Unsupported connector number: " + useConnectorNum);
|
||||||
{connector0, "alias.example.com", "/ctx/info", handlerA},
|
|
||||||
{connector1, "www.example.com.", "/ctx/info", handlerA},
|
|
||||||
{connector1, "www.example.com", "/ctx/info", handlerA},
|
|
||||||
{connector1, "alias.example.com", "/ctx/info", handlerA},
|
|
||||||
|
|
||||||
{connector1, "www.other.com", "/ctx", null},
|
|
||||||
{connector1, "www.other.com", "/ctx/", handlerB},
|
|
||||||
{connector1, "www.other.com", "/ctx/info", handlerB},
|
|
||||||
{connector0, "www.other.com", "/ctx/info", handlerC},
|
|
||||||
|
|
||||||
{connector0, "www.example.com", "/ctxinfo", handlerD},
|
|
||||||
{connector1, "unknown.com", "/unknown", handlerD},
|
|
||||||
|
|
||||||
{connector0, "alias.example.com", "/ctx/foo/info", handlerE},
|
|
||||||
{connector0, "alias.example.com", "/ctxlong/info", handlerF},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < tests.length; i++)
|
String rawRequest = ("""
|
||||||
{
|
GET %s HTTP/1.1\r
|
||||||
Object[] test = tests[i];
|
Host: %s\r
|
||||||
LocalConnector connector = (LocalConnector)test[0];
|
Connection: close\r
|
||||||
String host = (String)test[1];
|
\r
|
||||||
String uri = (String)test[2];
|
""").formatted(uri, host);
|
||||||
IsHandledHandler handler = (IsHandledHandler)test[3];
|
|
||||||
|
|
||||||
handlerA.reset();
|
String rawResponse = connector.getResponse(rawRequest);
|
||||||
handlerB.reset();
|
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
|
||||||
handlerC.reset();
|
|
||||||
handlerD.reset();
|
|
||||||
handlerE.reset();
|
|
||||||
handlerF.reset();
|
|
||||||
|
|
||||||
String t = String.format("test %d %s@%s --> %s | %s%n", i, uri, host, connector.getName(), handler);
|
assertThat(testInfo.getDisplayName(), response.getStatus(), is(expectedStatus));
|
||||||
String response = connector.getResponse("GET " + uri + " HTTP/1.0\nHost: " + host + "\n\n");
|
|
||||||
|
|
||||||
if (handler == null)
|
if (response.getStatus() == HttpStatus.OK_200)
|
||||||
{
|
{
|
||||||
assertThat(t, response, Matchers.containsString(" 302 "));
|
assertThat(testInfo.getDisplayName(), response.getContent(), endsWith(handlerRef));
|
||||||
}
|
assertThat(testInfo.getDisplayName(), response.get("X-IsHandled-Name"), is(handlerRef));
|
||||||
else
|
|
||||||
{
|
|
||||||
assertThat(t, response, endsWith(handler.toString()));
|
|
||||||
if (!handler.isHandled())
|
|
||||||
{
|
|
||||||
fail("FAILED " + t + "\n" + response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
@ -133,14 +151,115 @@ public class ContextHandlerCollectionTest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
public static Stream<Arguments> virtualHostWildcardMatchedCases()
|
||||||
public void testVirtualHostWildcard() throws Exception
|
{
|
||||||
|
List<Arguments> args = new ArrayList<>();
|
||||||
|
|
||||||
|
List<String> contextHosts;
|
||||||
|
|
||||||
|
contextHosts = List.of();
|
||||||
|
args.add(Arguments.of(contextHosts, "example.com"));
|
||||||
|
args.add(Arguments.of(contextHosts, ".example.com"));
|
||||||
|
args.add(Arguments.of(contextHosts, "vhost.example.com"));
|
||||||
|
|
||||||
|
contextHosts = List.of("example.com", "*.example.com");
|
||||||
|
args.add(Arguments.of(contextHosts, "example.com"));
|
||||||
|
args.add(Arguments.of(contextHosts, ".example.com"));
|
||||||
|
args.add(Arguments.of(contextHosts, "vhost.example.com"));
|
||||||
|
|
||||||
|
contextHosts = List.of("*.example.com");
|
||||||
|
args.add(Arguments.of(contextHosts, "vhost.example.com"));
|
||||||
|
args.add(Arguments.of(contextHosts, ".example.com"));
|
||||||
|
|
||||||
|
contextHosts = List.of("*.sub.example.com");
|
||||||
|
args.add(Arguments.of(contextHosts, "vhost.sub.example.com"));
|
||||||
|
args.add(Arguments.of(contextHosts, ".sub.example.com"));
|
||||||
|
|
||||||
|
return args.stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("virtualHostWildcardMatchedCases")
|
||||||
|
public void testVirtualHostWildcardMatched(List<String> contextHosts, String requestHost) throws Exception
|
||||||
{
|
{
|
||||||
Server server = new Server();
|
Server server = new Server();
|
||||||
LocalConnector connector = new LocalConnector(server);
|
LocalConnector connector = new LocalConnector(server);
|
||||||
server.setConnectors(new Connector[]{connector});
|
server.setConnectors(new Connector[]{connector});
|
||||||
|
|
||||||
ContextHandler context = new ContextHandler("/");
|
ContextHandler context = new ContextHandler("/");
|
||||||
|
context.setVirtualHosts(contextHosts);
|
||||||
|
context.setHandler(new IsHandledHandler("H"));
|
||||||
|
|
||||||
|
ContextHandlerCollection c = new ContextHandlerCollection();
|
||||||
|
c.addHandler(context);
|
||||||
|
|
||||||
|
server.setHandler(c);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
server.start();
|
||||||
|
|
||||||
|
String rawRequest = """
|
||||||
|
GET / HTTP/1.1\r
|
||||||
|
Host: %s\r
|
||||||
|
Connection:close\r
|
||||||
|
\r
|
||||||
|
""".formatted(requestHost);
|
||||||
|
|
||||||
|
String rawResponse = connector.getResponse(rawRequest);
|
||||||
|
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
|
||||||
|
assertThat("Response status for [GET " + requestHost + "]", response.getStatus(), is(HttpStatus.OK_200));
|
||||||
|
assertThat("Response body for [GET " + requestHost + "]", response.getContent(), is("H"));
|
||||||
|
assertThat("Response Header for [GET " + requestHost + "]", response.get("X-IsHandled-Name"), is("H"));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
server.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Stream<Arguments> virtualHostWildcardNoMatchCases()
|
||||||
|
{
|
||||||
|
List<Arguments> args = new ArrayList<>();
|
||||||
|
|
||||||
|
List<String> contextHosts;
|
||||||
|
|
||||||
|
contextHosts = List.of("example.com", "*.example.com");
|
||||||
|
args.add(Arguments.of(contextHosts, "badexample.com"));
|
||||||
|
args.add(Arguments.of(contextHosts, ".badexample.com"));
|
||||||
|
args.add(Arguments.of(contextHosts, "vhost.badexample.com"));
|
||||||
|
|
||||||
|
contextHosts = List.of("*.");
|
||||||
|
args.add(Arguments.of(contextHosts, "anything.anything"));
|
||||||
|
|
||||||
|
contextHosts = List.of("*.example.com");
|
||||||
|
args.add(Arguments.of(contextHosts, "vhost.www.example.com"));
|
||||||
|
args.add(Arguments.of(contextHosts, "example.com"));
|
||||||
|
args.add(Arguments.of(contextHosts, "www.vhost.example.com"));
|
||||||
|
|
||||||
|
contextHosts = List.of("*.sub.example.com");
|
||||||
|
args.add(Arguments.of(contextHosts, ".example.com"));
|
||||||
|
args.add(Arguments.of(contextHosts, "sub.example.com"));
|
||||||
|
args.add(Arguments.of(contextHosts, "vhost.example.com"));
|
||||||
|
|
||||||
|
contextHosts = List.of("example.*.com", "example.com.*");
|
||||||
|
args.add(Arguments.of(contextHosts, "example.vhost.com"));
|
||||||
|
args.add(Arguments.of(contextHosts, "example.com.vhost"));
|
||||||
|
args.add(Arguments.of(contextHosts, "example.com"));
|
||||||
|
|
||||||
|
return args.stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("virtualHostWildcardNoMatchCases")
|
||||||
|
public void testVirtualHostWildcardNoMatch(List<String> contextHosts, String requestHost) throws Exception
|
||||||
|
{
|
||||||
|
Server server = new Server();
|
||||||
|
LocalConnector connector = new LocalConnector(server);
|
||||||
|
server.setConnectors(new Connector[]{connector});
|
||||||
|
|
||||||
|
ContextHandler context = new ContextHandler("/");
|
||||||
|
context.setVirtualHosts(contextHosts);
|
||||||
|
|
||||||
IsHandledHandler handler = new IsHandledHandler("H");
|
IsHandledHandler handler = new IsHandledHandler("H");
|
||||||
context.setHandler(handler);
|
context.setHandler(handler);
|
||||||
|
@ -153,35 +272,22 @@ public class ContextHandlerCollectionTest
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
server.start();
|
server.start();
|
||||||
checkWildcardHost(true, server, null, new String[]{"example.com", ".example.com", "vhost.example.com"});
|
|
||||||
checkWildcardHost(false, server, new String[]{null}, new String[]{
|
|
||||||
"example.com", ".example.com", "vhost.example.com"
|
|
||||||
});
|
|
||||||
|
|
||||||
checkWildcardHost(true, server, new String[]{"example.com", "*.example.com"}, new String[]{
|
String rawRequest = """
|
||||||
"example.com", ".example.com", "vhost.example.com"
|
GET / HTTP/1.1\r
|
||||||
});
|
Host: %s\r
|
||||||
checkWildcardHost(false, server, new String[]{"example.com", "*.example.com"}, new String[]{
|
Connection:close\r
|
||||||
"badexample.com", ".badexample.com", "vhost.badexample.com"
|
\r
|
||||||
});
|
""".formatted(requestHost);
|
||||||
|
|
||||||
checkWildcardHost(false, server, new String[]{"*."}, new String[]{"anything.anything"});
|
String rawResponse = connector.getResponse(rawRequest);
|
||||||
|
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
|
||||||
|
assertThat("Response status for [GET " + requestHost + "]", response.getStatus(), is(HttpStatus.NOT_FOUND_404));
|
||||||
|
assertThat("Response body for [GET " + requestHost + "]", response.getContent(), containsString("<h2>HTTP ERROR 404 Not Found</h2>"));
|
||||||
|
assertThat("Response Header for [GET " + requestHost + "]", response.get("X-IsHandled-Name"), nullValue());
|
||||||
|
|
||||||
checkWildcardHost(true, server, new String[]{"*.example.com"}, new String[]{"vhost.example.com", ".example.com"});
|
connector.getResponse(rawRequest);
|
||||||
checkWildcardHost(false, server, new String[]{"*.example.com"}, new String[]{
|
assertFalse(handler.isHandled(), "'" + requestHost + "' should not have been handled.");
|
||||||
"vhost.www.example.com", "example.com", "www.vhost.example.com"
|
|
||||||
});
|
|
||||||
|
|
||||||
checkWildcardHost(true, server, new String[]{"*.sub.example.com"}, new String[]{
|
|
||||||
"vhost.sub.example.com", ".sub.example.com"
|
|
||||||
});
|
|
||||||
checkWildcardHost(false, server, new String[]{"*.sub.example.com"}, new String[]{
|
|
||||||
".example.com", "sub.example.com", "vhost.example.com"
|
|
||||||
});
|
|
||||||
|
|
||||||
checkWildcardHost(false, server, new String[]{"example.*.com", "example.com.*"}, new String[]{
|
|
||||||
"example.vhost.com", "example.com.vhost", "example.com"
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -189,33 +295,8 @@ public class ContextHandlerCollectionTest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkWildcardHost(boolean succeed, Server server, String[] contextHosts, String[] requestHosts) throws Exception
|
|
||||||
{
|
|
||||||
LocalConnector connector = (LocalConnector)server.getConnectors()[0];
|
|
||||||
ContextHandlerCollection handlerCollection = (ContextHandlerCollection)server.getHandler();
|
|
||||||
ContextHandler context = (ContextHandler)handlerCollection.getHandlers()[0];
|
|
||||||
IsHandledHandler handler = (IsHandledHandler)context.getHandler();
|
|
||||||
|
|
||||||
context.setVirtualHosts(contextHosts);
|
|
||||||
// trigger this manually
|
|
||||||
handlerCollection.mapContexts();
|
|
||||||
|
|
||||||
for (String host : requestHosts)
|
|
||||||
{
|
|
||||||
// System.err.printf("host=%s in %s%n",host,contextHosts==null?Collections.emptyList():Arrays.asList(contextHosts));
|
|
||||||
|
|
||||||
String response = connector.getResponse("GET / HTTP/1.0\n" + "Host: " + host + "\nConnection:close\n\n");
|
|
||||||
// System.err.println(response);
|
|
||||||
if (succeed)
|
|
||||||
assertTrue(handler.isHandled(), "'" + host + "' should have been handled.");
|
|
||||||
else
|
|
||||||
assertFalse(handler.isHandled(), "'" + host + "' should not have been handled.");
|
|
||||||
handler.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFindContainer() throws Exception
|
public void testFindContainer()
|
||||||
{
|
{
|
||||||
Server server = new Server();
|
Server server = new Server();
|
||||||
|
|
||||||
|
@ -225,7 +306,7 @@ public class ContextHandlerCollectionTest
|
||||||
|
|
||||||
ContextHandler contextB = new ContextHandler("/b");
|
ContextHandler contextB = new ContextHandler("/b");
|
||||||
IsHandledHandler handlerB = new IsHandledHandler("B");
|
IsHandledHandler handlerB = new IsHandledHandler("B");
|
||||||
HandlerWrapper wrapperB = new HandlerWrapper();
|
Handler.Wrapper wrapperB = new Handler.Wrapper();
|
||||||
wrapperB.setHandler(handlerB);
|
wrapperB.setHandler(handlerB);
|
||||||
contextB.setHandler(wrapperB);
|
contextB.setHandler(wrapperB);
|
||||||
|
|
||||||
|
@ -239,16 +320,16 @@ public class ContextHandlerCollectionTest
|
||||||
collection.addHandler(contextB);
|
collection.addHandler(contextB);
|
||||||
collection.addHandler(contextC);
|
collection.addHandler(contextC);
|
||||||
|
|
||||||
HandlerWrapper wrapper = new HandlerWrapper();
|
Handler.Wrapper wrapper = new Handler.Wrapper();
|
||||||
wrapper.setHandler(collection);
|
wrapper.setHandler(collection);
|
||||||
server.setHandler(wrapper);
|
server.setHandler(wrapper);
|
||||||
|
|
||||||
assertEquals(wrapper, AbstractHandlerContainer.findContainerOf(server, HandlerWrapper.class, handlerA));
|
assertEquals(wrapper, Handler.AbstractContainer.findContainerOf(server, Handler.Wrapper.class, handlerA));
|
||||||
assertEquals(contextA, AbstractHandlerContainer.findContainerOf(server, ContextHandler.class, handlerA));
|
assertEquals(contextA, Handler.AbstractContainer.findContainerOf(server, ContextHandler.class, handlerA));
|
||||||
assertEquals(contextB, AbstractHandlerContainer.findContainerOf(server, ContextHandler.class, handlerB));
|
assertEquals(contextB, Handler.AbstractContainer.findContainerOf(server, ContextHandler.class, handlerB));
|
||||||
assertEquals(wrapper, AbstractHandlerContainer.findContainerOf(server, HandlerWrapper.class, handlerB));
|
assertEquals(wrapper, Handler.AbstractContainer.findContainerOf(server, Handler.Wrapper.class, handlerB));
|
||||||
assertEquals(contextB, AbstractHandlerContainer.findContainerOf(collection, HandlerWrapper.class, handlerB));
|
assertEquals(contextB, Handler.AbstractContainer.findContainerOf(collection, Handler.Wrapper.class, handlerB));
|
||||||
assertEquals(wrapperB, AbstractHandlerContainer.findContainerOf(contextB, HandlerWrapper.class, handlerB));
|
assertEquals(wrapperB, Handler.AbstractContainer.findContainerOf(contextB, Handler.Wrapper.class, handlerB));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -264,18 +345,18 @@ public class ContextHandlerCollectionTest
|
||||||
ContextHandler left = new ContextHandler("/left");
|
ContextHandler left = new ContextHandler("/left");
|
||||||
left.setHandler(new IsHandledHandler("left"));
|
left.setHandler(new IsHandledHandler("left"));
|
||||||
|
|
||||||
HandlerList centre = new HandlerList();
|
Handler.Collection centre = new Handler.Collection();
|
||||||
ContextHandler centreLeft = new ContextHandler("/leftcentre");
|
ContextHandler centreLeft = new ContextHandler("/leftcentre");
|
||||||
centreLeft.setHandler(new IsHandledHandler("left of centre"));
|
centreLeft.setHandler(new IsHandledHandler("left of centre"));
|
||||||
ContextHandler centreRight = new ContextHandler("/rightcentre");
|
ContextHandler centreRight = new ContextHandler("/rightcentre");
|
||||||
centreRight.setHandler(new IsHandledHandler("right of centre"));
|
centreRight.setHandler(new IsHandledHandler("right of centre"));
|
||||||
centre.setHandlers(new Handler[]{centreLeft, new WrappedHandler(centreRight)});
|
centre.setHandlers(List.of(centreLeft, new WrappedHandler(centreRight)));
|
||||||
|
|
||||||
ContextHandler right = new ContextHandler("/right");
|
ContextHandler right = new ContextHandler("/right");
|
||||||
right.setHandler(new IsHandledHandler("right"));
|
right.setHandler(new IsHandledHandler("right"));
|
||||||
|
|
||||||
ContextHandlerCollection contexts = new ContextHandlerCollection();
|
ContextHandlerCollection contexts = new ContextHandlerCollection();
|
||||||
contexts.setHandlers(new Handler[]{root, left, centre, new WrappedHandler(right)});
|
contexts.setHandlers(List.of(root, left, centre, new WrappedHandler(right)));
|
||||||
|
|
||||||
server.setHandler(contexts);
|
server.setHandler(contexts);
|
||||||
server.start();
|
server.start();
|
||||||
|
@ -311,65 +392,6 @@ public class ContextHandlerCollectionTest
|
||||||
assertThat(response, containsString("Wrapped: TRUE"));
|
assertThat(response, containsString("Wrapped: TRUE"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAsyncWrappedContext() throws Exception
|
|
||||||
{
|
|
||||||
Server server = new Server();
|
|
||||||
LocalConnector connector = new LocalConnector(server);
|
|
||||||
server.setConnectors(new Connector[]{connector});
|
|
||||||
|
|
||||||
ContextHandler root = new ContextHandler("/");
|
|
||||||
root.setHandler(new AsyncHandler("root"));
|
|
||||||
|
|
||||||
ContextHandler left = new ContextHandler("/left");
|
|
||||||
left.setHandler(new AsyncHandler("left"));
|
|
||||||
|
|
||||||
ContextHandler centreLeft = new ContextHandler("/leftcentre");
|
|
||||||
centreLeft.setHandler(new AsyncHandler("left of centre"));
|
|
||||||
ContextHandler centreRight = new ContextHandler("/rightcentre");
|
|
||||||
centreRight.setHandler(new AsyncHandler("right of centre"));
|
|
||||||
HandlerList centre = new HandlerList(centreLeft, new WrappedHandler(centreRight));
|
|
||||||
|
|
||||||
ContextHandler right = new ContextHandler("/right");
|
|
||||||
right.setHandler(new AsyncHandler("right"));
|
|
||||||
|
|
||||||
ContextHandlerCollection contexts = new ContextHandlerCollection();
|
|
||||||
contexts.setHandlers(new Handler[]{root, left, centre, new WrappedHandler(right)});
|
|
||||||
|
|
||||||
server.setHandler(contexts);
|
|
||||||
server.start();
|
|
||||||
|
|
||||||
String response = connector.getResponse("GET / HTTP/1.0\r\n\r\n");
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, endsWith("root"));
|
|
||||||
assertThat(response, not(containsString("Wrapped: TRUE")));
|
|
||||||
|
|
||||||
response = connector.getResponse("GET /foobar/info HTTP/1.0\r\n\r\n");
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, endsWith("root"));
|
|
||||||
assertThat(response, not(containsString("Wrapped: TRUE")));
|
|
||||||
|
|
||||||
response = connector.getResponse("GET /left/info HTTP/1.0\r\n\r\n");
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, endsWith("left"));
|
|
||||||
assertThat(response, not(containsString("Wrapped: TRUE")));
|
|
||||||
|
|
||||||
response = connector.getResponse("GET /leftcentre/info HTTP/1.0\r\n\r\n");
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, endsWith("left of centre"));
|
|
||||||
assertThat(response, not(containsString("Wrapped: TRUE")));
|
|
||||||
|
|
||||||
response = connector.getResponse("GET /rightcentre/info HTTP/1.0\r\n\r\n");
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, endsWith("right of centre"));
|
|
||||||
assertThat(response, containsString("Wrapped: ASYNC"));
|
|
||||||
|
|
||||||
response = connector.getResponse("GET /right/info HTTP/1.0\r\n\r\n");
|
|
||||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
|
||||||
assertThat(response, endsWith("right"));
|
|
||||||
assertThat(response, containsString("Wrapped: ASYNC"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class WrappedHandler extends Handler.Wrapper
|
private static final class WrappedHandler extends Handler.Wrapper
|
||||||
{
|
{
|
||||||
WrappedHandler(Handler handler)
|
WrappedHandler(Handler handler)
|
||||||
|
@ -378,17 +400,24 @@ public class ContextHandlerCollectionTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
public Request.Processor handle(Request request) throws Exception
|
||||||
{
|
{
|
||||||
if (response.containsHeader("Wrapped"))
|
Request.Processor processor = super.handle(request);
|
||||||
response.getHeaders().put("Wrapped", "ASYNC");
|
if (processor == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return (req, resp, callback) ->
|
||||||
|
{
|
||||||
|
if (resp.getHeaders().contains("Wrapped"))
|
||||||
|
resp.getHeaders().put("Wrapped", "ASYNC");
|
||||||
else
|
else
|
||||||
response.getHeaders().put("Wrapped", "TRUE");
|
resp.getHeaders().put("Wrapped", "TRUE");
|
||||||
super.handle(target, baseRequest, request, response);
|
processor.process(req, resp, callback);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class IsHandledHandler extends AbstractHandler
|
private static final class IsHandledHandler extends Handler.Abstract
|
||||||
{
|
{
|
||||||
private boolean handled;
|
private boolean handled;
|
||||||
private final String name;
|
private final String name;
|
||||||
|
@ -404,11 +433,15 @@ public class ContextHandlerCollectionTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(String s, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
public Request.Processor handle(Request request)
|
||||||
|
{
|
||||||
|
return (req, resp, callback) ->
|
||||||
{
|
{
|
||||||
baseRequest.setHandled(true);
|
|
||||||
this.handled = true;
|
this.handled = true;
|
||||||
response.getWriter().print(name);
|
resp.getHeaders().put("X-IsHandled-Name", name);
|
||||||
|
ByteBuffer nameBuffer = BufferUtil.toBuffer(name, StandardCharsets.UTF_8);
|
||||||
|
resp.write(true, nameBuffer, callback);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset()
|
public void reset()
|
||||||
|
@ -422,41 +455,4 @@ public class ContextHandlerCollectionTest
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class AsyncHandler extends AbstractHandler
|
|
||||||
{
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
public AsyncHandler(String string)
|
|
||||||
{
|
|
||||||
name = string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handle(String s, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
|
||||||
{
|
|
||||||
baseRequest.setHandled(true);
|
|
||||||
|
|
||||||
String n = (String)baseRequest.getAttribute("async");
|
|
||||||
if (n == null)
|
|
||||||
{
|
|
||||||
AsyncContext async = baseRequest.startAsync();
|
|
||||||
async.setTimeout(1000);
|
|
||||||
baseRequest.setAttribute("async", name);
|
|
||||||
async.dispatch();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
response.getWriter().print(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue