2016-06-16 41 views
4

編輯:顯示在結尾處,發現升級標頭實際上已創建。Rails 5 ActionCable未返回狀態爲101的升級標題升級響應

我正在從action-cable-example代碼庫嘗試構建WebSocket應用程序。 「Chatty」應用程序依賴於應用程序中提供的瀏覽器客戶端,工作正常。但是,我不打算使用該客戶端,因爲我需要外部IoT連接。其結果是,我試圖實現WS/WSS的WebSocket協議,外部非瀏覽器的裝置和我的route.rb連接:

mount ActionCable.server => '/cable' 

我試過幾個外部客戶,例如Chrome簡單WebSocket客戶端擴展和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/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已被理解,並且交換協議應該CCur函數。

在這一切中,服務器是更快樂,直到客戶端被選中並關閉連接:

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的客戶端,簡單的,我打破了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", 
       @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:[email protected]:/Bitnami/rubystack-2.2.5-3/projects/websocket-client-simple/lib/websocket-client-simple/client.rb:37>, :params=>{:once=>true}, :id=>0}], 
    @thread=#<Thread:[email protected]:/Bitnami/rubystack-2.2.5-3/projects/websocket-client-simple/lib/websocket-client-simple/client.rb:42 sleep> 
>; 

在這種反應,我注意到了實例變量「@handshaked」返回假。這可能是相關的,但我還沒有找到在代碼中設置或引用到目前爲止。

更新: 發現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 
    true 
end 

handshake_response是:

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

回答

6

的問題是,我試圖用瘦服務器的發展。它會運作。然而,它實際上是傳遞其在處理過程中的響應頭,像這樣的:

Response Headers 
Connection:keep-alive 
Server:thin 

ActionCable竟是發送適當的升級頭,但它正在這樣做薄發出了自己的頭,所以客戶端後,纔沒有認出他們。

轉換回彪馬之後,我收到這些預期:

Response Headers 
HTTP/1.1 101 Switching Protocols 
Upgrade: websocket 
Connection: Upgrade 
Sec-WebSocket-Accept: XJOmp1e2IwQIMk5n0JV/RZZSIhs=