已解决 - 如何在 Spring 中自定义 WebSocket 升级请求的 HTTP 响应?

Posted

技术标签:

【中文标题】已解决 - 如何在 Spring 中自定义 WebSocket 升级请求的 HTTP 响应?【英文标题】:SOLVED - How to customize HTTP response for WebSocket upgrade request in Spring? 【发布时间】:2020-03-05 12:50:15 【问题描述】:

在我的WebSocketConfigurer 实现中,我有一个这样配置的 WebSocket 端点

public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) 
        registry.addHandler(new ExceptionWebSocketHandlerDecorator(myWebSocketHandler), "/ws/")
                .setAllowedOrigins("*")
                .addInterceptors(myHandshakeInterceptor);
    

myWebSocketHandler#beforeHandshake 中有一些检查,我想向用户发送一条错误消息,以防服务器决定拒绝升级连接。这个我试过了

response.setStatusCode(HttpStatus.BAD_GATEWAY);
try 
    response.getBody().write("Error".getBytes());
    response.getBody().flush();
 catch (IOException e) 
    log.error("Error writing response", e);

return false;

状态码有效,但正文为空。如何发送?

编辑:原来问题是我使用 Firefox 控制台来检查响应,但它没有显示任何内容。如果我使用 cURL 发出相同的请求,那么一切正常,我会看到我写到响应正文的消息!

【问题讨论】:

你是如何检查身体是空的? Spring 拦截器没有修改响应体 我在 Firefox 控制台中检查了响应。原来它没有显示响应正文。当我使用 curl 时,一切正常,我可以阅读响应。 您使用了拦截器或自定义处理程序? 【参考方案1】:

要更新响应正文,您需要编写自定义 RequestUpateStrategy。 正如来自 AbstractHandshakeHandler 的春季官方文档中所说:

The actual upgrade is delegated to a server-specific RequestUpgradeStrategy, which will update the response as necessary and initialize the WebSocket.

如果您使用 Tomcat 作为 servlet 容器,您可以扩展 TomcatRequestUpgradeStrategyclass 并提供您自己的逻辑如何处理 websocket 升级。

对于每个 servlet 容器,都有 RequestUpgradeStrategy 的实现 documentation

【讨论】:

感谢您的回复。不幸的是,在 HandshakeHandler 或 RequestUpgradeStrategy 中编写响应正文都不起作用。我仍然得到一个空的身体。 你能分享一个例子吗? 这是我的自定义处理程序和策略(代码太长,无法在评论中发布,抱歉)pastebin.com/scCcnLBU 可以分享github链接吗? 请看 AbstractHandshakeHandler 类方法 protected void handleInvalidUpgradeHeader(ServerHttpRequest request, ServerHttpResponse response)

以上是关于已解决 - 如何在 Spring 中自定义 WebSocket 升级请求的 HTTP 响应?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Boot 1.4 中自定义 Jackson

如何在grails中自定义spring security插件登录页面

如何在 Spring Security 中自定义“错误凭据”错误响应?

6.1 如何在spring中自定义xml标签

如何在 Spring Webflux 中自定义 Oauth2 的登录页面?

当自定义模板已应用于节点的内容类型时,如何在 Drupal 6 中自定义特定节点?