当我今天回到工作岗位时,有几件事在管理页面上引起了我的注意。以下是我对可以改进之处的一些想法。
allowed_internal_hosts 是在非公共环境中可靠嵌入的关键设置。它应该在此部分明确列出为相关设置——它的重要性毋庸置疑。
提供的配置代码片段非常有帮助,因为它包含了许多有用的信息。我认为我们可以利用这些信息提供额外的指导。
第一段
当前:
将以下 HTML 代码粘贴到您的网站中,以创建和嵌入 Discourse 主题。将 EMBED_URL 替换为您正在嵌入的页面的规范 URL。
替代:
将以下 HTML 粘贴到您希望评论显示在页面上的位置。
discourseEmbedUrl 是您页面的 URL——将从 Discourse 中链接到该页面。当您的页面首次加载时,Discourse 将尝试查找或创建一个与该 URL 相对应的主题,并链接回您的内容。
第二段
当前:
如果您想自定义样式,请取消注释并用主题的嵌入式 CSS 中定义的 CSS 类替换 CLASS_NAME。
替代:
使用 className 属性为嵌入式 iframe 中的 <html> 标签添加自定义类。 要对其进行样式设置,请转到 /admin/customize/themes,点击您主题的编辑按钮,然后点击编辑代码按钮,并勾选显示高级设置。将您的自定义 CSS 添加到嵌入式 CSS 部分。
第三段
当前:
将 DISCOURSE_USERNAME 替换为应该创建主题的作者的 Discourse 用户名。Discourse 将通过 name 属性设置为 discourse-username 或 author 的 <html> 标签的 content 属性自动查找用户。discourseUserName 参数已被弃用,将在 Discourse 3.2 中删除。
替代:
注意:该主题是由一个真实的 Discourse 用户创建的——而不是一个显示名称或作者字符串。它必须是一个有效且存在的帐户。有三种方法可以确定使用哪个用户:
- 默认回退——在 /admin/customize/embedding/posts_and_topics 中设置
- 每个主机的覆盖——在 /admin/customize/embedding/ 下设置
- 每个 URL 的控制——在您的页面上添加一个
<html> 标签,其中包含一个存在的 Discourse USERNAME: <meta name="discourse-username" content="USERNAME">
只有现有的 Discourse 用户的用户名才有效。如果找不到元标签用户,Discourse 将回退到主机级别或全局默认设置。此处所示的 <html> 标签方法允许对用于创建主题的 Discourse 用户进行编程的、每个 URL 的控制。例如,您可以将您网站上的博客文章作者映射到匹配的 Discourse 用户帐户。
“配置代码片段”部分
可折叠的“配置代码片段”部分很容易被忽略。在视觉上,它类似于一个标题,而微妙的箭头并不直观。与有颜色且引人注目的“了解更多”链接不同,这个链接感觉像是隐藏在显眼之处。
我知道这可能存在争议——有些人可能觉得 UI 干净且足够。但我个人在意识到这个部分是可点击的之前,已经错过了很多次。这告诉我,即使只是轻微的,也可以改进其可发现性。更清晰的视觉提示或默认展开可能会有很大帮助,特别是对于依赖示例的新用户。
代码片段
当前:
<div id='discourse-comments'></div>
<meta name='discourse-username' content='DISCOURSE_USERNAME'>
<script type="text/javascript">
DiscourseEmbed = {
discourseUrl: 'https://discourse.your-site.com/',
discourseEmbedUrl: 'EMBED_URL',
// className: 'CLASS_NAME',
};
(function() {
var d = document.createElement('script'); d.type = 'text/javascript'; d.async = true;
d.src = DiscourseEmbed.discourseUrl + 'javascripts/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(d);
})();
</script>
替代:
<div id="discourse-comments"></div>
<!-- Optional: specify which Discourse user account creates the topic -->
<!-- If omitted, Discourse falls back to the per-host or global default user -->
<meta name="discourse-username" content="DISCOURSE_USERNAME" />
<script type="text/javascript">
DiscourseEmbed = {
discourseUrl: 'https://discourse.mydomain.com/', // Trailing slash required
discourseEmbedUrl: window.location.href, // Or a hardcoded canonical URL string
// className: 'my-iframe-theme another-class',
// discourseReferrerPolicy: 'strict-origin-when-cross-origin',
// topicId: '1234',
};
(function() {
const d = document.createElement('script');
d.type = 'text/javascript';
d.async = true;
d.src = `${DiscourseEmbed.discourseUrl}javascripts/embed.js`;
document.head.appendChild(d);
})();
</script>
DiscourseEmbed 选项——简短描述
-
discourseUrl — 必需
您的 Discourse 实例的完整 URL。必须以斜杠结尾,例如 https://discourse.mydomain.com/
-
discourseEmbedUrl — 必需
正在嵌入评论的当前页面的完整 URL。这是 Discourse 识别和链接主题到您的内容的方式。
-
className — 可选
将自定义 CSS 类添加到iframe 内的 <html> 元素。在 Discourse 主题的“嵌入式 CSS”部分定义样式。
-
discourseReferrerPolicy — 可选
默认为 no-referrer-when-downgrade。参见:Referrer-Policy
-
topicId — 可选
如果设置,Discourse 将直接使用此主题。否则,它将查找与 discourseEmbedUrl 匹配的主题,如果不存在则创建一个。
DiscourseEmbed 上下文文档
discourseEmbedUrl 必须可供您的 Discourse 服务器访问。当 iframe 加载时,Discourse 会获取该 URL 的页面以创建或定位主题。这对于托管在公共平台上的网站来说可以无缝工作。
然而,如果您在本地开发,嵌入可能会卡在“正在加载讨论…”或根本不显示。这是因为本地开发 URL(如 localhost)可能会被 Discourse 的 SSRF 保护、force_https 选项或缺少 可嵌入主机 阻止。
如果您正在为现有网站构建新功能,一种解决方法是将 discourseEmbedUrl 指向生产 URL。当启用 embed_any_origin 时,即使 iframe 来自不同的源,Discourse 也允许嵌入正常工作。如果评论存在,它们将加载;否则,将显示“继续讨论”按钮。
或者,如果您的本地域(例如 localhost)已在 嵌入主机 下添加,您可能根本不需要 embed_any_origin。但您仍然需要将 localhost 添加为可嵌入主机。
一个注意事项:如果启用了 force_https 设置,而您的开发站点未使用 TLS,则嵌入将失败。在这种情况下,请在开发期间禁用 force_https,或考虑启动一个单独的 Discourse 实例进行测试。
**注意:**如果 discourseEmbedUrl 是公开可访问的,并且嵌入仍然显示“正在加载讨论…”而没有创建主题,您的域可能被 Discourse 的 SSRF 保护阻止。
这通常发生在您的 Discourse 实例运行在具有本地 DNS 解析的环境中时——例如 Docker、Kubernetes 或带有内部 DNS 服务器的 LAN。在这些情况下,Discourse 可能会将您站点的域解析为本地 IP 地址(例如 127.0.0.1 或 192.168.x.x)并将其视为不安全。
要允许访问,请将您的域添加到 allowed_internal_hosts 站点设置中。这会明确标记您的域为可安全抓取,从而绕过 SSRF 过滤。
被阻止的 IP 地址范围的完整列表可在 Discourse 的源代码 中找到。
允许的内部主机——[站点设置说明]((/admin/customize/embedding/settings`)
当前:
Discourse 可以安全抓取的内部主机列表,用于 oneboxing 和其他目的
替代:
允许 Discourse 抓取解析为内部 IP 的主机。当您的站点在本地 DNS(例如 Docker、LAN、Kubernetes)后面运行时需要。当 SSRF 保护否则会阻止访问时,对于评论嵌入、主题创建和 oneboxing 是必需的。
考虑因素
其中一些建议可能更适合作为指向官方文档的链接。事实上,这篇帖子本身可能就能完成这项工作,因为它应该像其他帖子一样被索引。其他一些建议可能需要一个正式的拉取请求——我最终可能会完成,但不是今天。
尽管如此,我所写的内容可能存在技术上的不准确之处。大部分内容来自实践经验,但我可能误解了某种行为,被缓存(哦,缓存……)所迷惑,或者仅仅是疏忽了某些东西。在这方面,我将听取资深的 Discourse 专家的意见。