Angular な SPA を、Amazon S3 + CloudFront の環境にアップロードしていたのですが、デフォルトのルーティング設定だと、リロード時に以下のようなアクセスエラー(403? 404?)が発生してしまいます。
<?xml version="1.0" encoding="ISO-8859-1"?> <Error> <Code>AccessDenied</Code> <Message>Access Denied</Message> <RequestId>774BF58712AE4AD1</RequestId> <HostId>bn3apgN2e40ffMEqNClgnOQz1RoZQfwWJ+X5qVnwLJGY0taPKcLer4zutZ9NPG8xgG80uZuEKmY=</HostId> </Error>
これは、例えば www.example.com/login
の login
部分が実際には存在しておらず、Angular が仮想的に作成しているもののためです。
これを解消するには、S3 で以下の設定を行えばよいと思いましたが、CloudFront と組み合わせると動作しないようですね。
この解決方法は簡単で、ルーティングモジュールの設定に { useHash: true }
を追加するだけです。
@NgModule({ imports: [RouterModule.forRoot(routes, { useHash: true })], exports: [RouterModule] })
但し、URLがwww.example.com/login
ではなくwww.example.com/#/login
と # が間に入ってしまいますが、エラーが発生するよりはずっといいですね。
ユーザーがブックマークするかもしれませんし、許容範囲ではないでしょうか。
追記:
OAuth 認証を行う際、このハッシュ設定だと動作しないのでさらに調べたところ、CloudFront + S3 環境なら、CloudFront 側でエラーのカスタマイズができることが分かりました。
403 エラーの時、/ を 200 でレスポンスを返してあげるよう設定すれば、リロード時も問題なくなります。
- 参考サイト