JavaScript埋め込みが表示されません。コンソールログに「DOMWindowでpostMessageの実行に失敗しました…」と表示されます。

こんにちは、当社のサイトに JavaScript 埋め込みを実装しようとした際、全く同じエラーが発生しています。

関連トピックや Google で検索してみましたが、この問題を解決するために何をすべきか完全には把握できていません。よろしくお願いいたします。

[編集] このエラーメッセージを常に表示したくないため、今回は古い投稿 1 件のみで有効化しています。

埋め込み設定:

試した設定:

host: royaleapi.com
path allowed: /blog/.*

host: royaleapi.com
path allowed: 

また、以下のドメインに対して CORS 元を有効化しました:

  • https://royaleapi.com
  • https://cdn.royaleapi.com

さらに app.yml 内の ENV に DISCOURSE_ENABLE_CORS: true を追加しましたが、ここで行き詰まってしまいました…

問題の原因が ?discuss=1 クエリパラメータではないと確信していますか?

ブログカテゴリにセキュリティ権限が設定されていますか、それとも「全員」グループが作成/返信/閲覧を許可する設定になっていますか?

あなたのサイトの Discourse のバージョンは何ですか?

また、Failed to execute postMessage on DOMWindow の後に表示される完全なエラーメッセージは何ですか?おそらく The target origin provided (<target_url>) does not match the recipient window's origin (<origin_url>) のような内容だと思います。

?discuss=1 パラメータとは全く関係ないことは確かです。このパラメータがない場合でも同じ問題が発生していました。ただ、これはライブサイトなので、ユーザーに巨大なエラーブロックを表示したくありません。ご質問いただいたので、サイトを編集し、訪問者がいないはずの非常に古い投稿の 1 つでのみ JavaScript 埋め込みを有効にしました。つまり、クエリ文字列はありません。(最初の投稿もこの点について更新しました)

https://royaleapi.com/blog/season3

https://royaleapi.com/blog/season3

Discourse バージョン

2.6.0.beta5

OS バージョン

Ubuntu 20.04.1 LTS

完全なエラーメッセージ

VM469 embed-application-9cef8308c816fc1d83137e63d6c556c6cc2b68fe2b6e5ce16cca6766ba2c0ae4.js:1 ‘postMessage’ の実行に失敗しました ‘DOMWindow’ 上:提供されたターゲットオリジン (‘https://discuss.royaleapi.com’) が、受信ウィンドウのオリジン (‘https://royaleapi.com’) と一致しません。

ブログカテゴリ

これは公開カテゴリで、誰でも利用可能です。実際には投稿がないように設定しました。カテゴリに 1 つのアイテムが必要かどうかを確認するため、今すぐ新しい投稿を作成しました。

スクリーンショット:デスクトップ

スクリーンショット:モバイル

「いいね!」 1

これが関連するかどうかはわかりませんが、ログにいくつかのエラーが表示されていますが、それが何なのかは不明です:

[Fri 06 Nov 2020 04:47:14 PM UTC] Domains not changed.
[Fri 06 Nov 2020 04:47:14 PM UTC] Skip, Next renewal time is: Mon 04 Jan 2021 08:07:59 AM UTC
[Fri 06 Nov 2020 04:47:14 PM UTC] Add '--force' to force to renew.
[Fri 06 Nov 2020 04:47:14 PM UTC] Installing key to:/shared/ssl/discuss.royaleapi.com_ecc.key
[Fri 06 Nov 2020 04:47:14 PM UTC] Installing full chain to:/shared/ssl/discuss.royaleapi.com_ecc.cer
[Fri 06 Nov 2020 04:47:14 PM UTC] Run reload cmd: sv reload nginx
warning: nginx: unable to open supervise/ok: file does not exist
[Fri 06 Nov 2020 04:47:14 PM UTC] Reload error for :
Started runsvdir, PID is 663
ok: run: redis: (pid 677) 0s
chgrp: invalid group: ‘syslog’
ok: run: postgres: (pid 675) 0s
rsyslogd: imklog: cannot open kernel log (/proc/kmsg): Operation not permitted.
rsyslogd: activation of module imklog failed [v8.1901.0 try https://www.rsyslog.com/e/2145 ]
supervisor pid: 671 unicorn pid: 702

また、これらの情報のうちマスキングすべきものがあるかどうかもお知らせください。すでに URL を投稿してしまったので、これらのファイルの場所はこのセットアップでは標準的なものと思われるため、問題ないだろうと考えました。

@simon これについてお手伝いいただけますか?これは想定された動作でしょうか、それとも今後のリリースで修正される予定でしょうか?

当社のサイトページへのコメント機能を可能にするためにこのフォーラムを追加しましたが、これが機能しない場合は、他の解決策を検討する必要があります。

よろしくお願いいたします!

このスクリーンショットには、以前は気づいていなかった問題があります:

パスのホワイトリストが /blog/.* ではなく /blog/* に設定されています(ドット文字の追加に注意してください)。

ホストエントリを編集して、パスのホワイトリストを /blog/.* に変更してみてください。

それでも問題が解決しない場合は、/.* を試してください。また、設定を空のままにしておくことも試してみてください。

「いいね!」 1

はい、私のスクリーンショットにはその問題が含まれていましたが、正規表現を使っている可能性に気づいたため、すでに /blog/.* に変更しました。しかし、問題は解決していません。

@simon 3 つすべて試しました:

/blog/.*
/.*

(最後のは空です)が、どれも機能しません。

コンソールに表示されるエラーは、他のものというよりは CORS の問題のように見えます。

_embed-application-9cef8308c816fc1d83137e63d6c556c6cc2b68fe2b6e5ce16cca6766ba2c0ae4.js:7 
'DOMWindow' 上の 'postMessage' の実行に失敗しました:
提供されたターゲットオリジン ('https://discuss.royaleapi.com') が、受信ウィンドウのオリジン ('https://royaleapi.com') と一致しません。

しかし、これをどのように修正すればよいかわかりません。テストのため、すでにアプリ設定に以下を追加してみました:

  DISCOURSE_ENABLE_CORS: true
  DISCOURSE_CORS_ORIGIN: '*'

実質的に完全に開放しましたが、これも機能しません。

Discourse 埋め込み設定ページで、「トピック作成時のユーザー名」設定を指定しましたか?設定されていない場合、Failed to execute 'postMessage' on 'DOMWindow' というエラーが発生します。

「いいね!」 1

@simon はい、トピック作成時のユーザー名は system に設定されています。自分のユーザー名に設定しても同じエラーが発生します。

興味深いことに、本日以下の点を確認しました。

curl -IXGET https://discuss.royaleapi.com

access-control-allow-origin: *
access-control-allow-headers: Content-Type, Cache-Control, X-Requested-With, 	X-CSRF-Token, Discourse-Present, User-Api-Key, User-Api-Client-Id, Authorization
access-control-allow-credentials: true
[truncated]

しかし、以下の場合:

curl -IXGET https://discuss.royaleapi.com/javascripts/embed.js

HTTP/2 200
server: nginx
date: Tue, 08 Dec 2020 23:52:26 GMT
content-type: application/javascript
content-length: 2404
last-modified: Tue, 01 Dec 2020 01:49:39 GMT
vary: Accept-Encoding
expires: Wed, 09 Dec 2020 23:52:26 GMT
cache-control: max-age=86400
cache-control: public,immutable
accept-ranges: bytes

これが原因でしょうか?ドメイン自体には access-control-allow-origin ヘッダーが含まれていますが、スクリプト自体には含まれていないようです。Docker イメージに組み込まれている設定を使わず、独自の nginx 設定を試すべきでしょうか?

@simon この問題は解決しました。

別の問題 Unable to generate preview for URLs - #4 by seeminglee を解決するために、サイト上で HEAD リクエストを有効にしたところ、すべての議論が表示されるようになり、結果としてブログ記事のスレッドが自動的に生成されるようになりました。

これは素晴らしいことです!CORS 関連の問題かどうかを特定しようと試行錯誤していた自分が信じられません。実際には HEAD リクエストが関係していました。この点はドキュメントに明記する必要があるかもしれません。

このissueをクローズしてください。

「いいね!」 2

この件についてフォローアップしてくださり、本当にありがとうございます!

おそらく、Embed Discourse comments on another website via Javascript の「トラブルシューティング」セクションに追加すべきでしょう。HEAD リクエストが無効になっているケースが一般的かどうかはわかりませんが、無効になっているサイトでは、この問題を特定するのが難しいためです。

「いいね!」 1

さて、GET リクエストに応答する URL に対してあえて HEAD リクエストをブロックし、RFC に違反するような設定をすれば、何らかの障害が発生するのは当然ですよね?

正直に言うと、その機能に依存しているサービスが存在するとは知りませんでした。必要だと知っていたら、そのメソッドを「無効化」しなかったはずです。

念のため補足しますが、あえてそのメソッドを無効化しようとしたわけではありません。単に、HEAD メソッドに対応するルートを書いていなかっただけです。なので、現在行ったのは、有効なエンドポイントに対するすべての HEAD リクエストに応答する関数を追加することです。

「いいね!」 2

実際、@Falco さんが示している通り、単に以下を実行するだけで、そのメソッドが実装されているか確認できます。

curl https://example.com/path/to -I

これは確認方法として良さそうです。

とにかく、二人とも本当に助かりました!

「いいね!」 2

あ、すいませんでした。Rails などのフレームワークに慣れすぎていて、Web サイトのデフォルト機能として最初から備わっているものだと思っていました :sweat_smile:

「いいね!」 2

はい、お願いいたします。トラブルシューティングセクションにこの内容を追加してください。CORS/フレームセキュリティの問題で詰まっており、@seeminglee の手順に従うことで解決できることを願っています。HEAD リクエストを有効にするにはどうすればよいでしょうか?

@willywongi 私の問題点が何か混同されているかもしれませんので、何が起きたのか説明させてください。

  1. 手順に従いましたが、コメントをサイトに埋め込めませんでした。
  2. 判明したのは、私の Discourse アプリ(異なるドメインにインストール済み)が、メインサイトがそれらの URL で HEAD メソッドを実装していなかったため、ブログ投稿の存在を「検証」できなかったという点です。
  3. これらのパスに対する HEAD リクエストのハンドラを実装したところ、埋め込みが機能するようになりました。

あなたも私と同じ問題を抱えているか確認するには、ブログ投稿を含む URL(またはコメント埋め込みを表示させたい場所)に対して curl を実行してください。

例えば、URL が https://example.com/blog/awesome-post の場合、ターミナルを開いて以下を実行します。

curl https://example.com/blog/awesome-post -I

これにより、その URL に対して HEAD リクエストが実行され、結果が返されます。ステータスコードが 200(レスポンスの最初の行にある数字)以外の値である場合、つまり以下のような場合です。

HTTP/2 200

サーバーが HEAD メソッドを実装していない(またはそれに応答する際に問題がある)ことを意味します。

もしレスポンスが 200 である場合、埋め込みの問題は HEAD リクエストとは無関係です。

「いいね!」 1

ハ、今ならっきりしました!ありがとう。
HEAD メソッドを確認しましたが、私のウェブサイトは正しく(200)レスポンスを返しています。

Discourse スレッドを埋め込むのにまだ苦労していますが、他に問題があれば新しいスレッドを立てます。

これに遭遇し、問題は「トピック作成用のユーザー名」の呼び出し方法を変更し、埋め込みページで更新し忘れたことだと判明しました。トピックを作成しようとした際にユーザー名が見つからなかったようです。埋め込み設定ページで更新すると、エラーは解消されました。

「いいね!」 1