Issue #5868 - allow request attributes to be set during websocket handshake

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
Lachlan Roberts 2021-02-02 17:48:11 +11:00
parent 5b97d91f59
commit 2ac50130d6
9 changed files with 571 additions and 95 deletions

View File

@ -37,6 +37,7 @@ import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.QuotedStringTokenizer;
@ -432,7 +433,8 @@ public abstract class CoreClientUpgradeRequest extends HttpRequest implements Re
customizer.customize(coreSession);
HttpClient httpClient = wsClient.getHttpClient();
WebSocketConnection wsConnection = new WebSocketConnection(endPoint, httpClient.getExecutor(), httpClient.getScheduler(), httpClient.getByteBufferPool(), coreSession);
ByteBufferPool bufferPool = wsClient.getWebSocketComponents().getBufferPool();
WebSocketConnection wsConnection = new WebSocketConnection(endPoint, httpClient.getExecutor(), httpClient.getScheduler(), bufferPool, coreSession);
wsClient.getEventListeners().forEach(wsConnection::addEventListener);
coreSession.setWebSocketConnection(wsConnection);
notifyUpgradeListeners((listener) -> listener.onHandshakeResponse(this, response));

View File

@ -19,15 +19,16 @@ import java.net.SocketAddress;
import java.net.URI;
import java.security.Principal;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
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 java.util.stream.Collectors;
import javax.servlet.ServletRequest;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@ -42,7 +43,7 @@ public class ServerUpgradeRequest
{
private final URI requestURI;
private final String queryString;
private final UpgradeHttpServletRequest request;
private final HttpServletRequest request;
private final boolean secure;
private final WebSocketNegotiation negotiation;
private List<HttpCookie> cookies;
@ -51,20 +52,17 @@ public class ServerUpgradeRequest
public ServerUpgradeRequest(WebSocketNegotiation negotiation) throws BadMessageException
{
this.negotiation = negotiation;
HttpServletRequest httpRequest = negotiation.getRequest();
this.queryString = httpRequest.getQueryString();
this.secure = httpRequest.isSecure();
this.request = negotiation.getRequest();
this.queryString = request.getQueryString();
this.secure = request.isSecure();
try
{
// TODO why is this URL and not URI?
StringBuffer uri = httpRequest.getRequestURL();
// WHY?
StringBuffer uri = request.getRequestURL();
if (this.queryString != null)
uri.append("?").append(this.queryString);
uri.replace(0, uri.indexOf(":"), secure ? "wss" : "ws");
this.requestURI = new URI(uri.toString());
this.request = new UpgradeHttpServletRequest(httpRequest);
}
catch (Throwable t)
{
@ -88,17 +86,9 @@ public class ServerUpgradeRequest
{
if (cookies == null)
{
Cookie[] requestCookies = request.getCookies();
if (requestCookies != null)
{
cookies = new ArrayList<>();
for (Cookie requestCookie : requestCookies)
{
HttpCookie cookie = new HttpCookie(requestCookie.getName(), requestCookie.getValue());
// No point handling domain/path/expires/secure/httponly on client request cookies
cookies.add(cookie);
}
}
cookies = Arrays.stream(request.getCookies())
.map(c -> new HttpCookie(c.getName(), c.getValue()))
.collect(Collectors.toList());
}
return cookies;
@ -130,12 +120,7 @@ public class ServerUpgradeRequest
*/
public int getHeaderInt(String name)
{
String val = request.getHeader(name);
if (val == null)
{
return -1;
}
return Integer.parseInt(val);
return request.getIntHeader(name);
}
/**
@ -144,7 +129,14 @@ public class ServerUpgradeRequest
*/
public Map<String, List<String>> getHeadersMap()
{
return request.getHeaders();
Map<String, List<String>> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements())
{
String name = headerNames.nextElement();
headers.put(name, Collections.list(request.getHeaders(name)));
}
return headers;
}
/**
@ -154,7 +146,10 @@ public class ServerUpgradeRequest
*/
public List<String> getHeaders(String name)
{
return request.getHeaders().get(name);
Enumeration<String> headers = request.getHeaders(name);
if (headers == null || !headers.hasMoreElements())
return null;
return Collections.list(headers);
}
/**
@ -163,7 +158,6 @@ public class ServerUpgradeRequest
*/
public String getHost()
{
// TODO why is this not HttpServletRequest#getHost ?
return requestURI.getHost();
}
@ -209,7 +203,7 @@ public class ServerUpgradeRequest
*/
public SocketAddress getLocalSocketAddress()
{
// TODO: fix when HttpServletRequest can use Unix Socket stuff
// TODO: fix when HttpServletRequest can use Unix Socket stuff.
return new InetSocketAddress(request.getLocalAddr(), request.getLocalPort());
}
@ -326,11 +320,17 @@ public class ServerUpgradeRequest
/**
* @return Request attribute map
* @see UpgradeHttpServletRequest#getAttributes()
*/
public Map<String, Object> getServletAttributes()
{
return request.getAttributes();
Map<String, Object> attributes = new HashMap<>(2);
Enumeration<String> attributeNames = request.getAttributeNames();
while (attributeNames.hasMoreElements())
{
String name = attributeNames.nextElement();
attributes.put(name, request.getAttribute(name));
}
return attributes;
}
/**
@ -377,9 +377,7 @@ public class ServerUpgradeRequest
for (String protocol : getSubProtocols())
{
if (protocol.equalsIgnoreCase(subprotocol))
{
return true;
}
}
return false;
}

View File

@ -59,7 +59,11 @@ public abstract class AbstractHandshaker implements Handshaker
if (!validateRequest(request))
return false;
WebSocketNegotiation negotiation = newNegotiation(request, response, components);
// After negotiation these can be set to copy data from request and disable unavailable methods.
UpgradeHttpServletRequest upgradeRequest = new UpgradeHttpServletRequest(request);
UpgradeHttpServletResponse upgradeResponse = new UpgradeHttpServletResponse(response);
WebSocketNegotiation negotiation = newNegotiation(upgradeRequest, upgradeResponse, components);
if (LOG.isDebugEnabled())
LOG.debug("negotiation {}", negotiation);
negotiation.negotiate();
@ -127,7 +131,7 @@ public abstract class AbstractHandshaker implements Handshaker
Negotiated negotiated = new Negotiated(baseRequest.getHttpURI().toURI(), protocol, baseRequest.isSecure(), extensionStack, WebSocketConstants.SPEC_VERSION_STRING);
// Create the Session
WebSocketCoreSession coreSession = newWebSocketCoreSession(request, handler, negotiated, components);
WebSocketCoreSession coreSession = newWebSocketCoreSession(upgradeRequest, handler, negotiated, components);
if (defaultCustomizer != null)
defaultCustomizer.customize(coreSession);
negotiator.customize(coreSession);
@ -159,6 +163,10 @@ public abstract class AbstractHandshaker implements Handshaker
baseRequest.setAttribute(HttpTransport.UPGRADE_CONNECTION_ATTRIBUTE, connection);
// Save state from request/response and remove reference to the base request/response.
upgradeRequest.upgrade();
upgradeResponse.upgrade();
if (LOG.isDebugEnabled())
LOG.debug("upgrade connection={} session={} framehandler={}", connection, coreSession, handler);

View File

@ -49,9 +49,10 @@ import org.eclipse.jetty.server.UserIdentity;
*/
public class UpgradeHttpServletRequest implements HttpServletRequest
{
private static final String UNSUPPORTED_WITH_WEBSOCKET_UPGRADE = "Feature unsupported with a Upgraded to WebSocket HttpServletRequest";
private static final String UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE = "Feature unsupported after Upgraded to WebSocket";
private HttpServletRequest request;
private final Request baseRequest;
private final ServletContext context;
private final DispatcherType dispatcher;
private final String method;
@ -88,6 +89,8 @@ public class UpgradeHttpServletRequest implements HttpServletRequest
{
// 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();
@ -107,7 +110,7 @@ public class UpgradeHttpServletRequest implements HttpServletRequest
remoteUser = httpRequest.getRemoteUser();
principal = httpRequest.getUserPrincipal();
baseRequest = Objects.requireNonNull(Request.getBaseRequest(httpRequest));
Request baseRequest = Objects.requireNonNull(Request.getBaseRequest(httpRequest));
authentication = baseRequest.getAuthentication();
scope = baseRequest.getUserIdentityScope();
@ -120,13 +123,6 @@ public class UpgradeHttpServletRequest implements HttpServletRequest
parameters.putAll(httpRequest.getParameterMap());
Enumeration<String> attributeNames = httpRequest.getAttributeNames();
while (attributeNames.hasMoreElements())
{
String name = attributeNames.nextElement();
attributes.put(name, httpRequest.getAttribute(name));
}
Enumeration<Locale> localeElements = httpRequest.getLocales();
while (localeElements.hasMoreElements())
{
@ -140,6 +136,23 @@ public class UpgradeHttpServletRequest implements HttpServletRequest
serverAddress = InetSocketAddress.createUnresolved(httpRequest.getServerName(), httpRequest.getServerPort());
}
public void upgrade()
{
Enumeration<String> attributeNames = request.getAttributeNames();
while (attributeNames.hasMoreElements())
{
String name = attributeNames.nextElement();
attributes.put(name, request.getAttribute(name));
}
request = null;
}
public HttpServletRequest getHttpServletRequest()
{
return request;
}
@Override
public String getAuthType()
{
@ -184,13 +197,13 @@ public class UpgradeHttpServletRequest implements HttpServletRequest
@Override
public long getDateHeader(String name)
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public int getIntHeader(String name)
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
@ -234,7 +247,6 @@ public class UpgradeHttpServletRequest implements HttpServletRequest
{
if (authentication instanceof Authentication.User)
return ((Authentication.User)authentication).isUserInRole(scope, role);
return false;
}
@ -265,8 +277,8 @@ public class UpgradeHttpServletRequest implements HttpServletRequest
@Override
public HttpSession getSession(boolean create)
{
if (create)
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
if (create && (session == null))
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
return session;
}
@ -276,56 +288,50 @@ public class UpgradeHttpServletRequest implements HttpServletRequest
return session;
}
public Request getBaseRequest()
{
return baseRequest;
}
@Override
public String getRequestedSessionId()
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public boolean isRequestedSessionIdValid()
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public boolean isRequestedSessionIdFromCookie()
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public boolean isRequestedSessionIdFromURL()
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public boolean isRequestedSessionIdFromUrl()
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public Object getAttribute(String name)
{
return attributes.get(name);
if (request == null)
return attributes.get(name);
return request.getAttribute(name);
}
@Override
public Enumeration<String> getAttributeNames()
{
return Collections.enumeration(attributes.keySet());
}
public Map<String, Object> getAttributes()
{
return Collections.unmodifiableMap(attributes);
if (request == null)
return Collections.enumeration(attributes.keySet());
return request.getAttributeNames();
}
@Override
@ -400,13 +406,17 @@ public class UpgradeHttpServletRequest implements HttpServletRequest
@Override
public void setAttribute(String name, Object value)
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
if (request == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
request.setAttribute(name, value);
}
@Override
public void removeAttribute(String name)
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
if (request == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
request.removeAttribute(name);
}
@Override
@ -468,73 +478,73 @@ public class UpgradeHttpServletRequest implements HttpServletRequest
@Override
public boolean authenticate(HttpServletResponse response)
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public String changeSessionId()
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public AsyncContext getAsyncContext()
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public String getCharacterEncoding()
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public int getContentLength()
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public long getContentLengthLong()
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public String getContentType()
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public ServletInputStream getInputStream()
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public Part getPart(String name)
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public Collection<Part> getParts()
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public BufferedReader getReader()
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public RequestDispatcher getRequestDispatcher(String path)
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
@ -552,36 +562,36 @@ public class UpgradeHttpServletRequest implements HttpServletRequest
@Override
public void login(String username, String password)
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public void logout()
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public void setCharacterEncoding(String enc)
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public AsyncContext startAsync() throws IllegalStateException
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
@Override
public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass)
{
throw new UnsupportedOperationException(UNSUPPORTED_WITH_WEBSOCKET_UPGRADE);
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
}
}

View File

@ -0,0 +1,367 @@
//
// ========================================================================
// Copyright (c) 1995-2021 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.websocket.core.server.internal;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
public class UpgradeHttpServletResponse implements HttpServletResponse
{
private static final String UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE = "Feature unsupported after Upgraded to WebSocket";
private HttpServletResponse _response;
private int _status;
private Map<String, Collection<String>> _headers;
private Locale _locale;
private String _characterEncoding;
private String _contentType;
public UpgradeHttpServletResponse(HttpServletResponse response)
{
_response = response;
}
public void upgrade()
{
_status = _response.getStatus();
_locale = _response.getLocale();
_characterEncoding = _response.getCharacterEncoding();
_contentType = _response.getContentType();
_headers = new HashMap<>();
for (String name : _response.getHeaderNames())
{
_headers.put(name, _response.getHeaders(name));
}
_response = null;
}
public HttpServletResponse getResponse()
{
return _response;
}
@Override
public int getStatus()
{
if (_response == null)
return _status;
return _response.getStatus();
}
@Override
public String getHeader(String s)
{
if (_response == null)
{
Collection<String> values = _headers.get(s);
if (values == null)
return null;
return values.stream().findFirst().orElse(null);
}
return _response.getHeader(s);
}
@Override
public Collection<String> getHeaders(String s)
{
if (_response == null)
return _headers.get(s);
return _response.getHeaders(s);
}
@Override
public Collection<String> getHeaderNames()
{
if (_response == null)
return _headers.keySet();
return _response.getHeaderNames();
}
@Override
public Locale getLocale()
{
if (_response == null)
return _locale;
return _response.getLocale();
}
@Override
public boolean containsHeader(String s)
{
if (_response == null)
{
Collection<String> values = _headers.get(s);
return values != null && !values.isEmpty();
}
return _response.containsHeader(s);
}
@Override
public String getCharacterEncoding()
{
if (_response == null)
return _characterEncoding;
return _response.getCharacterEncoding();
}
@Override
public String getContentType()
{
if (_response == null)
return _contentType;
return _response.getContentType();
}
@Override
public void addCookie(Cookie cookie)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.addCookie(cookie);
}
@Override
public String encodeURL(String s)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
return _response.encodeURL(s);
}
@Override
public String encodeRedirectURL(String s)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
return _response.encodeRedirectURL(s);
}
@Override
public String encodeUrl(String s)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
return _response.encodeUrl(s);
}
@Override
public String encodeRedirectUrl(String s)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
return _response.encodeRedirectUrl(s);
}
@Override
public ServletOutputStream getOutputStream() throws IOException
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
return _response.getOutputStream();
}
@Override
public PrintWriter getWriter() throws IOException
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
return _response.getWriter();
}
@Override
public void setCharacterEncoding(String s)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.setCharacterEncoding(s);
}
@Override
public void setContentLength(int i)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.setContentLength(i);
}
@Override
public void setContentLengthLong(long l)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.setContentLengthLong(l);
}
@Override
public void setContentType(String s)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.setContentType(s);
}
@Override
public void setBufferSize(int i)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.setBufferSize(i);
}
@Override
public int getBufferSize()
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
return _response.getBufferSize();
}
@Override
public void flushBuffer() throws IOException
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.flushBuffer();
}
@Override
public void resetBuffer()
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.resetBuffer();
}
@Override
public boolean isCommitted()
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
return _response.isCommitted();
}
@Override
public void reset()
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.reset();
}
@Override
public void setLocale(Locale locale)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.setLocale(locale);
}
@Override
public void sendError(int sc, String msg) throws IOException
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.sendError(sc, msg);
}
@Override
public void sendError(int sc) throws IOException
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.sendError(sc);
}
@Override
public void setHeader(String name, String value)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.setHeader(name, value);
}
@Override
public void sendRedirect(String s) throws IOException
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.sendRedirect(s);
}
@Override
public void setDateHeader(String s, long l)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.setDateHeader(s, l);
}
@Override
public void addDateHeader(String s, long l)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.addDateHeader(s, l);
}
@Override
public void addHeader(String name, String value)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.addHeader(name, value);
}
@Override
public void setIntHeader(String s, int i)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.setIntHeader(s, i);
}
@Override
public void addIntHeader(String s, int i)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.addIntHeader(s, i);
}
@Override
public void setStatus(int i)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.setStatus(i);
}
@Override
public void setStatus(int i, String s)
{
if (_response == null)
throw new UnsupportedOperationException(UNSUPPORTED_AFTER_WEBSOCKET_UPGRADE);
_response.setStatus(i, s);
}
}

View File

@ -37,6 +37,7 @@ import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -50,6 +51,7 @@ import org.testcontainers.utility.MountableFile;
import static org.junit.jupiter.api.Assertions.assertTrue;
@Disabled
@Testcontainers
public class AutobahnTests
{

View File

@ -124,9 +124,8 @@ public class JettyWebSocketServerContainer extends ContainerLifeCycle implements
throw new WebSocketException("Duplicate WebSocket Mapping for PathSpec");
WebSocketUpgradeFilter.ensureFilter(contextHandler.getServletContext());
webSocketMappings.addMapping(ps,
(req, resp) -> creator.createWebSocket(new DelegatedServerUpgradeRequest(req), new DelegatedServerUpgradeResponse(resp)),
frameHandlerFactory, customizer);
WebSocketCreator coreCreator = (req, resp) -> creator.createWebSocket(new DelegatedServerUpgradeRequest(req), new DelegatedServerUpgradeResponse(resp));
webSocketMappings.addMapping(ps, coreCreator, frameHandlerFactory, customizer);
}
public void addMapping(String pathSpec, final Class<?> endpointClass)

View File

@ -0,0 +1,90 @@
//
// ========================================================================
// Copyright (c) 1995-2021 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.websocket.tests;
import java.net.URI;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.jetty.websocket.server.JettyServerUpgradeRequest;
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class JettyWebSocketServletAttributeTest
{
private Server server;
private ServerConnector connector;
private WebSocketClient client;
private final EchoSocket serverEndpoint = new EchoSocket();
@BeforeEach
public void before()
{
server = new Server();
connector = new ServerConnector(server);
server.addConnector(connector);
client = new WebSocketClient();
}
@AfterEach
public void stop() throws Exception
{
client.stop();
server.stop();
}
public void start(JettyWebSocketServletContainerInitializer.Configurator configurator) throws Exception
{
ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
contextHandler.setContextPath("/");
server.setHandler(contextHandler);
JettyWebSocketServletContainerInitializer.configure(contextHandler, configurator);
server.start();
client.start();
}
@Test
public void testAttributeSetInNegotiation() throws Exception
{
start((context, container) -> container.addMapping("/", (req, resp) ->
{
req.setServletAttribute("myWebSocketCustomAttribute", "true");
return serverEndpoint;
}));
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + "/filterPath");
EventSocket clientEndpoint = new EventSocket();
client.connect(clientEndpoint, uri);
assertTrue(clientEndpoint.openLatch.await(5, TimeUnit.SECONDS));
assertTrue(serverEndpoint.openLatch.await(5, TimeUnit.SECONDS));
// We should have our custom attribute on the upgraded request, which was set in the negotiation.
JettyServerUpgradeRequest upgradeRequest = (JettyServerUpgradeRequest)serverEndpoint.session.getUpgradeRequest();
assertThat(upgradeRequest.getServletAttribute("myWebSocketCustomAttribute"), is("true"));
clientEndpoint.session.close();
assertTrue(clientEndpoint.closeLatch.await(5, TimeUnit.SECONDS));
}
}

View File

@ -347,8 +347,8 @@ public class WebSocketOverHTTP2Test
});
factory.addMapping("/ws/connectionClose", (request, response) ->
{
UpgradeHttpServletRequest servletRequest = (UpgradeHttpServletRequest)request.getHttpServletRequest();
Request baseRequest = servletRequest.getBaseRequest();
UpgradeHttpServletRequest upgradeRequest = (UpgradeHttpServletRequest)request.getHttpServletRequest();
Request baseRequest = (Request)upgradeRequest.getHttpServletRequest();
baseRequest.getHttpChannel().getEndPoint().close();
return new EchoSocket();
});