我正在使用action-cable-example代码库,尝试构建一个WebSocket应用程序. “Chatty”应用程序,取决于应用程序中提供的浏览器客户端,工作正常.但是,我不打算使用该客户端,因为我需要外部IoT连接.因此,我正在尝试将ws / wss WebSocket协议实现到外部非浏览器设备,并且我在route.rb中的连接是:
mount ActionCable.server => '/cable'
我尝试了几个外部客户端,例如Chrome Simple WebSocket ClIEnt扩展和gem websocket-client-simple使用sample / 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/cableRequest Method:GETStatus Code:101 Switching Protocols**Response headers**vIEw sourceConnection:keep-aliveServer:thin**Request headers**vIEw sourceAccept-EnCoding:gzip,deflate,sdchAccept-Language:en-US,en;q=0.8Cache-Control:no-cacheConnection:Upgradecookie:PPA_ID=<redacted>DNT:1Host:127.0.0.1:3000Origin:Chrome-extension://pfdhoblngboilpfeibdedpjgfnlcodooPragma:no-cacheSec-WebSocket-Extensions:permessage-deflate; clIEnt_max_window_bitsSec-WebSocket-Key:1vokmzewcWf9e2RwMth0Lw==Sec-WebSocket-Version:13Upgrade:websocketUser-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 ProtocolsUpgrade: websocketConnection: UpgradeSec-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 -0400Successfully 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,我将WebSocket分解为clIEnt.rb,它也显示了空标题.我正在显示代码,然后是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",@handler=#<WebSocket::Handshake::Handler::ClIEnt11:0x2e88400 ...>,@data="",@secure=false,@host="localhost",@port=3000,@path="/cable",@query=nil,@version=13>,@key="KUJ0/C0rvoCMruW8STp0Sw==">,@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(响应)应该通过EventMachine发送出去.
码:
def start return false unless @ready_state == 0 response = handshake_response return false unless response @socket.write(response) open unless @stage == -1 trueend
handshake_response是:
http/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: iJVnsG1ApNMFzABXGDSHN1V0i/s=解决方法 问题是我试图在开发中使用Thin服务器.它会运作.但是,它实际上是在处理过程中传输响应头,例如:
Response headersConnection:keep-aliveServer:thin
ActionCable实际上是在发送相应的升级标头,但只有在Thin发出自己的标头后才会这样做,因此客户端无法识别它们.
转换回Puma后,我按预期收到这些:
Response headershttp/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: XJOmp1e2IwQIMk5n0JV/RZZSIhs=总结
以上是内存溢出为你收集整理的ruby-on-rails – Rails 5 ActionCable未返回状态为101升级响应的升级标头全部内容,希望文章能够帮你解决ruby-on-rails – Rails 5 ActionCable未返回状态为101升级响应的升级标头所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)