5

I'm currently hosting both my rails app and a faye-server app on Heroku. The faye server has been cloned from here (https://github.com/ntenisOT/Faye-Heroku-Cedar) and seems to be running correctly. I have disabled websockets, as they are not supported on Heroku. Despite the claim on Faye's site that:

"Faye clients and servers transparently support cross-domain communication, so your client can connect to a server on any domain you like without further configuration."

I am still running into this error when I try to post to a faye channel:

    XMLHttpRequest cannot load http://MYFAYESERVER.herokuapp.com. Origin http://MYAPPURL.herokuapp.com is not allowed by Access-Control-Allow-Origin.

I have read about CORS and tried implementing some solutions outlined here: http://www.tsheffler.com/blog/?p=428 but have so far had no luck. I'd love to hear from someone who:

1) Has a rails app hosted on Heroku 2) Has a faye server hosted on Heroku 3) Has the two of them successfully communicating with each other!

Thanks so much.

b.john.son
  • 73
  • 1
  • 5

2 Answers2

1

I just got my faye and rails apps hosted on heroku communicating within the past hour or so... here are my observations:

  1. Make sure your FAYE_TOKEN is set on all of your servers if you're using an env variable.

  2. Disable websockets, which you've already done... client.disable(...) didn't work for me, I used Faye.Transport.WebSocket.isUsable = function(_,c) { c(false) } instead.

  3. This may or may not apply to you, but was the hardest thing to track down for me... in my dev environment, the port my application is running on will be tacked onto the end of the specified hostname for my faye server... but this appeared to cause a failure to communicate in production. I worked around that by creating a broadcast_server_uri method in application_controller.rb that handles inclusion of a port when necessary, and then use that anywhere I spin up a new channel.

....

class ApplicationController < ActionController::Base
  def broadcast_server
      if request.port.to_i != 80
        "http://my-faye-server.herokuapp.com:80/faye"
      else
        "http://my-faye-server.herokuapp.com/faye"
      end            
  end
  helper_method :broadcast_server

  def broadcast_message(channel, data)
    message = { :ext => {:auth_token => FAYE_TOKEN}, :channel => channel, :data => data}
    uri = URI.parse(broadcast_server)
    Net::HTTP.post_form(uri, :message => message.to_json)
  end


end

And in my app javascript, including

<script>
  var broadcast_server = "<%= broadcast_server %>"
  var faye;
$(function() {
    faye = new Faye.Client(broadcast_server);
    faye.setHeader('Access-Control-Allow-Origin', '*');
    faye.connect();
    Faye.Transport.WebSocket.isUsable = function(_,c) { c(false) }

      // spin off your subscriptions here
  });
</script>

FWIW, I wouldn't stress about setting Access-Control-Allow-Origin as it doesn't seem to be making a difference either way - I see XMLHttpRequest cannot load http://... regardless, but this should still works well enough to get you unblocked. (although I'd love to learn of a cleaner solution...)

soychicka
  • 68
  • 6
  • Hi Soychicka, thanks so much for this. I'm checking it out now. One question, did you modify the ApplicationController for your app or create one for the faye server? – b.john.son Aug 07 '12 at 23:01
  • Hmm... still not working. The subscription seems to be fine, but when I publish it is not picked up. The faye.publish('/channel', {data:"data"}) command does send a POST to the faye server, but there doesn't seem to be a response. One question, when you post, is your request payload encrypted like this: message=%5B%7B%22channel%22%3A%22%2Ffoo%22%2C%22data%22%3A%7B%22text%22%3A%22Hi%20there%22%7D%2C%22clientId%22%3A%22bqk8vbj7v6j10jqsoogrxr7cn%22%2C%22id%22%3A%221hj9hf41cgaa8m1x3nllu0zyzphv%22%7D%5D – b.john.son Aug 07 '12 at 23:50
  • How did you set up your faye server on heroku? Did you use a particular github repo? – b.john.son Aug 08 '12 at 00:33
  • The issue turned out to be that I was using an old version of faye on my server and also had a ServerAuth method that was spitting some weird things back at me. But the above was really very helpful. If you have a chance, could you let me know how your faye server is set up? Thanks! – b.john.son Aug 08 '12 at 01:48
  • Sorry for the delay... the mod was for the app's AppController. Server is based on https://github.com/ntenisOT/Faye-Heroku-Cedar.git, except I'm using env variables to set the Faye token in my initializer, my repo is at https://github.com/soychicka/faye-server.git. – soychicka Aug 08 '12 at 16:25
  • And I'm only using the faye server to push status updates to browser-based clients using the broadcast_message method above... `Net::HTTP.post_form(uri, :message => message.to_json)` seems to be preserving my message as json. – soychicka Aug 08 '12 at 16:32
0

Can't say I have used Rails/Faye on Heroku but have you tried setting the Access-Control-Allow-Origin header to something like Access-Control-Allow-Origin: your-domain.com?

For testing you could also do Access-Control-Allow-Origin: * to see if that helps

Custom headers

Some services require the use of additional HTTP headers to connect to their Bayeux server. You can add these headers using the setHeader() method, and they will be sent if the underlying transport supports user-defined headers (currently long-polling only).

client.setHeader('Authorization', 'OAuth abcd-1234');

Source: http://faye.jcoglan.com/browser.html

So try client.setHeader('Access-Control-Allow-Origin', '*');

arcyqwerty
  • 10,325
  • 4
  • 47
  • 84