Faye requesting an insecure script <URL> - ruby-on-rails

I'm was exploring faye to implement websocket feature but got stuck due to following issue.
The page at was loaded over HTTPS, but requested an insecure script http://xyz/faye?message=[{"channel":"/meta/handshake","version":"1.0","supportedConnectionTypes":["websocket","eventsource","long-polling","cross-origin-long-polling","callback-polling"],"id":"1"}]&jsonp=__jsonp1. This request has been blocked; the content must be served over HTTPS
Config details
rails( 4.2.11)
faye (1.3.0)
puma (4.3.1)
Everything fine locally since everything running over HTTP.
On staging, we are getting the above issue. Not sure what are we doing wrong. Points to note are:
Puma is running using --ssl.
https://xyz/faye.js renders the client JS (Note the https)
Ran faye server using rackup faye.ru -s thin -E production
nginx config below
server {
listen 80;
root /var/app/current;
location / {
proxy_pass http://mlp;
proxy_set_header Host $host;
rewrite /favicon.ico /public/favicon.ico;
}
location /faye {
proxy_set_header Host $host;
proxy_pass http://localhost:9292;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
}
}

Related

Rails5 Action Cable Nginx 404 and 502 errors

Everyone :).
I know people have already faced alot of problems related to mine. I have tried all but my issue has not been resolved. I have been working from past 3 days to fix this but I am unable to do it.
I am using ActionCable for the first time and on development server it is working fine. But in production where I am using Puma and Nginx I am facing terrible issues.
Initially when I had not (location /cable) settings in nginx configuration, server gives me 404 handshake error
i.e Error during WebSocket handshake: Unexpected response code: 404
Then after I add following location /cable configuration in nginx configuration I start getting 502 bad gateway error.
Note: I have not opened any port specifically for ActionCable. I assume it is not required. only port 80 is open on my server.
I need some expert to help me with this. I need quick help to get it fixed. Thanks in advance :)
I have these two lines present in my environment/production.rb
config.action_cable.url = "ws://my_linode_domain/cable"
config.action_cable.allowed_request_origins = [/http:\/\/*/, /https:\/\/*/]
This is my nginx config file
upstream app {
# Path to Puma SOCK file, as defined previously
server unix:/home/deploy/artcrate/shared/tmp/sockets/puma.sock fail_timeout=0;
}
server {
listen 80;
#server_name localhost;
server_name my_linode_domain
# prevents 502 bad gateway error
large_client_header_buffers 8 32k;
root /home/deploy/artcrate/current/public;
try_files $uri/index.html $uri #app;
location / {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_pass http://app;
}
location ~ ^/(assets|fonts|system)/|favicon.ico|robots.txt {
gzip_static on;
expires max;
add_header Cache-Control public;
}
location /cable{
proxy_pass http://app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
I have tried various proxy_pass options in location /cable settings but none worked.
Everyone. :)
After a week of struggle, hardwork and constantly playing around with nginx and puma configuration files and keenly reading blogs again and again, I was able to figure out the issue.
My nginx configurations were correct. I had to add two more lines to puma.rb configuration which don't come with default configurations. Those two lines are:
workers 2
daemonize true
daemonize true: this tells puma to run in the background by spawning a subprocess and detaching it from the executing shell. If you don't use daemonize, you need to run the puma process via nohup and put it in the background explicitly.
I am not sure if I required workers 2 but I had added them while resolving my issue. So I let it there. But after adding above two lines my ActionCable started to work normally.
RAILS and RUBY version I am using for this project is
Rails 5.0.7
ruby 2.3.1p112
ok. So today I wanted to integrate Action Cable again in my project but faced the same issue again. I applied my above solution but it didn't work. Last time although it worked but I wasn't satisfied with the solution thinking that why would ActionCable work in single thread/worker on local machine.
But this time I focussed and figured out the culprit.
Culprit is NGINX configuration
Configuration when I was facing 404 handshake errors
location /cable {
proxy_pass http://example.com;
proxy_http_version 1.1;
proxy_set_header Upgrade websocket;
proxy_set_header Connection Upgrade;
}
Configuration when all started working fine.
location /cable {
proxy_pass http://puma;
proxy_http_version 1.1;
proxy_set_header Upgrade websocket;
proxy_set_header Connection Upgrade;
}
so the culprit line was:
proxy_pass http://example.com;
Here we are pointing it to NGINX which is wrong, it should point to our puma server path which in my configuration is represented by 'puma'.
Here is the Summary of my implementation of ActionCable and its working copy on Production Server
So to integrate Action Cable with Rails 5 you need to follow following steps:
Setup Redis on default port.
Add these lines in environments/staging.rb or environments/production.rb, depending on your application environment.
config.action_cable.url = [/ws://*/, /wss://*/]
config.action_cable.allowed_request_origins = [/http://*/, /https://*/]
Finally setup you NGINX file as explained above. Here is my complete NGINX configuration in gist nginx.conf. I had replaced my site name with 'example.com' and project name with 'example'. So if you are copying anything, just make sure you replace those with yours otherwise nothing will work as paths will be broken.
I hope this will really release the pain while pushing ActionCable to live application and resolve this handshake error for anyone as this is very very tricky and technical thing and a lot of docs just mention to point action cable to your main site url and not puma server running behind your nginx.
Thanks.

Rails 5 actioncable freezes the server

I am having issue running Actioncable on nginx server, every time I mount actioncable
mount ActionCable.server => '/cable'
the server will return
Started GET "/cable" for ::1 at 2016-05-24 11:42:16 -0400
Started GET "/cable/" [WebSocket] for ::1 at 2016-05-24 11:42:16 -0400
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
before freezing
Any help is appreciated!
I was having this same issue once my application was being used by many users. My problem came from using Puma and Phusion Passenger together. This issue was solved by eliminating Puma from my application and configuring Nginx to use Action Cable with Passenger instead.
This article outlines the correct way to configure Action Cable + Nginx + Passenger
I had same problem. Rails server was freezing after connecting
This worked for me
In config.ru file
if defined?(PhusionPassenger)
PhusionPassenger.advertised_concurrency_level = 0
end
Idea is that set concurrency level to 0
Initially i was setting concurrency level 0 for cable server only in nginx.conf file
Hope this save someone's day
If you are using puma + nginx + rails you should use :
Inside your virtual host in nginx conf
# enables WS support
location /cable {
proxy_pass http://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";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
}

Faye + nginx. Client closed keepalive connection

I am using faye on my production server with Passenger and Nginx. I write this code to nginx config file of my site:
location /faye {
proxy_pass http://127.0.0.1:9292;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
In a Chrome Network/Websocket I see
Status 101.
Switching protocols
As I know it means, that I have a websocket connection.
But I dont get any messages from it. In nginx.error.log I see:
2015/05/29 13:46:38 [info] 27188#0: *32 client closed keepalive connection
How can I fix it?

Websocket-rails doesn't work on production evironment with Nginx and Unicorn

I have Rails 3.2 application with gem websocket-rails 0.7.
On development machine, all work fine
On production enviroment, I use Nginx/1.6 as proxy server and Unicorn as http server. Thin is used on standalone mode (following https://github.com/websocket-rails/websocket-rails/wiki/Standalone-Server-Mode).
nginx config:
location /websocket {
proxy_pass http://localhost:3001/websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
On backend side, I have the following code for send notification to clients
WebsocketRails[:callback_requests].trigger 'new', call_request
On client side, I got a connection using:
dispatcher = new WebSocketRails window.location.host + ':3001/websocket'
channel = dispatcher.subscribe 'callback_requests'
But notification doesn't come to the client.
Related issue on github - github.com/websocket-rails/websocket-rails/issues/211
Your nginx config is matching requests below /websocket/ with the trailing /. That is the directory component of /websocket/blah.
If you look in your nginx access log file you'll find your requests to /websocket are being 301 redirected to /websocket/.
Remove the trailing /
location /websocket {
proxy_pass http://localhost:3001/websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

Can one application with one server serve websockets and http traffic?

Is this somehow possible? Is it possible to do something like this in Ruby on top of Rack? I've seen there's websockets-rack but as far as I understand, that is only a rack module to serve ONLY websocket traffic not http also.
So basically, as the question states, is it possible to serve both protocols with just one server on the same port, instead of firing of something like Faye, websockets-rack or em-websockets?
Websockets are just an in-protocol upgrade of HTTP(s), so they are not normal TCP sockets but reuse the existing HTTP(S) connection (and thus use the same port). So, in theory it should work and from what I know it works with the Perl Mojolicious framework. But I don't know if it works work ruby/rack.
The short answer is - (AFAIK) no.
Currently, a ruby HTTP server (like rails or sinatra) and a websocket server are mutually exclusive.
After saying that, you could use a third party to emulate that. Specifically Ngnix. With Nginx you can listen to a single port, but, accroding to a path, decide whether you want to dispatch the request to the HTTP server or the Websocket server.
For example, you can run the HTTP server on port 3000, and the Websocket server on port 3020, and then configure the nginx.conf like this:
upstream http_app {
server 127.0.0.1:3000;
}
upstream websocket_app {
server 127.0.0.1:3020;
}
server {
listen 80;
server_name .example.com;
access_log /var/www/myapp.example.com/log/access.log;
error_log /var/www/myapp.example.com/log/error.log;
root /var/www/myapp.example.com;
index index.html;
location /web {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://http_app;
}
location /socket {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://websocket_app;
}
}
Now any request to http://www.example.com/web/... will reach the HTTP server, and any request to http://www.example.com/socket will reach the Websocket server.

Resources