Rails 5 ActionCable接收外部WebSocket消息遇JSON::ParserError
解决Rails 5 ActionCable接收非JSON消息的JSON::ParserError问题
从错误堆栈可以明确,问题出在ActionCable连接的decode方法中——ActionCable默认要求所有WebSocket消息必须是JSON格式,但你无法修改外部设备的消息输出,只能在服务端做适配。之前添加的Rack中间件无效,因为WebSocket消息是连接建立后的帧数据,不属于HTTP请求周期,Rack中间件只能处理初始的握手请求,管不到后续的消息解码流程。
1. 重写ActionCable连接的decode方法
在app/channels/application_cable/connection.rb中覆盖默认的decode方法,捕获JSON解析错误,将非JSON消息转换为可处理的格式:
# app/channels/application_cable/connection.rb module ApplicationCable class Connection < ActionCable::Connection::Base # 重写decode方法,兼容非JSON格式消息 def decode(message) # 尝试用默认逻辑解析JSON super rescue JSON::ParserError => e # 记录原始消息,便于排查 Rails.logger.warn "Received non-JSON message: #{message}" # 将纯文本消息包装为标准格式,方便频道统一处理 { type: "plain_text", content: message } end end end
2. 在频道中处理转换后的消息
在对应的频道类中,根据包装后的格式区分处理纯文本和JSON消息:
# 示例:app/channels/your_channel.rb class YourChannel < ApplicationCable::Channel def subscribed stream_from "your_stream_name" end def receive(data) if data["type"] == "plain_text" # 处理纯文本消息 handle_plain_text_message(data["content"]) else # 处理原本的JSON格式消息 handle_json_message(data) end end private def handle_plain_text_message(text) # 自定义处理逻辑,比如广播消息 ActionCable.server.broadcast "your_stream_name", { message: "Received text: #{text}" } end def handle_json_message(data) # 原有的JSON消息处理逻辑 # 例如:ActionCable.server.broadcast "your_stream_name", data end end
3. 可选:忽略无法处理的非JSON消息
如果不需要处理纯文本消息,只想避免报错,可以在rescue块中返回空哈希或直接忽略:
def decode(message) super rescue JSON::ParserError => e Rails.logger.debug "Ignored non-JSON message: #{message}" {} # 返回空哈希,频道receive方法可自行判断跳过处理 end
内容的提问来源于stack exchange,提问作者kernification
相关产品推荐
相关产品推荐

