Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ActionCable no longer working in production environment

I have a Rails 5 app which uses Action Cable for websocket functionality.

In my development environment everything works as expected and the browser clients successfully connect to the Action Cable channels.

In my production environment Action Cable was working at some point, but then suddenly stopped functioning without any immediate apparent cause.

If I change the RAILS_ENV to production while running the app on my development machine Action Cable works fine. Something seems different when running the app on the actual production machine although the basic environment is the same.

The specific error I see in the Chrome console:

mydomain.com/:1 WebSocket connection to 'wss://mydomain.com/cable' failed: WebSocket is closed before the connection is established. I get a similar error in other browsers so it doesn't appear to be browser related. I disabled any adblockers while testing just to be sure they do not interfere.

Development.rb ENV related setup:

config.action_cable.url = "ws://localhost:#{port}/cable"

Production.rb ENV related setup:

hostname = ENV.fetch('HOSTNAME')
  port = ENV.fetch('PORT')
  base_url = "#{hostname}:#{port}"

  config.action_cable.url = "wss://#{hostname}/cable"
  config.action_cable.allowed_request_origins = ["https://#{base_url}", "https://#{hostname}"]

I use Puma as a webserver. The webserver serves a SSL connection for which a valid certificate is installed. On the production machine Puma serves the application on port 3000 but this is forwarded to port 443 in the router.

The only notable difference with running the app on my dev machine and production is that in production SSL is used.

like image 985
edwardmp Avatar asked Sep 09 '25 10:09

edwardmp


2 Answers

I can now safely conclude this is a bug, probably in Rails/ActionCable itself. This is corroborated by other reports and as I told at one point it worked fine, this was when I used Rails 5.0.0.1. When I updated to 5.0.1 it broke and it remains broken on 5.0.2. I'm opening an issue on the GitHub issue tracker of the Rails project.

Edit July 2017: Rails did change something as to how it reads and writes to the Rack socket, however the actual webserver software you use needs to support these nonblocking read and write methods. In my case, Puma did not at that time hence websockets didn't work. For Puma there is now a new release with a workaround for this issue.

like image 133
edwardmp Avatar answered Sep 11 '25 10:09

edwardmp


As per your problem statement

  • Your Development environment works because you have set it to handle insecure web traffic but on your Production environment is set to handle secure traffic.

Development.rb ENV related setup:

config.action_cable.url = "ws://localhost:#{port}/cable"

Production.rb ENV related setup:

 config.action_cable.url = "wss://#{hostname}/cable"  

According to your network setup you have configured your SSL port redirection to port 3000 and serving web request from PUMA rb server.

Now the problem i see over here is wss://#{hostname} will try to listen on default port 443 for secure traffic instead your redirected port 3000

like image 32
Mandar Avatar answered Sep 11 '25 12:09

Mandar