在Spring Boot中如何禁用Tomcat的permessage-deflate WebSocket压缩?

5
我有一个Spring Boot服务器,我希望能够与无法处理permessage-deflate压缩消息的websocket客户端进行通信。我知道从以下两个类似主题的问题(下面链接),我可以添加VM参数-Dorg.apache.tomcat.websocket.DISABLE_BUILTIN_EXTENSIONS=true来禁用Tomcat的默认deflate压缩。 然而,我计划制作一个程序,让其他人也可以运行它,并且强迫他们始终包含特定的VM参数来更改设置似乎非常粗暴。
是否有一些替代方法来禁用Tomcat的websocket压缩,而不需要用户在运行时指定VM参数,例如使用Spring的Java配置或自定义websocket握手拦截器?
2个回答

2

您不仅可以使用JVM参数设置属性,还可以通过编程方式使用System.setProperty设置属性,如下所示:

System.setProperty("org.apache.tomcat.websocket.DISABLE_BUILTIN_EXTENSIONS",String.valueOf(true));

如果您使用嵌入式Tomcat将项目导出到JAR文件中,您可以在执行SpringApplication.run之前在main中运行它:

public static void main(String[] args) {
    System.setProperty("org.apache.tomcat.websocket.DISABLE_BUILTIN_EXTENSIONS",String.valueOf(true));
    SpringApplication.run(YourApplicationClass.class,args);
}

如果您将应用程序打包成WAR文件,可以尝试以下操作:
@SpringBootApplication
public class YourApplicationClass extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        System.setProperty("org.apache.tomcat.websocket.DISABLE_BUILTIN_EXTENSIONS",String.valueOf(true));
        return application.sources(YourApplicationClass.class);
    } 
} 

1
在Tomcat 10.1中,DISABLE_BUILTIN_EXTENSIONS选项已经被移除,所以dan1st的答案不再适用。
我通过使用过滤器从请求头中移除permessage-deflate来成功禁用了压缩功能。
@Component
public class WebSocketHeaderFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        HttpServletRequest req = new HttpServletRequestWrapper((HttpServletRequest) request) {
            @Override
            public String getHeader(String name) {
                if ("Sec-WebSocket-Extensions".equalsIgnoreCase(name)) {
                    return "";
                }
                return super.getHeader(name);
            }

            @Override
            public Enumeration<String> getHeaders(String name) {

                if ("Sec-WebSocket-Extensions".equalsIgnoreCase(name)) {
                    return Collections.enumeration(Collections.emptyList());
                }
                return super.getHeaders(name);
            }
        };

        chain.doFilter(req, httpResponse);
    
    }
}

在我的情况下,只需清除标题的值就足够了。但由于客户端可能请求其他WebSocket扩展,最好从标题中删除permessage-deflate

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接