Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Faye on Heroku: Cross-Domain Issues

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.

like image 846
b.john.son Avatar asked Nov 14 '22 00:11

b.john.son


1 Answers

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...)

like image 116
soychicka Avatar answered Dec 22 '22 14:12

soychicka