Merge pull request #8341 from eclipse/jetty-12.0.x-dispatcher-fixes
fix some tests for Jetty 12 ee10 servlets
This commit is contained in:
commit
0f35590ab4
|
@ -195,6 +195,7 @@ public class ServletPathSpec extends AbstractPathSpec
|
|||
servletPathSpec = "";
|
||||
if (servletPathSpec.startsWith("servlet|"))
|
||||
servletPathSpec = servletPathSpec.substring("servlet|".length());
|
||||
servletPathSpec = URIUtil.canonicalPath(servletPathSpec);
|
||||
assertValidServletPathSpec(servletPathSpec);
|
||||
|
||||
// The Root Path Spec
|
||||
|
|
|
@ -44,6 +44,7 @@ import org.eclipse.jetty.util.Callback;
|
|||
import org.eclipse.jetty.util.DecoratedObjectFactory;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.component.ClassLoaderDump;
|
||||
import org.eclipse.jetty.util.component.Dumpable;
|
||||
|
@ -669,7 +670,7 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace
|
|||
{
|
||||
if (isStarted())
|
||||
throw new IllegalStateException(getState());
|
||||
_contextPath = contextPath;
|
||||
_contextPath = URIUtil.canonicalPath(contextPath);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,13 +15,11 @@ package org.eclipse.jetty.ee10.servlet;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.servlet.DispatcherType;
|
||||
import jakarta.servlet.RequestDispatcher;
|
||||
|
@ -36,6 +34,7 @@ import jakarta.servlet.http.HttpServletResponse;
|
|||
import jakarta.servlet.http.HttpServletResponseWrapper;
|
||||
import org.eclipse.jetty.ee10.servlet.util.ServletOutputStreamWrapper;
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.util.Fields;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.UrlEncoded;
|
||||
|
@ -125,8 +124,16 @@ public class Dispatcher implements RequestDispatcher
|
|||
{
|
||||
HttpServletRequest httpRequest = (request instanceof HttpServletRequest) ? (HttpServletRequest)request : new ServletRequestHttpWrapper(request);
|
||||
HttpServletResponse httpResponse = (response instanceof HttpServletResponse) ? (HttpServletResponse)response : new ServletResponseHttpWrapper(response);
|
||||
ServletContextResponse baseResponse = ServletContextResponse.getBaseResponse(response);
|
||||
|
||||
_mappedServlet.handle(_servletHandler, _pathInContext, new IncludeRequest(httpRequest), new IncludeResponse(httpResponse));
|
||||
try
|
||||
{
|
||||
_mappedServlet.handle(_servletHandler, _pathInContext, new IncludeRequest(httpRequest), new IncludeResponse(httpResponse));
|
||||
}
|
||||
finally
|
||||
{
|
||||
baseResponse.included();
|
||||
}
|
||||
}
|
||||
|
||||
public void async(ServletRequest request, ServletResponse response) throws ServletException, IOException
|
||||
|
@ -139,85 +146,81 @@ public class Dispatcher implements RequestDispatcher
|
|||
|
||||
public class ParameterRequestWrapper extends HttpServletRequestWrapper
|
||||
{
|
||||
private Map<String, String[]> params;
|
||||
private final MultiMap<String> _params = new MultiMap<>();
|
||||
private boolean decodedParams = false;
|
||||
private final HttpServletRequest _httpServletRequest;
|
||||
private final ServletContextRequest _baseRequest;
|
||||
|
||||
public ParameterRequestWrapper(HttpServletRequest request)
|
||||
{
|
||||
super(request);
|
||||
_httpServletRequest = request;
|
||||
|
||||
// Have to assume ENCODING because we can't know otherwise.
|
||||
String targetQuery = (_uri == null) ? null : _uri.getQuery();
|
||||
if (targetQuery != null)
|
||||
UrlEncoded.decodeTo(targetQuery, _params, UrlEncoded.ENCODING);
|
||||
|
||||
_baseRequest = ServletContextRequest.getBaseRequest(_httpServletRequest);
|
||||
if (_baseRequest == null)
|
||||
throw new IllegalStateException();
|
||||
|
||||
Fields queryParams = _baseRequest.getServletApiRequest().getQueryParams();
|
||||
for (Fields.Field field : queryParams)
|
||||
{
|
||||
_params.addValues(field.getName(), field.getValues());
|
||||
}
|
||||
}
|
||||
|
||||
private MultiMap<String> getParams()
|
||||
{
|
||||
if (decodedParams)
|
||||
return _params;
|
||||
decodedParams = true;
|
||||
|
||||
Fields contentParams = _baseRequest.getServletApiRequest().getContentParams();
|
||||
for (Fields.Field field : contentParams)
|
||||
{
|
||||
_params.addValues(field.getName(), field.getValues());
|
||||
}
|
||||
return _params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameter(String name)
|
||||
{
|
||||
String[] strings = getParameterMap().get(name);
|
||||
if (strings == null || strings.length == 0)
|
||||
return null;
|
||||
return strings[0];
|
||||
return getParams().getValue(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String[]> getParameterMap()
|
||||
{
|
||||
if (params != null)
|
||||
return params;
|
||||
|
||||
Map<String, String[]> oldParams = super.getParameterMap();
|
||||
if (_uri == null || _uri.getQuery() == null)
|
||||
{
|
||||
params = oldParams;
|
||||
return oldParams;
|
||||
}
|
||||
|
||||
MultiMap<String> newParams = new MultiMap<>();
|
||||
UrlEncoded.decodeTo(_uri.getQuery(), newParams, UrlEncoded.ENCODING);
|
||||
for (Map.Entry<String, String[]> entry : oldParams.entrySet())
|
||||
{
|
||||
newParams.addValues(entry.getKey(), entry.getValue());
|
||||
}
|
||||
params = newParams.toStringArrayMap();
|
||||
return params;
|
||||
return Collections.unmodifiableMap(getParams().toStringArrayMap());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getParameterNames()
|
||||
{
|
||||
return Collections.enumeration(getParameterMap().entrySet().stream()
|
||||
.flatMap(o -> Arrays.stream(o.getValue()))
|
||||
.collect(Collectors.toList()));
|
||||
return Collections.enumeration(getParams().keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParameterValues(String name)
|
||||
{
|
||||
return getParameterMap().get(name);
|
||||
List<String> vals = getParams().getValues(name);
|
||||
if (vals == null)
|
||||
return null;
|
||||
return vals.toArray(new String[0]);
|
||||
}
|
||||
}
|
||||
|
||||
private class ForwardRequest extends ParameterRequestWrapper
|
||||
{
|
||||
private final HttpServletRequest _httpServletRequest;
|
||||
private final MultiMap<String> _params = new MultiMap<>();
|
||||
|
||||
public ForwardRequest(HttpServletRequest httpRequest)
|
||||
{
|
||||
super(httpRequest);
|
||||
|
||||
String targetQuery = (_uri == null) ? null : _uri.getQuery();
|
||||
if (targetQuery != null)
|
||||
{
|
||||
// Have to assume ENCODING because we can't know otherwise.
|
||||
UrlEncoded.decodeTo(targetQuery, _params, UrlEncoded.ENCODING);
|
||||
}
|
||||
|
||||
Enumeration<String> parameterNames = httpRequest.getParameterNames();
|
||||
while (parameterNames.hasMoreElements())
|
||||
{
|
||||
String name = parameterNames.nextElement();
|
||||
String[] parameterValues = httpRequest.getParameterValues(name);
|
||||
if (parameterValues != null)
|
||||
_params.addValues(name, parameterValues);
|
||||
}
|
||||
|
||||
_httpServletRequest = httpRequest;
|
||||
}
|
||||
|
||||
|
@ -261,33 +264,6 @@ public class Dispatcher implements RequestDispatcher
|
|||
return _httpServletRequest.getQueryString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameter(String name)
|
||||
{
|
||||
return _params.getValue(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String[]> getParameterMap()
|
||||
{
|
||||
return Collections.unmodifiableMap(_params.toStringArrayMap());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getParameterNames()
|
||||
{
|
||||
return Collections.enumeration(_params.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParameterValues(String name)
|
||||
{
|
||||
List<String> vals = _params.getValues(name);
|
||||
if (vals == null)
|
||||
return null;
|
||||
return vals.toArray(new String[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestURI()
|
||||
{
|
||||
|
@ -501,6 +477,7 @@ public class Dispatcher implements RequestDispatcher
|
|||
{
|
||||
super(httpRequest);
|
||||
_httpServletRequest = httpRequest;
|
||||
Objects.requireNonNull(_servletPathMapping);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -512,13 +489,22 @@ public class Dispatcher implements RequestDispatcher
|
|||
@Override
|
||||
public String getPathInfo()
|
||||
{
|
||||
return _mappedServlet.getServletPathMapping(_pathInContext).getPathInfo();
|
||||
// TODO what about a 404 dispatch?
|
||||
return Objects.requireNonNull(_servletPathMapping).getPathInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServletPath()
|
||||
{
|
||||
return _mappedServlet.getServletPathMapping(_pathInContext).getServletPath();
|
||||
// TODO what about a 404 dispatch?
|
||||
return Objects.requireNonNull(_servletPathMapping).getServletPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpServletMapping getHttpServletMapping()
|
||||
{
|
||||
// TODO what about a 404 dispatch?
|
||||
return Objects.requireNonNull(_servletPathMapping);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -419,7 +419,7 @@ public class ServletChannel implements Runnable
|
|||
}
|
||||
|
||||
Dispatcher dispatcher = new Dispatcher(getContextHandler(), uri, pathInContext);
|
||||
dispatcher.async(_request.getHttpServletRequest(), getResponse().getHttpServletResponse());
|
||||
dispatcher.async(asyncContextEvent.getSuppliedRequest(), asyncContextEvent.getSuppliedResponse());
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
@ -607,6 +607,7 @@ public class ServletChannel implements Runnable
|
|||
{
|
||||
try
|
||||
{
|
||||
_request.getResponse().getHttpOutput().reopen();
|
||||
_servletContextApi.getContext().getServletContextHandler().requestInitialized(_request, _request.getHttpServletRequest());
|
||||
getHttpOutput().reopen();
|
||||
_combinedListener.onBeforeDispatch(_request);
|
||||
|
|
|
@ -702,7 +702,7 @@ public class ServletContextHandler extends ContextHandler implements Graceful
|
|||
}
|
||||
|
||||
super.setContextPath(contextPath);
|
||||
_contextPathEncoded = URIUtil.encodePath(contextPath);
|
||||
_contextPathEncoded = URIUtil.canonicalPath(contextPath);
|
||||
|
||||
if (getServer() != null && (getServer().isStarting() || getServer().isStarted()))
|
||||
{
|
||||
|
|
|
@ -183,8 +183,7 @@ public class ServletContextRequest extends ContextRequest implements Runnable
|
|||
public void errorClose()
|
||||
{
|
||||
// TODO Actually make the response status and headers immutable temporarily
|
||||
// TODO: This soft close breaks ErrorPageTest, AsyncContextTest
|
||||
// _response.getHttpOutput().softClose();
|
||||
_response.getHttpOutput().softClose();
|
||||
}
|
||||
|
||||
public boolean isHead()
|
||||
|
@ -205,6 +204,11 @@ public class ServletContextRequest extends ContextRequest implements Runnable
|
|||
_queryEncoding = Charset.forName(queryEncoding);
|
||||
}
|
||||
|
||||
public Charset getQueryEncoding()
|
||||
{
|
||||
return _queryEncoding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String name)
|
||||
{
|
||||
|
@ -335,6 +339,18 @@ public class ServletContextRequest extends ContextRequest implements Runnable
|
|||
return apiSession.getCoreSession();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Fields getQueryParams()
|
||||
{
|
||||
extractQueryParameters();
|
||||
return _queryParameters;
|
||||
}
|
||||
|
||||
public Fields getContentParams()
|
||||
{
|
||||
extractContentParameters();
|
||||
return _contentParameters;
|
||||
}
|
||||
|
||||
public void setAuthentication(Authentication authentication)
|
||||
{
|
||||
|
@ -949,33 +965,8 @@ public class ServletContextRequest extends ContextRequest implements Runnable
|
|||
|
||||
private Fields getParameters()
|
||||
{
|
||||
if (!_contentParamsExtracted)
|
||||
{
|
||||
// content parameters need boolean protection as they can only be read
|
||||
// once, but may be reset to null by a reset
|
||||
_contentParamsExtracted = true;
|
||||
|
||||
// Extract content parameters; these cannot be replaced by a forward()
|
||||
// once extracted and may have already been extracted by getParts() or
|
||||
// by a processing happening after a form-based authentication.
|
||||
if (_contentParameters == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
extractContentParameters();
|
||||
}
|
||||
catch (IllegalStateException | IllegalArgumentException | ExecutionException | InterruptedException e)
|
||||
{
|
||||
LOG.warn(e.toString());
|
||||
throw new BadMessageException("Unable to parse form content", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract query string parameters; these may be replaced by a forward()
|
||||
// and may have already been extracted by mergeQueryParameters().
|
||||
if (_queryParameters == null)
|
||||
extractQueryParameters();
|
||||
extractContentParameters();
|
||||
extractQueryParameters();
|
||||
|
||||
// Do parameters need to be combined?
|
||||
if (isNoParams(_queryParameters) || _queryParameters.getSize() == 0)
|
||||
|
@ -994,28 +985,54 @@ public class ServletContextRequest extends ContextRequest implements Runnable
|
|||
return parameters == null ? NO_PARAMS : parameters;
|
||||
}
|
||||
|
||||
private void extractContentParameters() throws ExecutionException, InterruptedException
|
||||
private void extractContentParameters() throws BadMessageException
|
||||
{
|
||||
_contentParameters = FutureFormFields.forRequest(getRequest()).get();
|
||||
if (_contentParameters == null || _contentParameters.isEmpty())
|
||||
_contentParameters = NO_PARAMS;
|
||||
if (!_contentParamsExtracted)
|
||||
{
|
||||
// content parameters need boolean protection as they can only be read
|
||||
// once, but may be reset to null by a reset
|
||||
_contentParamsExtracted = true;
|
||||
|
||||
// Extract content parameters; these cannot be replaced by a forward()
|
||||
// once extracted and may have already been extracted by getParts() or
|
||||
// by a processing happening after a form-based authentication.
|
||||
if (_contentParameters == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_contentParameters = FutureFormFields.forRequest(getRequest()).get();
|
||||
if (_contentParameters == null || _contentParameters.isEmpty())
|
||||
_contentParameters = NO_PARAMS;
|
||||
}
|
||||
catch (IllegalStateException | IllegalArgumentException | ExecutionException | InterruptedException e)
|
||||
{
|
||||
LOG.warn(e.toString());
|
||||
throw new BadMessageException("Unable to parse form content", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void extractQueryParameters()
|
||||
private void extractQueryParameters() throws BadMessageException
|
||||
{
|
||||
HttpURI httpURI = ServletContextRequest.this.getHttpURI();
|
||||
if (httpURI == null || StringUtil.isEmpty(httpURI.getQuery()))
|
||||
_queryParameters = NO_PARAMS;
|
||||
else
|
||||
// Extract query string parameters; these may be replaced by a forward()
|
||||
// and may have already been extracted by mergeQueryParameters().
|
||||
if (_queryParameters == null)
|
||||
{
|
||||
try
|
||||
HttpURI httpURI = ServletContextRequest.this.getHttpURI();
|
||||
if (httpURI == null || StringUtil.isEmpty(httpURI.getQuery()))
|
||||
_queryParameters = NO_PARAMS;
|
||||
else
|
||||
{
|
||||
_queryParameters = Request.extractQueryParameters(ServletContextRequest.this, _queryEncoding);
|
||||
}
|
||||
catch (IllegalStateException | IllegalArgumentException e)
|
||||
{
|
||||
_queryParameters = BAD_PARAMS;
|
||||
throw new BadMessageException("Unable to parse URI query", e);
|
||||
try
|
||||
{
|
||||
_queryParameters = Request.extractQueryParameters(ServletContextRequest.this, _queryEncoding);
|
||||
}
|
||||
catch (IllegalStateException | IllegalArgumentException e)
|
||||
{
|
||||
_queryParameters = BAD_PARAMS;
|
||||
throw new BadMessageException("Unable to parse URI query", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,11 +134,17 @@ public class ServletContextResponse extends ContextResponse
|
|||
|
||||
public void resetForForward()
|
||||
{
|
||||
_httpOutput.resetBuffer();
|
||||
_httpOutput.reopen();
|
||||
_httpServletResponse.resetBuffer();
|
||||
_outputType = OutputType.NONE;
|
||||
}
|
||||
|
||||
public void included()
|
||||
{
|
||||
if (_outputType == OutputType.WRITER)
|
||||
_writer.reopen();
|
||||
_httpOutput.reopen();
|
||||
}
|
||||
|
||||
public void completeOutput(Callback callback)
|
||||
{
|
||||
if (_outputType == OutputType.WRITER)
|
||||
|
@ -218,7 +224,7 @@ public class ServletContextResponse extends ContextResponse
|
|||
{
|
||||
super.reset();
|
||||
|
||||
_httpOutput.resetBuffer();
|
||||
_httpServletResponse.resetBuffer();
|
||||
_outputType = OutputType.NONE;
|
||||
_contentLength = -1;
|
||||
_contentType = null;
|
||||
|
@ -695,6 +701,7 @@ public class ServletContextResponse extends ContextResponse
|
|||
*/
|
||||
public void sendRedirect(int code, String location) throws IOException
|
||||
{
|
||||
resetBuffer();
|
||||
FutureCallback callback = new FutureCallback();
|
||||
Response.sendRedirect(_request, ServletContextResponse.this, callback, code, location, false);
|
||||
callback.block();
|
||||
|
|
|
@ -38,7 +38,6 @@ import org.eclipse.jetty.server.handler.DefaultHandler;
|
|||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
@ -274,7 +273,6 @@ public class AsyncContextTest
|
|||
assertThat("servlet request uri async", responseBody, containsString("doGet.ASYNC.requestURI:/ctx/self/hello%20there"));
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
public void testDispatchAsyncContextEncodedPathAndQueryString() throws Exception
|
||||
{
|
||||
|
@ -290,13 +288,13 @@ public class AsyncContextTest
|
|||
|
||||
assertThat("servlet gets right path", responseBody, containsString("doGet:getServletPath:/servletPath2"));
|
||||
assertThat("async context gets right path in get", responseBody, containsString("doGet:async:getServletPath:/servletPath2"));
|
||||
assertThat("servlet path attr is original", responseBody, containsString("async:run:attr:servletPath:/path with spaces/servletPath"));
|
||||
assertThat("servlet path attr is original", responseBody, containsString("async:run:attr:servletPath:/path%20with%20spaces/servletPath"));
|
||||
assertThat("path info attr is correct", responseBody, containsString("async:run:attr:pathInfo:null"));
|
||||
assertThat("query string attr is correct", responseBody, containsString("async:run:attr:queryString:dispatch=true&queryStringWithEncoding=space%20space"));
|
||||
assertThat("context path attr is correct", responseBody, containsString("async:run:attr:contextPath:/ctx"));
|
||||
assertThat("request uri attr is correct", responseBody, containsString("async:run:attr:requestURI:/ctx/path%20with%20spaces/servletPath"));
|
||||
assertThat("http servlet mapping matchValue is correct", responseBody, containsString("async:run:attr:mapping:matchValue:path with spaces/servletPath"));
|
||||
assertThat("http servlet mapping pattern is correct", responseBody, containsString("async:run:attr:mapping:pattern:/path with spaces/servletPath"));
|
||||
assertThat("http servlet mapping matchValue is correct", responseBody, containsString("async:run:attr:mapping:matchValue:path%20with%20spaces/servletPath"));
|
||||
assertThat("http servlet mapping pattern is correct", responseBody, containsString("async:run:attr:mapping:pattern:/path%20with%20spaces/servletPath"));
|
||||
assertThat("http servlet mapping servletName is correct", responseBody, containsString("async:run:attr:mapping:servletName:"));
|
||||
assertThat("http servlet mapping mappingMatch is correct", responseBody, containsString("async:run:attr:mapping:mappingMatch:EXACT"));
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@ import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
|||
import org.hamcrest.Matchers;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
@ -60,7 +59,6 @@ import static org.hamcrest.Matchers.startsWith;
|
|||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
@Disabled("A lot of the test expectations are now broken because of the request wrapping done by Jetty 12 implementation.")
|
||||
public class AsyncServletTest
|
||||
{
|
||||
protected AsyncServlet _servlet = new AsyncServlet();
|
||||
|
@ -244,6 +242,7 @@ public class AsyncServletTest
|
|||
"onTimeout",
|
||||
"dispatch",
|
||||
"ASYNC /ctx/path/info?start=200&timeout=dispatch",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onComplete"));
|
||||
|
||||
|
@ -263,6 +262,7 @@ public class AsyncServletTest
|
|||
"onTimeout",
|
||||
"error",
|
||||
"ERROR /ctx/error/custom?start=200&timeout=error",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onComplete"));
|
||||
|
||||
|
@ -296,6 +296,7 @@ public class AsyncServletTest
|
|||
"start",
|
||||
"dispatch",
|
||||
"ASYNC /ctx/path/info?start=200&dispatch=10",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onComplete"));
|
||||
assertFalse(__history.contains("onTimeout"));
|
||||
|
@ -312,6 +313,7 @@ public class AsyncServletTest
|
|||
"start",
|
||||
"dispatch",
|
||||
"ASYNC /ctx/path/info?start=200&dispatch=0",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onComplete"));
|
||||
}
|
||||
|
@ -328,6 +330,7 @@ public class AsyncServletTest
|
|||
"start",
|
||||
"onError",
|
||||
"ERROR /ctx/error/custom?start=200&throw=1",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onComplete"));
|
||||
assertContains("ERROR DISPATCH: /ctx/error/custom", response);
|
||||
|
@ -376,11 +379,13 @@ public class AsyncServletTest
|
|||
"start",
|
||||
"dispatch",
|
||||
"ASYNC /ctx/path/info?start=1000&dispatch=10&start2=1000&dispatch2=10",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onStartAsync",
|
||||
"start",
|
||||
"dispatch",
|
||||
"ASYNC /ctx/path/info?start=1000&dispatch=10&start2=1000&dispatch2=10",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onComplete"));
|
||||
assertContains("DISPATCHED", response);
|
||||
|
@ -397,6 +402,7 @@ public class AsyncServletTest
|
|||
"start",
|
||||
"dispatch",
|
||||
"ASYNC /ctx/path/info?start=1000&dispatch=10&start2=1000&complete2=10",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onStartAsync",
|
||||
"start",
|
||||
|
@ -417,11 +423,13 @@ public class AsyncServletTest
|
|||
"start",
|
||||
"dispatch",
|
||||
"ASYNC /ctx/path/info?start=1000&dispatch=10&start2=10",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onStartAsync",
|
||||
"start",
|
||||
"onTimeout",
|
||||
"ERROR /ctx/error/custom?start=1000&dispatch=10&start2=10",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onComplete"));
|
||||
assertContains("ERROR DISPATCH: /ctx/error/custom", response);
|
||||
|
@ -438,11 +446,13 @@ public class AsyncServletTest
|
|||
"start",
|
||||
"onTimeout",
|
||||
"ERROR /ctx/error/custom?start=10&start2=1000&dispatch2=10",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onStartAsync",
|
||||
"start",
|
||||
"dispatch",
|
||||
"ASYNC /ctx/path/info?start=10&start2=1000&dispatch2=10",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onComplete"));
|
||||
assertContains("DISPATCHED", response);
|
||||
|
@ -459,6 +469,7 @@ public class AsyncServletTest
|
|||
"start",
|
||||
"onTimeout",
|
||||
"ERROR /ctx/error/custom?start=10&start2=1000&complete2=10",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onStartAsync",
|
||||
"start",
|
||||
|
@ -480,11 +491,13 @@ public class AsyncServletTest
|
|||
"start",
|
||||
"onTimeout",
|
||||
"ERROR /ctx/path/error?start=10&start2=10",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onStartAsync",
|
||||
"start",
|
||||
"onTimeout",
|
||||
"ERROR /ctx/path/error?start=10&start2=10",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onComplete")); // Error Page Loop!
|
||||
assertContains("AsyncContext timeout", response);
|
||||
|
@ -518,6 +531,7 @@ public class AsyncServletTest
|
|||
"start",
|
||||
"dispatch",
|
||||
"ASYNC /ctx/p%20th3?start=200&dispatch=20&path=/p%20th3",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onComplete"));
|
||||
assertContains("DISPATCHED", response);
|
||||
|
@ -531,11 +545,14 @@ public class AsyncServletTest
|
|||
assertThat(__history, contains(
|
||||
"FWD REQUEST /ctx/fwd/info?start=200&dispatch=20",
|
||||
"FORWARD /ctx/path1?forward=true",
|
||||
"wrapped REQ",
|
||||
"initial",
|
||||
"start",
|
||||
"dispatch",
|
||||
"FWD ASYNC /ctx/fwd/info?start=200&dispatch=20",
|
||||
"wrapped REQ",
|
||||
"FORWARD /ctx/path1?forward=true",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onComplete"));
|
||||
assertContains("DISPATCHED", response);
|
||||
|
@ -549,10 +566,12 @@ public class AsyncServletTest
|
|||
assertThat(__history, contains(
|
||||
"FWD REQUEST /ctx/fwd/info?start=200&dispatch=20&path=/path2",
|
||||
"FORWARD /ctx/path1?forward=true",
|
||||
"wrapped REQ",
|
||||
"initial",
|
||||
"start",
|
||||
"dispatch",
|
||||
"ASYNC /ctx/path2?start=200&dispatch=20&path=/path2",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onComplete"));
|
||||
assertContains("DISPATCHED", response);
|
||||
|
@ -566,6 +585,7 @@ public class AsyncServletTest
|
|||
assertThat(__history, contains(
|
||||
"FWD REQUEST /ctx/fwd/info?wrap=true&start=200&dispatch=20",
|
||||
"FORWARD /ctx/path1?forward=true",
|
||||
"wrapped REQ",
|
||||
"initial",
|
||||
"start",
|
||||
"dispatch",
|
||||
|
@ -584,6 +604,7 @@ public class AsyncServletTest
|
|||
assertThat(__history, contains(
|
||||
"FWD REQUEST /ctx/fwd/info?wrap=true&start=200&dispatch=20&path=/path2",
|
||||
"FORWARD /ctx/path1?forward=true",
|
||||
"wrapped REQ",
|
||||
"initial",
|
||||
"start",
|
||||
"dispatch",
|
||||
|
@ -622,6 +643,7 @@ public class AsyncServletTest
|
|||
"async-read=10",
|
||||
"dispatch",
|
||||
"ASYNC /ctx/path/info?start=2000&dispatch=1500",
|
||||
"wrapped REQ",
|
||||
"!initial",
|
||||
"onComplete"));
|
||||
}
|
||||
|
|
|
@ -1327,7 +1327,6 @@ public class DefaultServletTest
|
|||
}
|
||||
|
||||
@Test
|
||||
@Disabled("TODO: sendError not working (yet)")
|
||||
public void testWelcomeServlet() throws Exception
|
||||
{
|
||||
Path inde = docRoot.resolve("index.htm");
|
||||
|
@ -1353,7 +1352,7 @@ public class DefaultServletTest
|
|||
""");
|
||||
response = HttpTester.parseResponse(rawResponse);
|
||||
assertThat(response.toString(), response.getStatus(), is(HttpStatus.INTERNAL_SERVER_ERROR_500));
|
||||
// TODO: sendError not working (yet) assertThat(response.getContent(), containsString("JSP support not configured"));
|
||||
assertThat(response.getContent(), containsString("JSP support not configured"));
|
||||
|
||||
Files.writeString(index, "<h1>Hello Index</h1>", UTF_8);
|
||||
rawResponse = connector.getResponse("""
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.eclipse.jetty.server.Server;
|
|||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
@ -451,7 +450,6 @@ public class DispatcherForwardTest
|
|||
}
|
||||
|
||||
@Test
|
||||
@Disabled // TODO
|
||||
public void testContentCanBeReadViaInputStreamAfterForwardWithoutQuery() throws Exception
|
||||
{
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
|
@ -501,7 +499,6 @@ public class DispatcherForwardTest
|
|||
}
|
||||
|
||||
@Test
|
||||
@Disabled // TODO
|
||||
public void testContentCanBeReadViaInputStreamAfterForwardWithQuery() throws Exception
|
||||
{
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
|
|
|
@ -330,7 +330,6 @@ public class DispatcherTest
|
|||
}
|
||||
|
||||
@Test
|
||||
@Disabled("See ServletContextRequest.errorClose and softClose hack")
|
||||
public void testForwardSendError() throws Exception
|
||||
{
|
||||
_contextHandler.addServlet(ForwardServlet.class, "/forward/*");
|
||||
|
@ -549,7 +548,7 @@ public class DispatcherTest
|
|||
}
|
||||
|
||||
@Test
|
||||
@Disabled("References to ResourceHandler, a jetty-core ContextHandler cannot be referenced for a ServletContext")
|
||||
@Disabled("Cross context dispatch not yet supported in jetty-12")
|
||||
public void testIncludeToResourceHandler() throws Exception
|
||||
{
|
||||
_contextHandler.addServlet(DispatchToResourceServlet.class, "/resourceServlet/*");
|
||||
|
@ -568,7 +567,7 @@ public class DispatcherTest
|
|||
}
|
||||
|
||||
@Test
|
||||
@Disabled("References to ResourceHandler, a jetty-core ContextHandler cannot be referenced for a ServletContext")
|
||||
@Disabled("Cross context dispatch not yet supported in jetty-12")
|
||||
public void testForwardToResourceHandler() throws Exception
|
||||
{
|
||||
_contextHandler.addServlet(DispatchToResourceServlet.class, "/resourceServlet/*");
|
||||
|
@ -587,7 +586,7 @@ public class DispatcherTest
|
|||
}
|
||||
|
||||
@Test
|
||||
@Disabled("References to ResourceHandler, a jetty-core ContextHandler cannot be referenced for a ServletContext")
|
||||
@Disabled("Cross context dispatch not yet supported in jetty-12")
|
||||
public void testWrappedIncludeToResourceHandler() throws Exception
|
||||
{
|
||||
_contextHandler.addServlet(DispatchToResourceServlet.class, "/resourceServlet/*");
|
||||
|
@ -606,7 +605,7 @@ public class DispatcherTest
|
|||
}
|
||||
|
||||
@Test
|
||||
@Disabled("References to ResourceHandler, a jetty-core ContextHandler cannot be referenced for a ServletContext")
|
||||
@Disabled("Cross context dispatch not yet supported in jetty-12")
|
||||
public void testWrappedForwardToResourceHandler() throws Exception
|
||||
{
|
||||
_contextHandler.addServlet(DispatchToResourceServlet.class, "/resourceServlet/*");
|
||||
|
@ -675,17 +674,14 @@ public class DispatcherTest
|
|||
}
|
||||
|
||||
@Test
|
||||
@Disabled // TODO
|
||||
public void testDispatchMapping() throws Exception
|
||||
{
|
||||
_contextHandler.addServlet(new ServletHolder("TestServlet", MappingServlet.class), "/TestServlet");
|
||||
_contextHandler.addServlet(new ServletHolder("DispatchServlet", AsyncDispatch2TestServlet.class), "/DispatchServlet");
|
||||
_contextHandler.addServlet(new ServletHolder("DispatchServlet2", AsyncDispatch2TestServlet.class), "/DispatchServlet2");
|
||||
_contextHandler.addServlet(new ServletHolder("DispatchServlet", AsyncDispatchTestServlet.class), "/DispatchServlet");
|
||||
|
||||
HttpTester.Response response;
|
||||
String rawResponse;
|
||||
|
||||
// TODO Test TCK hack for https://github.com/eclipse-ee4j/jakartaee-tck/issues/585
|
||||
rawResponse = _connector.getResponse("""
|
||||
GET /context/DispatchServlet HTTP/1.1\r
|
||||
Host: local\r
|
||||
|
@ -693,17 +689,31 @@ public class DispatcherTest
|
|||
\r
|
||||
""");
|
||||
response = HttpTester.parseResponse(rawResponse);
|
||||
assertThat(response.getContent(), containsString("matchValue=DispatchServlet, pattern=/DispatchServlet, servletName=DispatchServlet, mappingMatch=EXACT"));
|
||||
assertThat(response.getContent(), containsString("matchValue=TestServlet, pattern=/TestServlet, servletName=TestServlet, mappingMatch=EXACT"));
|
||||
}
|
||||
|
||||
// TODO Test how it should work after fix for https://github.com/eclipse-ee4j/jakartaee-tck/issues/585
|
||||
@Test
|
||||
public void testDispatchMapping404() throws Exception
|
||||
{
|
||||
_contextHandler.addServlet(new ServletHolder("TestServlet", MappingServlet.class), "/TestServlet");
|
||||
_contextHandler.addServlet(new ServletHolder("DispatchServlet", AsyncDispatchTestServlet.class), "/DispatchServlet");
|
||||
|
||||
ErrorPageErrorHandler errorPageErrorHandler = new ErrorPageErrorHandler();
|
||||
_contextHandler.setErrorProcessor(errorPageErrorHandler);
|
||||
errorPageErrorHandler.addErrorPage(404, "/TestServlet");
|
||||
|
||||
HttpTester.Response response;
|
||||
String rawResponse;
|
||||
|
||||
// Test not found
|
||||
rawResponse = _connector.getResponse("""
|
||||
GET /context/DispatchServlet2 HTTP/1.1\r
|
||||
GET /context/DispatchServlet?target=/DoesNotExist HTTP/1.1\r
|
||||
Host: local\r
|
||||
Connection: close\r
|
||||
\r
|
||||
""");
|
||||
response = HttpTester.parseResponse(rawResponse);
|
||||
assertThat(response.getContent(), containsString("matchValue=TestServlet, pattern=/TestServlet, servletName=TestServlet, mappingMatch=EXACT"));
|
||||
assertThat(response.getContent(), containsString("matchValue=DispatchServlet, pattern=/DispatchServlet, servletName=DispatchServlet, mappingMatch=EXACT"));
|
||||
}
|
||||
|
||||
public static class WrappingFilter implements Filter
|
||||
|
@ -1335,14 +1345,16 @@ public class DispatcherTest
|
|||
}
|
||||
}
|
||||
|
||||
public static class AsyncDispatch2TestServlet extends HttpServlet
|
||||
public static class AsyncDispatchTestServlet extends HttpServlet
|
||||
{
|
||||
public void doGet(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws IOException
|
||||
{
|
||||
AsyncContext asyncContext = req.startAsync();
|
||||
asyncContext.setTimeout(0);
|
||||
asyncContext.dispatch("/TestServlet");
|
||||
String target = req.getParameter("target");
|
||||
target = StringUtil.isBlank(target) ? "/TestServlet" : target;
|
||||
asyncContext.dispatch(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,13 +35,13 @@ import org.eclipse.jetty.util.URIUtil;
|
|||
import org.hamcrest.Matchers;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
|
||||
@Disabled
|
||||
public class EncodedURITest
|
||||
{
|
||||
private Server _server;
|
||||
|
@ -90,8 +90,8 @@ public class EncodedURITest
|
|||
assertThat(response, startsWith("HTTP/1.1 200 "));
|
||||
assertThat(response, Matchers.containsString("requestURI=/c%6Fntext%20path/test%20servlet/path%20info"));
|
||||
assertThat(response, Matchers.containsString("contextPath=/context%20path"));
|
||||
assertThat(response, Matchers.containsString("servletPath=/test servlet"));
|
||||
assertThat(response, Matchers.containsString("pathInfo=/path info"));
|
||||
assertThat(response, Matchers.containsString("servletPath=/test%20servlet"));
|
||||
assertThat(response, Matchers.containsString("pathInfo=/path%20info"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -101,8 +101,8 @@ public class EncodedURITest
|
|||
assertThat(response, startsWith("HTTP/1.1 200 "));
|
||||
assertThat(response, Matchers.containsString("requestURI=/context%20path/test%20servlet/path%20info"));
|
||||
assertThat(response, Matchers.containsString("contextPath=/context%20path"));
|
||||
assertThat(response, Matchers.containsString("servletPath=/test servlet"));
|
||||
assertThat(response, Matchers.containsString("pathInfo=/path info"));
|
||||
assertThat(response, Matchers.containsString("servletPath=/test%20servlet"));
|
||||
assertThat(response, Matchers.containsString("pathInfo=/path%20info"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -112,8 +112,8 @@ public class EncodedURITest
|
|||
assertThat(response, startsWith("HTTP/1.1 200 "));
|
||||
assertThat(response, Matchers.containsString("requestURI=/context%20path/test%20servlet/path%20info"));
|
||||
assertThat(response, Matchers.containsString("contextPath=/context%20path"));
|
||||
assertThat(response, Matchers.containsString("servletPath=/test servlet"));
|
||||
assertThat(response, Matchers.containsString("pathInfo=/path info"));
|
||||
assertThat(response, Matchers.containsString("servletPath=/test%20servlet"));
|
||||
assertThat(response, Matchers.containsString("pathInfo=/path%20info"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -121,10 +121,10 @@ public class EncodedURITest
|
|||
{
|
||||
String response = _connector.getResponse("GET /context%20path/async%20servlet/path%20info HTTP/1.0\n\n");
|
||||
assertThat(response, startsWith("HTTP/1.1 200 "));
|
||||
assertThat(response, Matchers.containsString("requestURI=/context%20path/test servlet/path info"));
|
||||
assertThat(response, Matchers.containsString("requestURI=/context%20path/test%20servlet/path%20info"));
|
||||
assertThat(response, Matchers.containsString("contextPath=/context%20path"));
|
||||
assertThat(response, Matchers.containsString("servletPath=/test servlet"));
|
||||
assertThat(response, Matchers.containsString("pathInfo=/path info"));
|
||||
assertThat(response, Matchers.containsString("servletPath=/test%20servlet"));
|
||||
assertThat(response, Matchers.containsString("pathInfo=/path%20info"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -132,10 +132,29 @@ public class EncodedURITest
|
|||
{
|
||||
String response = _connector.getResponse("GET /context%20path/async%20servlet/path%20info?encode=true HTTP/1.0\n\n");
|
||||
assertThat(response, startsWith("HTTP/1.1 200 "));
|
||||
assertThat(response, Matchers.containsString("requestURI=/context%20path/test%20servlet/path%20info"));
|
||||
assertThat(response, Matchers.containsString("requestURI=/context%20path/test%20servlet/path%2520info"));
|
||||
assertThat(response, Matchers.containsString("contextPath=/context%20path"));
|
||||
assertThat(response, Matchers.containsString("servletPath=/test servlet"));
|
||||
assertThat(response, Matchers.containsString("pathInfo=/path info"));
|
||||
assertThat(response, Matchers.containsString("servletPath=/test%20servlet"));
|
||||
assertThat(response, Matchers.containsString("pathInfo=/path%2520info"));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"%2F", "%3F"})
|
||||
public void testCanonicallyEncodedUris(String separator) throws Exception
|
||||
{
|
||||
_server.stop();
|
||||
ServletContextHandler context2 = new ServletContextHandler();
|
||||
context2.setContextPath("/context_path".replace("_", separator));
|
||||
_contextCollection.addHandler(context2);
|
||||
context2.addServlet(TestServlet.class, "/test_servlet/*".replace("_", separator));
|
||||
_server.start();
|
||||
|
||||
String response = _connector.getResponse("GET /context_path/test_servlet/path_info HTTP/1.0\n\n".replace("_", separator));
|
||||
assertThat(response, startsWith("HTTP/1.1 200 "));
|
||||
assertThat(response, Matchers.containsString("requestURI=/context_path/test_servlet/path_info".replace("_", separator)));
|
||||
assertThat(response, Matchers.containsString("contextPath=/context_path".replace("_", separator)));
|
||||
assertThat(response, Matchers.containsString("servletPath=/test_servlet".replace("_", separator)));
|
||||
assertThat(response, Matchers.containsString("pathInfo=/path_info".replace("_", separator)));
|
||||
}
|
||||
|
||||
public static class TestServlet extends HttpServlet
|
||||
|
|
Loading…
Reference in New Issue