Issue #5868 - allow request attributes to be set during websocket handshake
Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
parent
5b97d91f59
commit
2ac50130d6
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue