Embeds:読み込みで固まる、トピックが作成されない、ログもない - どうすればいいですか!

今日仕事に戻ると、管理ページでいくつか気になる点がありました。改善できると思われる点をいくつか挙げます。

埋め込み設定 — /admin/customize/embedding/settings

allowed_internal_hosts は、非公開環境で埋め込みを確実に機能させるための重要な設定です。このセクションで関連設定として明示的にリストされるべきです。その重要性については疑いの余地はありません

埋め込みホスト — /admin/customize/embedding

提供されている設定スニペットは非常に役立ち、多くの有用な情報が含まれています。これを利用して、さらにガイダンスを提供できると思います。

段落1

現在:

以下のHTMLコードをサイトに貼り付けて、Discourseトピックを作成および埋め込みます。EMBED_URL を、埋め込んでいるページの正規URLに置き換えてください。

代替案:

コメントを表示したいページに、以下のHTMLを貼り付けてください。
discourseEmbedUrl は、あなたのページのURLです。これはDiscourseからリンクされます。ページが最初に読み込まれると、DiscourseはそのURLのトピックを検索または作成し、あなたのコンテンツにリンクを戻そうとします。

段落2

現在:

スタイルをカスタマイズしたい場合は、コメントアウトを解除し、CLASS_NAME を、テーマの埋め込みCSSで定義されたCSSクラスに置き換えてください。

代替案:

className プロパティを使用して、埋め込まれたiframe内の <html> タグにカスタムクラスを追加します。スタイルを設定するには、/admin/customize/themes に移動し、テーマの編集ボタンをクリックし、次にコードの編集ボタンをクリックして、詳細を表示を確認します。カスタムCSSを埋め込みCSSセクションに追加します。

段落3

現在:

DISCOURSE_USERNAME を、トピックを作成するべき作成者のDiscourseユーザー名に置き換えてください。Discourseは、discourse-username または author という名前属性を持つ <meta> タグの content 属性によってユーザーを自動的に検索します。discourseUserName パラメータは非推奨であり、Discourse 3.2で削除される予定です。

代替案:

注意: トピックは、表示名や作成者文字列ではなく、実際のDiscourseユーザーによって作成されます。有効な既存のアカウントである必要があります。どのユーザーが使用されるかを決定するには、3つの方法があります。

  1. デフォルトフォールバック/admin/customize/embedding/posts_and_topics で設定
  2. ホストごとの上書き/admin/customize/embedding/ で設定
  3. URLごとの制御 — 既存のDiscourse USERNAME を指定して、ページに <meta name="discourse-username" content="USERNAME"> タグを追加します。

既存のDiscourseユーザーのユーザー名のみが機能します。メタタグのユーザーが見つからない場合、Discourseはホストレベルまたはグローバルデフォルトにフォールバックします。ここで示す <meta> タグの方法は、トピックを作成するために使用される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オプション
    iframe内の <html> 要素にカスタムCSSクラスを追加します。スタイルはDiscourseテーマの「埋め込みCSS」セクションで定義します。

  • discourseReferrerPolicyオプション
    デフォルトは no-referrer-when-downgrade です。参照: Referrer-Policy

  • topicIdオプション
    設定されている場合、Discourseはこのトピックを直接使用します。それ以外の場合は、discourseEmbedUrl に一致するトピックを探すか、存在しない場合は作成します。

DiscourseEmbed コンテキストドキュメント

discourseEmbedUrl はDiscourseサーバーからアクセス可能である必要があります。iframeが読み込まれると、DiscourseはそのURLのページを取得してトピックを作成または検索します。これは、公開プラットフォームでホストされているWebサイトではシームレスに機能します。

ただし、ローカルで開発している場合、埋め込みが「ディスカッションを読み込み中…」で停止したり、まったく表示されなかったりすることがあります。これは、ローカル開発URL(例: localhost)がDiscourseのSSRF保護force_httpsオプションによってブロックされるか、埋め込み可能なホストが見つからないためです。

既存のサイトの新機能を作成している場合、回避策の1つは、discourseEmbedUrl を本番URLにポイントすることです。embed_any_origin が有効になっている場合、iframeが異なるオリジンから提供されていても、Discourseは埋め込みを機能させます。コメントが存在する場合は読み込まれ、「ディスカッションを続ける」ボタンが表示されます。

または、ローカルドメイン(例: localhost)が埋め込みホストの下に追加されている場合、embed_any_origin がまったく必要ないかもしれません。しかし、依然として localhost埋め込み可能なホストとして追加する必要があります。

:warning: 1つの注意点: 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のベテランに委ねます。