diff --git a/config/application.rb b/config/application.rb index eb0daffde..8d1ff37a0 100644 --- a/config/application.rb +++ b/config/application.rb @@ -135,9 +135,6 @@ module Discourse # supports etags (post 1.7) config.middleware.delete Rack::ETag - require 'middleware/apply_cdn' - config.middleware.use Middleware::ApplyCDN - # route all exceptions via our router config.exceptions_app = self.routes diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 4e6222ed1..feae6e063 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -945,6 +945,7 @@ en: s3_access_key_id: "The Amazon S3 access key id that will be used to upload images." s3_secret_access_key: "The Amazon S3 secret access key that will be used to upload images." s3_region: "The Amazon S3 region name that will be used to upload images." + s3_cdn_url: "The CDN URL to use for all s3 assets (for example: https://cdn.somewhere.com). WARNING: after changing this setting you must rebake all old posts." avatar_sizes: "List of automatically generated avatar sizes." diff --git a/config/site_settings.yml b/config/site_settings.yml index aa38b98d2..088551919 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -531,7 +531,10 @@ files: enum: 'S3RegionSiteSetting' s3_upload_bucket: default: '' - regex: "^[^A-Z._]+$" + regex: '^[^A-Z._]+$' + s3_cdn_url: + default: '' + regex: '^https?:\/\/.+[^\/]$' allow_profile_backgrounds: client: true default: true diff --git a/lib/middleware/apply_cdn.rb b/lib/middleware/apply_cdn.rb deleted file mode 100644 index 60995b476..000000000 --- a/lib/middleware/apply_cdn.rb +++ /dev/null @@ -1,24 +0,0 @@ -module Middleware - - class ApplyCDN - - def initialize(app, settings={}) - @app = app - end - - def call(env) - status, headers, response = @app.call(env) - - if Discourse.asset_host.present? && - Discourse.store.external? && - (headers["Content-Type"].start_with?("text/") || - headers["Content-Type"].start_with?("application/json")) - response.body = response.body.gsub(Discourse.store.absolute_base_url, Discourse.asset_host) - end - - [status, headers, response] - end - - end - -end diff --git a/lib/pretty_text.rb b/lib/pretty_text.rb index de418dc18..9652dc2b5 100644 --- a/lib/pretty_text.rb +++ b/lib/pretty_text.rb @@ -208,18 +208,33 @@ module PrettyText options[:topicId] = opts[:topic_id] sanitized = markdown(text.dup, options) - sanitized = add_rel_nofollow_to_user_content(sanitized) if !options[:omit_nofollow] && SiteSetting.add_rel_nofollow_to_user_content - sanitized + + doc = Nokogiri::HTML.fragment(sanitized) + + if !options[:omit_nofollow] && SiteSetting.add_rel_nofollow_to_user_content + add_rel_nofollow_to_user_content(doc) + end + + if SiteSetting.s3_cdn_url.present? && SiteSetting.enable_s3_uploads + add_s3_cdn(doc) + end + + doc.to_html end - def self.add_rel_nofollow_to_user_content(html) + def self.add_s3_cdn(doc) + doc.css("img").each do |img| + img["src"] = img["src"].sub(Discourse.store.absolute_base_url, SiteSetting.s3_cdn_url) + end + end + + def self.add_rel_nofollow_to_user_content(doc) whitelist = [] domains = SiteSetting.exclude_rel_nofollow_domains whitelist = domains.split('|') if domains.present? site_uri = nil - doc = Nokogiri::HTML.fragment(html) doc.css("a").each do |l| href = l["href"].to_s begin @@ -238,7 +253,6 @@ module PrettyText l["rel"] = "nofollow" end end - doc.to_html end class DetectedLink diff --git a/spec/components/pretty_text_spec.rb b/spec/components/pretty_text_spec.rb index 5b1dfd26c..4f6a0f6f4 100644 --- a/spec/components/pretty_text_spec.rb +++ b/spec/components/pretty_text_spec.rb @@ -308,4 +308,17 @@ describe PrettyText do expect(PrettyText.cook("```cpp\ncpp\n```")).to match_html("<p></p><pre><code class='lang-cpp'>cpp</code></pre>") end + it 'can substitute s3 cdn correctly' do + SiteSetting.enable_s3_uploads = true + SiteSetting.s3_access_key_id = "XXX" + SiteSetting.s3_secret_access_key = "XXX" + SiteSetting.s3_upload_bucket = "test" + SiteSetting.s3_cdn_url = "https://awesome.cdn" + + raw = "<img src='#{Discourse.store.absolute_base_url}/original/9/9/99c9384b8b6d87f8509f8395571bc7512ca3cad1.jpg'" + cooked = "<p><img src='https://awesome.cdn/original/9/9/99c9384b8b6d87f8509f8395571bc7512ca3cad1.jpg'></p>" + + expect(PrettyText.cook(raw)).to match_html(cooked) + end + end