FIX: `StaticController#favicon` reads from disk when using local store. (#7160)

Since uploads site settings are now backed by an actual upload, we don't
have to reach over the network just to fetch the favicon. Instead, we
can just read the upload directly from disk.
This commit is contained in:
Guo Xiang Tan 2019-03-14 04:17:36 +08:00 committed by GitHub
parent 4f74210949
commit 1c6a2262b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 39 deletions

View File

@ -62,10 +62,7 @@ const Discourse = Ember.Application.extend({
@observes("notifyCount") @observes("notifyCount")
faviconChanged() { faviconChanged() {
if (Discourse.User.currentProp("dynamic_favicon")) { if (Discourse.User.currentProp("dynamic_favicon")) {
let url = Discourse.SiteSettings.site_favicon_url; const url = Discourse.getURL("/favicon/proxied");
if (/^http/.test(url)) {
url = Discourse.getURL("/favicon/proxied?" + encodeURIComponent(url));
}
new window.Favcount(url).set(this.get("notifyCount")); new window.Favcount(url).set(this.get("notifyCount"));
} }
}, },

View File

@ -124,22 +124,28 @@ class StaticController < ApplicationController
is_asset_path is_asset_path
hijack do hijack do
data = DistributedMemoizer.memoize(FAVICON + SiteSetting.site_favicon_url, 60 * 30) do data = DistributedMemoizer.memoize("FAVICON#{SiteSetting.favicon&.id}", 60 * 30) do
begin favicon = SiteSetting.favicon
file = FileHelper.download( next "" unless favicon
UrlHelper.absolute(SiteSetting.site_favicon_url),
max_file_size: 50.kilobytes, if Discourse.store.external?
tmp_file_name: FAVICON, begin
follow_redirect: true file = FileHelper.download(
) UrlHelper.absolute(favicon.url),
file ||= Tempfile.new([FAVICON, ".png"]) max_file_size: favicon.filesize,
data = file.read tmp_file_name: FAVICON,
file.unlink follow_redirect: true
data )
rescue => e
AdminDashboardData.add_problem_message('dashboard.bad_favicon_url', 1800) file&.read || ""
Rails.logger.debug("Invalid favicon_url #{SiteSetting.site_favicon_url}: #{e}\n#{e.backtrace}") rescue => e
"" AdminDashboardData.add_problem_message('dashboard.bad_favicon_url', 1800)
Rails.logger.warn("Failed to fetch faivcon #{favicon.url}: #{e}\n#{e.backtrace}")
ensure
file&.unlink
end
else
File.read(Rails.root.join("public", favicon.url[1..-1]))
end end
end end

View File

@ -4,38 +4,65 @@ describe StaticController do
let(:upload) { Fabricate(:upload) } let(:upload) { Fabricate(:upload) }
context '#favicon' do context '#favicon' do
let(:png) { Base64.decode64("R0lGODlhAQABALMAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwICAgP8AAAD/AP//AAAA//8A/wD//wBiZCH5BAEAAA8ALAAAAAABAAEAAAQC8EUAOw==") } let(:filename) { 'smallest.png' }
let(:file) { file_from_fixtures(filename) }
before { FinalDestination.stubs(:lookup_ip).returns("1.2.3.4") } let(:upload) do
UploadCreator.new(file, filename).create_for(Discourse.system_user.id)
end
after do after do
DistributedMemoizer.flush! DistributedMemoizer.flush!
end end
it 'returns the default favicon for a missing download' do describe 'local store' do
url = UrlHelper.absolute(upload.url) it 'returns the default favicon if favicon has not been configured' do
SiteSetting.favicon = upload get '/favicon/proxied'
stub_request(:get, url).to_return(status: 404)
get '/favicon/proxied' expect(response.status).to eq(200)
expect(response.content_type).to eq('image/png')
expect(response.body.bytesize).to eq(SiteSetting.favicon.filesize)
end
favicon = File.read(Rails.root + "public/images/default-favicon.png") it 'returns the configured favicon' do
SiteSetting.favicon = upload
expect(response.status).to eq(200) get '/favicon/proxied'
expect(response.content_type).to eq('image/png')
expect(response.body.bytesize).to eq(favicon.bytesize) expect(response.status).to eq(200)
expect(response.content_type).to eq('image/png')
expect(response.body.bytesize).to eq(upload.filesize)
end
end end
it 'can proxy a favicon correctly' do describe 'external store' do
url = UrlHelper.absolute(upload.url) let(:upload) do
SiteSetting.favicon = upload Upload.create!(
stub_request(:get, url).to_return(status: 200, body: png) url: '//s3-upload-bucket.s3-us-east-1.amazonaws.com/somewhere/a.png',
original_filename: filename,
filesize: file.size,
user_id: Discourse.system_user.id
)
end
get '/favicon/proxied' before do
SiteSetting.enable_s3_uploads = true
SiteSetting.s3_access_key_id = 'X'
SiteSetting.s3_secret_access_key = 'X'
end
expect(response.status).to eq(200) it 'can proxy a favicon correctly' do
expect(response.content_type).to eq('image/png') SiteSetting.favicon = upload
expect(response.body.bytesize).to eq(png.bytesize)
stub_request(:get, "https:/#{upload.url}")
.to_return(status: 200, body: file)
get '/favicon/proxied'
expect(response.status).to eq(200)
expect(response.content_type).to eq('image/png')
expect(response.body.bytesize).to eq(upload.filesize)
end
end end
end end