Rails 5 ActionCable WebSockets 未返回状态为 101 升级响应的升级标头

2023-12-09

编辑:显示在最后,发现升级标头实际上已创建。

我的工作地点是动作电缆示例代码库,尝试构建一个 WebSocket 应用程序。 “Chatty”应用程序依赖于应用程序中提供的浏览器客户端,工作正常。但是,我不会使用该客户端,因为我需要外部物联网连接。因此,我尝试将 ws/wss WebSocket 协议实现到外部非浏览器设备,我在 router.rb 中的连接是:

mount ActionCable.server => '/cable'

我尝试过几个外部客户端,例如 Chrome Simple WebSocket Client 扩展和 gemwebsocket 客户端简单使用样本/client.rb。在这两种情况下,ActionCable 都不会返回升级标头。 Chrome 扩展抱怨如下:

WebSocket connection to 'ws://127.0.0.1:3000/cable' failed: Error during WebSocket handshake: 'Upgrade' header is missing 

实际的握手表明这是真的,如下所示:

**General**
Request URL:ws://127.0.0.1:3000/cable
Request Method:GET
Status Code:101 Switching Protocols
**Response Headers**
view source
Connection:keep-alive
Server:thin
**Request Headers**
view source
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache
Connection:Upgrade
Cookie:PPA_ID=<redacted>
DNT:1
Host:127.0.0.1:3000
Origin:chrome-extension://pfdhoblngboilpfeibdedpjgfnlcodoo
Pragma:no-cache
Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits
Sec-WebSocket-Key:1vokmzewcWf9e2RwMth0Lw==
Sec-WebSocket-Version:13
Upgrade:websocket
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36

根据标准,响应标头应如下所示:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat

Sec-WebSocket-Accept 特别重要,因为它是基于请求标头的 Sec-WebSocket-Key 的计算,以确认 ws/wss 被理解并且应该发生切换协议。

在这一切过程中,服务器会更加高兴,直到客户端被勾选并关闭连接:

Started GET "/cable" for 127.0.0.1 at 2016-06-16 19:19:17 -0400
  ActiveRecord::SchemaMigration Load (1.0ms)  SELECT "schema_migrations".* FROM "schema_migrations"
Started GET "/cable/" [WebSocket] for 127.0.0.1 at 2016-06-16 19:19:17 -0400
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
Finished "/cable/" [WebSocket] for 127.0.0.1 at 2016-06-16 19:19:18 -0400

查看 websocket-client-simple,我将返回到 client.rb 的 WebSocket 分解,它还显示空标头。我先展示代码,然后展示 WebSocket:

url = ARGV.shift || 'ws://localhost:3000/cable'
ws = WebSocket::Client::Simple.connect url

#<WebSocket::Client::Simple::Client:0x2cdaf68 
    @url="ws://localhost:3000/cable", 
    @socket=#<TCPSocket:fd 3>, 
    @handshake=<WebSocket::Handshake::Client:0x013231c8 
        @url="ws://localhost:3000/cable", 
        @headers={}, 
        @state=:new, 
        @handler=#<WebSocket::Handshake::Handler::Client11:0x2e88400 
            @handshake=<WebSocket::Handshake::Client:0x013231c8 
                @url="ws://localhost:3000/cable", 
                @headers={}, 
                @state=:new, 
                @handler=#<WebSocket::Handshake::Handler::Client11:0x2e88400 ...>, 
                @data="", 
                @secure=false, 
                @host="localhost", 
                @port=3000, 
                @path="/cable", 
                @query=nil, 
                @version=13>, 
            @key="KUJ0/C0rvoCMruW8STp0Sw==">, 
        @data="", 
        @secure=false, 
        @host="localhost", 
        @port=3000, 
        @path="/cable", 
        @query=nil, 
        @version=13>, 
    @handshaked=false, 
    @pipe_broken=false, 
    @closed=false, 
    @__events=[{:type=>:__close, :listener=>#<Proc:0x2d10ae8@D:/Bitnami/rubystack-2.2.5-3/projects/websocket-client-simple/lib/websocket-client-simple/client.rb:37>, :params=>{:once=>true}, :id=>0}], 
    @thread=#<Thread:0x2d10a70@D:/Bitnami/rubystack-2.2.5-3/projects/websocket-client-simple/lib/websocket-client-simple/client.rb:42 sleep>
>;

在此响应中,我注意到实例变量“@handshaked”返回为 false。这可能是相关的,但到目前为止我还没有找到代码中设置或引用的位置。

更新: 发现 WebSocket::Driver.start 实际上创建了升级标头。并且,@socket.write(响应)should通过 EventMachine 将它们发送出去。 代码:

def start
  return false unless @ready_state == 0
  response = handshake_response
  return false unless response
  @socket.write(response)
  open unless @stage == -1
  true
end

握手响应是:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: iJVnsG1ApNMFzABXGDSHN1V0i/s=

问题是我试图在开发中使用瘦服务器。它会运作。然而,它实际上在处理过程中传输响应标头,如下所示:

Response Headers
Connection:keep-alive
Server:thin

ActionCable 实际上正在发送适当的升级标头,但只有在 Thin 发送出自己的标头之后才会这样做,因此客户端无法识别它们。

转换回 Puma 后,我收到了预期的信息:

Response Headers
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: XJOmp1e2IwQIMk5n0JV/RZZSIhs=
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Rails 5 ActionCable WebSockets 未返回状态为 101 升级响应的升级标头 的相关文章

  • 如何在 Rails 模型中获取 request.uri?

    request request 当我在控制器中写这个时 它就会起作用 但是如果我在模型或应用程序控制器中需要这个变量 我该怎么办 模型存在于 Web 请求的上下文之外 您可以在 irb 中实例化它们 可以在延迟作业或脚本等中实例化它们 如果
  • 使用 Ruby on Rails 的多个应用程序

    单个 Ruby on Rails 安装是否可以拥有多个共享通用模型的应用程序 例如 我想要一个前端应用程序以及后端管理控制台 但两者共享相同的模型 这类似于 Symfony 在 PHP 中的工作方式 提前致谢 拥有管理面板的最简单方法是使用
  • 如何在 Rails ActiveRecord 中的日期指定小于今天的条件

    我正在尝试找出如何提取我的集合中的所有记录的字段publish是真的并且expires比今天少 我有以下内容 但我认为小于部分不起作用 有人可以指出我正确的轨道吗 Announcement where publish true expire
  • Rails 3.1 引擎迁移不起作用

    我正在创建一个带有迁移的 Rails 3 1 引擎 rake db migration 在该引擎和主机应用程序内运行良好 但我需要将此引擎包含到另一个 Rails 引擎中 第二个引擎包含用于测试的虚拟应用程序 我将这一行添加到该虚拟应用程序
  • Rails 教程 - User.rb 文件错误

    我正在关注 Railstutorial org 第 7 章 我正在尝试运行该应用程序 但出现以下代码错误 该错误表明我需要在文件末尾添加另一个 结束 但我已经尝试过此操作 但没有成功 错误是 Users woshea rails sampl
  • 在Rails 3中,如何使用button_to更改布尔值?

    我正在尝试编写一个button to 语句来更新我的activerecord 数据库中的布尔值 这是我尝试过的 从更大的角度来看 我想做的是有一个按钮可以更新支付对象并触发对宝石汇款与亚马逊支付进行通信的私有方法的调用 所以 1 如何使用b
  • Grails(现在)值得吗? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我知道这是一个复制 https stackoverflow com questions 397228 is grails worth it然而
  • 部署到 Heroku 时出现“rake 中止!堆栈级别太深”

    我的网站曾经运行正常 Heroku 预编译了资产和所有内容 现在 似乎不知从何而来 我开始在部署时收到此消息 Preparing app for Rails asset pipeline Running rake assets precom
  • 使用 PayPal REST API,如何取消付款?

    使用 PayPal REST API 在客户点击 取消订单并返回网站 链接后 我似乎无法弄清楚如何取消付款 也许在生产模式下 PayPal 会自动取消这些付款 但在沙盒模式下它们似乎仍处于 已创建 状态 这一观察结果使我相信 我需要在返回网
  • 从邮件程序访问助手?

    我试图从 Rails 3 邮件程序访问帮助程序方法 以便访问会话的当前用户 我将 helper application 放在我的邮件程序类中 这似乎可以工作 但其中定义的方法对我的邮件程序不可用 我收到未定义的错误 有谁知道这应该如何运作
  • 如何在 Rails 中重定向到 404?

    我想在 Rails 中 伪造 404 页面 在 PHP 中 我只发送一个带有错误代码的标头 如下所示 header HTTP 1 0 404 Not Found Rails 是如何做到这一点的 不要自己渲染 404 没有理由这样做 Rail
  • 在 Heroku 上的生产模式下使用 Rails 同步 gem 与 Faye 和 Thin

    我正在尝试设置 同步 gem 以在我的 Rails 应用程序中启用实时更新 它使用 Faye 作为实时推送服务 并使用 Thin 作为网络服务器 我对此非常陌生 所以任何建议都会受到赞赏 我的本地服务器上有这个工作 但不知道如何让它在 He
  • Rails:ENV.fetch() 和 ENV[] 之间的区别

    这两种语法有什么区别 ENV fetch MY VAR ENV MY VAR 我见过 Rails 5 在不同的地方使用了这两个版本 但无法弄清楚其中的区别 除了第一个需要输入更多字符之外 The ENVhash like 对象是普通的 Ru
  • 需要帮助设置 ruby​​ on Rails javascript 运行时环境

    我在我的机器上设置 ruby on Rails 时遇到问题 我一直在关注 Agile Web Development with Rails 这本书 到目前为止一切都进展顺利 我遇到的问题是当我输入时 rails server 我收到以下错误
  • ActiveStorage上传大型base64编码字符串?

    如果我有在客户端上使用 JavaScript 编辑 生成的图像 例如 裁剪的照片或画布绘图的结果 是否可以使用 ActiveStorage 上传它 它通常是一个包含以下内容的大字符串 img src 它存储在 JavaScript 变量中
  • Rails:RSpec - nil:NilClass 的未定义方法“cookie_jar”

    铁轨新手 尝试遵循迈克尔 哈特尔的教程 尝试添加辅助方法来模拟 RSpec 测试中的日志时陷入困境 describe when the a user has logged in and attempts to visit the page
  • 如何在rails中创建带有外键别名的装置?

    我有两个模型 App and User 其中App有一个创造者 他是User app rb class App lt ActiveRecord Base belongs to creator class name User end user
  • 为什么私有辅助方法仍然可以在视图中访问?

    另一个 为什么会这样 的问题 我注意到私有辅助方法仍然可以在视图中访问 为什么 有没有办法防止这种情况 例如 当具有只能从另一个助手中调用的助手方法时 帮手是混合在一起的模块 http www ruby doc org docs Progr
  • RSpec 找不到我的控制器未初始化常量

    我的 Rails 应用程序最近从 Rails 3 迁移到 Rails 4 我一直在尝试在各个规范 控制器 模型等 上运行 rspec 但实际定位对象时似乎存在问题 例如 当我尝试运行以下代码时 它会出现未初始化常量错误 这似乎发生在多个控制
  • Turbolinks 访问的页面中缺少 hubspot 聊天界面,但可用于全页面刷新

    我想将 hubspot 聊天界面集成到我的 Rails 4 Turbolinks 应用程序中 我已将 Google 跟踪代码管理器配置为在每个页面加载事件中显示支持聊天界面 该界面工作正常 GTM 标签 自定义 html PROBLEM 当

随机推荐