Node.jsアプリを生成AIで作ったら、HTTPアクセスで困った話

Node.jsアプリを生成AIで作ったら、HTTPアクセスで困った話

生成AIのおかげでアプリやコンテンツは簡単に作れる時代になりましたが、実際に動かすには基礎的な技術や知識は必要です。
Clock Icon2025.07.21

こんにちは。テクニカルサポートチームのShiinaです。

はじめに

最近では、Claude Code などの生成 AI によるコーディング支援ツールのおかげで、Web アプリを手軽に作れるようになってきました。
アプリケーションの機能や特徴をわかりやすく伝えるために、プロトタイプを作って試したい、という場面も多いですよね。
そんなとき、プロトタイプはセットアップが簡単な HTTP でサクッと動かしたいと思いませんか?
Node.js の Web アプリを EC2 にデプロイし、HTTP アクセスで動かそうとしたところ、思わぬトラブルにハマってしまいました。
今回はそのときの経験をまとめました。似たようなことでお困りの方のヒントになれば幸いです。

困っていたこと

Node.js の Express アプリケーションを EC2 インスタンスにデプロイしたのですが、HTTP アクセスしようとすると読み込みがタイムアウトしてしまい、正しく動作しませんでした。

具体的な事象

  • CSS や JavaScript が "ERR_ADDRESS_UNREACHABLE" エラーで読み込まれない
  • アプリケーション側にはログやエラーメッセージが記録されていない
  • ローカルホストで動作させた場合には問題が発生しない

結論

HTTP レスポンスヘッダーStrict-Transport-SecurityおよびContent-Security-Policyによる、強制的な HTTPS アクセス試行が原因でした。
Express アプリケーションのセキュリティを強化するために利用していたパッケージ「Helmet」により、以下のヘッダーが自動的に設定されていました。
Strict-Transport-Security ヘッダ
デフォルトでStrict-Transport-Securityヘッダーが設定されます。

Strict-Transport-Security: max-age=15552000; includeSubDomains

Content-Security-Policy ヘッダ
デフォルトでContent-Security-Policyヘッダにupgrade-insecure-requestsディレクティブが設定されます。

Content-Security-Policy: default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests

Strict-Transport-Security とは

ウェブサイトが安全な HTTPS 通信だけを使うようにブラウザに指示する仕組みです。
これを設定すると、ユーザーが間違って HTTP でアクセスしても自動的に HTTPS に切り替わります。

Content-Security-Policy とは

ウェブサイトのセキュリティを高めるための設定です。
リソース(画像やスクリプトなど)へのアクセスを、自動的に「https://」に書き換えて安全に読み込むように指示できます。
これにより、混在コンテンツ(HTTPS ページ内に HTTP リソースがある状態)を防ぎ、通信の安全性を保てます。

ヘッダーを確認してみる

事象が発生した際のレスポンスヘッダーに Strict-Transport-SecurityおよびContent-Security-Policyが設定されているか確認してみました。

開発ツール
ブラウザの開発者ツールでネットワークアクティビティを確認することで、ヘッダーの設定を確認できます。
ヘッダ確認-png-4398×2614--07-21-2025_09_33_AM

curl コマンド
curl コマンドの -I オプションを利用することで、レスポンスヘッダーを確認できます。

curl -I http://<IPアドレス>/ 

HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)
Date: Tue, 08 Jul 2025 07:16:53 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 4564
Connection: keep-alive
Vary: Accept-Encoding
Content-Security-Policy: default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-origin
Origin-Agent-Cluster: ?1
Referrer-Policy: no-referrer
Strict-Transport-Security: max-age=15552000; includeSubDomains
X-Content-Type-Options: nosniff
X-Content-Type-Options: nosniff
X-DNS-Prefetch-Control: off
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-Frame-Options: DENY
X-Permitted-Cross-Domain-Policies: none
X-XSS-Protection: 0
X-XSS-Protection: 1; mode=block
Access-Control-Allow-Origin: *
ETag: W/"11d4-d+p88cyMAjFJXU46aRWJM+DRhwI"
Set-Cookie: connect.sid=s%3AlDU2OwmQoHE1nNNt_9JmhlOqbMoI5YqF.ur3m%2F41Wd9IG4XiUsQ0wWFAGcZcGAysI%2F9C0ZtCQ2TI; Path=/; Expires=Wed, 09 Jul 2025 07:16:53 GMT; HttpOnly
Cf-Team: 288a7e20290000d518c0532400000001

Helmets の設定変更する

一時的なデモやプロトタイプ用途であれば、ヘッダーを無効化することで HTTP でも動作させることができます。
app.js の Helmet 設定でStrict-Transport-SecurityおよびContent-Security-Policyを無効化します。

app.js
app.use(helmet({
  strictTransportSecurity: false,
  contentSecurityPolicy: false
}));

設定を変更した後は、アプリケーションを再起動してください。
また、ブラウザにキャッシュが残っている場合があるため、一度ブラウザのキャッシュをクリアしてから動作を確認してください。
変更後-png-4398×2614--07-21-2025_09_36_AM
無事に HTTP アクセスできるようなりました。

まとめ

今回のトラブルは、最初はセキュリティグループやファイアウォール、リバースプロキシなどネットワーク周りの設定ミスを疑っていましたが、実際は HTTP ヘッダーの設定が原因という、罠でした。
生成 AI の進化によってアプリケーションやコンテンツ自体は簡単に作れるようになっていますが、
実際に動かすとなると、やはりフレームワークやミドルウェアの仕組み、セキュリティ設定などの基礎知識が重要だと改めて実感しました!

本記事が同じようなトラブルで悩んでいる方の参考になれば幸いです。

参考

https://www.npmjs.com/package/helmet

https://developer.mozilla.org/ja/docs/Web/HTTP/Reference/Headers/Strict-Transport-Security
https://developer.mozilla.org/ja/docs/Web/HTTP/Reference/Headers/Upgrade-Insecure-Requests

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.