Yt.w
10월 27, 2024, 6:27오전
1
다음 lib/highlight_js.rb 안의 코드는 일부 도메인에서는 작동하지만 다른 도메인에서는 작동하지 않습니다:
def self.path
"/highlight-js/#{Discourse.current_hostname}/#{version SiteSetting.highlighted_languages}.js"
end
저에게는 두 개의 Discourse 사이트가 있습니다. 이 코드는 www.abc.com 도메인에서는 작동하지만 efg.com에서는 작동하지 않습니다. 브라우저 콘솔에서 다음 오류를 확인했습니다:
formatter.js:383 Uncaught (in promise) TypeError: Failed to resolve module specifier '/highlight-js/efg.com/9797975efac87d28baa695ae13ca72ccaf5120f5.js'. The base URL is about:blank because import() is called from a CORS-cross-origin script.
highlight_js.rb의 self.path를 다음과 같이 수정한 후 문제가 해결되었습니다:
def self.path
"https://#{Discourse.current_hostname}/highlight-js/#{Discourse.current_hostname}/#{version SiteSetting.highlighted_languages}.js"
end
import('/highlight-js/efg.com/9797975efac87d28baa695ae13ca72ccaf5120f5.js')와 같은 상대 경로 사용은 CORS 문제를 일으키지만, import('https://efg.com/highlight-js/efg.com/9797975efac87d28baa695ae13ca72ccaf5120f5.js')와 같은 절대 URL을 사용하면 문제가 없이 잘 작동하는 것으로 보입니다.
1개의 좋아요
abc.com에서는 작동하는데 efg.com에서는 작동하지 않는다는 점이 좀 이상하네요. 두 라우트가 완전히 다르기 때문이죠
Yt.w
10월 27, 2024, 9:04오전
3
즉, www.abc.com에서는 동작하지만 efg.com에서는 동작하지 않아요. 이유는 모르겠지만 제 환경에서는 이런 일이 발생하거든요.
1개의 좋아요
simonk
(Simon King)
10월 28, 2024, 11:49오전
4
해당 사이트 중 어느 곳에서든 CDN을 사용하고 계신가요? 제 사이트에서 코드 하이라이팅이 더 이상 작동하지 않는 것을 확인했는데, 이 것이 원인인 것 같습니다:
The change which made this noticeable was most likely DEV: Modernise highlightjs loading (#24197) · discourse/discourse@0878dde · GitHub , which switched highlightjs to load via native import(), which requires CORS headers when fetching from a CDN.
But even before that change, you likely would have had some issues with things like custom Fonts (which also require CORS headers for cross-origin requests).
In theory, Discourse itself should be adding the CORS header to CDN responses. If it’s not, …
제 경우, CDN이 highlightjs 파일에 대해 Access-Control-Allow-Origin 헤더를 반환하지 않고 있습니다. Meta의 CDN은 해당 헤더를 포함하고 있는 것을 확인했기 때문에, 무엇이 다른지 궁금합니다.
$ curl --silent -I https://d3bpeqsaub0i6y.cloudfront.net/highlight-js/meta.discourse.org/9797975efac87d28baa695ae13ca72ccaf5120f5.js | grep -i access-control
access-control-allow-origin: *
access-control-allow-methods: GET, HEAD, OPTIONS
그러나 해당 헤더는 원본 서버(Origin server)에서 제공되지 않고 있습니다:
$ curl --silent -I https://meta.discourse.org/highlight-js/meta.discourse.org/9797975efac87d28baa695ae13ca72ccaf5120f5.js | grep -i access-control
<no output>
제가 파악한 바로는, Discourse는 highlightjs 파일에 access-control 헤더를 추가하도록 설계되어 있습니다:
# frozen_string_literal: true
class HighlightJsController < ApplicationController
skip_before_action :preload_json,
:redirect_to_login_if_required,
:redirect_to_profile_if_required,
:check_xhr,
:verify_authenticity_token,
only: [:show]
before_action :apply_cdn_headers, only: [:show]
def show
no_cookies
RailsMultisite::ConnectionManagement.with_hostname(params[:hostname]) do
current_version = HighlightJs.version(SiteSetting.highlighted_languages)
return redirect_to path(HighlightJs.path) if current_version != params[:version]
# note, this can be slightly optimised by caching the bundled file, it cuts down on N reads
그러나 이 헤더는 요청이 "CDN 요청"인 경우에만 적용됩니다:
return unless mini_profiler_enabled?
Rack::MiniProfiler.authorize_request
end
def check_xhr
# bypass xhr check on PUT / POST / DELETE provided api key is there, otherwise calling api is annoying
return if !request.get? && (is_api? || is_user_api?)
raise ApplicationController::RenderEmpty.new if !request.format&.json? && !request.xhr?
end
def apply_cdn_headers
if Discourse.is_cdn_request?(request.env, request.method)
Discourse.apply_cdn_headers(response.headers)
end
end
def self.requires_login(arg = {})
@requires_login_arg = arg
end
def self.requires_login_arg
end
mattr_accessor :redis
def self.is_parallel_test?
ENV["RAILS_ENV"] == "test" && ENV["TEST_ENV_NUMBER"]
end
CDN_REQUEST_METHODS ||= %w[GET HEAD OPTIONS]
def self.is_cdn_request?(env, request_method)
return if CDN_REQUEST_METHODS.exclude?(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)
이것은 Discourse가 "CDN 요청"을 위한 별도의 호스트 이름으로 구성된 경우에만 작동합니다.
1개의 좋아요
simonk
(Simon King)
10월 28, 2024, 12:02오후
5
cdn_origin_hostname라는 설정이 있습니다. 이 설정을 일반적인 discourse 호스트 이름으로 설정할 수 있을 것 같습니다:
# authorization key that will be included as a header in requests made by the
# snapshots transporter to the URL specified above. The destination should
# know this key and only accept requests that have this key in the
# `Mini-Profiler-Transport-Auth` header.
mini_profiler_snapshots_transport_auth_key =
# recommended, cdn used to access assets
cdn_url =
# The hostname used by the CDN to request assets
cdn_origin_hostname =
# comma delimited list of emails that have developer level access
developer_emails =
# redis server address
redis_host = localhost
# redis server port
redis_port = 6379
이렇게 하면 is_cdn_request 체크를 통과하게 될 것이라고 생각하지만, 부정적인 부작용이 있을지는 모르겠습니다.
Yt.w
10월 28, 2024, 12:48오후
6
네, efg.com에는 CDN을 사용 중입니다. 하지만 js 파일에 접근하면 올바른 Access-Control-Allow-Origin 이 반환되는데, 이 부분이 좀 혼란스러웠습니다.
simonk
(Simon King)
10월 29, 2024, 5:48오후
7
추가로, cdn_origin_hostname을 내 Discourse 인스턴스의 일반 도메인 이름으로 설정하고 CDN 캐시를 플러시한 결과, 이제 highlightjs가 다시 작동하고 있습니다. 아직 알아챈 부작용은 없는데…
cuo_wu
(James)
5월 18, 2025, 11:34오전
8
저도 이 문제를 겪고 있습니다. 업데이트가 있나요?