diff --git a/Gemfile.lock b/Gemfile.lock
index 0673cfb167b..0fe4be8d306 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -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
diff --git a/app/assets/javascripts/discourse/initializers/subscribe-user-notifications.js.es6 b/app/assets/javascripts/discourse/initializers/subscribe-user-notifications.js.es6
index 0104f6b2ddf..fe79cb98e9e 100644
--- a/app/assets/javascripts/discourse/initializers/subscribe-user-notifications.js.es6
+++ b/app/assets/javascripts/discourse/initializers/subscribe-user-notifications.js.es6
@@ -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);
});
}
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index ee4f386ac47..4493cd92bdb 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -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")
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index 67dd5a727b8..b1d4532e0e3 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -10,6 +10,10 @@
<%- end %>
+ <%- if shared_session_key %>
+
+ <%- end %>
+
<%= script "preload_store" %>
<%= script "locales/#{I18n.locale}" %>
<%= script "vendor" %>
diff --git a/config/initializers/04-message_bus.rb b/config/initializers/04-message_bus.rb
index efc333f2d62..18c4f0c878a 100644
--- a/config/initializers/04-message_bus.rb
+++ b/config/initializers/04-message_bus.rb
@@ -2,6 +2,14 @@ MessageBus.site_id_lookup do
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
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index df85e0096c5..ac0b5543ee0 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -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"
diff --git a/config/site_settings.yml b/config/site_settings.yml
index 9189bd1abe5..d34d8faa20a 100644
--- a/config/site_settings.yml
+++ b/config/site_settings.yml
@@ -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
diff --git a/lib/auth/default_current_user_provider.rb b/lib/auth/default_current_user_provider.rb
index 4b71c9682b4..94c7a8e914a 100644
--- a/lib/auth/default_current_user_provider.rb
+++ b/lib/auth/default_current_user_provider.rb
@@ -18,6 +18,17 @@ class Auth::DefaultCurrentUserProvider
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]