mirror of
https://github.com/discourse/discourse-ai.git
synced 2025-02-16 16:34:45 +00:00
FIX: automatically bust cache for share ai assets (#942)
* FIX: automatically bust cache for share ai assets CDNs can be configured to strip query params in Discourse hosting. This is generally safe, but in this case we had no way of busting the cache using the path. New design properly caches and properly breaks busts the cache if asset changes so we don't need to worry about versions * one day I will set up conditional lint on save :)
This commit is contained in:
parent
2c78961bed
commit
86cf4ccba7
@ -7,7 +7,8 @@ module DiscourseAi
|
||||
requires_login only: %i[create update destroy]
|
||||
before_action :require_site_settings!
|
||||
|
||||
skip_before_action :preload_json, :check_xhr, only: %i[show]
|
||||
skip_before_action :preload_json, :check_xhr, only: %i[show asset]
|
||||
skip_before_action :verify_authenticity_token, only: ["asset"]
|
||||
|
||||
def create
|
||||
ensure_allowed_create!
|
||||
@ -50,6 +51,30 @@ module DiscourseAi
|
||||
end
|
||||
end
|
||||
|
||||
def asset
|
||||
no_cookies
|
||||
|
||||
name = params[:name]
|
||||
path, content_type =
|
||||
if name == "share"
|
||||
%w[share.css text/css]
|
||||
elsif name == "highlight"
|
||||
%w[highlight.min.js application/javascript]
|
||||
else
|
||||
raise Discourse::NotFound
|
||||
end
|
||||
|
||||
content = File.read(DiscourseAi.public_asset_path("ai-share/#{path}"))
|
||||
|
||||
# note, path contains a ":version" which automatically busts the cache
|
||||
# based on file content, so this is safe
|
||||
response.headers["Last-Modified"] = 10.years.ago.httpdate
|
||||
response.headers["Content-Length"] = content.bytesize.to_s
|
||||
immutable_for 1.year
|
||||
|
||||
render plain: content, disposition: :nil, content_type: content_type
|
||||
end
|
||||
|
||||
def preview
|
||||
ensure_allowed_preview!
|
||||
data = SharedAiConversation.build_conversation_data(@topic, include_usernames: true)
|
||||
|
@ -2,13 +2,29 @@
|
||||
module DiscourseAi
|
||||
module AiBot
|
||||
module SharedAiConversationsHelper
|
||||
# bump up version when assets change
|
||||
# long term we may want to change this cause it is hard to remember
|
||||
# to bump versions, but for now this does the job
|
||||
VERSION = "1"
|
||||
# keeping it here for caching
|
||||
def self.share_asset_url(asset_name)
|
||||
if !%w[share.css highlight.js].include?(asset_name)
|
||||
raise StandardError, "unknown asset type #{asset_name}"
|
||||
end
|
||||
|
||||
def share_asset_url(short_path)
|
||||
::UrlHelper.absolute("/plugins/discourse-ai/ai-share/#{short_path}?#{VERSION}")
|
||||
@urls ||= {}
|
||||
url = @urls[asset_name]
|
||||
return url if url
|
||||
|
||||
path = asset_name
|
||||
path = "highlight.min.js" if asset_name == "highlight.js"
|
||||
|
||||
content = File.read(DiscourseAi.public_asset_path("ai-share/#{path}"))
|
||||
sha1 = Digest::SHA1.hexdigest(content)
|
||||
|
||||
url = "/discourse-ai/ai-bot/shared-ai-conversations/asset/#{sha1}/#{asset_name}"
|
||||
|
||||
@urls[asset_name] = GlobalPath.cdn_path(url)
|
||||
end
|
||||
|
||||
def share_asset_url(asset_name)
|
||||
DiscourseAi::AiBot::SharedAiConversationsHelper.share_asset_url(asset_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -10,7 +10,7 @@
|
||||
<meta name="twitter:title" content="<%= I18n.t("discourse_ai.share_ai.title", title: @shared_conversation.title, site_name: SiteSetting.title) %>">
|
||||
<meta name="twitter:description" content="<%= @shared_conversation.formatted_excerpt %>">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<link rel="stylesheet" href="<%= ::UrlHelper.absolute("/plugins/discourse-ai/ai-share/share.css?v=1") %>">
|
||||
<link rel="stylesheet" href="<%= share_asset_url("share.css") %>">
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
@ -54,7 +54,7 @@
|
||||
</article>
|
||||
<% end %>
|
||||
</section>
|
||||
<script src="<%= share_asset_url("highlight.min.js") %>" nonce="<%= csp_nonce_placeholder %>" ></script>
|
||||
<script src="<%= share_asset_url("highlight.js") %>" nonce="<%= csp_nonce_placeholder %>" ></script>
|
||||
<script nonce="<%= csp_nonce_placeholder %>">
|
||||
document.querySelectorAll('pre code').forEach((el) => {
|
||||
hljs.highlightElement(el);
|
||||
|
@ -30,6 +30,7 @@ DiscourseAi::Engine.routes.draw do
|
||||
post "/" => "shared_ai_conversations#create"
|
||||
delete "/:share_key" => "shared_ai_conversations#destroy"
|
||||
get "/:share_key" => "shared_ai_conversations#show"
|
||||
get "/asset/:version/:name" => "shared_ai_conversations#asset"
|
||||
get "/preview/:topic_id" => "shared_ai_conversations#preview"
|
||||
end
|
||||
|
||||
|
@ -43,6 +43,10 @@ register_asset "stylesheets/modules/ai-bot/common/ai-artifact.scss"
|
||||
|
||||
module ::DiscourseAi
|
||||
PLUGIN_NAME = "discourse-ai"
|
||||
|
||||
def self.public_asset_path(name)
|
||||
File.expand_path(File.join(__dir__, "public", name))
|
||||
end
|
||||
end
|
||||
|
||||
Rails.autoloaders.main.push_dir(File.join(__dir__, "lib"), namespace: ::DiscourseAi)
|
||||
|
@ -294,6 +294,30 @@ RSpec.describe DiscourseAi::AiBot::SharedAiConversationsController do
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET asset" do
|
||||
let(:helper) { Class.new { extend DiscourseAi::AiBot::SharedAiConversationsHelper } }
|
||||
|
||||
it "renders highlight js correctly" do
|
||||
get helper.share_asset_url("highlight.js")
|
||||
|
||||
expect(response).to be_successful
|
||||
expect(response.headers["Content-Type"]).to eq("application/javascript; charset=utf-8")
|
||||
|
||||
js = File.read(DiscourseAi.public_asset_path("ai-share/highlight.min.js"))
|
||||
expect(response.body).to eq(js)
|
||||
end
|
||||
|
||||
it "renders css correctly" do
|
||||
get helper.share_asset_url("share.css")
|
||||
|
||||
expect(response).to be_successful
|
||||
expect(response.headers["Content-Type"]).to eq("text/css; charset=utf-8")
|
||||
|
||||
css = File.read(DiscourseAi.public_asset_path("ai-share/share.css"))
|
||||
expect(response.body).to eq(css)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET preview" do
|
||||
it "denies preview from logged out users" do
|
||||
get "#{path}/preview/#{user_pm_share.id}.json"
|
Loading…
x
Reference in New Issue
Block a user