# Embeds: 加载卡住或主题未创建且无 logs，怎么办！

**URL:** https://meta.discourse.org/t/embeds-stuck-on-loading-discussion-topic-not-created-heres-the-fix/374029
**Category:** Support
**Created:** [2025年七月13日 05:50 UTC](https://meta.discourse.org/t/embeds-stuck-on-loading-discussion-topic-not-created-heres-the-fix/374029 "2025-07-13T05:50:46Z")
**Posts on this page:** 1
**Showing post:** 2

<div class="post-metadata">

### Author: ![nlambert](https://avatars.discourse-cdn.com/v4/letter/n/ecccb3/32.png) [@nlambert](https://meta.discourse.org/u/nlambert)
#### Post date: [2025年七月13日 21:57 UTC](https://meta.discourse.org/t/embeds-stuck-on-loading-discussion-topic-not-created-heres-the-fix/374029/2 "2025-07-13T21:57:42Z")

</div>

当我今天回到工作岗位时，有几件事在管理页面上引起了我的注意。以下是我对可以改进之处的一些想法。

## 嵌入设置 — [/admin/customize/embedding/settings](https://meta.discourse.org/admin/customize/embedding/settings%60)

`allowed_internal_hosts` 是在非公共环境中可靠嵌入的关键设置。它应该在此部分明确列出为相关设置——它的重要性 **毋庸置疑** 。

## 嵌入主机 — [/admin/customize/embedding](https://meta.discourse.org/admin/customize/embedding)

提供的_配置代码片段_非常有帮助，因为它包含了许多有用的信息。我认为我们可以利用这些信息提供额外的指导。

### 第一段

_当前：_

> 将以下 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 用户创建的——而不是一个显示名称或作者字符串。它必须是一个有效且存在的帐户。有三种方法可以确定使用哪个用户** ：
> 
> 1. **默认回退** ——在 [/admin/customize/embedding/posts\_and\_topics](https://meta.discourse.org/admin/customize/embedding/posts_and_topics) 中设置
> 2. **每个主机的覆盖** ——在 [/admin/customize/embedding/](https://meta.discourse.org/admin/customize/embedding/) 下设置
> 3. **每个 URL 的控制** ——在您的页面上添加一个 `<html>` 标签，其中包含一个 **存在的** Discourse `USERNAME`：` <meta name="discourse-username" content="USERNAME">`
> 
> 只有现有的 Discourse 用户的用户名才有效。如果找不到元标签用户，Discourse 将回退到主机级别或全局默认设置。此处所示的 `<html>` 标签方法允许对用于创建主题的 Discourse 用户进行 **编程的、每个 URL 的控制** 。例如，您可以将您网站上的博客文章作者映射到匹配的 Discourse 用户帐户。

### “配置代码片段”部分

可折叠的“配置代码片段”部分很容易被忽略。在视觉上，它类似于一个标题，而微妙的箭头并不直观。与有颜色且引人注目的“了解更多”链接不同，这个链接感觉像是隐藏在显眼之处。

我知道这可能存在争议——有些人可能觉得 UI 干净且足够。但我个人在意识到这个部分是可点击的之前，已经错过了很多次。这告诉我，即使只是轻微的，也可以改进其可发现性。更清晰的视觉提示或默认展开可能会有很大帮助，特别是对于依赖示例的新用户。

### 代码片段

_当前：_

```html
<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>

```

_替代：_

```html
<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](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy)
> 
> - `topicId` — **可选**  
> 如果设置，Discourse 将直接使用此主题。否则，它将查找与 `discourseEmbedUrl` 匹配的主题，如果不存在则创建一个。

### `DiscourseEmbed` 上下文文档

> `discourseEmbedUrl` 必须可供您的 Discourse 服务器访问。当 iframe 加载时，Discourse 会获取该 URL 的页面以创建或定位主题。这对于托管在公共平台上的网站来说可以无缝工作。
> 
> 然而，如果您在本地开发，嵌入可能会卡在“正在加载讨论…”或根本不显示。这是因为本地开发 URL（如 `localhost`）可能会被 Discourse 的 [SSRF 保护](https://meta.discourse.org/admin/site_settings/category/all_results?filter=allowed_internal_hosts)、[`force_https`](https://meta.discourse.org/admin/site_settings/category/all_results?filter=force_https) 选项或缺少 [可嵌入主机](https://meta.discourse.org/admin/customize/embedding) 阻止。
> 
> 如果您正在为现有网站构建新功能，一种解决方法是将 `discourseEmbedUrl` 指向生产 URL。当启用 [`embed_any_origin`](https://meta.discourse.org/admin/customize/embedding/settings?filter=embed_any_origin) 时，即使 iframe 来自不同的源，Discourse 也允许嵌入正常工作。如果评论存在，它们将加载；否则，将显示“继续讨论”按钮。
> 
> 或者，如果您的本地域（例如 `localhost`）已在 [嵌入主机](https://meta.discourse.org/admin/customize/embedding) 下添加，您可能根本不需要 `embed_any_origin`。但您仍然需要将 `localhost` 添加为[可嵌入主机](https://meta.discourse.org/admin/customize/embedding)。
> 
> ⚠ 一个注意事项：如果启用了 `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`](https://meta.discourse.org/admin/site_settings/category/all_results?filter=allowed_internal_hosts) 站点设置中。这会明确标记您的域为可安全抓取，从而绕过 SSRF 过滤。
> 
> 被阻止的 IP 地址范围的完整列表可在 [Discourse 的源代码](https://github.com/discourse/discourse/blob/main/lib/final_destination/ssrf_detector.rb#L11-L51) 中找到。

### 允许的内部主机——[站点设置说明]((/admin/customize/embedding/settings`)

_当前_：

> Discourse 可以安全抓取的内部主机列表，用于 oneboxing 和其他目的

_替代_：

> 允许 Discourse 抓取解析为内部 IP 的主机。当您的站点在本地 DNS（例如 Docker、LAN、Kubernetes）后面运行时需要。当 [SSRF](https://meta.discourse.org/t/allow-list-of-internal-hosts-for-scanning/64442) 保护否则会阻止访问时，对于评论嵌入、主题创建和 [oneboxing](https://meta.discourse.org/t/creating-rich-link-previews-with-onebox/98088) 是必需的。

## 考虑因素

其中一些建议可能更适合作为指向官方文档的链接。事实上，这篇帖子本身可能就能完成这项工作，因为它应该像其他帖子一样被索引。其他一些建议可能需要一个正式的拉取请求——我最终可能会完成，但不是今天。

尽管如此，我所写的内容可能存在技术上的不准确之处。大部分内容来自实践经验，但我可能误解了某种行为，被缓存（哦，缓存……）所迷惑，或者仅仅是疏忽了某些东西。在这方面，我将听取资深的 Discourse 专家的意见。

---

_[View the full topic](https://meta.discourse.org/t/embeds-stuck-on-loading-discussion-topic-not-created-heres-the-fix/374029)._
