DEV: apply allow origin response header for CDN requests. (#11893)

Currently, it creates a CORS error while accessing those static files.
This commit is contained in:
Vinoth Kannan 2021-01-29 07:44:49 +05:30 committed by GitHub
parent 4af4d36175
commit a5923ad603
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 62 additions and 6 deletions

View File

@ -680,6 +680,10 @@ class ApplicationController < ActionController::Base
raise ApplicationController::RenderEmpty.new unless ((request.format && request.format.json?) || request.xhr?)
end
def apply_cdn_headers
Discourse.apply_cdn_headers(response.headers) if Discourse.is_cdn_request?(request.env, request.method)
end
def self.requires_login(arg = {})
@requires_login_arg = arg
end

View File

@ -3,6 +3,8 @@
class HighlightJsController < ApplicationController
skip_before_action :preload_json, :redirect_to_login_if_required, :check_xhr, :verify_authenticity_token, only: [:show]
before_action :apply_cdn_headers, only: [:show]
def show
no_cookies

View File

@ -7,6 +7,8 @@ class StaticController < ApplicationController
skip_before_action :preload_json, only: [:brotli_asset, :cdn_asset, :enter, :favicon, :service_worker_asset]
skip_before_action :handle_theme, only: [:brotli_asset, :cdn_asset, :enter, :favicon, :service_worker_asset]
before_action :apply_cdn_headers, only: [:brotli_asset, :cdn_asset, :enter, :favicon, :service_worker_asset]
PAGES_WITH_EMAIL_PARAM = ['login', 'password_reset', 'signup']
MODAL_PAGES = ['password_reset', 'signup']

View File

@ -3,6 +3,8 @@
class StylesheetsController < ApplicationController
skip_before_action :preload_json, :redirect_to_login_if_required, :check_xhr, :verify_authenticity_token, only: [:show, :show_source_map, :color_scheme]
before_action :apply_cdn_headers, only: [:show, :show_source_map, :color_scheme]
def show_source_map
show_resource(source_map: true)
end

View File

@ -3,6 +3,8 @@
class SvgSpriteController < ApplicationController
skip_before_action :preload_json, :redirect_to_login_if_required, :check_xhr, :verify_authenticity_token, only: [:show, :search, :svg_icon]
before_action :apply_cdn_headers, only: [:show, :search, :svg_icon]
requires_login except: [:show, :svg_icon]
def show

View File

@ -11,7 +11,7 @@ class ThemeJavascriptsController < ApplicationController
only: [:show]
)
before_action :is_asset_path, :no_cookies, only: [:show]
before_action :is_asset_path, :no_cookies, :apply_cdn_headers, only: [:show]
def show
raise Discourse::NotFound unless last_modified.present?

View File

@ -8,7 +8,7 @@ class UploadsController < ApplicationController
skip_before_action :preload_json, :check_xhr, :redirect_to_login_if_required, only: [:show, :show_short, :show_secure]
protect_from_forgery except: :show
before_action :is_asset_path, only: [:show, :show_short, :show_secure]
before_action :is_asset_path, :apply_cdn_headers, only: [:show, :show_short, :show_secure]
SECURE_REDIRECT_GRACE_SECONDS = 5

View File

@ -4,6 +4,8 @@ class UserAvatarsController < ApplicationController
skip_before_action :preload_json, :redirect_to_login_if_required, :check_xhr, :verify_authenticity_token, only: [:show, :show_letter, :show_proxy_letter]
before_action :apply_cdn_headers, only: [:show, :show_letter, :show_proxy_letter]
def refresh_gravatar
user = User.find_by(username_lower: params[:username].downcase)
guardian.ensure_can_edit!(user)

View File

@ -25,15 +25,18 @@ class Discourse::Cors
status, headers, body = @app.call(env)
headers ||= {}
Discourse::Cors.apply_headers(cors_origins, env, headers) if cors_origins
Discourse::Cors.apply_headers(cors_origins, env, headers)
[status, headers, body]
end
def self.apply_headers(cors_origins, env, headers)
origin = nil
request_method = env['REQUEST_METHOD']
if cors_origins
if env['SCRIPT_NAME'] == "/assets" && Discourse.is_cdn_request?(env, request_method)
Discourse.apply_cdn_headers(headers)
elsif cors_origins
origin = nil
if origin = env['HTTP_ORIGIN']
origin = nil unless cors_origins.include?(origin)
end
@ -48,6 +51,6 @@ class Discourse::Cors
end
end
if GlobalSetting.enable_cors
if GlobalSetting.enable_cors || GlobalSetting.cdn_url
Rails.configuration.middleware.insert_before ActionDispatch::Flash, Discourse::Cors
end

View File

@ -17,6 +17,7 @@ end
module Discourse
DB_POST_MIGRATE_PATH ||= "db/post_migrate"
REQUESTED_HOSTNAME ||= "REQUESTED_HOSTNAME"
require 'sidekiq/exception_handler'
class SidekiqExceptionHandler
@ -917,6 +918,24 @@ module Discourse
def self.is_parallel_test?
ENV['RAILS_ENV'] == "test" && ENV['TEST_ENV_NUMBER']
end
CDN_REQUEST_METHODS ||= ["GET", "HEAD", "OPTIONS"]
def self.is_cdn_request?(env, request_method)
return unless CDN_REQUEST_METHODS.include?(request_method)
cdn_hostnames = GlobalSetting.cdn_hostnames
return if cdn_hostnames.blank?
requested_hostname = env[REQUESTED_HOSTNAME] || env[Rack::HTTP_HOST]
cdn_hostnames.include?(requested_hostname)
end
def self.apply_cdn_headers(headers)
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = CDN_REQUEST_METHODS.join(", ")
headers
end
end
# rubocop:enable Style/GlobalVars

View File

@ -17,6 +17,7 @@ module Middleware
allowed_hostnames = RailsMultisite::ConnectionManagement.current_db_hostnames
requested_hostname = env[Rack::HTTP_HOST]
env[Discourse::REQUESTED_HOSTNAME] = requested_hostname
env[Rack::HTTP_HOST] = allowed_hostnames.find { |h| h == requested_hostname } || Discourse.current_hostname
@app.call(env)

View File

@ -116,6 +116,25 @@ describe StaticController do
File.delete(file_path)
end
end
it 'has correct cors headers for brotli assets' do
begin
assets_path = Rails.root.join("public/assets")
FileUtils.mkdir_p(assets_path)
file_path = assets_path.join("test.js.br")
File.write(file_path, 'fake brotli file')
GlobalSetting.stubs(:cdn_url).returns("https://www.example.com/")
get "/brotli_asset/test.js"
expect(response.status).to eq(200)
expect(response.headers["Access-Control-Allow-Origin"]).to match("*")
ensure
File.delete(file_path)
end
end
end
context '#cdn_asset' do