AngularなSPAでリロード時にアクセスエラーが起きる問題の解消方法


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/loginlogin 部分が実際には存在しておらず、Angular が仮想的に作成しているもののためです。

これを解消するには、S3 で以下の設定を行えばよいと思いましたが、CloudFront と組み合わせると動作しないようですね。

f:id:fnyablog:20181027112842p:plain:w480

この解決方法は簡単で、ルーティングモジュールの設定に { 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 でレスポンスを返してあげるよう設定すれば、リロード時も問題なくなります。

f:id:fnyablog:20181029124733p:plain:w480

  • 参考サイト

christina04.hatenablog.com