Permalink
Browse files

FEATURE: allow long polling to go to a different url

Added the site setting long_polling_base_url , this allows you
to farm long polling to a different server.

This setting is very important if a CDN is serving dynamic content.
  • Loading branch information...
1 parent 1962563 commit aa9b3bb35accce498438e22344a3c352a9bc6592 @SamSaffron SamSaffron committed Oct 24, 2014
View
@@ -163,7 +163,7 @@ GEM
mime-types (~> 1.16)
treetop (~> 1.4.8)
memory_profiler (0.0.4)
- message_bus (1.0.0)
+ message_bus (1.0.4)
eventmachine
rack (>= 1.1.3)
redis
@@ -2,7 +2,7 @@
Subscribes to user events on the message bus
**/
export default {
- name: "subscribe-user-notifications",
+ name: 'subscribe-user-notifications',
after: 'message-bus',
initialize: function(container) {
var user = Discourse.User.current();
@@ -13,14 +13,25 @@ export default {
var bus = Discourse.MessageBus;
bus.callbackInterval = siteSettings.anon_polling_interval;
bus.backgroundCallbackInterval = siteSettings.background_polling_interval;
+ bus.baseUrl = siteSettings.long_polling_base_url;
+
+ if (bus.baseUrl !== '/') {
+ // zepto compatible, 1 param only
+ bus.ajax = function(opts){
+ opts.headers = opts.headers || {};
+ opts.headers['X-Shared-Session-Key'] = $('meta[name=shared_session_key]').attr('content');
+ return $.ajax(opts);
+ };
+ } else {
+ bus.baseUrl = Discourse.getURL('/');
+ }
if (user) {
bus.callbackInterval = siteSettings.polling_interval;
bus.enableLongPolling = true;
- bus.baseUrl = Discourse.getURL("/");
if (user.admin || user.moderator) {
- bus.subscribe("/flagged_counts", function(data) {
+ bus.subscribe('/flagged_counts', function(data) {
user.set('site_flagged_posts_count', data.total);
});
}
@@ -11,6 +11,17 @@ module ApplicationHelper
include CanonicalURL::Helpers
include ConfigurableUrls
+ def shared_session_key
+ if SiteSetting.long_polling_base_url != '/'.freeze && current_user
+ sk = "shared_session_key"
+ return request.env[sk] if request.env[sk]
+
+ request.env[sk] = key = (session[sk] ||= SecureRandom.hex)
+ $redis.setex "#{sk}_#{key}", 7.days, current_user.id.to_s
+ key
+ end
+ end
+
def script(*args)
if SiteSetting.enable_cdn_js_debugging && GlobalSetting.cdn_url
tags = javascript_include_tag(*args, "crossorigin" => "anonymous")
@@ -10,6 +10,10 @@
<meta name="fragment" content="!">
<%- end %>
+ <%- if shared_session_key %>
+ <meta name="shared_session_key" content="<%= shared_session_key %>">
+ <%- end %>
+
<%= script "preload_store" %>
<%= script "locales/#{I18n.locale}" %>
<%= script "vendor" %>
@@ -2,6 +2,14 @@
RailsMultisite::ConnectionManagement.current_db
end
+MessageBus.extra_response_headers_lookup do |env|
+ {
+ "Access-Control-Allow-Origin" => Discourse.base_url,
+ "Access-Control-Allow-Methods" => "GET, POST",
+ "Access-Control-Allow-Headers" => "X-SILENCE-LOGGER, X-Shared-Session-Key"
+ }
+end
+
MessageBus.user_id_lookup do |env|
user = CurrentUser.lookup_from_env(env)
user.id if user
@@ -698,6 +698,7 @@ en:
enable_private_messages: "Allow trust level 1 users to create private messages and reply to private messages"
enable_long_polling: "Message bus used for notification can use long polling"
+ long_polling_base_url: "Base URL used for long polling (when a CDN is serving dynamic content, be sure to set this to origin pull) eg: http://origin.site.com"
long_polling_interval: "Amount of time the server should wait before responding to clients when there is no data to send (logged on users only)"
polling_interval: "When not long polling, how often should logged on clients poll in milliseconds"
anon_polling_interval: "How often should anonymous clients poll in milliseconds"
@@ -616,6 +616,9 @@ developer:
client: true
default: true
long_polling_interval: 25000
+ long_polling_base_url:
+ client: true
+ default: '/'
background_polling_interval:
client: true
default: 60000
@@ -18,6 +18,17 @@ def initialize(env)
def current_user
return @env[CURRENT_USER_KEY] if @env.key?(CURRENT_USER_KEY)
+ # bypass if we have the shared session header
+ if shared_key = @env['HTTP_X_SHARED_SESSION_KEY']
+ uid = $redis.get("shared_session_key_#{shared_key}")
+ user = nil
+ if uid
+ user = User.find_by(id: uid.to_i)
+ end
+ @env[CURRENT_USER_KEY] = user
+ return user
+ end
+
request = @request
auth_token = request.cookies[TOKEN_COOKIE]

0 comments on commit aa9b3bb

Please sign in to comment.