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
favicon = SiteSetting.favicon
next "" unless favicon
if Discourse.store.external?
begin begin
file = FileHelper.download( file = FileHelper.download(
UrlHelper.absolute(SiteSetting.site_favicon_url), UrlHelper.absolute(favicon.url),
max_file_size: 50.kilobytes, max_file_size: favicon.filesize,
tmp_file_name: FAVICON, tmp_file_name: FAVICON,
follow_redirect: true follow_redirect: true
) )
file ||= Tempfile.new([FAVICON, ".png"])
data = file.read file&.read || ""
file.unlink
data
rescue => e rescue => e
AdminDashboardData.add_problem_message('dashboard.bad_favicon_url', 1800) AdminDashboardData.add_problem_message('dashboard.bad_favicon_url', 1800)
Rails.logger.debug("Invalid favicon_url #{SiteSetting.site_favicon_url}: #{e}\n#{e.backtrace}") 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
stub_request(:get, url).to_return(status: 404)
get '/favicon/proxied' get '/favicon/proxied'
favicon = File.read(Rails.root + "public/images/default-favicon.png")
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(response.content_type).to eq('image/png') expect(response.content_type).to eq('image/png')
expect(response.body.bytesize).to eq(favicon.bytesize) expect(response.body.bytesize).to eq(SiteSetting.favicon.filesize)
end
it 'returns the configured favicon' do
SiteSetting.favicon = upload
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
describe 'external store' do
let(:upload) do
Upload.create!(
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
before do
SiteSetting.enable_s3_uploads = true
SiteSetting.s3_access_key_id = 'X'
SiteSetting.s3_secret_access_key = 'X'
end end
it 'can proxy a favicon correctly' do it 'can proxy a favicon correctly' do
url = UrlHelper.absolute(upload.url)
SiteSetting.favicon = upload SiteSetting.favicon = upload
stub_request(:get, url).to_return(status: 200, body: png)
stub_request(:get, "https:/#{upload.url}")
.to_return(status: 200, body: file)
get '/favicon/proxied' get '/favicon/proxied'
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(response.content_type).to eq('image/png') expect(response.content_type).to eq('image/png')
expect(response.body.bytesize).to eq(png.bytesize) expect(response.body.bytesize).to eq(upload.filesize)
end
end end
end end