diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketClientExtensionHandler.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketClientExtensionHandler.java index 47073a7b23..165c1cdfc8 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketClientExtensionHandler.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketClientExtensionHandler.java @@ -63,15 +63,14 @@ public class WebSocketClientExtensionHandler extends ChannelDuplexHandler { if (msg instanceof HttpRequest && WebSocketExtensionUtil.isWebsocketUpgrade(((HttpRequest) msg).headers())) { HttpRequest request = (HttpRequest) msg; String headerValue = request.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS); - List extraExtensions = - new ArrayList(extensionHandshakers.size()); - for (WebSocketClientExtensionHandshaker extensionHandshaker : extensionHandshakers) { - extraExtensions.add(extensionHandshaker.newRequestData()); - } - String newHeaderValue = WebSocketExtensionUtil - .computeMergeExtensionsHeaderValue(headerValue, extraExtensions); - request.headers().set(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS, newHeaderValue); + for (WebSocketClientExtensionHandshaker extensionHandshaker : extensionHandshakers) { + WebSocketExtensionData extensionData = extensionHandshaker.newRequestData(); + headerValue = WebSocketExtensionUtil.appendExtension(headerValue, + extensionData.name(), extensionData.parameters()); + } + + request.headers().set(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS, headerValue); } super.write(ctx, msg, promise); diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketExtensionUtil.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketExtensionUtil.java index 01f1c0036c..567e49e6bf 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketExtensionUtil.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketExtensionUtil.java @@ -72,53 +72,25 @@ public final class WebSocketExtensionUtil { } } - static String computeMergeExtensionsHeaderValue(String userDefinedHeaderValue, - List extraExtensions) { - List userDefinedExtensions = - userDefinedHeaderValue != null ? - extractExtensions(userDefinedHeaderValue) : - Collections.emptyList(); + static String appendExtension(String currentHeaderValue, String extensionName, + Map extensionParameters) { - for (WebSocketExtensionData userDefined: userDefinedExtensions) { - WebSocketExtensionData matchingExtra = null; - int i; - for (i = 0; i < extraExtensions.size(); i ++) { - WebSocketExtensionData extra = extraExtensions.get(i); - if (extra.name().equals(userDefined.name())) { - matchingExtra = extra; - break; - } - } - if (matchingExtra == null) { - extraExtensions.add(userDefined); - } else { - // merge with higher precedence to user defined parameters - Map mergedParameters = new HashMap(matchingExtra.parameters()); - mergedParameters.putAll(userDefined.parameters()); - extraExtensions.set(i, new WebSocketExtensionData(matchingExtra.name(), mergedParameters)); + StringBuilder newHeaderValue = new StringBuilder( + currentHeaderValue != null ? currentHeaderValue.length() : extensionName.length() + 1); + if (currentHeaderValue != null && !currentHeaderValue.trim().isEmpty()) { + newHeaderValue.append(currentHeaderValue); + newHeaderValue.append(EXTENSION_SEPARATOR); + } + newHeaderValue.append(extensionName); + for (Entry extensionParameter : extensionParameters.entrySet()) { + newHeaderValue.append(PARAMETER_SEPARATOR); + newHeaderValue.append(extensionParameter.getKey()); + if (extensionParameter.getValue() != null) { + newHeaderValue.append(PARAMETER_EQUAL); + newHeaderValue.append(extensionParameter.getValue()); } } - - StringBuilder sb = new StringBuilder(150); - - for (WebSocketExtensionData data: extraExtensions) { - sb.append(data.name()); - for (Entry parameter : data.parameters().entrySet()) { - sb.append(PARAMETER_SEPARATOR); - sb.append(parameter.getKey()); - if (parameter.getValue() != null) { - sb.append(PARAMETER_EQUAL); - sb.append(parameter.getValue()); - } - } - sb.append(EXTENSION_SEPARATOR); - } - - if (!extraExtensions.isEmpty()) { - sb.setLength(sb.length() - EXTENSION_SEPARATOR.length()); - } - - return sb.toString(); + return newHeaderValue.toString(); } private WebSocketExtensionUtil() { diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketServerExtensionHandler.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketServerExtensionHandler.java index e00090bb79..9e45bcfa63 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketServerExtensionHandler.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketServerExtensionHandler.java @@ -124,13 +124,13 @@ public class WebSocketServerExtensionHandler extends ChannelDuplexHandler { if (validExtensions != null) { String headerValue = headers.getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS); - List extraExtensions = - new ArrayList(extensionHandshakers.size()); + for (WebSocketServerExtension extension : validExtensions) { - extraExtensions.add(extension.newReponseData()); + WebSocketExtensionData extensionData = extension.newReponseData(); + headerValue = WebSocketExtensionUtil.appendExtension(headerValue, + extensionData.name(), + extensionData.parameters()); } - String newHeaderValue = WebSocketExtensionUtil - .computeMergeExtensionsHeaderValue(headerValue, extraExtensions); promise.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) { @@ -148,7 +148,7 @@ public class WebSocketServerExtensionHandler extends ChannelDuplexHandler { }); if (headerValue != null) { - headers.set(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS, newHeaderValue); + headers.set(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS, headerValue); } } diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketExtensionUtilTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketExtensionUtilTest.java index eab3b3ba46..12aa06ed66 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketExtensionUtilTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketExtensionUtilTest.java @@ -21,63 +21,19 @@ import io.netty.handler.codec.http.HttpHeaderValues; import io.netty.handler.codec.http.HttpHeaders; import org.junit.Test; -import java.util.List; - import static org.junit.Assert.*; -import static io.netty.handler.codec.http.websocketx.extensions.WebSocketExtensionUtil.*; public class WebSocketExtensionUtilTest { @Test public void testIsWebsocketUpgrade() { HttpHeaders headers = new DefaultHttpHeaders(); - assertFalse(isWebsocketUpgrade(headers)); + assertFalse(WebSocketExtensionUtil.isWebsocketUpgrade(headers)); headers.add(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET); - assertFalse(isWebsocketUpgrade(headers)); + assertFalse(WebSocketExtensionUtil.isWebsocketUpgrade(headers)); headers.add(HttpHeaderNames.CONNECTION, "Keep-Alive, Upgrade"); - assertTrue(isWebsocketUpgrade(headers)); - } - - @Test - public void computeMergeExtensionsHeaderValueWhenNoUserDefinedHeader() { - List extras = extractExtensions("permessage-deflate; client_max_window_bits," + - "permessage-deflate; client_no_context_takeover; client_max_window_bits," + - "deflate-frame," + - "x-webkit-deflate-frame"); - String newHeaderValue = computeMergeExtensionsHeaderValue(null, extras); - assertEquals("permessage-deflate;client_max_window_bits," + - "permessage-deflate;client_no_context_takeover;client_max_window_bits," + - "deflate-frame," + - "x-webkit-deflate-frame", newHeaderValue); - } - - @Test - public void computeMergeExtensionsHeaderValueWhenNoConflictingUserDefinedHeader() { - List extras = extractExtensions("permessage-deflate; client_max_window_bits," + - "permessage-deflate; client_no_context_takeover; client_max_window_bits," + - "deflate-frame," + - "x-webkit-deflate-frame"); - String newHeaderValue = computeMergeExtensionsHeaderValue("foo, bar", extras); - assertEquals("permessage-deflate;client_max_window_bits," + - "permessage-deflate;client_no_context_takeover;client_max_window_bits," + - "deflate-frame," + - "x-webkit-deflate-frame," + - "foo," + - "bar", newHeaderValue); - } - - @Test - public void computeMergeExtensionsHeaderValueWhenConflictingUserDefinedHeader() { - List extras = extractExtensions("permessage-deflate; client_max_window_bits," + - "permessage-deflate; client_no_context_takeover; client_max_window_bits," + - "deflate-frame," + - "x-webkit-deflate-frame"); - String newHeaderValue = computeMergeExtensionsHeaderValue("permessage-deflate; client_max_window_bits", extras); - assertEquals("permessage-deflate;client_max_window_bits," + - "permessage-deflate;client_no_context_takeover;client_max_window_bits," + - "deflate-frame," + - "x-webkit-deflate-frame", newHeaderValue); + assertTrue(WebSocketExtensionUtil.isWebsocketUpgrade(headers)); } }