Affects: \5.3.3
In spring, one can add an undertow websocket extension by:
@Bean
public WebServerFactoryCustomizer<UndertowServletWebServerFactory> deploymentCustomizer() {
return factory -> {
UndertowDeploymentInfoCustomizer customizer = deploymentInfo -> {
WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo();
webSocketDeploymentInfo.addExtension(new PerMessageDeflateHandshake());
deploymentInfo.addServletContextAttribute(WebSocketDeploymentInfo.ATTRIBUTE_NAME, webSocketDeploymentInfo);
};
factory.addDeploymentInfoCustomizers(customizer);
};
}
But that extension does not work when processing requests. I have found that spring wraps extensions in org.springframework.web.socket.server.standard.AbstractStandardUpgradeStrategy.getInstalledExtensions(...)
protected List<WebSocketExtension> getInstalledExtensions(WebSocketContainer container) {
List<WebSocketExtension> result = new ArrayList<>();
for (Extension extension : container.getInstalledExtensions()) {
result.add(new StandardToWebSocketExtensionAdapter(extension));
}
return result;
}
which breaks the extension matching in
org.springframework.web.socket.server.support.filterRequestedExtensions(...)
protected List<WebSocketExtension> filterRequestedExtensions(ServerHttpRequest request,
List<WebSocketExtension> requestedExtensions, List<WebSocketExtension> supportedExtensions) {
List<WebSocketExtension> result = new ArrayList<>(requestedExtensions.size());
for (WebSocketExtension extension : requestedExtensions) {
if (supportedExtensions.contains(extension)) {
result.add(extension);
}
}
return result;
}
I have been unable to find a workaround for this, and I am not sure what an appropriate fix would be.
Comment From: rstoyanchev
How does it break? Does it not find the installed extensions or something in the equals() of the wrapper?
Comment From: piotrblasiak
@rstoyanchev it finds the installed extension but it wraps it in a StandardToWebSocketExtensionAdapter, which makes the filterRequestedExtensions method not include it in the final list of extensions to apply to the request. I am thinking perhaps it should not be wrapped or the filterRequestedExtensions could be changed to filter by name and not Collection.contains().
Comment From: rstoyanchev
Okay so WebSocketExtension
has an equals
method but the getClass()
check would fail to match, WebSocketExtension
for the requested vs StandardToWebSocketExtensionAdapter
for the installed.
Comment From: rstoyanchev
I'll add a fix. A workaround could be to override getInstalledExtensions
and return WebSocketExtension
instances and plug the RequestUpgradeStrategy
into the DefaultHandshakeHandler
.
Comment From: rstoyanchev
@piotrblasiak I've committed a fix if you'd like to check it with a 5.3.4-SNAPSHOT in your codebase.
Comment From: piotrblasiak
@rstoyanchev I can confirm it has been fixed and it is now working as expected. Thank you!
Comment From: rstoyanchev
Great, thanks for testing it! I will now backport it to 5.2.x.