Merge pull request #11886 from jetty/fix/12.0.x/cross-context-testing-2
Initial work for Cross Context Dispatch testing suite
This commit is contained in:
commit
422d73da38
|
@ -15,6 +15,7 @@
|
|||
<module>jetty-jmh</module>
|
||||
<module>jetty-test-multipart</module>
|
||||
<module>jetty-test-session-common</module>
|
||||
<module>test-cross-context-dispatch</module>
|
||||
<module>test-distribution</module>
|
||||
<module>test-integration</module>
|
||||
<module>test-jpms</module>
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.tests.ccd</groupId>
|
||||
<artifactId>test-cross-context-dispatch</artifactId>
|
||||
<version>12.0.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>ccd-common</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Tests :: Cross Context Dispatch :: Common</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-session</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,215 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.common;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
|
||||
public class DispatchPlan
|
||||
{
|
||||
private final Deque<Step> steps = new LinkedBlockingDeque<>();
|
||||
private final List<String> events = new ArrayList<>();
|
||||
private final List<String> expectedEvents = new ArrayList<>();
|
||||
private final List<Property> expectedProperties = new ArrayList<>();
|
||||
private final List<String> expectedOutput = new ArrayList<>();
|
||||
private HttpRequest requestStep;
|
||||
private String id;
|
||||
private String expectedContentType;
|
||||
// if true, assert that all Session.id seen in request attributes are the same id.
|
||||
private boolean expectedSessionIds;
|
||||
|
||||
public DispatchPlan()
|
||||
{
|
||||
}
|
||||
|
||||
public static DispatchPlan read(Path inputText) throws IOException
|
||||
{
|
||||
DispatchPlan plan = new DispatchPlan();
|
||||
|
||||
plan.id = inputText.getFileName().toString();
|
||||
|
||||
for (String line : Files.readAllLines(inputText, StandardCharsets.UTF_8))
|
||||
{
|
||||
if (line.startsWith("#"))
|
||||
continue; // skip
|
||||
if (line.startsWith("REQUEST|"))
|
||||
{
|
||||
plan.setRequestStep(HttpRequest.parse(line));
|
||||
}
|
||||
else if (line.startsWith("STEP|"))
|
||||
{
|
||||
plan.addStep(Step.parse(line));
|
||||
}
|
||||
else if (line.startsWith("EXPECTED_CONTENT_TYPE|"))
|
||||
{
|
||||
plan.setExpectedContentType(dropType(line));
|
||||
}
|
||||
else if (line.startsWith("EXPECTED_EVENT|"))
|
||||
{
|
||||
plan.addExpectedEvent(dropType(line));
|
||||
}
|
||||
else if (line.startsWith("EXPECTED_PROP|"))
|
||||
{
|
||||
plan.addExpectedProperty(Property.parse(line));
|
||||
}
|
||||
else if (line.startsWith("EXPECTED_OUTPUT|"))
|
||||
{
|
||||
plan.addExpectedOutput(dropType(line));
|
||||
}
|
||||
else if (line.startsWith("EXPECTED_SESSION_IDS|"))
|
||||
{
|
||||
plan.setExpectedSessionIds(Boolean.parseBoolean(dropType(line)));
|
||||
}
|
||||
}
|
||||
return plan;
|
||||
}
|
||||
|
||||
private static String dropType(String line)
|
||||
{
|
||||
int idx = line.indexOf("|");
|
||||
return line.substring(idx + 1);
|
||||
}
|
||||
|
||||
public void addEvent(String format, Object... args)
|
||||
{
|
||||
events.add(String.format(format, args));
|
||||
}
|
||||
|
||||
public void addExpectedEvent(String event)
|
||||
{
|
||||
expectedEvents.add(event);
|
||||
}
|
||||
|
||||
public void addExpectedOutput(String output)
|
||||
{
|
||||
expectedOutput.add(output);
|
||||
}
|
||||
|
||||
public void addExpectedProperty(String name, String value)
|
||||
{
|
||||
expectedProperties.add(new Property(name, value));
|
||||
}
|
||||
|
||||
public void addExpectedProperty(Property property)
|
||||
{
|
||||
expectedProperties.add(property);
|
||||
}
|
||||
|
||||
public void addStep(Step step)
|
||||
{
|
||||
steps.add(step);
|
||||
}
|
||||
|
||||
public List<String> getEvents()
|
||||
{
|
||||
return events;
|
||||
}
|
||||
|
||||
public String getExpectedContentType()
|
||||
{
|
||||
return expectedContentType;
|
||||
}
|
||||
|
||||
public void setExpectedContentType(String expectedContentType)
|
||||
{
|
||||
this.expectedContentType = expectedContentType;
|
||||
}
|
||||
|
||||
public List<String> getExpectedEvents()
|
||||
{
|
||||
return expectedEvents;
|
||||
}
|
||||
|
||||
public void setExpectedEvents(String[] events)
|
||||
{
|
||||
expectedEvents.clear();
|
||||
expectedEvents.addAll(List.of(events));
|
||||
}
|
||||
|
||||
public List<String> getExpectedOutput()
|
||||
{
|
||||
return expectedOutput;
|
||||
}
|
||||
|
||||
public void setExpectedOutput(String[] output)
|
||||
{
|
||||
expectedOutput.clear();
|
||||
expectedOutput.addAll(List.of(output));
|
||||
}
|
||||
|
||||
public List<Property> getExpectedProperties()
|
||||
{
|
||||
return expectedProperties;
|
||||
}
|
||||
|
||||
public void setExpectedProperties(Property[] properties)
|
||||
{
|
||||
expectedProperties.clear();
|
||||
expectedProperties.addAll(List.of(properties));
|
||||
}
|
||||
|
||||
public HttpRequest getRequestStep()
|
||||
{
|
||||
return requestStep;
|
||||
}
|
||||
|
||||
public void setRequestStep(HttpRequest requestStep)
|
||||
{
|
||||
this.requestStep = requestStep;
|
||||
}
|
||||
|
||||
public Deque<Step> getSteps()
|
||||
{
|
||||
return steps;
|
||||
}
|
||||
|
||||
public void setSteps(Step[] stepArr)
|
||||
{
|
||||
steps.clear();
|
||||
for (Step step: stepArr)
|
||||
steps.add(step);
|
||||
}
|
||||
|
||||
public boolean isExpectedSessionIds()
|
||||
{
|
||||
return expectedSessionIds;
|
||||
}
|
||||
|
||||
public void setExpectedSessionIds(boolean expectedSessionIds)
|
||||
{
|
||||
this.expectedSessionIds = expectedSessionIds;
|
||||
}
|
||||
|
||||
public String id()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public Step popStep()
|
||||
{
|
||||
return steps.pollFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "DispatchPlan[id=" + id + "]";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.common;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Response;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class DispatchPlanHandler extends Handler.Wrapper
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DispatchPlanHandler.class);
|
||||
private Path plansDir;
|
||||
|
||||
public Path getPlansDir()
|
||||
{
|
||||
return plansDir;
|
||||
}
|
||||
|
||||
public void setPlansDir(Path plansDir)
|
||||
{
|
||||
this.plansDir = plansDir;
|
||||
}
|
||||
|
||||
public void setPlansDir(String plansDir)
|
||||
{
|
||||
this.setPlansDir(Path.of(plansDir));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Request request, Response response, Callback callback) throws Exception
|
||||
{
|
||||
DispatchPlan dispatchPlan = (DispatchPlan)request.getAttribute(DispatchPlan.class.getName());
|
||||
|
||||
if (dispatchPlan == null)
|
||||
{
|
||||
String planName = request.getHeaders().get("X-DispatchPlan");
|
||||
if (planName != null)
|
||||
{
|
||||
Path planPath = plansDir.resolve(planName);
|
||||
if (!Files.isRegularFile(planPath))
|
||||
{
|
||||
callback.failed(new IOException("Unable to find: " + planPath));
|
||||
}
|
||||
dispatchPlan = DispatchPlan.read(planPath);
|
||||
dispatchPlan.addEvent("Initial plan: %s", planName);
|
||||
request.setAttribute(DispatchPlan.class.getName(), dispatchPlan);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.info("Missing Request Header [X-DispatchPlan], skipping DispatchPlan behaviors for this request: {}", request.getHttpURI().toURI());
|
||||
}
|
||||
}
|
||||
|
||||
if (dispatchPlan != null)
|
||||
dispatchPlan.addEvent("DispatchPlanHandler.handle() method=%s path-query=%s", request.getMethod(), request.getHttpURI().getPathQuery());
|
||||
|
||||
return super.handle(request, response, callback);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.common;
|
||||
|
||||
public enum DispatchType
|
||||
{
|
||||
INCLUDE,
|
||||
FORWARD;
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.common;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class HttpRequest implements Step
|
||||
{
|
||||
private String method;
|
||||
private String requestPath;
|
||||
private String body;
|
||||
private Map<String, String> headers;
|
||||
|
||||
public static HttpRequest parse(String line)
|
||||
{
|
||||
String[] parts = line.split("\\|");
|
||||
HttpRequest request = new HttpRequest();
|
||||
request.setMethod(parts[1]);
|
||||
request.setRequestPath(parts[2]);
|
||||
if (parts.length > 4)
|
||||
request.setBody(parts[3]);
|
||||
return request;
|
||||
}
|
||||
|
||||
public String getMethod()
|
||||
{
|
||||
return method;
|
||||
}
|
||||
|
||||
public void setMethod(String method)
|
||||
{
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public String getRequestPath()
|
||||
{
|
||||
return requestPath;
|
||||
}
|
||||
|
||||
public void setRequestPath(String requestPath)
|
||||
{
|
||||
this.requestPath = requestPath;
|
||||
}
|
||||
|
||||
public String getBody()
|
||||
{
|
||||
return body;
|
||||
}
|
||||
|
||||
public void setBody(String body)
|
||||
{
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public Map<String, String> getHeaders()
|
||||
{
|
||||
return headers;
|
||||
}
|
||||
|
||||
public void setHeaders(Map<String, String> headers)
|
||||
{
|
||||
this.headers = headers;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.common;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
|
||||
import org.eclipse.jetty.session.DefaultSessionCache;
|
||||
import org.eclipse.jetty.session.ManagedSession;
|
||||
import org.eclipse.jetty.session.NullSessionDataStore;
|
||||
import org.eclipse.jetty.session.SessionData;
|
||||
import org.eclipse.jetty.session.SessionManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class PlanSessionCache extends DefaultSessionCache
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(PlanSessionCache.class);
|
||||
private final Path outputFile;
|
||||
|
||||
public PlanSessionCache(SessionManager manager)
|
||||
{
|
||||
super(manager);
|
||||
outputFile = Path.of(System.getProperty("jetty.base"), "work/session.log");
|
||||
setSessionDataStore(new NullSessionDataStore());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedSession newSession(SessionData data)
|
||||
{
|
||||
logEvent("newSession()", data);
|
||||
return super.newSession(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit(ManagedSession session) throws Exception
|
||||
{
|
||||
logEvent("commit()", session);
|
||||
super.commit(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release(ManagedSession session) throws Exception
|
||||
{
|
||||
logEvent("release()", session);
|
||||
super.release(session);
|
||||
}
|
||||
|
||||
private void logEvent(String eventType, SessionData data)
|
||||
{
|
||||
String name = "SessionCache.event." + eventType;
|
||||
String value = "";
|
||||
if (data != null)
|
||||
{
|
||||
value = String.format("id=%s|contextPath=%s", data.getId(), data.getContextPath());
|
||||
}
|
||||
logAttribute(name, value);
|
||||
}
|
||||
|
||||
private void logEvent(String eventType, ManagedSession session)
|
||||
{
|
||||
String name = "SessionCache.event." + eventType;
|
||||
String value = "";
|
||||
if (session != null)
|
||||
{
|
||||
value = String.format("id=%s", session.getId());
|
||||
SessionData data = session.getSessionData();
|
||||
if (data != null)
|
||||
{
|
||||
value = String.format("id=%s|contextPath=%s", data.getId(), data.getContextPath());
|
||||
}
|
||||
}
|
||||
logAttribute(name, value);
|
||||
}
|
||||
|
||||
private void logAttribute(String name, String value)
|
||||
{
|
||||
String line = name + "=" + value;
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info(line);
|
||||
|
||||
try
|
||||
{
|
||||
Files.writeString(outputFile, line + "\n", StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.APPEND);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.warn("Unable to write to " + outputFile, e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.common;
|
||||
|
||||
public class Property
|
||||
{
|
||||
private String name;
|
||||
private String value;
|
||||
|
||||
public Property()
|
||||
{
|
||||
}
|
||||
|
||||
public Property(String name, String value)
|
||||
{
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static Property parse(String line)
|
||||
{
|
||||
String[] parts = line.split("\\|");
|
||||
String name = parts[1];
|
||||
String value = null;
|
||||
if (parts.length > 2)
|
||||
value = parts[2];
|
||||
return new Property(name, value);
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Property{" +
|
||||
"name='" + name + '\'' +
|
||||
", value='" + value + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.common;
|
||||
|
||||
public interface Step
|
||||
{
|
||||
static Step parse(String line)
|
||||
{
|
||||
String[] parts = line.split("\\|");
|
||||
switch (parts[1])
|
||||
{
|
||||
case "CONTEXT_FORWARD" ->
|
||||
{
|
||||
ContextRedispatch step = new ContextRedispatch();
|
||||
step.setDispatchType(DispatchType.FORWARD);
|
||||
step.setContextPath(parts[2]);
|
||||
step.setDispatchPath(parts[3]);
|
||||
return step;
|
||||
}
|
||||
case "CONTEXT_INCLUDE" ->
|
||||
{
|
||||
ContextRedispatch step = new ContextRedispatch();
|
||||
step.setDispatchType(DispatchType.INCLUDE);
|
||||
step.setContextPath(parts[2]);
|
||||
step.setDispatchPath(parts[3]);
|
||||
return step;
|
||||
}
|
||||
case "REQUEST_FORWARD" ->
|
||||
{
|
||||
RequestDispatch step = new RequestDispatch();
|
||||
step.setDispatchType(DispatchType.FORWARD);
|
||||
step.setDispatchPath(parts[2]);
|
||||
return step;
|
||||
}
|
||||
case "REQUEST_INCLUDE" ->
|
||||
{
|
||||
RequestDispatch step = new RequestDispatch();
|
||||
step.setDispatchType(DispatchType.INCLUDE);
|
||||
step.setDispatchPath(parts[2]);
|
||||
return step;
|
||||
}
|
||||
case "GET_HTTP_SESSION_ATTRIBUTE" ->
|
||||
{
|
||||
GetHttpSession step = new GetHttpSession();
|
||||
step.setName(parts[2]);
|
||||
return step;
|
||||
}
|
||||
case "SET_HTTP_SESSION_ATTRIBUTE" ->
|
||||
{
|
||||
String name = parts[2];
|
||||
String value = parts[3];
|
||||
Property prop = new Property(name, value);
|
||||
HttpSessionSetAttribute step = new HttpSessionSetAttribute(prop);
|
||||
return step;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Unknown STEP type [" + parts[1] + "]");
|
||||
}
|
||||
|
||||
/**
|
||||
* Will cause an Attribute to be set on the HttpSession via {@code HttpSession.setAttribute(String, Object)}
|
||||
*/
|
||||
class HttpSessionSetAttribute implements Step
|
||||
{
|
||||
private Property property;
|
||||
|
||||
public HttpSessionSetAttribute(Property property)
|
||||
{
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public Property getProperty()
|
||||
{
|
||||
return property;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Will cause the HttpSession to be fetched via {@code HttpServletRequest#getHttpSession(false)}
|
||||
* and report the state of the HttpSession in the events (even if null).
|
||||
*/
|
||||
class GetHttpSession implements Step
|
||||
{
|
||||
private String name;
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a Redispatch with FORWARD or INCLUDE types using the {@code ServletContext}.
|
||||
* Uses the {@code ServletContext.getContext(contextPath)} to obtain the
|
||||
* {@code ServletContext} to then use {@code ServletContext.getRequestDispatcher(dispatchPath)}
|
||||
* against, which then results in a {@code RequestDispatcher.include} or {@code RequestDispatcher.forward}
|
||||
* call.
|
||||
*/
|
||||
class ContextRedispatch implements Step
|
||||
{
|
||||
private DispatchType dispatchType;
|
||||
private String contextPath;
|
||||
private String dispatchPath;
|
||||
|
||||
public DispatchType getDispatchType()
|
||||
{
|
||||
return dispatchType;
|
||||
}
|
||||
|
||||
public void setDispatchType(DispatchType dispatchType)
|
||||
{
|
||||
this.dispatchType = dispatchType;
|
||||
}
|
||||
|
||||
public String getContextPath()
|
||||
{
|
||||
return contextPath;
|
||||
}
|
||||
|
||||
public void setContextPath(String contextPath)
|
||||
{
|
||||
this.contextPath = contextPath;
|
||||
}
|
||||
|
||||
public String getDispatchPath()
|
||||
{
|
||||
return dispatchPath;
|
||||
}
|
||||
|
||||
public void setDispatchPath(String dispatchPath)
|
||||
{
|
||||
this.dispatchPath = dispatchPath;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a Redispatch with FORWARD or INCLUDE types using the {@code HttpServletRequest}.
|
||||
* Uses the {@code HttpServletRequest.getRequestDispatcher(dispatchPath)} which then
|
||||
* results in a {@code RequestDispatcher.include} or {@code RequestDispatcher.forward}
|
||||
* call.
|
||||
*/
|
||||
class RequestDispatch implements Step
|
||||
{
|
||||
private DispatchType dispatchType;
|
||||
private String dispatchPath;
|
||||
|
||||
public DispatchType getDispatchType()
|
||||
{
|
||||
return dispatchType;
|
||||
}
|
||||
|
||||
public void setDispatchType(DispatchType dispatchType)
|
||||
{
|
||||
this.dispatchType = dispatchType;
|
||||
}
|
||||
|
||||
public String getDispatchPath()
|
||||
{
|
||||
return dispatchPath;
|
||||
}
|
||||
|
||||
public void setDispatchPath(String dispatchPath)
|
||||
{
|
||||
this.dispatchPath = dispatchPath;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.common;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.eclipse.jetty.toolchain.test.MavenPaths;
|
||||
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
@ExtendWith(WorkDirExtension.class)
|
||||
public class DispatchPlanLoadTest
|
||||
{
|
||||
@Test
|
||||
public void testRead() throws IOException
|
||||
{
|
||||
Path planPath = MavenPaths.findTestResourceFile("forward-include-dump.txt");
|
||||
DispatchPlan plan = DispatchPlan.read(planPath);
|
||||
assertNotNull(plan);
|
||||
|
||||
assertThat("plan.id", plan.id(), is(planPath.getFileName().toString()));
|
||||
|
||||
HttpRequest httpRequestStep = plan.getRequestStep();
|
||||
assertThat(httpRequestStep.getMethod(), is("GET"));
|
||||
assertThat(httpRequestStep.getRequestPath(), is("/ccd-ee10/redispatch/ee10"));
|
||||
assertThat(httpRequestStep.getBody(), is(nullValue()));
|
||||
|
||||
assertEquals(3, plan.getSteps().size());
|
||||
|
||||
Step step = plan.popStep();
|
||||
assertThat(step, instanceOf(Step.ContextRedispatch.class));
|
||||
Step.ContextRedispatch contextRedispatchStep = (Step.ContextRedispatch)step;
|
||||
assertThat(contextRedispatchStep.getDispatchType(), is(DispatchType.FORWARD));
|
||||
assertThat(contextRedispatchStep.getContextPath(), is("/ccd-ee8"));
|
||||
assertThat(contextRedispatchStep.getDispatchPath(), is("/redispatch/ee8"));
|
||||
|
||||
step = plan.popStep();
|
||||
assertThat(step, instanceOf(Step.ContextRedispatch.class));
|
||||
contextRedispatchStep = (Step.ContextRedispatch)step;
|
||||
assertThat(contextRedispatchStep.getDispatchType(), is(DispatchType.FORWARD));
|
||||
assertThat(contextRedispatchStep.getContextPath(), is("/ccd-ee9"));
|
||||
assertThat(contextRedispatchStep.getDispatchPath(), is("/redispatch/ee9"));
|
||||
|
||||
step = plan.popStep();
|
||||
assertThat(step, instanceOf(Step.RequestDispatch.class));
|
||||
Step.RequestDispatch requestRedispatchStep = (Step.RequestDispatch)step;
|
||||
assertThat(requestRedispatchStep.getDispatchType(), is(DispatchType.INCLUDE));
|
||||
assertThat(requestRedispatchStep.getDispatchPath(), is("/dump/ee9"));
|
||||
|
||||
assertThat(plan.getExpectedContentType(), is("text/x-java-properties; charset=utf-8"));
|
||||
|
||||
assertThat("Expected Events", plan.getExpectedEvents().size(), is(6));
|
||||
assertThat("Expected Output", plan.getExpectedOutput().size(), is(1));
|
||||
assertThat("Expected Properties", plan.getExpectedProperties().size(), is(18));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
REQUEST|GET|/ccd-ee10/redispatch/ee10
|
||||
STEP|CONTEXT_FORWARD|/ccd-ee8|/redispatch/ee8
|
||||
STEP|CONTEXT_FORWARD|/ccd-ee9|/redispatch/ee9
|
||||
STEP|REQUEST_INCLUDE|/dump/ee9
|
||||
EXPECTED_CONTENT_TYPE|text/x-java-properties; charset=utf-8
|
||||
EXPECTED_EVENT|Initial plan: ee10-forward-to-ee8-include-ee9-dump.json
|
||||
EXPECTED_EVENT|DispatchPlanHandler.handle() method=GET path-query=/ccd-ee10/redispatch/ee10
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee10.CCDServlet.service() dispatcherType=REQUEST method=GET requestUri=/ccd-ee10/redispatch/ee10
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee8.CCDServlet.service() dispatcherType=FORWARD method=GET requestUri=/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee9.CCDServlet.service() dispatcherType=FORWARD method=GET requestUri=/ccd-ee9/redispatch/ee9
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee9.DumpServlet.service() dispatcherType=INCLUDE method=GET requestUri=/ccd-ee9/redispatch/ee9
|
||||
EXPECTED_PROP|request.dispatcherType|INCLUDE
|
||||
EXPECTED_PROP|request.requestURI|/ccd-ee9/redispatch/ee9
|
||||
EXPECTED_PROP|attr[jakarta.servlet.forward.context_path]|/ccd-ee8
|
||||
EXPECTED_PROP|attr[jakarta.servlet.forward.path_info]|/ee8
|
||||
EXPECTED_PROP|attr[jakarta.servlet.forward.request_uri]|/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_PROP|attr[jakarta.servlet.forward.servlet_path]|/redispatch
|
||||
EXPECTED_PROP|attr[jakarta.servlet.include.context_path]/ccd-ee9
|
||||
EXPECTED_PROP|attr[jakarta.servlet.include.path_info]|/ee9
|
||||
EXPECTED_PROP|attr[jakarta.servlet.include.request_uri]|/ccd-ee9/dump/ee9
|
||||
EXPECTED_PROP|attr[jakarta.servlet.include.servlet_path]/dump
|
||||
EXPECTED_PROP|attr[javax.servlet.include.context_path]|<null>
|
||||
EXPECTED_PROP|attr[javax.servlet.include.path_info]|<null>
|
||||
EXPECTED_PROP|attr[javax.servlet.include.request_uri]|<null>
|
||||
EXPECTED_PROP|attr[javax.servlet.include.servlet_path]|<null>
|
||||
EXPECTED_PROP|attr[javax.servlet.forward.context_path]|/ccd-ee8
|
||||
EXPECTED_PROP|attr[javax.servlet.forward.path_info]|/ee8
|
||||
EXPECTED_PROP|attr[javax.servlet.forward.request_uri]|/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_PROP|attr[javax.servlet.forward.servlet_path]|/redispatch
|
||||
EXPECTED_OUTPUT|foo-bar
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.tests.ccd</groupId>
|
||||
<artifactId>test-cross-context-dispatch</artifactId>
|
||||
<version>12.0.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>ccd-ee10-webapp</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<name>Tests :: Cross Context Dispatch :: ee10 WebApp</name>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.ee10</groupId>
|
||||
<artifactId>jetty-ee10-bom</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<version>6.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.tests.ccd</groupId>
|
||||
<artifactId>ccd-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,108 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.ee10;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
import jakarta.servlet.RequestDispatcher;
|
||||
import jakarta.servlet.ServletContext;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import org.eclipse.jetty.tests.ccd.common.DispatchPlan;
|
||||
import org.eclipse.jetty.tests.ccd.common.Property;
|
||||
import org.eclipse.jetty.tests.ccd.common.Step;
|
||||
|
||||
public class CCDServlet extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
|
||||
{
|
||||
DispatchPlan dispatchPlan = (DispatchPlan)req.getAttribute(DispatchPlan.class.getName());
|
||||
|
||||
if (dispatchPlan == null)
|
||||
throw new ServletException("Unable to find DispatchPlan");
|
||||
|
||||
dispatchPlan.addEvent("%s.service() dispatcherType=%s method=%s requestUri=%s",
|
||||
this.getClass().getName(),
|
||||
req.getDispatcherType(), req.getMethod(), req.getRequestURI());
|
||||
|
||||
Step step;
|
||||
|
||||
while ((step = dispatchPlan.popStep()) != null)
|
||||
{
|
||||
if (step instanceof Step.ContextRedispatch contextRedispatchStep)
|
||||
{
|
||||
ServletContext otherContext = getServletContext().getContext(contextRedispatchStep.getContextPath());
|
||||
if (otherContext == null)
|
||||
throw new NullPointerException("ServletContext.getContext(\"" + contextRedispatchStep.getContextPath() + "\") returned null");
|
||||
RequestDispatcher dispatcher = otherContext.getRequestDispatcher(contextRedispatchStep.getDispatchPath());
|
||||
if (dispatcher == null)
|
||||
throw new NullPointerException("ServletContext.getRequestDispatcher(\"" + contextRedispatchStep.getDispatchPath() + "\") returned null");
|
||||
switch (contextRedispatchStep.getDispatchType())
|
||||
{
|
||||
case FORWARD -> dispatcher.forward(req, resp);
|
||||
case INCLUDE -> dispatcher.include(req, resp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (step instanceof Step.RequestDispatch requestDispatchStep)
|
||||
{
|
||||
RequestDispatcher dispatcher = req.getRequestDispatcher(requestDispatchStep.getDispatchPath());
|
||||
if (dispatcher == null)
|
||||
throw new NullPointerException("HttpServletRequest.getRequestDispatcher(\"" + requestDispatchStep.getDispatchPath() + "\") returned null");
|
||||
switch (requestDispatchStep.getDispatchType())
|
||||
{
|
||||
case FORWARD -> dispatcher.forward(req, resp);
|
||||
case INCLUDE -> dispatcher.include(req, resp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (step instanceof Step.GetHttpSession getHttpSessionTask)
|
||||
{
|
||||
HttpSession session = req.getSession(false);
|
||||
if (session == null)
|
||||
{
|
||||
dispatchPlan.addEvent("%s.service() HttpSession is null",
|
||||
this.getClass().getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
String name = getHttpSessionTask.getName();
|
||||
Object value = session.getAttribute(name);
|
||||
dispatchPlan.addEvent("%s.service() HttpSession exists: [%s]=[%s]",
|
||||
this.getClass().getName(),
|
||||
name,
|
||||
Objects.toString(value)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
else if (step instanceof Step.HttpSessionSetAttribute sessionSetAttribute)
|
||||
{
|
||||
HttpSession session = req.getSession(true);
|
||||
req.setAttribute("session[" + req.getRequestURI() + "].id", session.getId());
|
||||
Property prop = sessionSetAttribute.getProperty();
|
||||
session.setAttribute(prop.getName(), prop.getValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException("Unable to execute task " + step + " in " + this.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.ee10;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import org.eclipse.jetty.tests.ccd.common.DispatchPlan;
|
||||
|
||||
public class DumpServlet extends HttpServlet
|
||||
{
|
||||
private static final String NULL = "<null>";
|
||||
|
||||
@Override
|
||||
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException
|
||||
{
|
||||
DispatchPlan dispatchPlan = (DispatchPlan)req.getAttribute(DispatchPlan.class.getName());
|
||||
|
||||
if (dispatchPlan != null)
|
||||
{
|
||||
dispatchPlan.addEvent("%s.service() dispatcherType=%s method=%s requestUri=%s",
|
||||
this.getClass().getName(),
|
||||
req.getDispatcherType(), req.getMethod(), req.getRequestURI());
|
||||
}
|
||||
|
||||
Properties props = new Properties();
|
||||
props.setProperty("requestType", req.getClass().getName());
|
||||
props.setProperty("responseType", resp.getClass().getName());
|
||||
|
||||
props.setProperty("request.authType", Objects.toString(req.getAuthType(), NULL));
|
||||
props.setProperty("request.characterEncoding", Objects.toString(req.getCharacterEncoding(), NULL));
|
||||
props.setProperty("request.contentLength", Long.toString(req.getContentLengthLong()));
|
||||
props.setProperty("request.contentType", Objects.toString(req.getContentType(), NULL));
|
||||
props.setProperty("request.contextPath", Objects.toString(req.getContextPath(), NULL));
|
||||
props.setProperty("request.dispatcherType", Objects.toString(req.getDispatcherType(), NULL));
|
||||
props.setProperty("request.localAddr", Objects.toString(req.getLocalAddr(), NULL));
|
||||
props.setProperty("request.localName", Objects.toString(req.getLocalName(), NULL));
|
||||
props.setProperty("request.localPort", Integer.toString(req.getLocalPort()));
|
||||
props.setProperty("request.locale", Objects.toString(req.getLocale(), NULL));
|
||||
props.setProperty("request.method", Objects.toString(req.getMethod(), NULL));
|
||||
props.setProperty("request.pathInfo", Objects.toString(req.getPathInfo(), NULL));
|
||||
props.setProperty("request.pathTranslated", Objects.toString(req.getPathTranslated(), NULL));
|
||||
props.setProperty("request.protocol", Objects.toString(req.getProtocol(), NULL));
|
||||
props.setProperty("request.queryString", Objects.toString(req.getQueryString(), NULL));
|
||||
props.setProperty("request.remoteAddr", Objects.toString(req.getRemoteAddr(), NULL));
|
||||
props.setProperty("request.remoteHost", Objects.toString(req.getRemoteHost(), NULL));
|
||||
props.setProperty("request.remotePort", Integer.toString(req.getRemotePort()));
|
||||
props.setProperty("request.remoteUser", Objects.toString(req.getRemoteUser(), NULL));
|
||||
props.setProperty("request.requestedSessionId", Objects.toString(req.getRequestedSessionId(), NULL));
|
||||
props.setProperty("request.requestURI", Objects.toString(req.getRequestURI(), NULL));
|
||||
props.setProperty("request.requestURL", Objects.toString(req.getRequestURL(), NULL));
|
||||
props.setProperty("request.serverPort", Integer.toString(req.getServerPort()));
|
||||
props.setProperty("request.servletPath", Objects.toString(req.getServletPath(), NULL));
|
||||
|
||||
props.setProperty("request.session.exists", "false");
|
||||
HttpSession httpSession = req.getSession(false);
|
||||
if (httpSession != null)
|
||||
{
|
||||
props.setProperty("request.session.exists", "true");
|
||||
List<String> attrNames = Collections.list(httpSession.getAttributeNames());
|
||||
attrNames
|
||||
.forEach((name) ->
|
||||
{
|
||||
Object attrVal = httpSession.getAttribute(name);
|
||||
props.setProperty("session[" + name + "]", Objects.toString(attrVal, NULL));
|
||||
});
|
||||
}
|
||||
|
||||
addAttributes(props, "req", req::getAttributeNames, req::getAttribute);
|
||||
addAttributes(props, "context",
|
||||
() -> getServletContext().getAttributeNames(),
|
||||
(name) -> getServletContext().getAttribute(name));
|
||||
|
||||
List<String> headerNames = Collections.list(req.getHeaderNames());
|
||||
headerNames
|
||||
.forEach((name) ->
|
||||
{
|
||||
String headerVal = req.getHeader(name);
|
||||
props.setProperty("header[" + name + "]", Objects.toString(headerVal, NULL));
|
||||
});
|
||||
|
||||
if (dispatchPlan != null)
|
||||
{
|
||||
int eventCount = dispatchPlan.getEvents().size();
|
||||
props.setProperty("dispatchPlan.events.count", Integer.toString(dispatchPlan.getEvents().size()));
|
||||
for (int i = 0; i < eventCount; i++)
|
||||
{
|
||||
props.setProperty("dispatchPlan.event[" + i + "]", dispatchPlan.getEvents().get(i));
|
||||
}
|
||||
}
|
||||
|
||||
resp.setStatus(HttpServletResponse.SC_OK);
|
||||
resp.setCharacterEncoding("utf-8");
|
||||
resp.setContentType("text/x-java-properties");
|
||||
PrintWriter out = resp.getWriter();
|
||||
props.store(out, "From " + this.getClass().getName());
|
||||
}
|
||||
|
||||
private void addAttributes(Properties props,
|
||||
String prefix,
|
||||
Supplier<Enumeration<String>> getNamesSupplier,
|
||||
Function<String, Object> getAttributeFunction)
|
||||
{
|
||||
List<String> attrNames = Collections.list(getNamesSupplier.get());
|
||||
attrNames
|
||||
.forEach((name) ->
|
||||
{
|
||||
Object attrVal = getAttributeFunction.apply(name);
|
||||
props.setProperty(prefix + ".attr[" + name + "]", Objects.toString(attrVal, NULL));
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.ee10;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
import jakarta.servlet.RequestDispatcher;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
public class ForwardServlet extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
|
||||
{
|
||||
String forwardTo = req.getHeader("X-ForwardTo");
|
||||
Objects.requireNonNull(forwardTo);
|
||||
RequestDispatcher requestDispatcher = req.getRequestDispatcher(forwardTo);
|
||||
requestDispatcher.forward(req, resp);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.ee10;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* A servlet filter that will harshly change the return value of
|
||||
* {@link HttpServletRequest#getRequestURI()} to something that does
|
||||
* not satisfy the Servlet spec URI invariant {@code request URI == context path + servlet path + path info}
|
||||
*/
|
||||
public class InternalRequestURIFilter implements Filter
|
||||
{
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
|
||||
{
|
||||
HttpServletRequest httpServletRequest = (HttpServletRequest)request;
|
||||
HttpServletResponse httpServletResponse = (HttpServletResponse)response;
|
||||
InternalRequestURIWrapper requestURIWrapper = new InternalRequestURIWrapper(httpServletRequest);
|
||||
chain.doFilter(requestURIWrapper, httpServletResponse);
|
||||
}
|
||||
|
||||
private static class InternalRequestURIWrapper extends HttpServletRequestWrapper
|
||||
{
|
||||
public InternalRequestURIWrapper(HttpServletRequest request)
|
||||
{
|
||||
super(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestURI()
|
||||
{
|
||||
return "/internal/";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
|
||||
version="6.0">
|
||||
|
||||
<display-name>ccd-ee10</display-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>ccd</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.tests.ccd.ee10.CCDServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>dump</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.tests.ccd.ee10.DumpServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>ccd</servlet-name>
|
||||
<url-pattern>/redispatch/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>dump</servlet-name>
|
||||
<url-pattern>/dump/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.tests.ccd</groupId>
|
||||
<artifactId>test-cross-context-dispatch</artifactId>
|
||||
<version>12.0.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>ccd-ee8-webapp</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<name>Tests :: Cross Context Dispatch :: ee8 WebApp</name>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.ee8</groupId>
|
||||
<artifactId>jetty-ee8-bom</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<version>4.0.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.tests.ccd</groupId>
|
||||
<artifactId>ccd-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,107 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.ee8;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.eclipse.jetty.tests.ccd.common.DispatchPlan;
|
||||
import org.eclipse.jetty.tests.ccd.common.Property;
|
||||
import org.eclipse.jetty.tests.ccd.common.Step;
|
||||
|
||||
public class CCDServlet extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
|
||||
{
|
||||
DispatchPlan dispatchPlan = (DispatchPlan)req.getAttribute(DispatchPlan.class.getName());
|
||||
|
||||
if (dispatchPlan == null)
|
||||
throw new ServletException("Unable to find DispatchPlan");
|
||||
|
||||
dispatchPlan.addEvent("%s.service() dispatcherType=%s method=%s requestUri=%s",
|
||||
this.getClass().getName(),
|
||||
req.getDispatcherType(), req.getMethod(), req.getRequestURI());
|
||||
|
||||
Step step;
|
||||
|
||||
while ((step = dispatchPlan.popStep()) != null)
|
||||
{
|
||||
if (step instanceof Step.ContextRedispatch contextRedispatchStep)
|
||||
{
|
||||
ServletContext otherContext = getServletContext().getContext(contextRedispatchStep.getContextPath());
|
||||
if (otherContext == null)
|
||||
throw new NullPointerException("ServletContext.getContext(\"" + contextRedispatchStep.getContextPath() + "\") returned null");
|
||||
RequestDispatcher dispatcher = otherContext.getRequestDispatcher(contextRedispatchStep.getDispatchPath());
|
||||
if (dispatcher == null)
|
||||
throw new NullPointerException("ServletContext.getRequestDispatcher(\"" + contextRedispatchStep.getDispatchPath() + "\") returned null");
|
||||
switch (contextRedispatchStep.getDispatchType())
|
||||
{
|
||||
case FORWARD -> dispatcher.forward(req, resp);
|
||||
case INCLUDE -> dispatcher.include(req, resp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (step instanceof Step.RequestDispatch requestDispatchStep)
|
||||
{
|
||||
RequestDispatcher dispatcher = req.getRequestDispatcher(requestDispatchStep.getDispatchPath());
|
||||
if (dispatcher == null)
|
||||
throw new NullPointerException("HttpServletRequest.getRequestDispatcher(\"" + requestDispatchStep.getDispatchPath() + "\") returned null");
|
||||
switch (requestDispatchStep.getDispatchType())
|
||||
{
|
||||
case FORWARD -> dispatcher.forward(req, resp);
|
||||
case INCLUDE -> dispatcher.include(req, resp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (step instanceof Step.GetHttpSession getHttpSessionTask)
|
||||
{
|
||||
HttpSession session = req.getSession(false);
|
||||
if (session == null)
|
||||
{
|
||||
dispatchPlan.addEvent("%s.service() HttpSession is null",
|
||||
this.getClass().getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
String name = getHttpSessionTask.getName();
|
||||
Object value = session.getAttribute(name);
|
||||
dispatchPlan.addEvent("%s.service() HttpSession exists: [%s]=[%s]",
|
||||
this.getClass().getName(),
|
||||
name,
|
||||
Objects.toString(value)
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (step instanceof Step.HttpSessionSetAttribute sessionSetAttribute)
|
||||
{
|
||||
HttpSession session = req.getSession(true);
|
||||
req.setAttribute("session[" + req.getRequestURI() + "].id", session.getId());
|
||||
Property prop = sessionSetAttribute.getProperty();
|
||||
session.setAttribute(prop.getName(), prop.getValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException("Unable to execute task " + step + " in " + this.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.ee8;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.eclipse.jetty.tests.ccd.common.DispatchPlan;
|
||||
|
||||
public class DumpServlet extends HttpServlet
|
||||
{
|
||||
private static final String NULL = "<null>";
|
||||
|
||||
@Override
|
||||
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException
|
||||
{
|
||||
DispatchPlan dispatchPlan = (DispatchPlan)req.getAttribute(DispatchPlan.class.getName());
|
||||
|
||||
if (dispatchPlan != null)
|
||||
{
|
||||
dispatchPlan.addEvent("%s.service() dispatcherType=%s method=%s requestUri=%s",
|
||||
this.getClass().getName(),
|
||||
req.getDispatcherType(), req.getMethod(), req.getRequestURI());
|
||||
}
|
||||
|
||||
Properties props = new Properties();
|
||||
props.setProperty("requestType", req.getClass().getName());
|
||||
props.setProperty("responseType", resp.getClass().getName());
|
||||
|
||||
props.setProperty("request.authType", Objects.toString(req.getAuthType(), NULL));
|
||||
props.setProperty("request.characterEncoding", Objects.toString(req.getCharacterEncoding(), NULL));
|
||||
props.setProperty("request.contentLength", Long.toString(req.getContentLengthLong()));
|
||||
props.setProperty("request.contentType", Objects.toString(req.getContentType(), NULL));
|
||||
props.setProperty("request.contextPath", Objects.toString(req.getContextPath(), NULL));
|
||||
props.setProperty("request.dispatcherType", Objects.toString(req.getDispatcherType(), NULL));
|
||||
props.setProperty("request.localAddr", Objects.toString(req.getLocalAddr(), NULL));
|
||||
props.setProperty("request.localName", Objects.toString(req.getLocalName(), NULL));
|
||||
props.setProperty("request.localPort", Integer.toString(req.getLocalPort()));
|
||||
props.setProperty("request.locale", Objects.toString(req.getLocale(), NULL));
|
||||
props.setProperty("request.method", Objects.toString(req.getMethod(), NULL));
|
||||
props.setProperty("request.pathInfo", Objects.toString(req.getPathInfo(), NULL));
|
||||
props.setProperty("request.pathTranslated", Objects.toString(req.getPathTranslated(), NULL));
|
||||
props.setProperty("request.protocol", Objects.toString(req.getProtocol(), NULL));
|
||||
props.setProperty("request.queryString", Objects.toString(req.getQueryString(), NULL));
|
||||
props.setProperty("request.remoteAddr", Objects.toString(req.getRemoteAddr(), NULL));
|
||||
props.setProperty("request.remoteHost", Objects.toString(req.getRemoteHost(), NULL));
|
||||
props.setProperty("request.remotePort", Integer.toString(req.getRemotePort()));
|
||||
props.setProperty("request.remoteUser", Objects.toString(req.getRemoteUser(), NULL));
|
||||
props.setProperty("request.requestedSessionId", Objects.toString(req.getRequestedSessionId(), NULL));
|
||||
props.setProperty("request.requestURI", Objects.toString(req.getRequestURI(), NULL));
|
||||
props.setProperty("request.requestURL", Objects.toString(req.getRequestURL(), NULL));
|
||||
props.setProperty("request.serverPort", Integer.toString(req.getServerPort()));
|
||||
props.setProperty("request.servletPath", Objects.toString(req.getServletPath(), NULL));
|
||||
|
||||
props.setProperty("request.session.exists", "false");
|
||||
HttpSession httpSession = req.getSession(false);
|
||||
if (httpSession != null)
|
||||
{
|
||||
props.setProperty("request.session.exists", "true");
|
||||
List<String> attrNames = Collections.list(httpSession.getAttributeNames());
|
||||
attrNames
|
||||
.forEach((name) ->
|
||||
{
|
||||
Object attrVal = httpSession.getAttribute(name);
|
||||
props.setProperty("session[" + name + "]", Objects.toString(attrVal, NULL));
|
||||
});
|
||||
}
|
||||
|
||||
addAttributes(props, "req", req::getAttributeNames, req::getAttribute);
|
||||
addAttributes(props, "context",
|
||||
() -> getServletContext().getAttributeNames(),
|
||||
(name) -> getServletContext().getAttribute(name));
|
||||
|
||||
List<String> headerNames = Collections.list(req.getHeaderNames());
|
||||
headerNames
|
||||
.forEach((name) ->
|
||||
{
|
||||
String headerVal = req.getHeader(name);
|
||||
props.setProperty("header[" + name + "]", Objects.toString(headerVal, NULL));
|
||||
});
|
||||
|
||||
if (dispatchPlan != null)
|
||||
{
|
||||
int eventCount = dispatchPlan.getEvents().size();
|
||||
props.setProperty("dispatchPlan.events.count", Integer.toString(dispatchPlan.getEvents().size()));
|
||||
for (int i = 0; i < eventCount; i++)
|
||||
{
|
||||
props.setProperty("dispatchPlan.event[" + i + "]", dispatchPlan.getEvents().get(i));
|
||||
}
|
||||
}
|
||||
|
||||
resp.setStatus(HttpServletResponse.SC_OK);
|
||||
resp.setCharacterEncoding("utf-8");
|
||||
resp.setContentType("text/x-java-properties");
|
||||
PrintWriter out = resp.getWriter();
|
||||
props.store(out, "From " + this.getClass().getName());
|
||||
}
|
||||
|
||||
private void addAttributes(Properties props,
|
||||
String prefix,
|
||||
Supplier<Enumeration<String>> getNamesSupplier,
|
||||
Function<String, Object> getAttributeFunction)
|
||||
{
|
||||
List<String> attrNames = Collections.list(getNamesSupplier.get());
|
||||
attrNames
|
||||
.forEach((name) ->
|
||||
{
|
||||
Object attrVal = getAttributeFunction.apply(name);
|
||||
props.setProperty(prefix + ".attr[" + name + "]", Objects.toString(attrVal, NULL));
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.ee8;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class ForwardServlet extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
|
||||
{
|
||||
String forwardTo = req.getHeader("X-ForwardTo");
|
||||
Objects.requireNonNull(forwardTo);
|
||||
RequestDispatcher requestDispatcher = req.getRequestDispatcher(forwardTo);
|
||||
requestDispatcher.forward(req, resp);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.ee8;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* A servlet filter that will harshly change the return value of
|
||||
* {@link HttpServletRequest#getRequestURI()} to something that does
|
||||
* not satisfy the Servlet spec URI invariant {@code request URI == context path + servlet path + path info}
|
||||
*/
|
||||
public class InternalRequestURIFilter implements Filter
|
||||
{
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
|
||||
{
|
||||
HttpServletRequest httpServletRequest = (HttpServletRequest)request;
|
||||
HttpServletResponse httpServletResponse = (HttpServletResponse)response;
|
||||
InternalRequestURIWrapper requestURIWrapper = new InternalRequestURIWrapper(httpServletRequest);
|
||||
chain.doFilter(requestURIWrapper, httpServletResponse);
|
||||
}
|
||||
|
||||
private static class InternalRequestURIWrapper extends HttpServletRequestWrapper
|
||||
{
|
||||
public InternalRequestURIWrapper(HttpServletRequest request)
|
||||
{
|
||||
super(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestURI()
|
||||
{
|
||||
return "/internal/";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
|
||||
version="4.0">
|
||||
|
||||
<display-name>ccd-ee8</display-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>ccd</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.tests.ccd.ee8.CCDServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>forwardto</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.tests.ccd.ee8.ForwardServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>dump</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.tests.ccd.ee8.DumpServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>ccd</servlet-name>
|
||||
<url-pattern>/redispatch/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>forwardto</servlet-name>
|
||||
<url-pattern>/forwardto/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>dump</servlet-name>
|
||||
<url-pattern>/dump/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
</web-app>
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.tests.ccd</groupId>
|
||||
<artifactId>test-cross-context-dispatch</artifactId>
|
||||
<version>12.0.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>ccd-ee9-webapp</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<name>Tests :: Cross Context Dispatch :: ee9 WebApp</name>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.ee9</groupId>
|
||||
<artifactId>jetty-ee9-bom</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<version>5.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.tests.ccd</groupId>
|
||||
<artifactId>ccd-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,108 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.ee9;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
import jakarta.servlet.RequestDispatcher;
|
||||
import jakarta.servlet.ServletContext;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import org.eclipse.jetty.tests.ccd.common.DispatchPlan;
|
||||
import org.eclipse.jetty.tests.ccd.common.Property;
|
||||
import org.eclipse.jetty.tests.ccd.common.Step;
|
||||
|
||||
public class CCDServlet extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
|
||||
{
|
||||
DispatchPlan dispatchPlan = (DispatchPlan)req.getAttribute(DispatchPlan.class.getName());
|
||||
|
||||
if (dispatchPlan == null)
|
||||
throw new ServletException("Unable to find DispatchPlan");
|
||||
|
||||
dispatchPlan.addEvent("%s.service() dispatcherType=%s method=%s requestUri=%s",
|
||||
this.getClass().getName(),
|
||||
req.getDispatcherType(), req.getMethod(), req.getRequestURI());
|
||||
|
||||
Step step;
|
||||
|
||||
while ((step = dispatchPlan.popStep()) != null)
|
||||
{
|
||||
if (step instanceof Step.ContextRedispatch contextRedispatchStep)
|
||||
{
|
||||
ServletContext otherContext = getServletContext().getContext(contextRedispatchStep.getContextPath());
|
||||
if (otherContext == null)
|
||||
throw new NullPointerException("ServletContext.getContext(\"" + contextRedispatchStep.getContextPath() + "\") returned null");
|
||||
RequestDispatcher dispatcher = otherContext.getRequestDispatcher(contextRedispatchStep.getDispatchPath());
|
||||
if (dispatcher == null)
|
||||
throw new NullPointerException("ServletContext.getRequestDispatcher(\"" + contextRedispatchStep.getDispatchPath() + "\") returned null");
|
||||
switch (contextRedispatchStep.getDispatchType())
|
||||
{
|
||||
case FORWARD -> dispatcher.forward(req, resp);
|
||||
case INCLUDE -> dispatcher.include(req, resp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (step instanceof Step.RequestDispatch requestDispatchStep)
|
||||
{
|
||||
RequestDispatcher dispatcher = req.getRequestDispatcher(requestDispatchStep.getDispatchPath());
|
||||
if (dispatcher == null)
|
||||
throw new NullPointerException("HttpServletRequest.getRequestDispatcher(\"" + requestDispatchStep.getDispatchPath() + "\") returned null");
|
||||
switch (requestDispatchStep.getDispatchType())
|
||||
{
|
||||
case FORWARD -> dispatcher.forward(req, resp);
|
||||
case INCLUDE -> dispatcher.include(req, resp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (step instanceof Step.GetHttpSession getHttpSessionTask)
|
||||
{
|
||||
HttpSession session = req.getSession(false);
|
||||
if (session == null)
|
||||
{
|
||||
dispatchPlan.addEvent("%s.service() HttpSession is null",
|
||||
this.getClass().getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
String name = getHttpSessionTask.getName();
|
||||
Object value = session.getAttribute(name);
|
||||
dispatchPlan.addEvent("%s.service() HttpSession exists: [%s]=[%s]",
|
||||
this.getClass().getName(),
|
||||
name,
|
||||
Objects.toString(value)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
else if (step instanceof Step.HttpSessionSetAttribute sessionSetAttribute)
|
||||
{
|
||||
HttpSession session = req.getSession(true);
|
||||
req.setAttribute("session[" + req.getRequestURI() + "].id", session.getId());
|
||||
Property prop = sessionSetAttribute.getProperty();
|
||||
session.setAttribute(prop.getName(), prop.getValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException("Unable to execute task " + step + " in " + this.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.ee9;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import org.eclipse.jetty.tests.ccd.common.DispatchPlan;
|
||||
|
||||
public class DumpServlet extends HttpServlet
|
||||
{
|
||||
private static final String NULL = "<null>";
|
||||
|
||||
@Override
|
||||
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException
|
||||
{
|
||||
DispatchPlan dispatchPlan = (DispatchPlan)req.getAttribute(DispatchPlan.class.getName());
|
||||
|
||||
if (dispatchPlan != null)
|
||||
{
|
||||
dispatchPlan.addEvent("%s.service() dispatcherType=%s method=%s requestUri=%s",
|
||||
this.getClass().getName(),
|
||||
req.getDispatcherType(), req.getMethod(), req.getRequestURI());
|
||||
}
|
||||
|
||||
Properties props = new Properties();
|
||||
props.setProperty("requestType", req.getClass().getName());
|
||||
props.setProperty("responseType", resp.getClass().getName());
|
||||
|
||||
props.setProperty("request.authType", Objects.toString(req.getAuthType(), NULL));
|
||||
props.setProperty("request.characterEncoding", Objects.toString(req.getCharacterEncoding(), NULL));
|
||||
props.setProperty("request.contentLength", Long.toString(req.getContentLengthLong()));
|
||||
props.setProperty("request.contentType", Objects.toString(req.getContentType(), NULL));
|
||||
props.setProperty("request.contextPath", Objects.toString(req.getContextPath(), NULL));
|
||||
props.setProperty("request.dispatcherType", Objects.toString(req.getDispatcherType(), NULL));
|
||||
props.setProperty("request.localAddr", Objects.toString(req.getLocalAddr(), NULL));
|
||||
props.setProperty("request.localName", Objects.toString(req.getLocalName(), NULL));
|
||||
props.setProperty("request.localPort", Integer.toString(req.getLocalPort()));
|
||||
props.setProperty("request.locale", Objects.toString(req.getLocale(), NULL));
|
||||
props.setProperty("request.method", Objects.toString(req.getMethod(), NULL));
|
||||
props.setProperty("request.pathInfo", Objects.toString(req.getPathInfo(), NULL));
|
||||
props.setProperty("request.pathTranslated", Objects.toString(req.getPathTranslated(), NULL));
|
||||
props.setProperty("request.protocol", Objects.toString(req.getProtocol(), NULL));
|
||||
props.setProperty("request.queryString", Objects.toString(req.getQueryString(), NULL));
|
||||
props.setProperty("request.remoteAddr", Objects.toString(req.getRemoteAddr(), NULL));
|
||||
props.setProperty("request.remoteHost", Objects.toString(req.getRemoteHost(), NULL));
|
||||
props.setProperty("request.remotePort", Integer.toString(req.getRemotePort()));
|
||||
props.setProperty("request.remoteUser", Objects.toString(req.getRemoteUser(), NULL));
|
||||
props.setProperty("request.requestedSessionId", Objects.toString(req.getRequestedSessionId(), NULL));
|
||||
props.setProperty("request.requestURI", Objects.toString(req.getRequestURI(), NULL));
|
||||
props.setProperty("request.requestURL", Objects.toString(req.getRequestURL(), NULL));
|
||||
props.setProperty("request.serverPort", Integer.toString(req.getServerPort()));
|
||||
props.setProperty("request.servletPath", Objects.toString(req.getServletPath(), NULL));
|
||||
|
||||
props.setProperty("request.session.exists", "false");
|
||||
HttpSession httpSession = req.getSession(false);
|
||||
if (httpSession != null)
|
||||
{
|
||||
props.setProperty("request.session.exists", "true");
|
||||
List<String> attrNames = Collections.list(httpSession.getAttributeNames());
|
||||
attrNames
|
||||
.forEach((name) ->
|
||||
{
|
||||
Object attrVal = httpSession.getAttribute(name);
|
||||
props.setProperty("session[" + name + "]", Objects.toString(attrVal, NULL));
|
||||
});
|
||||
}
|
||||
|
||||
addAttributes(props, "req", req::getAttributeNames, req::getAttribute);
|
||||
addAttributes(props, "context",
|
||||
() -> getServletContext().getAttributeNames(),
|
||||
(name) -> getServletContext().getAttribute(name));
|
||||
|
||||
List<String> headerNames = Collections.list(req.getHeaderNames());
|
||||
headerNames
|
||||
.forEach((name) ->
|
||||
{
|
||||
String headerVal = req.getHeader(name);
|
||||
props.setProperty("header[" + name + "]", Objects.toString(headerVal, NULL));
|
||||
});
|
||||
|
||||
if (dispatchPlan != null)
|
||||
{
|
||||
int eventCount = dispatchPlan.getEvents().size();
|
||||
props.setProperty("dispatchPlan.events.count", Integer.toString(dispatchPlan.getEvents().size()));
|
||||
for (int i = 0; i < eventCount; i++)
|
||||
{
|
||||
props.setProperty("dispatchPlan.event[" + i + "]", dispatchPlan.getEvents().get(i));
|
||||
}
|
||||
}
|
||||
|
||||
resp.setStatus(HttpServletResponse.SC_OK);
|
||||
resp.setCharacterEncoding("utf-8");
|
||||
resp.setContentType("text/x-java-properties");
|
||||
PrintWriter out = resp.getWriter();
|
||||
props.store(out, "From " + this.getClass().getName());
|
||||
}
|
||||
|
||||
private void addAttributes(Properties props,
|
||||
String prefix,
|
||||
Supplier<Enumeration<String>> getNamesSupplier,
|
||||
Function<String, Object> getAttributeFunction)
|
||||
{
|
||||
List<String> attrNames = Collections.list(getNamesSupplier.get());
|
||||
attrNames
|
||||
.forEach((name) ->
|
||||
{
|
||||
Object attrVal = getAttributeFunction.apply(name);
|
||||
props.setProperty(prefix + ".attr[" + name + "]", Objects.toString(attrVal, NULL));
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.ee9;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
import jakarta.servlet.RequestDispatcher;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
public class ForwardServlet extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
|
||||
{
|
||||
String forwardTo = req.getHeader("X-ForwardTo");
|
||||
Objects.requireNonNull(forwardTo);
|
||||
RequestDispatcher requestDispatcher = req.getRequestDispatcher(forwardTo);
|
||||
requestDispatcher.forward(req, resp);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.ccd.ee9;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* A servlet filter that will harshly change the return value of
|
||||
* {@link HttpServletRequest#getRequestURI()} to something that does
|
||||
* not satisfy the Servlet spec URI invariant {@code request URI == context path + servlet path + path info}
|
||||
*/
|
||||
public class InternalRequestURIFilter implements Filter
|
||||
{
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
|
||||
{
|
||||
HttpServletRequest httpServletRequest = (HttpServletRequest)request;
|
||||
HttpServletResponse httpServletResponse = (HttpServletResponse)response;
|
||||
InternalRequestURIWrapper requestURIWrapper = new InternalRequestURIWrapper(httpServletRequest);
|
||||
chain.doFilter(requestURIWrapper, httpServletResponse);
|
||||
}
|
||||
|
||||
private static class InternalRequestURIWrapper extends HttpServletRequestWrapper
|
||||
{
|
||||
public InternalRequestURIWrapper(HttpServletRequest request)
|
||||
{
|
||||
super(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestURI()
|
||||
{
|
||||
return "/internal/";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
|
||||
version="5.0">
|
||||
|
||||
<display-name>ccd-ee9</display-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>ccd</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.tests.ccd.ee9.CCDServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>dump</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.tests.ccd.ee9.DumpServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>ccd</servlet-name>
|
||||
<url-pattern>/redispatch/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>dump</servlet-name>
|
||||
<url-pattern>/dump/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
|
@ -0,0 +1,86 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.tests.ccd</groupId>
|
||||
<artifactId>test-cross-context-dispatch</artifactId>
|
||||
<version>12.0.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>ccd-tests</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Tests :: Cross Context Dispatch :: Tests</name>
|
||||
|
||||
<properties>
|
||||
|
||||
<!-- <junit.jupiter.execution.parallel.enabled>false</junit.jupiter.execution.parallel.enabled>-->
|
||||
<junit.jupiter.execution.parallel.config.fixed.parallelism>1</junit.jupiter.execution.parallel.config.fixed.parallelism>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-bom</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.tests.ccd</groupId>
|
||||
<artifactId>ccd-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-client</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-deploy</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.tests</groupId>
|
||||
<artifactId>jetty-testers</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<mavenRepoPath>${session.repositorySession.localRepository.basedir.absolutePath}</mavenRepoPath>
|
||||
<jettyVersion>${project.version}</jettyVersion>
|
||||
<distribution.debug.port>$(distribution.debug.port}</distribution.debug.port>
|
||||
<home.start.timeout>${home.start.timeout}</home.start.timeout>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,216 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.redispatch;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.client.ContentResponse;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.tests.testers.JettyHomeTester;
|
||||
import org.eclipse.jetty.tests.testers.Tester;
|
||||
import org.eclipse.jetty.toolchain.test.FS;
|
||||
import org.eclipse.jetty.toolchain.test.MavenPaths;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.TestInfo;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public abstract class AbstractRedispatchTest
|
||||
{
|
||||
protected static final int START_TIMEOUT = Integer.getInteger("home.start.timeout", 30);
|
||||
protected static final List<String> ENVIRONMENTS = List.of("ee8", "ee9", "ee10");
|
||||
|
||||
static String toResponseDetails(ContentResponse response)
|
||||
{
|
||||
return new ResponseDetails(response).get();
|
||||
}
|
||||
|
||||
static class InitializedJettyBase
|
||||
{
|
||||
public Path jettyBase;
|
||||
public JettyHomeTester distribution;
|
||||
public int httpPort;
|
||||
|
||||
public InitializedJettyBase(TestInfo testInfo) throws Exception
|
||||
{
|
||||
Path testsDir = MavenPaths.targetTests();
|
||||
String cleanBaseName = toCleanDirectoryName(testInfo);
|
||||
jettyBase = testsDir.resolve(cleanBaseName);
|
||||
FS.ensureEmpty(jettyBase);
|
||||
String jettyVersion = System.getProperty("jettyVersion");
|
||||
distribution = JettyHomeTester.Builder.newInstance()
|
||||
.jettyVersion(jettyVersion)
|
||||
.jettyBase(jettyBase)
|
||||
.build();
|
||||
|
||||
httpPort = Tester.freePort();
|
||||
|
||||
List<String> configList = new ArrayList<>();
|
||||
configList.add("--add-modules=http,resources");
|
||||
for (String env : ENVIRONMENTS)
|
||||
{
|
||||
configList.add("--add-modules=" + env + "-deploy," + env + "-webapp");
|
||||
}
|
||||
|
||||
try (JettyHomeTester.Run runConfig = distribution.start(configList))
|
||||
{
|
||||
assertTrue(runConfig.awaitFor(START_TIMEOUT, TimeUnit.SECONDS));
|
||||
assertEquals(0, runConfig.getExitValue());
|
||||
|
||||
Path libDir = jettyBase.resolve("lib");
|
||||
FS.ensureDirExists(libDir);
|
||||
Path etcDir = jettyBase.resolve("etc");
|
||||
FS.ensureDirExists(etcDir);
|
||||
Path modulesDir = jettyBase.resolve("modules");
|
||||
FS.ensureDirExists(modulesDir);
|
||||
Path startDir = jettyBase.resolve("start.d");
|
||||
FS.ensureDirExists(startDir);
|
||||
|
||||
// Configure the DispatchPlanHandler
|
||||
Path ccdJar = distribution.resolveArtifact("org.eclipse.jetty.tests.ccd:ccd-common:jar:" + jettyVersion);
|
||||
Files.copy(ccdJar, libDir.resolve(ccdJar.getFileName()));
|
||||
|
||||
Path installDispatchPlanXml = MavenPaths.findTestResourceFile("install-ccd-handler.xml");
|
||||
Files.copy(installDispatchPlanXml, etcDir.resolve(installDispatchPlanXml.getFileName()));
|
||||
|
||||
String module = """
|
||||
[depend]
|
||||
server
|
||||
|
||||
[lib]
|
||||
lib/jetty-util-ajax-$J.jar
|
||||
lib/ccd-common-$J.jar
|
||||
|
||||
[xml]
|
||||
etc/install-ccd-handler.xml
|
||||
|
||||
[ini]
|
||||
jetty.webapp.addProtectedClasses+=,org.eclipse.jetty.tests.ccd.common.
|
||||
jetty.webapp.addHiddenClasses+=,-org.eclipse.jetty.tests.ccd.common.
|
||||
""".replace("$J", jettyVersion);
|
||||
Files.writeString(modulesDir.resolve("ccd.mod"), module, StandardCharsets.UTF_8);
|
||||
|
||||
// -- Error Handler
|
||||
Path errorHandlerXml = MavenPaths.findTestResourceFile("error-handler.xml");
|
||||
Files.copy(errorHandlerXml, etcDir.resolve("error-handler.xml"));
|
||||
String errorHandlerIni = """
|
||||
etc/error-handler.xml
|
||||
""";
|
||||
Files.writeString(startDir.resolve("error-handler.ini"), errorHandlerIni);
|
||||
|
||||
// -- Plans Dir
|
||||
Path plansDir = MavenPaths.findTestResourceDir("plans");
|
||||
|
||||
Path ccdIni = startDir.resolve("ccd.ini");
|
||||
String ini = """
|
||||
--module=ccd
|
||||
ccd-plans-dir=$D
|
||||
""".replace("$D", plansDir.toString());
|
||||
Files.writeString(ccdIni, ini, StandardCharsets.UTF_8);
|
||||
|
||||
// -- Add the test wars
|
||||
for (String env : ENVIRONMENTS)
|
||||
{
|
||||
Path war = distribution.resolveArtifact("org.eclipse.jetty.tests.ccd:ccd-" + env + "-webapp:war:" + jettyVersion);
|
||||
distribution.installWar(war, "ccd-" + env);
|
||||
Path warProperties = jettyBase.resolve("webapps/ccd-" + env + ".properties");
|
||||
Files.writeString(warProperties, "environment: " + env, StandardCharsets.UTF_8);
|
||||
|
||||
Path webappXmlSrc = MavenPaths.findTestResourceFile("webapp-xmls/ccd-" + env + ".xml");
|
||||
Path webappXmlDest = jettyBase.resolve("webapps/ccd-" + env + ".xml");
|
||||
Files.copy(webappXmlSrc, webappXmlDest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a name that can be used as a Jetty Base home directory in a safe way.
|
||||
*
|
||||
* Note: unlike the WorkDir object, this strips out {@code [} and {@code ]} characters
|
||||
* and also makes any non-alpha-numeric character just {@code _}, which results in
|
||||
* a happy {@code ${jetty.base}} and {@code start.jar}.
|
||||
*
|
||||
* Failure to use this method can result in start.jar behaving in unintended ways
|
||||
* when it goes through the Java -> Runtime.exec -> OS behaviors.
|
||||
*
|
||||
* This change also makes the created directory named {@code target/tests/<method-name>.<display-name>}
|
||||
* live and suitable for execution via a console without accidental shell interpretation of special
|
||||
* characters in the directory name (that can result from characters like "[]" used in a directory name)
|
||||
*
|
||||
* @param testInfo the TestInfo to use to generate directory name from.
|
||||
* @return the safe to use directory name.
|
||||
*/
|
||||
public static String toCleanDirectoryName(TestInfo testInfo)
|
||||
{
|
||||
StringBuilder name = new StringBuilder();
|
||||
if (testInfo.getTestMethod().isPresent())
|
||||
{
|
||||
name.append(testInfo.getTestMethod().get().getName());
|
||||
name.append(".");
|
||||
}
|
||||
for (char c: testInfo.getDisplayName().toCharArray())
|
||||
{
|
||||
if (Character.isLetterOrDigit(c) || c == '.' || c == '-')
|
||||
name.append(c);
|
||||
else if (c != '[' && c != ']')
|
||||
name.append("_");
|
||||
}
|
||||
return name.toString();
|
||||
}
|
||||
}
|
||||
|
||||
protected HttpClient client;
|
||||
|
||||
@BeforeEach
|
||||
public void startClient() throws Exception
|
||||
{
|
||||
client = new HttpClient();
|
||||
client.start();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void stopClient()
|
||||
{
|
||||
LifeCycle.stop(client);
|
||||
}
|
||||
|
||||
public static void dumpProperties(Properties props)
|
||||
{
|
||||
props.stringPropertyNames().stream()
|
||||
.sorted()
|
||||
.forEach((name) ->
|
||||
System.out.printf(" %s=%s%n", name, props.getProperty(name)));
|
||||
}
|
||||
|
||||
public static void assertProperty(Properties props, String name, Matcher<String> valueMatcher)
|
||||
{
|
||||
assertThat("Property [" + name + "]", props.getProperty(name), valueMatcher);
|
||||
}
|
||||
|
||||
public static void assertProperty(String id, Properties props, String name, Matcher<String> valueMatcher)
|
||||
{
|
||||
assertThat("id[" + id + "] property[" + name + "]", props.getProperty(name), valueMatcher);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.redispatch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jetty.client.ContentResponse;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.tests.ccd.common.DispatchPlan;
|
||||
import org.eclipse.jetty.tests.ccd.common.HttpRequest;
|
||||
import org.eclipse.jetty.tests.ccd.common.Property;
|
||||
import org.eclipse.jetty.tests.testers.JettyHomeTester;
|
||||
import org.eclipse.jetty.toolchain.test.MavenPaths;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
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.hasItem;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class RedispatchPlansTests extends AbstractRedispatchTest
|
||||
{
|
||||
private InitializedJettyBase jettyBase;
|
||||
private JettyHomeTester.Run runStart;
|
||||
|
||||
@BeforeEach
|
||||
public void startJettyBase(TestInfo testInfo) throws Exception
|
||||
{
|
||||
jettyBase = new InitializedJettyBase(testInfo);
|
||||
|
||||
String[] argsStart = {
|
||||
"jetty.http.port=" + jettyBase.httpPort
|
||||
};
|
||||
|
||||
runStart = jettyBase.distribution.start(argsStart);
|
||||
|
||||
assertTrue(runStart.awaitConsoleLogsFor("Started oejs.Server@", START_TIMEOUT, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void stopJettyBase()
|
||||
{
|
||||
if (runStart.getProcess().isAlive())
|
||||
runStart.close();
|
||||
}
|
||||
|
||||
public static Stream<Arguments> dispatchPlans() throws IOException
|
||||
{
|
||||
List<Arguments> plans = new ArrayList<>();
|
||||
|
||||
List<String> disabledTests = new ArrayList<>();
|
||||
disabledTests.add("ee10-session-ee8-ee9-ee8.txt"); // causes an ISE
|
||||
|
||||
Path testPlansDir = MavenPaths.findTestResourceDir("plans");
|
||||
try (Stream<Path> plansStream = Files.list(testPlansDir))
|
||||
{
|
||||
List<Path> testPlans = plansStream
|
||||
.filter(Files::isRegularFile)
|
||||
.filter((file) -> file.getFileName().toString().endsWith(".txt"))
|
||||
.filter((file) -> !disabledTests.contains(file.getFileName().toString()))
|
||||
.toList();
|
||||
|
||||
for (Path plansText : testPlans)
|
||||
{
|
||||
plans.add(Arguments.of(DispatchPlan.read(plansText)));
|
||||
}
|
||||
}
|
||||
|
||||
return plans.stream();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("dispatchPlans")
|
||||
public void testRedispatch(DispatchPlan dispatchPlan) throws Exception
|
||||
{
|
||||
HttpRequest requestStep = dispatchPlan.getRequestStep();
|
||||
assertNotNull(requestStep);
|
||||
ContentResponse response = client.newRequest("localhost", jettyBase.httpPort)
|
||||
.method(requestStep.getMethod())
|
||||
.headers((headers) ->
|
||||
headers.put("X-DispatchPlan", dispatchPlan.id()))
|
||||
.path(requestStep.getRequestPath())
|
||||
.send();
|
||||
String responseDetails = toResponseDetails(response);
|
||||
assertThat(responseDetails, response.getStatus(), is(HttpStatus.OK_200));
|
||||
|
||||
Properties responseProps = new Properties();
|
||||
try (StringReader stringReader = new StringReader(response.getContentAsString()))
|
||||
{
|
||||
responseProps.load(stringReader);
|
||||
}
|
||||
|
||||
dumpProperties(responseProps);
|
||||
|
||||
int expectedEventCount = dispatchPlan.getExpectedEvents().size();
|
||||
assertThat(responseProps.getProperty("dispatchPlan.events.count"), is(Integer.toString(expectedEventCount)));
|
||||
for (int i = 0; i < expectedEventCount; i++)
|
||||
{
|
||||
assertThat("id[" + dispatchPlan.id() + "] event[" + i + "]", responseProps.getProperty("dispatchPlan.event[" + i + "]"), is(dispatchPlan.getExpectedEvents().get(i)));
|
||||
}
|
||||
|
||||
if (dispatchPlan.getExpectedContentType() != null)
|
||||
{
|
||||
assertThat("Expected ContentType", response.getHeaders().get(HttpHeader.CONTENT_TYPE), is(dispatchPlan.getExpectedContentType()));
|
||||
}
|
||||
|
||||
for (Property expectedProperty : dispatchPlan.getExpectedProperties())
|
||||
{
|
||||
assertProperty(dispatchPlan.id(), responseProps, expectedProperty.getName(), is(expectedProperty.getValue()));
|
||||
}
|
||||
|
||||
// Ensure that all seen session ids are the same.
|
||||
if (dispatchPlan.isExpectedSessionIds())
|
||||
{
|
||||
// Verify that Request Attributes for Session.id are in agreement
|
||||
List<String> attrNames = responseProps.keySet().stream()
|
||||
.map(Object::toString)
|
||||
.filter((name) -> name.startsWith("req.attr[session["))
|
||||
.toList();
|
||||
|
||||
if (attrNames.size() > 1)
|
||||
{
|
||||
String expectedId = responseProps.getProperty(attrNames.get(0));
|
||||
for (String name : attrNames)
|
||||
{
|
||||
assertEquals(expectedId, responseProps.getProperty(name));
|
||||
}
|
||||
}
|
||||
|
||||
// stop the forked running server.
|
||||
// we need to verify the session behaviors, and can only do that on a stopped server.
|
||||
runStart.close();
|
||||
|
||||
// Verify that Context Attributes for Session.id are in agreement
|
||||
// And that all ids have had their .commit() and .release() methods called.
|
||||
Path sessionLog = jettyBase.jettyBase.resolve("work/session.log");
|
||||
assertTrue(Files.isRegularFile(sessionLog), "Missing " + sessionLog);
|
||||
|
||||
List<String> logEntries = Files.readAllLines(sessionLog);
|
||||
List<String> newSessions = logEntries.stream()
|
||||
.filter(line -> line.contains("SessionCache.event.newSession()"))
|
||||
.map(line -> line.substring(line.indexOf("=") + 1))
|
||||
.toList();
|
||||
// we should have the commit() and release() for each new Session.
|
||||
for (String sessionId : newSessions)
|
||||
{
|
||||
assertThat(logEntries, hasItem("SessionCache.event.commit()=" + sessionId));
|
||||
assertThat(logEntries, hasItem("SessionCache.event.release()=" + sessionId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.redispatch;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.client.ContentResponse;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.tests.testers.JettyHomeTester;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInfo;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class RedispatchTests extends AbstractRedispatchTest
|
||||
{
|
||||
private JettyHomeTester.Run runStart;
|
||||
|
||||
@AfterEach
|
||||
public void stopRun()
|
||||
{
|
||||
runStart.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test ee8 behavior if an HttpServletRequestWrapper messes with the
|
||||
* {@code getRequestURI()} method.
|
||||
* see {@code org.eclipse.jetty.tests.ccd.ee8.InternalRequestURIFilter}
|
||||
*/
|
||||
@Test
|
||||
public void testEe8FilterWithAwkwardRequestURI(TestInfo testInfo) throws Exception
|
||||
{
|
||||
InitializedJettyBase jettyBase = new InitializedJettyBase(testInfo);
|
||||
|
||||
// Now add the filter to the webapp xml init
|
||||
String xml = """
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
|
||||
<Configure class="org.eclipse.jetty.ee8.webapp.WebAppContext">
|
||||
<Set name="contextPath">/ccd-ee8</Set>
|
||||
<Set name="war"><Property name="jetty.webapps" default="." />/ccd-ee8</Set>
|
||||
<Set name="crossContextDispatchSupported">true</Set>
|
||||
<Call name="addFilter">
|
||||
<Arg type="String">org.eclipse.jetty.tests.ccd.ee8.InternalRequestURIFilter</Arg>
|
||||
<Arg type="String">/*</Arg>
|
||||
<Arg>
|
||||
<Call class="java.util.EnumSet" name="of">
|
||||
<Arg><Get class="javax.servlet.DispatcherType" name="REQUEST"/></Arg>
|
||||
<Arg><Get class="javax.servlet.DispatcherType" name="FORWARD"/></Arg>
|
||||
<Arg><Get class="javax.servlet.DispatcherType" name="INCLUDE"/></Arg>
|
||||
</Call>
|
||||
</Arg>
|
||||
</Call>
|
||||
</Configure>
|
||||
""";
|
||||
// Note: the InternalRequestURIFilter messes with the requestURI
|
||||
Files.writeString(jettyBase.jettyBase.resolve("webapps/ccd-ee8.xml"), xml, StandardCharsets.UTF_8);
|
||||
|
||||
// Start Jetty instance
|
||||
String[] argsStart = {
|
||||
"jetty.http.port=" + jettyBase.httpPort
|
||||
};
|
||||
|
||||
runStart = jettyBase.distribution.start(argsStart);
|
||||
assertTrue(runStart.awaitConsoleLogsFor("Started oejs.Server@", START_TIMEOUT, TimeUnit.SECONDS));
|
||||
|
||||
ContentResponse response = client.newRequest("localhost", jettyBase.httpPort)
|
||||
.method(HttpMethod.GET)
|
||||
.headers((headers) ->
|
||||
headers.put("X-ForwardTo", "/dump/ee8")
|
||||
)
|
||||
.path("/ccd-ee8/forwardto/ee8")
|
||||
.send();
|
||||
|
||||
String responseDetails = toResponseDetails(response);
|
||||
assertThat(responseDetails, response.getStatus(), is(HttpStatus.OK_200));
|
||||
|
||||
Properties responseProps = new Properties();
|
||||
try (StringReader stringReader = new StringReader(response.getContentAsString()))
|
||||
{
|
||||
responseProps.load(stringReader);
|
||||
}
|
||||
|
||||
dumpProperties(responseProps);
|
||||
|
||||
assertProperty(responseProps, "request.dispatcherType", is("FORWARD"));
|
||||
assertProperty(responseProps, "request.requestURI", is("/internal/")); // the key change to look for
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.redispatch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.eclipse.jetty.client.ContentResponse;
|
||||
|
||||
class ResponseDetails implements Supplier<String>
|
||||
{
|
||||
private final ContentResponse response;
|
||||
|
||||
public ResponseDetails(ContentResponse response)
|
||||
{
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get()
|
||||
{
|
||||
try (StringWriter str = new StringWriter();
|
||||
PrintWriter out = new PrintWriter(str))
|
||||
{
|
||||
out.println(response.toString());
|
||||
out.println(response.getHeaders().toString());
|
||||
out.println(response.getContentAsString());
|
||||
out.flush();
|
||||
return str.toString();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException("Unable to produce Response details", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<Set name="errorHandler">
|
||||
<New class="org.eclipse.jetty.server.handler.ErrorHandler">
|
||||
<Set name="showStacks">true</Set>
|
||||
</New>
|
||||
</Set>
|
||||
</Configure>
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://eclipse.dev/jetty/configure_10_0.dtd">
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<Call name="insertHandler">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.tests.ccd.common.DispatchPlanHandler">
|
||||
<Set name="plansDir"><Property name="ccd-plans-dir"/></Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
</Configure>
|
|
@ -0,0 +1,12 @@
|
|||
REQUEST|GET|/ccd-ee10/redispatch/ee10
|
||||
STEP|CONTEXT_FORWARD|/ccd-ee10|/dump/ee10
|
||||
EXPECTED_EVENT|Initial plan: context-ee10-forward-dump.txt
|
||||
EXPECTED_EVENT|DispatchPlanHandler.handle() method=GET path-query=/ccd-ee10/redispatch/ee10
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee10.CCDServlet.service() dispatcherType=REQUEST method=GET requestUri=/ccd-ee10/redispatch/ee10
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee10.DumpServlet.service() dispatcherType=FORWARD method=GET requestUri=/ccd-ee10/dump/ee10
|
||||
EXPECTED_PROP|request.dispatcherType|FORWARD
|
||||
EXPECTED_PROP|request.requestURI|/ccd-ee10/dump/ee10
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.forward.context_path]|/ccd-ee10
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.forward.path_info]|/ee10
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.forward.request_uri]|/ccd-ee10/redispatch/ee10
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.forward.servlet_path]|/redispatch
|
|
@ -0,0 +1,12 @@
|
|||
REQUEST|GET|/ccd-ee8/redispatch/ee8
|
||||
STEP|CONTEXT_FORWARD|/ccd-ee8|/dump/ee8
|
||||
EXPECTED_EVENT|Initial plan: context-ee8-forward-dump.txt
|
||||
EXPECTED_EVENT|DispatchPlanHandler.handle() method=GET path-query=/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee8.CCDServlet.service() dispatcherType=REQUEST method=GET requestUri=/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee8.DumpServlet.service() dispatcherType=FORWARD method=GET requestUri=/ccd-ee8/dump/ee8
|
||||
EXPECTED_PROP|request.dispatcherType|FORWARD
|
||||
EXPECTED_PROP|request.requestURI|/ccd-ee8/dump/ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.context_path]|/ccd-ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.path_info]|/ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.request_uri]|/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.servlet_path]|/redispatch
|
|
@ -0,0 +1,14 @@
|
|||
REQUEST|GET|/ccd-ee8/redispatch/ee8
|
||||
STEP|CONTEXT_INCLUDE|/ccd-ee8|/dump/ee8
|
||||
EXPECTED_EVENT|Initial plan: context-ee8-include-dump.txt
|
||||
EXPECTED_EVENT|DispatchPlanHandler.handle() method=GET path-query=/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee8.CCDServlet.service() dispatcherType=REQUEST method=GET requestUri=/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee8.DumpServlet.service() dispatcherType=INCLUDE method=GET requestUri=/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_PROP|request.dispatcherType|INCLUDE
|
||||
EXPECTED_PROP|request.contextPath|/ccd-ee8
|
||||
EXPECTED_PROP|request.pathInfo|/ee8
|
||||
EXPECTED_PROP|request.requestURI|/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.include.context_path]|/ccd-ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.include.path_info]|/ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.include.request_uri]|/ccd-ee8/dump/ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.include.servlet_path]|/dump
|
|
@ -0,0 +1,30 @@
|
|||
REQUEST|GET|/ccd-ee10/redispatch/ee10
|
||||
STEP|SET_HTTP_SESSION_ATTRIBUTE|test-name-10|test-value-ee10
|
||||
STEP|CONTEXT_FORWARD|/ccd-ee8|/redispatch/ee8
|
||||
STEP|CONTEXT_FORWARD|/ccd-ee9|/redispatch/ee9
|
||||
STEP|REQUEST_INCLUDE|/dump/ee9
|
||||
EXPECTED_EVENT|Initial plan: ee10-forward-to-ee8-include-ee9-dump.txt
|
||||
EXPECTED_EVENT|DispatchPlanHandler.handle() method=GET path-query=/ccd-ee10/redispatch/ee10
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee10.CCDServlet.service() dispatcherType=REQUEST method=GET requestUri=/ccd-ee10/redispatch/ee10
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee8.CCDServlet.service() dispatcherType=FORWARD method=GET requestUri=/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee9.CCDServlet.service() dispatcherType=FORWARD method=GET requestUri=/ccd-ee9/redispatch/ee9
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee9.DumpServlet.service() dispatcherType=INCLUDE method=GET requestUri=/ccd-ee9/redispatch/ee9
|
||||
EXPECTED_PROP|request.dispatcherType|INCLUDE
|
||||
EXPECTED_PROP|request.requestURI|/ccd-ee9/redispatch/ee9
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.forward.context_path]|/ccd-ee8
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.forward.path_info]|/ee8
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.forward.request_uri]|/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.forward.servlet_path]|/redispatch
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.include.context_path]/ccd-ee9
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.include.path_info]|/ee9
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.include.request_uri]|/ccd-ee9/dump/ee9
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.include.servlet_path]/dump
|
||||
EXPECTED_PROP|req.attr[javax.servlet.include.context_path]|<null>
|
||||
EXPECTED_PROP|req.attr[javax.servlet.include.path_info]|<null>
|
||||
EXPECTED_PROP|req.attr[javax.servlet.include.request_uri]|<null>
|
||||
EXPECTED_PROP|req.attr[javax.servlet.include.servlet_path]|<null>
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.context_path]|/ccd-ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.path_info]|/ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.request_uri]|/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.servlet_path]|/redispatch
|
||||
EXPECTED_SESSION_IDS|true
|
|
@ -0,0 +1,12 @@
|
|||
REQUEST|GET|/ccd-ee10/redispatch/ee10
|
||||
STEP|REQUEST_FORWARD|/dump/ee10
|
||||
EXPECTED_EVENT|Initial plan: ee10-request-forward-dump.txt
|
||||
EXPECTED_EVENT|DispatchPlanHandler.handle() method=GET path-query=/ccd-ee10/redispatch/ee10
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee10.CCDServlet.service() dispatcherType=REQUEST method=GET requestUri=/ccd-ee10/redispatch/ee10
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee10.DumpServlet.service() dispatcherType=FORWARD method=GET requestUri=/ccd-ee10/dump/ee10
|
||||
EXPECTED_PROP|request.dispatcherType|FORWARD
|
||||
EXPECTED_PROP|request.requestURI|/ccd-ee10/dump/ee10
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.forward.context_path]|/ccd-ee10
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.forward.path_info]|/ee10
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.forward.request_uri]|/ccd-ee10/redispatch/ee10
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.forward.servlet_path]|/redispatch
|
|
@ -0,0 +1,12 @@
|
|||
REQUEST|GET|/ccd-ee10/redispatch/ee10
|
||||
STEP|REQUEST_INCLUDE|/dump/ee10
|
||||
EXPECTED_EVENT|Initial plan: ee10-request-include-dump.txt
|
||||
EXPECTED_EVENT|DispatchPlanHandler.handle() method=GET path-query=/ccd-ee10/redispatch/ee10
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee10.CCDServlet.service() dispatcherType=REQUEST method=GET requestUri=/ccd-ee10/redispatch/ee10
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee10.DumpServlet.service() dispatcherType=INCLUDE method=GET requestUri=/ccd-ee10/redispatch/ee10
|
||||
EXPECTED_PROP|request.dispatcherType|INCLUDE
|
||||
EXPECTED_PROP|request.requestURI|/ccd-ee10/redispatch/ee10
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.include.context_path]|/ccd-ee10
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.include.path_info]|/ee10
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.include.request_uri]|/ccd-ee10/dump/ee10
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.include.servlet_path]|/dump
|
|
@ -0,0 +1,36 @@
|
|||
REQUEST|GET|/ccd-ee10/redispatch/ee10
|
||||
# we reach ee10
|
||||
STEP|SET_HTTP_SESSION_ATTRIBUTE|test-name-10|test-value-ee10
|
||||
STEP|CONTEXT_FORWARD|/ccd-ee8|/redispatch/ee8
|
||||
# we reach ee8
|
||||
STEP|GET_HTTP_SESSION_ATTRIBUTE|test-name-10
|
||||
STEP|SET_HTTP_SESSION_ATTRIBUTE|test-name-8|test-value-ee8
|
||||
STEP|GET_HTTP_SESSION_ATTRIBUTE|test-name-10
|
||||
STEP|CONTEXT_FORWARD|/ccd-ee9|/redispatch/ee9
|
||||
# we reach ee9
|
||||
STEP|CONTEXT_FORWARD|/ccd-ee8|/redispatch/ee8
|
||||
# we reach ee8 again (does the HttpSession still exist, and has values?)
|
||||
STEP|GET_HTTP_SESSION_ATTRIBUTE|test-name-8
|
||||
STEP|REQUEST_FORWARD|/dump/ee8
|
||||
EXPECTED_EVENT|Initial plan: ee10-session-ee8-ee9-ee8.txt
|
||||
EXPECTED_EVENT|DispatchPlanHandler.handle() method=GET path-query=/ccd-ee10/redispatch/ee10
|
||||
# we reach ee10
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee10.CCDServlet.service() dispatcherType=REQUEST method=GET requestUri=/ccd-ee10/redispatch/ee10
|
||||
# we reach ee8
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee8.CCDServlet.service() dispatcherType=FORWARD method=GET requestUri=/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee8.CCDServlet.service() HttpSession is null
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee8.CCDServlet.service() HttpSession exists: [test-name-10]=[null]
|
||||
# we reach ee9
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee9.DumpServlet.service() dispatcherType=INCLUDE method=GET requestUri=/ccd-ee9/redispatch/ee9
|
||||
# we reached ee8 again
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee8.CCDServlet.service() HttpSession exists: [test-name-8]=[test-value-ee8]
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee8.DumpServlet.service() dispatcherType=FORWARD method=GET requestUri=/ccd-ee8/dump/ee8
|
||||
EXPECTED_PROP|request.dispatcherType|FORWARD
|
||||
EXPECTED_PROP|request.requestURI|/ccd-ee8/dump/ee8
|
||||
EXPECTED_PROP|request.session.exists|true
|
||||
EXPECTED_PROP|session[test-name-8]|test-value-ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.context_path]|/ccd-ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.path_info]|/ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.request_uri]|/ccd-ee8/dump/ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.servlet_path]|/dump
|
||||
EXPECTED_SESSION_IDS|true
|
|
@ -0,0 +1,50 @@
|
|||
REQUEST|GET|/ccd-ee10/redispatch/ee10
|
||||
# we reach ee10
|
||||
STEP|SET_HTTP_SESSION_ATTRIBUTE|test-name-10|test-value-ee10
|
||||
STEP|CONTEXT_FORWARD|/ccd-ee8|/redispatch/ee8
|
||||
# we reach ee8
|
||||
STEP|GET_HTTP_SESSION_ATTRIBUTE|test-name-10
|
||||
STEP|SET_HTTP_SESSION_ATTRIBUTE|test-name-8|test-value-ee8
|
||||
STEP|GET_HTTP_SESSION_ATTRIBUTE|test-name-10
|
||||
STEP|CONTEXT_FORWARD|/ccd-ee9|/redispatch/ee9
|
||||
# we reach ee9
|
||||
STEP|GET_HTTP_SESSION_ATTRIBUTE|test-name-10
|
||||
STEP|SET_HTTP_SESSION_ATTRIBUTE|test-name|test-value-ee9
|
||||
STEP|GET_HTTP_SESSION_ATTRIBUTE|test-name-10
|
||||
STEP|GET_HTTP_SESSION_ATTRIBUTE|test-name-8
|
||||
STEP|REQUEST_INCLUDE|/dump/ee9
|
||||
EXPECTED_EVENT|Initial plan: ee10-session-forward-to-ee8-session-include-ee9-dump.txt
|
||||
EXPECTED_EVENT|DispatchPlanHandler.handle() method=GET path-query=/ccd-ee10/redispatch/ee10
|
||||
# we reach ee10
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee10.CCDServlet.service() dispatcherType=REQUEST method=GET requestUri=/ccd-ee10/redispatch/ee10
|
||||
# we reach ee8
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee8.CCDServlet.service() dispatcherType=FORWARD method=GET requestUri=/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee8.CCDServlet.service() HttpSession is null
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee8.CCDServlet.service() HttpSession exists: [test-name-10]=[null]
|
||||
# we reach ee9
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee9.CCDServlet.service() dispatcherType=FORWARD method=GET requestUri=/ccd-ee9/redispatch/ee9
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee9.CCDServlet.service() HttpSession is null
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee9.CCDServlet.service() HttpSession exists: [test-name-10]=[null]
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee9.CCDServlet.service() HttpSession exists: [test-name-8]=[null]
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee9.DumpServlet.service() dispatcherType=INCLUDE method=GET requestUri=/ccd-ee9/redispatch/ee9
|
||||
EXPECTED_PROP|request.dispatcherType|INCLUDE
|
||||
EXPECTED_PROP|request.requestURI|/ccd-ee9/redispatch/ee9
|
||||
EXPECTED_PROP|request.session.exists|true
|
||||
EXPECTED_PROP|session[test-name]|test-value-ee9
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.forward.context_path]|/ccd-ee8
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.forward.path_info]|/ee8
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.forward.request_uri]|/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.forward.servlet_path]|/redispatch
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.include.context_path]/ccd-ee9
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.include.path_info]|/ee9
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.include.request_uri]|/ccd-ee9/dump/ee9
|
||||
EXPECTED_PROP|req.attr[jakarta.servlet.include.servlet_path]/dump
|
||||
EXPECTED_PROP|req.attr[javax.servlet.include.context_path]|<null>
|
||||
EXPECTED_PROP|req.attr[javax.servlet.include.path_info]|<null>
|
||||
EXPECTED_PROP|req.attr[javax.servlet.include.request_uri]|<null>
|
||||
EXPECTED_PROP|req.attr[javax.servlet.include.servlet_path]|<null>
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.context_path]|/ccd-ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.path_info]|/ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.request_uri]|/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.servlet_path]|/redispatch
|
||||
EXPECTED_SESSION_IDS|true
|
|
@ -0,0 +1,12 @@
|
|||
REQUEST|GET|/ccd-ee8/redispatch/ee8
|
||||
STEP|REQUEST_FORWARD|/dump/ee8
|
||||
EXPECTED_EVENT|Initial plan: ee8-request-forward-dump.txt
|
||||
EXPECTED_EVENT|DispatchPlanHandler.handle() method=GET path-query=/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee8.CCDServlet.service() dispatcherType=REQUEST method=GET requestUri=/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee8.DumpServlet.service() dispatcherType=FORWARD method=GET requestUri=/ccd-ee8/dump/ee8
|
||||
EXPECTED_PROP|request.dispatcherType|FORWARD
|
||||
EXPECTED_PROP|request.requestURI|/ccd-ee8/dump/ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.context_path]|/ccd-ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.path_info]|/ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.request_uri]|/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.forward.servlet_path]|/redispatch
|
|
@ -0,0 +1,12 @@
|
|||
REQUEST|GET|/ccd-ee8/redispatch/ee8
|
||||
STEP|REQUEST_INCLUDE|/dump/ee8
|
||||
EXPECTED_EVENT|Initial plan: ee8-request-include-dump.txt
|
||||
EXPECTED_EVENT|DispatchPlanHandler.handle() method=GET path-query=/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee8.CCDServlet.service() dispatcherType=REQUEST method=GET requestUri=/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_EVENT|org.eclipse.jetty.tests.ccd.ee8.DumpServlet.service() dispatcherType=INCLUDE method=GET requestUri=/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_PROP|request.dispatcherType|INCLUDE
|
||||
EXPECTED_PROP|request.requestURI|/ccd-ee8/redispatch/ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.include.context_path]|/ccd-ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.include.path_info]|/ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.include.request_uri]|/ccd-ee8/dump/ee8
|
||||
EXPECTED_PROP|req.attr[javax.servlet.include.servlet_path]|/dump
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
|
||||
|
||||
<Configure id="wac" class="org.eclipse.jetty.ee10.webapp.WebAppContext">
|
||||
<Set name="contextPath">/ccd-ee10</Set>
|
||||
<Set name="war"><Property name="jetty.webapps" default="." />/ccd-ee10</Set>
|
||||
<Set name="crossContextDispatchSupported">true</Set>
|
||||
|
||||
<Get id="sessMan" name="sessionHandler">
|
||||
<Set name="sessionCache">
|
||||
<New class="org.eclipse.jetty.tests.ccd.common.PlanSessionCache">
|
||||
<Arg>
|
||||
<Ref refid="sessMan"/>
|
||||
</Arg>
|
||||
</New>
|
||||
</Set>
|
||||
</Get>
|
||||
</Configure>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
|
||||
|
||||
<Configure id="wac" class="org.eclipse.jetty.ee8.webapp.WebAppContext">
|
||||
<Set name="contextPath">/ccd-ee8</Set>
|
||||
<Set name="war"><Property name="jetty.webapps" default="." />/ccd-ee8</Set>
|
||||
<Set name="crossContextDispatchSupported">true</Set>
|
||||
|
||||
<Get name="sessionHandler">
|
||||
<Get id="sessMan" name="sessionManager">
|
||||
<Set name="sessionCache">
|
||||
<New class="org.eclipse.jetty.tests.ccd.common.PlanSessionCache">
|
||||
<Arg>
|
||||
<Ref refid="sessMan"/>
|
||||
</Arg>
|
||||
</New>
|
||||
</Set>
|
||||
</Get>
|
||||
</Get>
|
||||
</Configure>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
|
||||
|
||||
<Configure id="wac" class="org.eclipse.jetty.ee9.webapp.WebAppContext">
|
||||
<Set name="contextPath">/ccd-ee9</Set>
|
||||
<Set name="war"><Property name="jetty.webapps" default="." />/ccd-ee9</Set>
|
||||
<Set name="crossContextDispatchSupported">true</Set>
|
||||
|
||||
<Get name="sessionHandler">
|
||||
<Get id="sessMan" name="sessionManager">
|
||||
<Set name="sessionCache">
|
||||
<New class="org.eclipse.jetty.tests.ccd.common.PlanSessionCache">
|
||||
<Arg>
|
||||
<Ref refid="sessMan"/>
|
||||
</Arg>
|
||||
</New>
|
||||
</Set>
|
||||
</Get>
|
||||
</Get>
|
||||
</Configure>
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.tests</groupId>
|
||||
<artifactId>tests</artifactId>
|
||||
<version>12.0.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>org.eclipse.jetty.tests.ccd</groupId>
|
||||
<artifactId>test-cross-context-dispatch</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<name>Tests :: Cross Context Dispatch :: Parent</name>
|
||||
|
||||
<modules>
|
||||
<module>ccd-common</module>
|
||||
<module>ccd-ee10-webapp</module>
|
||||
<module>ccd-ee9-webapp</module>
|
||||
<module>ccd-ee8-webapp</module>
|
||||
<module>ccd-tests</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<distribution.debug.port>-1</distribution.debug.port>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<mavenRepoPath>${session.repositoryCrossContext.localRepository.basedir.absolutePath}</mavenRepoPath>
|
||||
<jettyVersion>${project.version}</jettyVersion>
|
||||
<distribution.debug.port>$(distribution.debug.port}</distribution.debug.port>
|
||||
<home.start.timeout>${home.start.timeout}</home.start.timeout>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
Loading…
Reference in New Issue