#260 Messaging with Faye
Apr 04, 2011 | 13 minutes |
Plugins
Faye is a subscription/publishing server which makes it easy to do push notifications within a Rails app.
- Download:
- source codeProject Files in Zip (266 KB)
- mp4Full Size H.264 Video (19.2 MB)
- m4vSmaller H.264 Video (13.5 MB)
- webmFull Size VP8 Video (36.7 MB)
- ogvFull Size Theora Video (26.5 MB)
Wondering how to secure which channels people can listen to. As far as I understand, in theory anybody can listen to your messages through javascript in this example.
Nice episode, thank you.
What about using juggernaut for server push?
Its nice solution too with support of different server-push methods.
Just been doing something very similar with EventMachine as I wanted to interface directly with AS3 over sockets.
I'll have to dig around this bayeux protocol and see if Faye can do the job easier.
Really great cast ! I was recently searching for this kind of solution without finding anything I was happy with. Thanks to make me discover Faye.
In the code, I think application.js should be included as well.
@Nico you can implement authorization as an extension to the server -- see 'Extensions' docs at http://faye.jcoglan.com/ruby.html
Thanks a lot for this screencast! Do you think Faye could work on Heroku?
@James: Thanks, sounds good!
Faye is awesome!
How compatible is this solution? Does it work on mobile browsers? Does it automatically change transport if websockets are disabled?
Thanks for this screencast!
@Benoit It should work as long as you keep your faye instance running in a different server.
Hi @Ryan, this is great, Got what i needed when I needed...
thanks a lot
sameera
@Oleg, I haven't tried Juggernaut because Faye worked so well for me and did exactly what I needed, but Juggernaut does look great as well. I should give it a try. Thanks for the suggestion.
@ybart, application.js is included automatically by the :defaults option.
@Benoit, if you're using Heroku you probably don't want to worry about managing servers and scaling. In that case I recommend using Pusher. It's also listed on the Heroku Add-ons page.
@rbates Sorry, I was meaning including the source code of application.js on this page. Of course, application.js should be included by rails application layout as well.
@rbates Is the implementation of faye any difference from the pusherapp(http://webpulp.tv/post/1626829659/pusher-app-martyn-loughran)? Are they both using eventmachine?
It's so awesome! I have been looking for the same stuff for a long time...(even thinking of building one).
@rbates If faye is using eventmanchine? Do I need to make sure my implementation in rails is asynchronous by using eventmachine as well? From my understanding, rails is blocking the IO.
Once again, thanks for the post!!!
Very interesting subject! Websockets are definitely in my TODO list.
Ryan, could you please add the link to async_sinatra & others to the show notes?
Thanks!
It took me a little to figure out that for best results web browser must support WebSockets. I was using Opera 11 and Firefox 4 in which WebSockets are disabled by default.
@ybart, oops, I forgot that. It's up there now.
@Jingwen, The approach I show here is very similar to Pusher, but I don't know if they use EventMachine internally. the RackAdapter inside of Faye does use EventMachine, the Node.js server version does not.
The beautify of this approach is that you don't have to worry about any of this. Your Rails app does not need to use EventMachine because it just sends a quick post request to Faye.
@Javi, done.
Has anyone tried this same thing with Amazon SNS? Interestingly I am not finding much of comparison between pusherapp and the like to SNS.
You could use Faye to allow live updating of the browser as you edit your code.
1) Setup watchr to watch your files (I suggest SASS and HAML) and get it to execute a curl request (crude but effective) when they change.
2) Get Faye to reload the page when it receives the message from watchr.
3) Start editing and watch the page update as you save!
Cool screencast Ryan. But wouldn't you consider sending and executing raw javascript a serious security flaw? E.g.does anything prevent me from redirecting every other user to another website?
Thank you for all the amazing material you put out.
@Jonas : I thought that too before looking more closely and running the app. Basically since the message view is a standard rails 3 form it has html escaping and csrf tag (look application layout <%= csrf_meta_tag %>): you can't post javascript nor html through the form nor can you post in the form from another site.
That leaves a curl post, which is closed due to the security with FAYE_TOKEN (and the fact if your server has a good firewall you close the 9292 for outside world). So in essence even though not at first glance it is pretty secure ;)
Now getting it working with https might be another deal (meaning a clever one can read messages from other rooms even when you implement authentication but that's true for facebook, twitter also).
@Walter, yeah it makes sense. I initially thought the broadcast was being executed on the client side so that a hacker could tamper the data.
Imho, sending requests to the pub/sub server from view code looks strange and doesn't fit in the Rails MVC paradigm.
In spite of this, Ryan, thank you for your great contribution to the rails community.
Just wanted to add one quick comment regarding Goliath. Goliath isn't a web framework, it's more of an API framework.
The general use case for Goliath is to serve data through JSON, XML or whatever format that can be consumed by front end web apps or other applications.
For example at PostRank, we use various Goliath servers to power our APIs which serve data displayed by the Rails applications.
Really great work! I just want to know what about using juggernaut for server push?
Does faye allow you to push a message through them using messaging queue like RabbitMQ?
Oh, and thanks so much for all your work Ryan. This just made my week. I've been spending time trying to figure out how to get node and ruby working together and you just obviated that.
Giving Rails, faye and Backbone.js a try now.
Hi all. this railscast is awesome. But i've question, how to push a message for specific client. For example in facebook, if somebody send me a message or tag my photo, that was notification only for me. Thanks
@users/1488: I would guess you have to use a separate channel per user. Then the trick is to get the application.js to listen on this channel, as it has to be generated per user. Not sure how to do that yet, but I'm sure someone more used to Javascript and Rails will be able to tell you how.
Nice cast! If you're already fronting your webapp with Nginx I can also recommend the Nginx HTTP Push module which is very easy to setup and does pretty much the same thing in this example. Then you can setup locations in your Ngixx conf where you can long poll for messages on various channels and HTTP post to another location from your Rails app, which Nginx will forward to all active connections to the relevant channel.
Easy and very resource friendly on your web server machine.
You can have a public "pull" location but protect your "push" location in the conf so that posting messages need to go through your Rails app, but you can also have public locations for pushing where you wouldn't even need to hit your Rails app to create a shoutbox or something.
Hi Gregor.
This is really interesting. Any chance that you can share a config example for setting up nginx_http_push_module with faye?
great post! small question though. but i'm wondering - how do i make faye server work automatically on production server ? right now i'm calling rack manually over ssh - there must be a better way :)
Great post! I have a question though. I have downloaded the source code for this episode. I start with the "chatter-before" project and follow along with the screencast.
My question is why when I send my curl command nothing happens? I have not set the faye token or set any security. I followed along exactly and just want the 'alert' function to happen before moving on.
How can I deploy it to heroku together with my rails app? Anyone did it?
why the respond from faye can not be understood by browser(the chat window and text field are not reloaded)?
it's k now, but the broadcasting doesn't work - it doesn't reload messages inside chat window, when anoyher client adds something
Has anybody had any luck testing Faye with Cucumber?
I've been fine testing Faye with Cucumber in a single browser session but as soon as one of my features spins up a second browser and starts testing the interaction between the two WebDriver hangs and times out. It's definitely Faye, probably the WebSocket connection, causing the issue. I have not found a work around. Not much information out there about it unfortunately.
What is to stop somebody from looking at the source javascript and extracting the FAYE_TOKEN manually, and using it via curl afterwards?
FAYE_TOKEN isn't in the source javascript. It's a token used on two backend servers which communicate between each other. The end user never sees, sends or intercepts that communication.
ah, ok, yes I see that now, thanks!
I want to use Faye on production server. how can I start faye server automatically or as a daemon process.
Because when I start faye server using SSH it shutdown as i close ssh connection. Please guide me its really urgent.
@adnan4721 you should start Faye using Thin (as a separate process). You'll find a Rackup example for that on the Faye site: http://faye.jcoglan.com/ruby.html
Put your config into faye_config.ru and start it with the following command:
thin -R faye_config.ru start
Since thin's default timeout is 30 seconds, it is better to use this:
faye_server = Faye::RackAdapter.new(:mount => '/faye', :timeout => 25)
Anybody able to get this working with an IPad?
@tatumszymczak Were you able to get this working? I've got the same problem. Thinking it may be related to mobile browsers
I just got this working. I had to adjust the variable
localhost
to my server's ip address in both theapplication.html.erb
(layout) file and theapplication.js
file.I'm in development mode. I can get faye working for my app however when I try from a different machine using the IP of my development machine. The changes do not occur. Any ideas why? I've tried to replace localhost with the IP address... but still no joy.
I can confirm what tatumszymczak said. It doesn't work for other ips in the network, be them PCs or mobile phones (HTC Desire for example).
I have changed from localhost to my network ip, so it should be working.
@Ryan Bates can you look into that man? Thanks
Edit: Nevermind, I discovered what the error was. I forgot to change localhost in the file application.html.erb (layouts) too. Hope that helps you folks :)
hi !
i got some js periodic js errors saying that the connexion has been interrupted while the page was loading every 20 30 seconds, whatever is the timeout.
Does anybody experience this kind of problem ?
Yes, i have the same problem but no solution.
A simple Procfile for chatter-after is:
Then run with "foreman start", and the main app is at http://localhost:5000
Hello,
I am trying to make a chat on my website looking like google talk. I
want to manage the disconnect event. A user can disconnect on several
way :
So, how can i detect when my connection on a channel is closed? Each
user has his own channel build with his id.
Thank you for help.
Please tag this episode with "async" and "asynchronous". It was really hard to dig back up, not remembering how the technology was applied or that the gem is called Faye.
Great Tutorial now only problem I have with this ( After upgrading to rails 3.1)
Missing template messages/create
I cloned the rails casts and setup the 260 after version in a clean directory.
create.js.erb is also there,
anyone an idea how to get this to work with 3.1? Thx!
A revisited episode of this would be fantastic as well as a look at alternatives :)
same thing
same
Same for me.
I've updated the Ip to be set for production, but the messages are not being transmitted. There is no problem with the connection as well as there is no error found when trying to do the message post in firebug. Can you guys suggest how I debug whats going on wrong?
I've updated the Ip to be set for production, but the messages are not being transmitted. There is no problem with the connection as well as there is no error found when trying to do the message post in firebug. Can you guys suggest how I debug whats going on wrong?
Hey Ryan nice episode but i have couple of questions.
First, is Faye a nice push server to use when there are thousands of requests coming at a time? Can it support 100,000 concurrent users like APE?
Secondly, if the answer is yes, please tell me the way to configure it as by default it can handle 1024 concurrent users.
Hi Ryan, How can we use this gem if our domain is on HTTPS? And how to use the ruby client available with the GEM, not using Net::HTTP.
How would you force the rendering of the create.js file as well on receiving a JSON message ( Among a JSON messge)?
I figured it out... I believe this is more of a hack but it could be usefull for others.
You can't render two views. So what i did was....
Now both the javascript will get rendered (empty string) and json will be rendered properly..
Is there a more elegant solution?
There is a faye-rails gem which makes integration much easier.
Just put this in your routes file:
and then this in your application.js
Browse to localhost:9292 and you should find everything works.
is this working for you ? if I set it to listen on 9292, it crashes right after start.
Whem im using it on its defaults - port 3000, and approach explained here in this railscast, it works perfectly using
curl
, but when I try to makeNet::HTTP
request in broadcast method, it fails on timeout.Any ideas how to make it work?
Hey guys,
Suggestions on this question? How to list active subscribers using Faye - Thanks.
You have mistyped:
Must be:
Note - this episode was written around version 0.6.x of the faye gem. If you're trying to upgrade to a current version (0.8.7 at time of writing) then you'll need to do the following:
First, add the following to your Gemfile
Second, add the following to your faye.ru file right after the require statements.
Thanks "Cailinanne"
Chunky Bacon!
if some one else has a problem with create.js using rails 3.2 you need to change the controller action create
Great solution, works for me .
The problem of create.js is over :)
Great resolution! Thanks a lot!
Between this and Private Pub seems like a great solution. I have a use case for this gem however I will be using devise for authentication and need to somehow get the current_user and have them show up in a chat window.
Does anyone know a clean way to get this or something similar working. It's kind of pointless to have a chat system with 20 people logged in whom you can't tell who's who.
Thanks!
Things I found useful while working on this:
everytime i want to start "rackup faye.ru -s thin -E production" i only get the error
`require': cannot load such file -- faye (LoadError) but the gem is installed.. anybody an idea ?
Include inside your Gemfile
gem "thin"
gem "faye"
Try adding
gem 'faye'
to your Gemfile and then update your faye.ru asI could not get the code provided by Ryan to work until I added the line
Faye::WebSocket.load_adapter('thin')
to my
faye.ru
file.I just want to point out that using eval to execute anything that comes over the channel is really insecure and opens you up to XSS attacks.
Also, Ryan forgot to delete the
FAYE_TOKEN
from outgoing messages in his Faye extension, so anyone who connects to his chat app could execute arbitrary code on all of the connected clients...faye is really great ...I was using private_pub for 2 months then due to slow ajax requests and using thin server which is not suitable for thousands for connections I used nodejs server and It's more fast than ruby server but I am facing problem in security as I have a chat application and I am using the simple script for running faye
'
var http = require('http'),
faye = require('faye');
var bayeux = new faye.NodeAdapter({mount: '/faye', timeout: 45});
console.log('faye starting');
bayeux.listen(8080);
'
I hope I could find anyone who is running the nodejs server to help me
Nice. Any idea on how to deploy with Capistrano? I didn't find recipes.
Many thanks in advance.
I found https://github.com/faye/faye/wiki/Deploy-Best-Practices
hi,,what are the changes required for this tutoial,me using rails 4.0.0 version
Faye is really nice! However, in a lot of companies a lot of ports are blocked. So the setup breaks.
Is there a way to run my Rails app AND the Faye app on the same port (80)?
For eyample, given your app runs on example.com:80, you could serve faye via proxying from a different vHost (faye.example.com:80 -> localhost:9292).
I build a web app using faye. Works great, but then I tried to access my site on android chrome and nothing. None of the js is getting executed on my android devices. Anyone know a fix? I tried to google and didn't have much luck.
If not getting the publishing to work on android, anyone got any ideas for fallback methods so at least the client initiating the change receives updates outside of faye?
Ok forget this comment. I'm an idiot. I was trying to load faye.js from localhost. Didn't update the application layout with prod location of faye.js. doh!
this should be so:
we have to check for message['ext'].nil? because if we don't and someone sends a request without the auth token, the server crashes.
Thanks David, this was annoying me!
Any idea why it just crashes the server like that? Seems pretty flimsy to me but what do I know.
Hey guys -
Does anyone know if there's a way to get the Faye server (the one that Thin is used for) to actually log anything to console?
When I rackup the Faye server, I don't have the nice Rails-y output in the terminal - it just seems to hang (though it's definitely serving requests, just not saying anything about what it's doing in the background).
Here's what I mean:
http://cl.ly/image/0r2f3S1Y3P1P
It'd be nice if I could specify something in the
faye.ru
file (some config option) that told Faye to expose verbose server logs.You can use
puts "code"
to print a log in your terminalNow that there's HTML5 Server-Sent Events, should one still use Faye?
(See how Juggernaut was 'depreciated' )
how to make that chat application ?
in which episode this chat application is created step by step ?
How to only update one partial, such as comments_count or notifiactions_count
Hey I was trying to invoke the message change for all pages so when i tried to use "/" i.e. root_path as a channel in broadcast method it didnt work but if i use any other link it works fine can some1 explain this ?