🖼️

Cloud9のPreviewエラーとX-Frame-Options

2023/01/17に公開

要約

AWS Cloud9でWebアプリケーションを開発する際、レスポンスヘッダーにX-Frame-Options: "SAMEORIGIN"または"DENY"を指定していると、Preview Running Applicationでプレビューしたときに「接続が拒否されました」というエラー画面になります。

ブラウザで直接開いてプレビューする方法ならX-Frame-Optionsの問題はありません。ただし、マイナーなブラウザを使用しているとブラウザで直接開くプレビューが全て不可となります。

問題発生時の状況

近頃はAWS Cloud9の便利さに気づいて、個人開発(というか各種実験)はそちらでやっています。

しかしgit cloneしたとあるWebアプリケーションをlocalhost:8080ポートで実行した際、Preview Running Applicationでプレビュー表示しようとしても「接続が拒否されました」というエラー画面になって表示になりました。

しかし、アプリケーションのログ上はHTTPコード200で正常レスポンスが返っています。

 * Running on http://127.0.0.1:8080
127.0.0.1 - - [16/Jan/2023 15:22:36] "GET / HTTP/1.1" 200 -

また、下記のようにcurlでは正常レスポンスが返ります。

$ curl localhost:8080
<!DOCTYPE html>
(以下略)

このアプリケーションはFlaskで作成されているのですが、別のFlaskアプリケーションを同じCloud9の環境で実行した場合は、ちゃんとプレビュー表示されるので何かコード内に問題がありそうです。

別タブでのプレビュー

とりあえず事象について検索すると、インスタンスを再起動しろとかいう謎な記事のほかは、ブラウザのタブで直接開くように案内しているものが見られます。プレビュー画面の右上にあるPop Out Into New Windowというボタンを押すと別タブでプレビューが開きます。

しかし、私の場合はこれもうまくいきませんでした。Oops VFS connection does not existとのことです。

AWSのドキュメントによると、IDEを開いているのと同じブラウザでないと動作しないとのことで、ちょっと不思議な仕組みです。

This URL works only when the IDE for the environment is open and the application is running in the same web browser.

結論的には、私がOopsの画面になった原因はBraveというマイナーなブラウザを使用していたことでした。

「同じブラウザで開いている」というチェックのせいかと思われますが、Braveだと(Chromiumベースなのですが)その通りに実行してもプレビューできません。正規のGoogle ChromeでCloud9を開き、Pop Out Into New Windowを押すと正常にプレビューできました。(IDE内のプレビューは同じエラーのまま)

原因

Chromeだと別タブでプレビューできるとはいえ、それでは元々の原因がわからないままですし、Braveでは見れないままです。

プレビュー可能な単純なアプリケーションと問題のアプリケーションの差異を探る形で調査したところ、下記の1行があるとプレビューできないことがわかりました。

response.headers["X-Frame-Options"] = "SAMEORIGIN"

これは考えてみれば当然のことでした。

X-Frame-Optionsヘッダーはiframe等で別サイトに埋め込みされることを禁止するヘッダーです。Cloud9のIDEはブラウザで開いているのだから、アプリケーションのWeb表示が埋め込まれる動作になっているのが自然です。

実際、ブラウザの開発者ツールで確認するとプレビュー部分はiframeで表示されていました。

だからX-Frame-Optionsを付与するアプリケーションをプレビューするには直接ブラウザで開いてやる必要があるわけですね。そして公式ドキュメントをよく見るとその注意書きもありました……。トラブルシューティングばかりではなく本来のページを注意深く読まないといけないです。

The preview application is run within the IDE and is loaded inside an iframe element. Some application servers might by default block requests that come from iframe elements, such as the X-Frame-Options header. If your preview application isn't displayed in the preview tab, make sure that your application server doesn't prohibit displaying the content in iframes.

私の場合はとりあえず設定の1行をコメントアウトしてIDE内のプレビューを使うことにしました。

Discussion