web-dev-qa-db-de.com

ActionCable - Fehler beim Upgrade auf WebSocket in der Produktion

ActionCable funktioniert nicht in der Produktion. Funktioniert gut in der Entwicklung, aber nicht in der Produktion.

Nginx mit Puma auf Ubuntu laufen lassen 14.04. Ich habe überprüft, dass der Redis-Server läuft.

Schienen -v 5.0.0.1

production.log:

INFO -- : Started GET "/cable/"[non-WebSocket] for 178.213.184.193 at 2016-11-25 14:55:39 +0100
ERROR -- : Failed to upgrade to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: close, HTTP_UPGRADE: )
INFO -- : Finished "/cable/"[non-WebSocket] for 178.213.184.193 at 2016-11-25 14:55:39 +0100

Anfrage vom Kunden:

GET ws://mityakoval.com/cable HTTP/1.1
Host: mityakoval.com
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: http://mityakoval.com
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4,uk;q=0.2,nb;q=0.2
Cookie: _vaktdagboka_session=******
Sec-WebSocket-Key: *******
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Protocol: actioncable-v1-json, actioncable-unsupported

Antwort: 

HTTP/1.1 404 Not Found
Server: nginx/1.4.6 (Ubuntu)
Date: Fri, 25 Nov 2016 13:52:21 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive
Cache-Control: no-cache
X-Request-Id: d6374238-69ef-476e-8fc5-e2f8bbb663de
X-Runtime: 0.002500

nginx.conf:

upstream puma {
  server unix:///home/mityakoval/apps/vaktdagboka/shared/tmp/sockets/vaktdagboka-puma.sock;
}

server {
  listen 80 default_server deferred;
  # server_name example.com;

  root /home/mityakoval/apps/vaktdagboka/current/public;
  access_log /home/mityakoval/apps/vaktdagboka/current/log/nginx.access.log;
  error_log /home/mityakoval/apps/vaktdagboka/current/log/nginx.error.log info;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  try_files $uri/index.html $uri @puma;
  location @puma {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_Host;
    proxy_redirect off;

    proxy_pass http://puma;
  }

  location /cable {
    proxy_pass http://puma;
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_Host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
  }

  error_page 500 502 503 504 /500.html;
  client_max_body_size 10M;
  keepalive_timeout 10;
}

cable.yml:

redis: &redis
  adapter: redis
  url: redis://127.0.0.1:6379

production: *redis

development:
  adapter: async

test:
  adapter: async

in production.rb:

config.action_cable.allowed_request_origins = ["http://mityakoval.com"]

in routes.rb:

mount ActionCable.server, at: '/cable'

UPDATE:

Vergiss nicht, Nginx neu zu starten :) Das war das Problem für mich.

12
mityakoval

Sie sollten den Wert der proxy_pass-Eigenschaft von http://puma in http://puma/cable ändern.

Der korrekte location-Abschnitt für den /cable lautet daher:

location /cable {
  proxy_pass http://puma/cable;
  proxy_http_version 1.1;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header Host $http_Host;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "Upgrade";
}
6
Tsutomu

Super spät für dieses Gespräch, jedoch für alle, die dieselbe Fehlermeldung mit Rails5, Action Cable usw. erhalten. &DEVISESie lösen es einfach wie vorgeschlagen hier . Es kommt alles darauf an, dass der Web-Socket-Server keine Sitzung hat, daher die Fehlermeldung.

app/channels/application_cable/connection.rb

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
      logger.add_tags 'ActionCable', current_user.name
    end

    protected
      def find_verified_user
        verified_user = User.find_by(id: cookies.signed['user.id'])
        if verified_user && cookies.signed['user.expires_at'] > Time.now
          verified_user
        else
          reject_unauthorized_connection
        end
      end
  end
end

app/config/initializers/warden_hooks.rb

Warden::Manager.after_set_user do |user,auth,opts|
  scope = opts[:scope]
  auth.cookies.signed["#{scope}.id"] = user.id
  auth.cookies.signed["#{scope}.expires_at"] = 30.minutes.from_now
end
Warden::Manager.before_logout do |user, auth, opts|
  scope = opts[:scope]
  auth.cookies.signed["#{scope}.id"] = nil
  auth.cookies.signed["#{scope}.expires_at"] = nil
end

Lösung wurde von Greg Molnar entwickelt

2

Die Auflösung, die eine NGINX-Konfiguration erfordert, ändert sich, um diese Aktionskabelanforderung zu akzeptieren .

location / {
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
}

Fügen Sie Ihrem Standortblock in der nginx-Standortkonfiguration die obigen Zeilen hinzu, und starten Sie dann nginx erneut.

1
errakeshpd

Meine Lösung bestand darin, diese Zeilen meiner production.rb-Datei hinzuzufügen:

  config.action_cable.url = 'ws://your_site.com/your_action_cable'
  config.action_cable.allowed_request_origins = [ 'http://your_site.com' ]
0
Aarón Castro

Arbeitete mit:

location ^~ /cable {
  ...
}

Standort erfordert ^~

0

Sie können Ihre Nginx-Konfiguration über /cable ändern.

proxy_set_header X-Forwarded-Proto http;

Ich habe Sie nginx config verwendet und diese Änderung auf myu Server hinzugefügt, es funktioniert gut.

0
Alvin