From 23dcefcd4722578b7c04cad1b449ab77e415cbfd Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Mon, 9 May 2022 17:07:48 +1000 Subject: [PATCH] copy servlet attributes & params on jetty websocket upgrade Signed-off-by: Lachlan Roberts --- .../core/server/ServerUpgradeRequest.java | 62 +- .../core/server/ServerUpgradeResponse.java | 6 +- .../core/server/WebSocketNegotiation.java | 12 +- .../server/internal/AbstractHandshaker.java | 2 + .../server/internal/CreatorNegotiator.java | 4 +- .../DelegatedServerUpgradeRequest.java | 38 +- .../JettyServerFrameHandlerFactory.java | 10 +- .../internal/UpgradeHttpServletRequest.java | 660 ++++++++++++++++++ .../JettyWebSocketServletAttributeTest.java | 2 - 9 files changed, 769 insertions(+), 27 deletions(-) create mode 100644 jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/internal/UpgradeHttpServletRequest.java diff --git a/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/ServerUpgradeRequest.java b/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/ServerUpgradeRequest.java index 56a7eb96fae..24c76edefef 100644 --- a/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/ServerUpgradeRequest.java +++ b/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/ServerUpgradeRequest.java @@ -14,10 +14,12 @@ package org.eclipse.jetty.websocket.core.server; import java.util.List; +import java.util.Set; import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.util.Attributes; import org.eclipse.jetty.websocket.core.ExtensionConfig; import org.eclipse.jetty.websocket.core.WebSocketConstants; @@ -29,13 +31,65 @@ public class ServerUpgradeRequest extends Request.Wrapper { private final Request request; private final WebSocketNegotiation negotiation; + private final Attributes attributes = new Attributes.Lazy(); + private boolean upgraded = false; - public ServerUpgradeRequest(WebSocketNegotiation negotiation) throws BadMessageException + public ServerUpgradeRequest(WebSocketNegotiation negotiation, Request baseRequest) throws BadMessageException { - super(negotiation.getRequest()); - + super(baseRequest); this.negotiation = negotiation; - this.request = negotiation.getRequest(); + this.request = baseRequest; + } + + public void upgrade() + { + attributes.clearAttributes(); + for (String name : request.getAttributeNameSet()) + { + attributes.setAttribute(name, request.getAttribute(name)); + } + upgraded = true; + } + + @Override + public Object removeAttribute(String name) + { + if (upgraded) + return attributes.removeAttribute(name); + return super.removeAttribute(name); + } + + @Override + public Object setAttribute(String name, Object attribute) + { + if (upgraded) + return attributes.setAttribute(name, attribute); + return super.setAttribute(name, attribute); + } + + @Override + public Object getAttribute(String name) + { + if (upgraded) + return attributes.getAttribute(name); + return super.getAttribute(name); + } + + @Override + public Set getAttributeNameSet() + { + if (upgraded) + return attributes.getAttributeNameSet(); + return super.getAttributeNameSet(); + } + + @Override + public void clearAttributes() + { + if (upgraded) + attributes.clearAttributes(); + else + super.clearAttributes(); } /** diff --git a/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/ServerUpgradeResponse.java b/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/ServerUpgradeResponse.java index 61fb02083ca..7b41d061bf8 100644 --- a/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/ServerUpgradeResponse.java +++ b/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/ServerUpgradeResponse.java @@ -31,11 +31,11 @@ public class ServerUpgradeResponse extends Response.Wrapper private final WebSocketNegotiation negotiation; private final HttpFields.Mutable fields; - public ServerUpgradeResponse(WebSocketNegotiation negotiation) + public ServerUpgradeResponse(WebSocketNegotiation negotiation, Response baseResponse) { - super(negotiation.getRequest(), negotiation.getResponse()); + super(baseResponse.getRequest(), baseResponse); this.negotiation = negotiation; - this.response = negotiation.getResponse(); + this.response = baseResponse; this.fields = new WebSocketHttpFieldsWrapper(response.getHeaders(), this, negotiation); } diff --git a/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/WebSocketNegotiation.java b/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/WebSocketNegotiation.java index 9e17a80e344..8fd222b7477 100644 --- a/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/WebSocketNegotiation.java +++ b/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/WebSocketNegotiation.java @@ -31,8 +31,8 @@ import org.eclipse.jetty.websocket.core.WebSocketComponents; public abstract class WebSocketNegotiation { - private final Request request; - private final Response response; + private final ServerUpgradeRequest request; + private final ServerUpgradeResponse response; private final Callback callback; private final WebSocketComponents components; private String version; @@ -43,18 +43,18 @@ public abstract class WebSocketNegotiation public WebSocketNegotiation(Request request, Response response, Callback callback, WebSocketComponents webSocketComponents) { - this.request = request; - this.response = response; + this.request = new ServerUpgradeRequest(this, request); + this.response = new ServerUpgradeResponse(this, response); this.callback = callback; this.components = webSocketComponents; } - public Request getRequest() + public ServerUpgradeRequest getRequest() { return request; } - public Response getResponse() + public ServerUpgradeResponse getResponse() { return response; } diff --git a/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/internal/AbstractHandshaker.java b/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/internal/AbstractHandshaker.java index 978adc758d0..dd6c056649b 100644 --- a/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/internal/AbstractHandshaker.java +++ b/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/internal/AbstractHandshaker.java @@ -145,6 +145,8 @@ public abstract class AbstractHandshaker implements Handshaker } }); + negotiation.getRequest().upgrade(); + if (LOG.isDebugEnabled()) LOG.debug("upgrade connection={} session={} framehandler={}", connection, coreSession, handler); response.write(true, callback); diff --git a/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/internal/CreatorNegotiator.java b/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/internal/CreatorNegotiator.java index c38a9d6737d..0dd960cf52f 100644 --- a/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/internal/CreatorNegotiator.java +++ b/jetty-core/jetty-websocket/websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/internal/CreatorNegotiator.java @@ -51,8 +51,8 @@ public class CreatorNegotiator extends WebSocketNegotiator.AbstractNegotiator public FrameHandler negotiate(WebSocketNegotiation negotiation) throws IOException { Context context = negotiation.getRequest().getContext(); - ServerUpgradeRequest upgradeRequest = new ServerUpgradeRequest(negotiation); - ServerUpgradeResponse upgradeResponse = new ServerUpgradeResponse(negotiation); + ServerUpgradeRequest upgradeRequest = negotiation.getRequest(); + ServerUpgradeResponse upgradeResponse = negotiation.getResponse(); Object websocketPojo; try diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/internal/DelegatedServerUpgradeRequest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/internal/DelegatedServerUpgradeRequest.java index 9bb374a45a2..7a5c4c4ec2f 100644 --- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/internal/DelegatedServerUpgradeRequest.java +++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/internal/DelegatedServerUpgradeRequest.java @@ -35,12 +35,16 @@ import org.eclipse.jetty.ee10.servlet.ServletContextRequest; import org.eclipse.jetty.ee10.websocket.api.ExtensionConfig; import org.eclipse.jetty.ee10.websocket.common.JettyExtensionConfig; import org.eclipse.jetty.ee10.websocket.server.JettyServerUpgradeRequest; +import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.websocket.core.server.ServerUpgradeRequest; public class DelegatedServerUpgradeRequest implements JettyServerUpgradeRequest { + private final URI requestURI; + private final String queryString; private final ServerUpgradeRequest upgradeRequest; private final HttpServletRequest httpServletRequest; private List cookies; @@ -48,9 +52,27 @@ public class DelegatedServerUpgradeRequest implements JettyServerUpgradeRequest public DelegatedServerUpgradeRequest(ServerUpgradeRequest request) { - upgradeRequest = request; - ServletContextRequest servletContextRequest = Request.as(upgradeRequest, ServletContextRequest.class); - this.httpServletRequest = servletContextRequest.getHttpServletRequest(); + this(request, Request.as(request, ServletContextRequest.class).getHttpServletRequest()); + } + + public DelegatedServerUpgradeRequest(ServerUpgradeRequest request, HttpServletRequest servletRequest) + { + this.upgradeRequest = request; + this.httpServletRequest = servletRequest; + this.queryString = httpServletRequest.getQueryString(); + + try + { + StringBuffer uri = httpServletRequest.getRequestURL(); + if (this.queryString != null) + uri.append("?").append(this.queryString); + uri.replace(0, uri.indexOf(":"), request.isSecure() ? "wss" : "ws"); + this.requestURI = new URI(uri.toString()); + } + catch (Throwable t) + { + throw new BadMessageException("Bad WebSocket UpgradeRequest", t); + } } @Override @@ -159,13 +181,13 @@ public class DelegatedServerUpgradeRequest implements JettyServerUpgradeRequest @Override public String getQueryString() { - return upgradeRequest.getHttpURI().getQuery(); + return queryString; } @Override public URI getRequestURI() { - return upgradeRequest.getHttpURI().toURI(); + return requestURI; } @Override @@ -207,7 +229,7 @@ public class DelegatedServerUpgradeRequest implements JettyServerUpgradeRequest @Override public HttpServletRequest getHttpServletRequest() { - return getHttpServletRequest(); + return httpServletRequest; } @Override @@ -237,13 +259,13 @@ public class DelegatedServerUpgradeRequest implements JettyServerUpgradeRequest @Override public String getRequestPath() { - return upgradeRequest.getPathInContext(); + return URIUtil.addPaths(httpServletRequest.getServletPath(), httpServletRequest.getPathInfo()); } @Override public Object getServletAttribute(String name) { - return upgradeRequest.getAttribute(name); + return httpServletRequest.getAttribute(name); } @Override diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/internal/JettyServerFrameHandlerFactory.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/internal/JettyServerFrameHandlerFactory.java index 37078ca6128..9e62dfae289 100644 --- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/internal/JettyServerFrameHandlerFactory.java +++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/internal/JettyServerFrameHandlerFactory.java @@ -14,9 +14,11 @@ package org.eclipse.jetty.ee10.websocket.server.internal; import jakarta.servlet.ServletContext; +import org.eclipse.jetty.ee10.servlet.ServletContextRequest; import org.eclipse.jetty.ee10.websocket.common.JettyWebSocketFrameHandler; import org.eclipse.jetty.ee10.websocket.common.JettyWebSocketFrameHandlerFactory; import org.eclipse.jetty.ee10.websocket.server.JettyWebSocketServerContainer; +import org.eclipse.jetty.server.Request; import org.eclipse.jetty.websocket.core.FrameHandler; import org.eclipse.jetty.websocket.core.WebSocketComponents; import org.eclipse.jetty.websocket.core.server.FrameHandlerFactory; @@ -39,9 +41,13 @@ public class JettyServerFrameHandlerFactory extends JettyWebSocketFrameHandlerFa @Override public FrameHandler newFrameHandler(Object websocketPojo, ServerUpgradeRequest upgradeRequest, ServerUpgradeResponse upgradeResponse) { - // TODO: do we need to extract and use the Servlet req/resp as this occurs within ServletChannel handling? + // Copy servlet params and attributes with UpgradeHttpServletRequest which may be inaccessible after upgrade. + ServletContextRequest servletContextRequest = Request.as(upgradeRequest, ServletContextRequest.class); + UpgradeHttpServletRequest httpServletRequest = new UpgradeHttpServletRequest(servletContextRequest.getHttpServletRequest()); + httpServletRequest.upgrade(); + JettyWebSocketFrameHandler frameHandler = super.newJettyFrameHandler(websocketPojo); - frameHandler.setUpgradeRequest(new DelegatedServerUpgradeRequest(upgradeRequest)); + frameHandler.setUpgradeRequest(new DelegatedServerUpgradeRequest(upgradeRequest, httpServletRequest)); frameHandler.setUpgradeResponse(new DelegatedServerUpgradeResponse(upgradeResponse)); return frameHandler; } diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/internal/UpgradeHttpServletRequest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/internal/UpgradeHttpServletRequest.java new file mode 100644 index 00000000000..e83473013d2 --- /dev/null +++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-server/src/main/java/org/eclipse/jetty/ee10/websocket/server/internal/UpgradeHttpServletRequest.java @@ -0,0 +1,660 @@ +// +// ======================================================================== +// Copyright (c) 1995-2022 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.ee10.websocket.server.internal; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.InetSocketAddress; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.TreeMap; + +import jakarta.servlet.AsyncContext; +import jakarta.servlet.DispatcherType; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletConnection; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; +import jakarta.servlet.http.HttpUpgradeHandler; +import jakarta.servlet.http.Part; + +/** + * An immutable, feature limited, HttpServletRequest that will not be recycled by Jetty. + */ +public class UpgradeHttpServletRequest implements HttpServletRequest +{ + private static final String UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE = "Feature unsupported after Upgraded to WebSocket"; + + private HttpServletRequest request; + + private final ServletContext context; + private final DispatcherType dispatcher; + private final String method; + private final String protocol; + private final String scheme; + private final boolean secure; + private final String requestURI; + private final StringBuffer requestURL; + private final String pathInfo; + private final String pathTranslated; + private final String servletPath; + private final String query; + private final String authType; + private final Cookie[] cookies; + private final String remoteUser; + private final Principal principal; + private final String requestId; + private final String protocolRequestId; + private final ServletConnection servletConnection; + + private final Map> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + private final Map parameters = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + private final Map attributes = new HashMap<>(2); + private final List locales = new ArrayList<>(2); + + private final HttpSession session; + + private final InetSocketAddress localAddress; + private final String localName; + private final InetSocketAddress remoteAddress; + private final String remoteName; + private final InetSocketAddress serverAddress; + + private boolean isAsyncStarted; + private boolean isAsyncSupported; + + public UpgradeHttpServletRequest(HttpServletRequest httpRequest) + { + // The original request object must be held temporarily for the duration of the handshake + // in order to be able to implement methods such as isUserInRole() and setAttribute(). + request = httpRequest; + + context = httpRequest.getServletContext(); + dispatcher = httpRequest.getDispatcherType(); + + method = httpRequest.getMethod(); + protocol = httpRequest.getProtocol(); + scheme = httpRequest.getScheme(); + secure = httpRequest.isSecure(); + requestURI = httpRequest.getRequestURI(); + requestURL = httpRequest.getRequestURL(); + pathInfo = httpRequest.getPathInfo(); + pathTranslated = httpRequest.getPathTranslated(); + servletPath = httpRequest.getServletPath(); + query = httpRequest.getQueryString(); + authType = httpRequest.getAuthType(); + cookies = httpRequest.getCookies(); + session = httpRequest.getSession(false); + requestId = httpRequest.getRequestId(); + protocolRequestId = httpRequest.getProtocolRequestId(); + servletConnection = httpRequest.getServletConnection(); + + remoteUser = httpRequest.getRemoteUser(); + principal = httpRequest.getUserPrincipal(); + + Enumeration headerNames = httpRequest.getHeaderNames(); + while (headerNames.hasMoreElements()) + { + String name = headerNames.nextElement(); + headers.put(name, Collections.list(httpRequest.getHeaders(name))); + } + + parameters.putAll(httpRequest.getParameterMap()); + + Enumeration localeElements = httpRequest.getLocales(); + while (localeElements.hasMoreElements()) + { + locales.add(localeElements.nextElement()); + } + + localAddress = InetSocketAddress.createUnresolved(httpRequest.getLocalAddr(), httpRequest.getLocalPort()); + localName = httpRequest.getLocalName(); + remoteAddress = InetSocketAddress.createUnresolved(httpRequest.getRemoteAddr(), httpRequest.getRemotePort()); + remoteName = httpRequest.getRemoteHost(); + serverAddress = InetSocketAddress.createUnresolved(httpRequest.getServerName(), httpRequest.getServerPort()); + } + + public void upgrade() + { + Enumeration attributeNames = request.getAttributeNames(); + while (attributeNames.hasMoreElements()) + { + String name = attributeNames.nextElement(); + attributes.put(name, request.getAttribute(name)); + } + + this.isAsyncStarted = request.isAsyncStarted(); + this.isAsyncSupported = request.isAsyncSupported(); + request = null; + } + + public HttpServletRequest getHttpServletRequest() + { + return request; + } + + @Override + public String getAuthType() + { + return authType; + } + + @Override + public Cookie[] getCookies() + { + return cookies; + } + + @Override + public String getHeader(String name) + { + List values = headers.get(name); + if (values == null || values.isEmpty()) + return null; + return values.get(0); + } + + @Override + public Enumeration getHeaders(String name) + { + List values = headers.get(name); + if (values == null) + return Collections.emptyEnumeration(); + return Collections.enumeration(values); + } + + public Map> getHeaders() + { + return Collections.unmodifiableMap(headers); + } + + @Override + public Enumeration getHeaderNames() + { + return Collections.enumeration(headers.keySet()); + } + + @Override + public long getDateHeader(String name) + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.getDateHeader(name); + } + + @Override + public int getIntHeader(String name) + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.getIntHeader(name); + } + + @Override + public String getMethod() + { + return method; + } + + @Override + public String getPathInfo() + { + return pathInfo; + } + + @Override + public String getPathTranslated() + { + return pathTranslated; + } + + @Override + public String getContextPath() + { + return context.getContextPath(); + } + + @Override + public String getQueryString() + { + return query; + } + + @Override + public String getRemoteUser() + { + return remoteUser; + } + + @Override + public boolean isUserInRole(String role) + { + // TODO: + return false; + } + + @Override + public Principal getUserPrincipal() + { + return principal; + } + + @Override + public String getRequestURI() + { + return requestURI; + } + + @Override + public StringBuffer getRequestURL() + { + return requestURL; + } + + @Override + public String getServletPath() + { + return servletPath; + } + + @Override + public HttpSession getSession(boolean create) + { + if (create && (session == null)) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return session; + } + + @Override + public HttpSession getSession() + { + return session; + } + + @Override + public String getRequestedSessionId() + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.getRequestedSessionId(); + } + + @Override + public boolean isRequestedSessionIdValid() + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.isRequestedSessionIdValid(); + } + + @Override + public boolean isRequestedSessionIdFromCookie() + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.isRequestedSessionIdFromCookie(); + } + + @Override + public boolean isRequestedSessionIdFromURL() + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.isRequestedSessionIdFromURL(); + } + + @Override + public Object getAttribute(String name) + { + if (request == null) + return attributes.get(name); + return request.getAttribute(name); + } + + @Override + public Enumeration getAttributeNames() + { + if (request == null) + return Collections.enumeration(attributes.keySet()); + return request.getAttributeNames(); + } + + @Override + public String getParameter(String name) + { + String[] values = parameters.get(name); + if (values == null || values.length == 0) + return null; + return values[0]; + } + + @Override + public Enumeration getParameterNames() + { + return Collections.enumeration(parameters.keySet()); + } + + @Override + public String[] getParameterValues(String name) + { + return parameters.get(name); + } + + @Override + public Map getParameterMap() + { + return parameters; + } + + @Override + public String getProtocol() + { + return protocol; + } + + @Override + public String getScheme() + { + return scheme; + } + + @Override + public String getServerName() + { + return serverAddress.getHostString(); + } + + @Override + public int getServerPort() + { + return serverAddress.getPort(); + } + + @Override + public String getRemoteAddr() + { + return remoteAddress.getHostString(); + } + + @Override + public int getRemotePort() + { + return remoteAddress.getPort(); + } + + @Override + public String getRemoteHost() + { + return remoteName; + } + + @Override + public void setAttribute(String name, Object value) + { + if (request == null) + attributes.put(name, value); + request.setAttribute(name, value); + } + + @Override + public void removeAttribute(String name) + { + if (request == null) + attributes.remove(name); + request.removeAttribute(name); + } + + @Override + public Locale getLocale() + { + if (locales.isEmpty()) + return Locale.getDefault(); + return locales.get(0); + } + + @Override + public Enumeration getLocales() + { + return Collections.enumeration(locales); + } + + @Override + public boolean isSecure() + { + return secure; + } + + @Override + public String getLocalName() + { + return localName; + } + + @Override + public String getLocalAddr() + { + return localAddress.getHostString(); + } + + @Override + public int getLocalPort() + { + return localAddress.getPort(); + } + + @Override + public ServletContext getServletContext() + { + return context; + } + + @Override + public DispatcherType getDispatcherType() + { + return dispatcher; + } + + @Override + public String getRequestId() + { + return requestId; + } + + @Override + public String getProtocolRequestId() + { + return protocolRequestId; + } + + @Override + public ServletConnection getServletConnection() + { + return servletConnection; + } + + @Override + public boolean authenticate(HttpServletResponse response) throws IOException, ServletException + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.authenticate(response); + } + + @Override + public String changeSessionId() + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.changeSessionId(); + } + + @Override + public AsyncContext getAsyncContext() + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.getAsyncContext(); + } + + @Override + public String getCharacterEncoding() + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.getCharacterEncoding(); + } + + @Override + public int getContentLength() + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.getContentLength(); + } + + @Override + public long getContentLengthLong() + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.getContentLengthLong(); + } + + @Override + public String getContentType() + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.getContentType(); + } + + @Override + public ServletInputStream getInputStream() throws IOException + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.getInputStream(); + } + + @Override + public Part getPart(String name) throws IOException, ServletException + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.getPart(name); + } + + @Override + public Collection getParts() throws IOException, ServletException + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.getParts(); + } + + @Override + public BufferedReader getReader() throws IOException + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.getReader(); + } + + @Override + public RequestDispatcher getRequestDispatcher(String path) + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.getRequestDispatcher(path); + } + + @Override + public boolean isAsyncStarted() + { + if (request == null) + return isAsyncStarted; + return request.isAsyncStarted(); + } + + @Override + public boolean isAsyncSupported() + { + if (request == null) + return isAsyncSupported; + return request.isAsyncSupported(); + } + + @Override + public void login(String username, String password) throws ServletException + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + request.login(username, password); + } + + @Override + public void logout() throws ServletException + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + request.logout(); + } + + @Override + public void setCharacterEncoding(String enc) throws UnsupportedEncodingException + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + request.setCharacterEncoding(enc); + } + + @Override + public AsyncContext startAsync() throws IllegalStateException + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.startAsync(); + } + + @Override + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.startAsync(servletRequest, servletResponse); + } + + @Override + public T upgrade(Class handlerClass) throws IOException, ServletException + { + if (request == null) + throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE); + return request.upgrade(handlerClass); + } +} diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketServletAttributeTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketServletAttributeTest.java index 37d77c422ea..e415bec8ce1 100644 --- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketServletAttributeTest.java +++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jetty-tests/src/test/java/org/eclipse/jetty/ee10/websocket/tests/JettyWebSocketServletAttributeTest.java @@ -24,7 +24,6 @@ import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; 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; @@ -66,7 +65,6 @@ public class JettyWebSocketServletAttributeTest client.start(); } - @Disabled @Test public void testAttributeSetInNegotiation() throws Exception {