ASF Bugzilla – Attachment 35193 Details for
Bug 57767
Websocket client proprietary configuration
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
websocket upgrade redirect
.patch (text/plain), 8.57 KB, created by
J Fernandez
on 2017-08-01 02:42:35 UTC
(
hide
)
Description:
websocket upgrade redirect
Filename:
MIME Type:
Creator:
J Fernandez
Created:
2017-08-01 02:42:35 UTC
Size:
8.57 KB
patch
obsolete
>Index: java/org/apache/tomcat/websocket/Constants.java >=================================================================== >--- java/org/apache/tomcat/websocket/Constants.java (revision 1803605) >+++ java/org/apache/tomcat/websocket/Constants.java (working copy) >@@ -80,11 +80,20 @@ > public static final String ORIGIN_HEADER_NAME = "Origin"; > public static final String CONNECTION_HEADER_NAME = "Connection"; > public static final String CONNECTION_HEADER_VALUE = "upgrade"; >+ public static final String LOCATION_HEADER_NAME = "Location"; > public static final String WS_VERSION_HEADER_NAME = "Sec-WebSocket-Version"; > public static final String WS_VERSION_HEADER_VALUE = "13"; > public static final String WS_KEY_HEADER_NAME = "Sec-WebSocket-Key"; > public static final String WS_PROTOCOL_HEADER_NAME = "Sec-WebSocket-Protocol"; > public static final String WS_EXTENSIONS_HEADER_NAME = "Sec-WebSocket-Extensions"; >+ >+ /// HTTP redirection status codes >+ public static final int MULTIPLE_CHOICES = 300; >+ public static final int MOVED_PERMANENTLY = 301; >+ public static final int FOUND = 302; >+ public static final int SEE_OTHER = 303; >+ public static final int USE_PROXY = 305; >+ public static final int TEMPORARY_REDIRECT = 307; > > // Configuration for Origin header in client > static final String DEFAULT_ORIGIN_HEADER_VALUE = >@@ -115,6 +124,12 @@ > // Configuration for stream behavior > static final boolean STREAMS_DROP_EMPTY_MESSAGES = > Boolean.getBoolean("org.apache.tomcat.websocket.STREAMS_DROP_EMPTY_MESSAGES"); >+ >+ static final boolean REDIRECT_ENABLED = Boolean.getBoolean("org.apache.tomcat.websocket.REDIRECT_ENABLED"); >+ >+ //RFC 2616 recommends a maximum of 5 redirections >+ static final int MAX_REDIRECTIONS = >+ Integer.getInteger("org.apache.tomcat.websocket.MAX_REDIRECTIONS",5).intValue(); > > public static final boolean STRICT_SPEC_COMPLIANCE = > Boolean.getBoolean( >Index: java/org/apache/tomcat/websocket/LocalStrings.properties >=================================================================== >--- java/org/apache/tomcat/websocket/LocalStrings.properties (revision 1803605) >+++ java/org/apache/tomcat/websocket/LocalStrings.properties (working copy) >@@ -136,3 +136,6 @@ > wsWebSocketContainer.proxyConnectFail=Failed to connect to the configured Proxy [{0}]. The HTTP response code was [{1}] > wsWebSocketContainer.sessionCloseFail=Session with ID [{0}] did not close cleanly > wsWebSocketContainer.sslEngineFail=Unable to create SSLEngine to support SSL/TLS connections >+wsWebSocketContainer.redirectDisabled=Failed to handle HTTP response code [{0}]. HTTP redirection is disabled >+wsWebSocketContainer.missingLocationHeader=Failed to handle HTTP response code [{0}]. Missing Location header in response >+wsWebSocketContainer.redirectThreshold=Cyclic Location header [{0}] detected / reached max number of redirects [{1}] of max [{2}] >\ No newline at end of file >Index: java/org/apache/tomcat/websocket/WsWebSocketContainer.java >=================================================================== >--- java/org/apache/tomcat/websocket/WsWebSocketContainer.java (revision 1803605) >+++ java/org/apache/tomcat/websocket/WsWebSocketContainer.java (working copy) >@@ -26,6 +26,7 @@ > import java.net.ProxySelector; > import java.net.SocketAddress; > import java.net.URI; >+import java.net.URISyntaxException; > import java.nio.ByteBuffer; > import java.nio.channels.AsynchronousChannelGroup; > import java.nio.channels.AsynchronousSocketChannel; >@@ -98,6 +99,7 @@ > private volatile long defaultMaxSessionIdleTimeout = 0; > private int backgroundProcessCount = 0; > private int processPeriod = Constants.DEFAULT_PROCESS_PERIOD; >+ private final Set<URI> redirectSet = new HashSet<>(Constants.MAX_REDIRECTIONS); > > private InstanceManager instanceManager; > >@@ -340,8 +342,47 @@ > writeRequest(channel, request, timeout); > > HttpResponse httpResponse = processResponse(response, channel, timeout); >- // TODO: Handle redirects >- if (httpResponse.status != 101) { >+ >+ if (httpResponse.status != 101) { >+ if(isRedirectStatus(httpResponse.status)){ >+ if (!Constants.REDIRECT_ENABLED) { >+ throw new DeploymentException(sm.getString("wsWebSocketContainer.redirectDisabled", >+ Integer.toString(httpResponse.status))); >+ } >+ >+ List<String> locationHeader = httpResponse.getHandshakeResponse().getHeaders() >+ .get(Constants.LOCATION_HEADER_NAME); >+ >+ if (locationHeader == null || locationHeader.isEmpty() || locationHeader.get(0) == null >+ || locationHeader.get(0).isEmpty()) { >+ throw new DeploymentException(sm.getString("wsWebSocketContainer.missingLocationHeader", >+ Integer.toString(httpResponse.status))); >+ } >+ >+ URI redirectLocation = URI.create(locationHeader.get(0)).normalize(); >+ >+ if (!redirectLocation.isAbsolute()) { >+ redirectLocation = path.resolve(redirectLocation); >+ } >+ >+ String redirectScheme = redirectLocation.getScheme().toLowerCase(); >+ >+ if (redirectScheme.startsWith("http")) { >+ redirectLocation = new URI(redirectScheme.replace("http", "ws"), >+ redirectLocation.getUserInfo(), redirectLocation.getHost(), >+ redirectLocation.getPort(), redirectLocation.getPath(), >+ redirectLocation.getQuery(), redirectLocation.getFragment()); >+ } >+ >+ if (!redirectSet.add(redirectLocation) || redirectSet.size() > Constants.MAX_REDIRECTIONS) { >+ throw new DeploymentException(sm.getString("wsWebSocketContainer.redirectThreshold", >+ redirectLocation, Integer.toString(redirectSet.size()), >+ Integer.toString(Constants.MAX_REDIRECTIONS))); >+ } >+ >+ return connectToServer(endpoint, clientEndpointConfiguration, redirectLocation); >+ >+ } > throw new DeploymentException(sm.getString("wsWebSocketContainer.invalidStatus", > Integer.toString(httpResponse.status))); > } >@@ -390,7 +431,7 @@ > > success = true; > } catch (ExecutionException | InterruptedException | SSLException | >- EOFException | TimeoutException e) { >+ EOFException | TimeoutException | URISyntaxException e) { > throw new DeploymentException( > sm.getString("wsWebSocketContainer.httpRequestFailed"), e); > } finally { >@@ -446,8 +487,28 @@ > toWrite -= thisWrite.intValue(); > } > } >+ >+ >+ private static boolean isRedirectStatus(int httpResponseCode) { > >+ boolean isRedirect = false; > >+ switch (httpResponseCode) { >+ case Constants.MULTIPLE_CHOICES: >+ case Constants.MOVED_PERMANENTLY: >+ case Constants.FOUND: >+ case Constants.SEE_OTHER: >+ case Constants.USE_PROXY: >+ case Constants.TEMPORARY_REDIRECT: >+ isRedirect = true; >+ break; >+ default: >+ break; >+ } >+ >+ return isRedirect; >+ } >+ > private static ByteBuffer createProxyRequest(String host, int port) { > StringBuilder request = new StringBuilder(); > request.append("CONNECT "); >Index: test/org/apache/tomcat/websocket/TestWebSocketFrameClient.java >=================================================================== >--- test/org/apache/tomcat/websocket/TestWebSocketFrameClient.java (revision 1803605) >+++ test/org/apache/tomcat/websocket/TestWebSocketFrameClient.java (working copy) >@@ -82,6 +82,8 @@ > @Test > public void testConnectToRootEndpoint() throws Exception { > >+ System.setProperty("org.apache.tomcat.websocket.REDIRECT_ENABLED", "true"); >+ > Tomcat tomcat = getTomcatInstance(); > // No file system docBase required > Context ctx = tomcat.addContext("", null); >@@ -94,14 +96,10 @@ > ctx2.addServletMappingDecoded("/", "default"); > > tomcat.start(); >- >+ > echoTester(""); > echoTester("/"); >- // FIXME: The ws client doesn't handle any response other than the upgrade, >- // which may or may not be allowed. In that case, the server will return >- // a redirect to the root of the webapp to avoid possible broken relative >- // paths. >- // echoTester("/foo"); >+ echoTester("/foo"); > echoTester("/foo/"); > } >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 57767
: 35193 |
35289