Merge remote-tracking branch 'origin/jetty-12.0.x' into jetty-12.1.x
# Conflicts: # jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java
This commit is contained in:
commit
73d2b4ddf1
|
@ -43,7 +43,7 @@ public class SessionAuthentication extends LoginAuthenticator.UserAuthentication
|
|||
|
||||
private final String _name;
|
||||
private final Object _credentials;
|
||||
private Session _session;
|
||||
private transient Session _session;
|
||||
|
||||
public SessionAuthentication(String method, UserIdentity userIdentity, Object credentials)
|
||||
{
|
||||
|
|
|
@ -653,11 +653,11 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Alias
|
|||
*/
|
||||
protected void notifyExitScope(Request request)
|
||||
{
|
||||
for (ContextScopeListener listener : TypeUtil.reverse(_contextListeners))
|
||||
for (ListIterator<ContextScopeListener> i = TypeUtil.listIteratorAtEnd(_contextListeners); i.hasPrevious();)
|
||||
{
|
||||
try
|
||||
{
|
||||
listener.exitScope(_context, request);
|
||||
i.previous().exitScope(_context, request);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
|
|
|
@ -34,6 +34,7 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.ServiceConfigurationError;
|
||||
|
@ -174,18 +175,29 @@ public class TypeUtil
|
|||
}
|
||||
|
||||
/**
|
||||
* <p>Returns a new list with the elements of the specified list in reverse order.</p>
|
||||
* <p>The specified list is not modified, differently from {@link Collections#reverse(List)}.</p>
|
||||
*
|
||||
* @param list the list whose elements are to be reversed
|
||||
* @return a new list with the elements in reverse order
|
||||
* <p>Returns a {@link ListIterator} positioned at the last item in a list.</p>
|
||||
* @param list the list
|
||||
* @param <T> the element type
|
||||
* @return A {@link ListIterator} positioned at the last item of the list.
|
||||
*/
|
||||
public static <T> List<T> reverse(List<T> list)
|
||||
public static <T> ListIterator<T> listIteratorAtEnd(List<T> list)
|
||||
{
|
||||
List<T> result = new ArrayList<>(list);
|
||||
Collections.reverse(result);
|
||||
return result;
|
||||
try
|
||||
{
|
||||
int size = list.size();
|
||||
if (size == 0)
|
||||
return Collections.emptyListIterator();
|
||||
return list.listIterator(size);
|
||||
}
|
||||
catch (IndexOutOfBoundsException e)
|
||||
{
|
||||
// list was concurrently modified, so do this the hard way
|
||||
ListIterator<T> i = list.listIterator();
|
||||
while (i.hasNext())
|
||||
i.next();
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,6 +31,7 @@ import java.util.EventListener;
|
|||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
@ -517,11 +518,11 @@ public class ServletContextHandler extends ContextHandler
|
|||
//Call context listeners
|
||||
Throwable multiException = null;
|
||||
ServletContextEvent event = new ServletContextEvent(getServletContext());
|
||||
for (ServletContextListener listener : TypeUtil.reverse(_destroyServletContextListeners))
|
||||
for (ListIterator<ServletContextListener> i = TypeUtil.listIteratorAtEnd(_destroyServletContextListeners); i.hasPrevious();)
|
||||
{
|
||||
try
|
||||
{
|
||||
callContextDestroyed(listener, event);
|
||||
callContextDestroyed(i.previous(), event);
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
|
@ -568,17 +569,17 @@ public class ServletContextHandler extends ContextHandler
|
|||
if (!_servletRequestListeners.isEmpty())
|
||||
{
|
||||
final ServletRequestEvent sre = new ServletRequestEvent(getServletContext(), request);
|
||||
for (ServletRequestListener listener : TypeUtil.reverse(_servletRequestListeners))
|
||||
for (ListIterator<ServletRequestListener> i = TypeUtil.listIteratorAtEnd(_servletRequestListeners); i.hasPrevious();)
|
||||
{
|
||||
listener.requestDestroyed(sre);
|
||||
i.previous().requestDestroyed(sre);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_servletRequestAttributeListeners.isEmpty())
|
||||
{
|
||||
for (ServletRequestAttributeListener listener : TypeUtil.reverse(_servletRequestAttributeListeners))
|
||||
for (ListIterator<ServletRequestAttributeListener> i = TypeUtil.listIteratorAtEnd(_servletRequestAttributeListeners); i.hasPrevious();)
|
||||
{
|
||||
scopedRequest.removeEventListener(listener);
|
||||
scopedRequest.removeEventListener(i.previous());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1217,11 +1218,11 @@ public class ServletContextHandler extends ContextHandler
|
|||
ServletContextRequest scopedRequest = Request.as(request, ServletContextRequest.class);
|
||||
if (!_contextListeners.isEmpty())
|
||||
{
|
||||
for (ServletContextScopeListener listener : TypeUtil.reverse(_contextListeners))
|
||||
for (ListIterator<ServletContextScopeListener> i = TypeUtil.listIteratorAtEnd(_contextListeners); i.hasPrevious(); )
|
||||
{
|
||||
try
|
||||
{
|
||||
listener.exitScope(getContext(), scopedRequest);
|
||||
i.previous().exitScope(getContext(), scopedRequest);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.util.Enumeration;
|
|||
import java.util.EventListener;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -572,9 +573,9 @@ public class SessionHandler extends AbstractSessionManager implements Handler.Si
|
|||
getSessionContext().run(() ->
|
||||
{
|
||||
HttpSessionEvent event = new HttpSessionEvent(session.getApi());
|
||||
for (HttpSessionListener listener : TypeUtil.reverse(_sessionListeners))
|
||||
for (ListIterator<HttpSessionListener> i = TypeUtil.listIteratorAtEnd(_sessionListeners); i.hasPrevious();)
|
||||
{
|
||||
listener.sessionDestroyed(event);
|
||||
i.previous().sessionDestroyed(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.eclipse.jetty.http.ComplianceViolation;
|
||||
import org.eclipse.jetty.http.HttpCompliance;
|
||||
import org.eclipse.jetty.http.UriCompliance;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.LocalConnector;
|
||||
|
@ -87,8 +88,8 @@ public class ComplianceViolations2616Test
|
|||
{
|
||||
resp.setContentType("text/plain");
|
||||
PrintWriter out = resp.getWriter();
|
||||
List<String> headerNames = new ArrayList<>();
|
||||
headerNames.addAll(Collections.list(req.getHeaderNames()));
|
||||
out.printf("%s %s%s%s\n", req.getMethod(), req.getContextPath(), req.getServletPath(), req.getPathInfo());
|
||||
List<String> headerNames = new ArrayList<>(Collections.list(req.getHeaderNames()));
|
||||
Collections.sort(headerNames);
|
||||
for (String name : headerNames)
|
||||
{
|
||||
|
@ -183,4 +184,25 @@ public class ComplianceViolations2616Test
|
|||
assertThat("Response headers", response, containsString("X-Http-Violation-0: Line Folding not supported"));
|
||||
assertThat("Response body", response, containsString("[Name] = [Some Value]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAmbiguousSlash() throws Exception
|
||||
{
|
||||
String request = """
|
||||
GET /dump/foo//bar HTTP/1.1\r
|
||||
Host: local\r
|
||||
Connection: close\r
|
||||
\r
|
||||
""";
|
||||
|
||||
String response = connector.getResponse(request);
|
||||
assertThat(response, containsString("HTTP/1.1 400 Bad"));
|
||||
|
||||
connector.getConnectionFactory(HttpConnectionFactory.class).getHttpConfiguration().setUriCompliance(UriCompliance.RFC3986.with("test", UriCompliance.Violation.AMBIGUOUS_EMPTY_SEGMENT));
|
||||
server.getContainedBeans(ServletHandler.class).stream().findFirst().get().setDecodeAmbiguousURIs(true);
|
||||
|
||||
response = connector.getResponse(request);
|
||||
assertThat(response, containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response, containsString("GET /dump/foo//bar"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import java.util.EventListener;
|
|||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
@ -516,11 +517,11 @@ public class ServletContextHandler extends ContextHandler
|
|||
//Call context listeners
|
||||
Throwable multiException = null;
|
||||
ServletContextEvent event = new ServletContextEvent(getServletContext());
|
||||
for (ServletContextListener listener : TypeUtil.reverse(_destroyServletContextListeners))
|
||||
for (ListIterator<ServletContextListener> i = TypeUtil.listIteratorAtEnd(_destroyServletContextListeners); i.hasPrevious();)
|
||||
{
|
||||
try
|
||||
{
|
||||
callContextDestroyed(listener, event);
|
||||
callContextDestroyed(i.previous(), event);
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
|
@ -567,17 +568,17 @@ public class ServletContextHandler extends ContextHandler
|
|||
if (!_servletRequestListeners.isEmpty())
|
||||
{
|
||||
ServletRequestEvent sre = new ServletRequestEvent(getServletContext(), request);
|
||||
for (ServletRequestListener listener : TypeUtil.reverse(_servletRequestListeners))
|
||||
for (ListIterator<ServletRequestListener> i = TypeUtil.listIteratorAtEnd(_servletRequestListeners); i.hasPrevious();)
|
||||
{
|
||||
listener.requestDestroyed(sre);
|
||||
i.previous().requestDestroyed(sre);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_servletRequestAttributeListeners.isEmpty())
|
||||
{
|
||||
for (ServletRequestAttributeListener listener : TypeUtil.reverse(_servletRequestAttributeListeners))
|
||||
for (ListIterator<ServletRequestAttributeListener> i = TypeUtil.listIteratorAtEnd(_servletRequestAttributeListeners); i.hasPrevious();)
|
||||
{
|
||||
scopedRequest.removeEventListener(listener);
|
||||
scopedRequest.removeEventListener(i.previous());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1217,11 +1218,11 @@ public class ServletContextHandler extends ContextHandler
|
|||
ServletContextRequest scopedRequest = Request.as(request, ServletContextRequest.class);
|
||||
if (!_contextListeners.isEmpty())
|
||||
{
|
||||
for (ServletContextScopeListener listener : TypeUtil.reverse(_contextListeners))
|
||||
for (ListIterator<ServletContextScopeListener> i = TypeUtil.listIteratorAtEnd(_contextListeners); i.hasPrevious(); )
|
||||
{
|
||||
try
|
||||
{
|
||||
listener.exitScope(getContext(), scopedRequest);
|
||||
i.previous().exitScope(getContext(), scopedRequest);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.util.Enumeration;
|
|||
import java.util.EventListener;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -616,9 +617,9 @@ public class SessionHandler extends AbstractSessionManager implements Handler.Si
|
|||
getSessionContext().run(() ->
|
||||
{
|
||||
HttpSessionEvent event = new HttpSessionEvent(session.getApi());
|
||||
for (HttpSessionListener listener : TypeUtil.reverse(_sessionListeners))
|
||||
for (ListIterator<HttpSessionListener> i = TypeUtil.listIteratorAtEnd(_sessionListeners); i.hasPrevious();)
|
||||
{
|
||||
listener.sessionDestroyed(event);
|
||||
i.previous().sessionDestroyed(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.eclipse.jetty.http.ComplianceViolation;
|
||||
import org.eclipse.jetty.http.HttpCompliance;
|
||||
import org.eclipse.jetty.http.UriCompliance;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.LocalConnector;
|
||||
|
@ -87,8 +88,8 @@ public class ComplianceViolations2616Test
|
|||
{
|
||||
resp.setContentType("text/plain");
|
||||
PrintWriter out = resp.getWriter();
|
||||
List<String> headerNames = new ArrayList<>();
|
||||
headerNames.addAll(Collections.list(req.getHeaderNames()));
|
||||
out.printf("%s %s%s%s\n", req.getMethod(), req.getContextPath(), req.getServletPath(), req.getPathInfo());
|
||||
List<String> headerNames = new ArrayList<>(Collections.list(req.getHeaderNames()));
|
||||
Collections.sort(headerNames);
|
||||
for (String name : headerNames)
|
||||
{
|
||||
|
@ -183,4 +184,25 @@ public class ComplianceViolations2616Test
|
|||
assertThat("Response headers", response, containsString("X-Http-Violation-0: Line Folding not supported"));
|
||||
assertThat("Response body", response, containsString("[Name] = [Some Value]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAmbiguousSlash() throws Exception
|
||||
{
|
||||
String request = """
|
||||
GET /dump/foo//bar HTTP/1.1\r
|
||||
Host: local\r
|
||||
Connection: close\r
|
||||
\r
|
||||
""";
|
||||
|
||||
String response = connector.getResponse(request);
|
||||
assertThat(response, containsString("HTTP/1.1 400 Bad"));
|
||||
|
||||
connector.getConnectionFactory(HttpConnectionFactory.class).getHttpConfiguration().setUriCompliance(UriCompliance.RFC3986.with("test", UriCompliance.Violation.AMBIGUOUS_EMPTY_SEGMENT));
|
||||
server.getContainedBeans(ServletHandler.class).stream().findFirst().get().setDecodeAmbiguousURIs(true);
|
||||
|
||||
response = connector.getResponse(request);
|
||||
assertThat(response, containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response, containsString("GET /dump/foo//bar"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.EventListener;
|
|||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
@ -1000,17 +1001,17 @@ public class ContextHandler extends ScopedHandler implements Attributes, Supplie
|
|||
if (!_servletRequestListeners.isEmpty())
|
||||
{
|
||||
final ServletRequestEvent sre = new ServletRequestEvent(_apiContext, request);
|
||||
for (ServletRequestListener listener : TypeUtil.reverse(_servletRequestListeners))
|
||||
for (ListIterator<ServletRequestListener> i = TypeUtil.listIteratorAtEnd(_servletRequestListeners); i.hasPrevious();)
|
||||
{
|
||||
listener.requestDestroyed(sre);
|
||||
i.previous().requestDestroyed(sre);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_servletRequestAttributeListeners.isEmpty())
|
||||
{
|
||||
for (ServletRequestAttributeListener listener : TypeUtil.reverse(_servletRequestAttributeListeners))
|
||||
for (ListIterator<ServletRequestAttributeListener> i = TypeUtil.listIteratorAtEnd(_servletRequestAttributeListeners); i.hasPrevious();)
|
||||
{
|
||||
baseRequest.removeEventListener(listener);
|
||||
baseRequest.removeEventListener(i.previous());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1070,11 +1071,11 @@ public class ContextHandler extends ScopedHandler implements Attributes, Supplie
|
|||
{
|
||||
if (!_contextListeners.isEmpty())
|
||||
{
|
||||
for (ContextScopeListener listener : TypeUtil.reverse(_contextListeners))
|
||||
for (ListIterator<ContextScopeListener> i = TypeUtil.listIteratorAtEnd(_contextListeners); i.hasPrevious();)
|
||||
{
|
||||
try
|
||||
{
|
||||
listener.exitScope(_apiContext, request);
|
||||
i.previous().exitScope(_apiContext, request);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.util.EnumSet;
|
|||
import java.util.Enumeration;
|
||||
import java.util.EventListener;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.function.Function;
|
||||
|
@ -835,9 +836,9 @@ public class SessionHandler extends ScopedHandler implements SessionConfig.Mutab
|
|||
Runnable r = () ->
|
||||
{
|
||||
HttpSessionEvent event = new HttpSessionEvent(session.getApi());
|
||||
for (HttpSessionListener listener : TypeUtil.reverse(_sessionListeners))
|
||||
for (ListIterator<HttpSessionListener> i = TypeUtil.listIteratorAtEnd(_sessionListeners); i.hasPrevious();)
|
||||
{
|
||||
listener.sessionDestroyed(event);
|
||||
i.previous().sessionDestroyed(event);
|
||||
}
|
||||
};
|
||||
_contextHandler.getCoreContextHandler().getContext().run(r);
|
||||
|
|
Loading…
Reference in New Issue