Angular Routing en Amazon S3 y CloudFront
La implementación de un sitio en Angular hosteado sobre Amazon S3 y CloudFront presenta algunos desafíos de configuración para poder ajustar el routing de manera correcta.
El problema es que cuando uno accede a una URL generada por el router de Angular, el path en realidad no existe, y al recargar la página, Amazon, según la configuración que tengamos, nos devolverá un 403 o un 404.
Cuando realizamos la configuración de S3 y CloudFront para servir el contenido, podemos elegir entre dos configuraciones de seguridad para el acceso al contenido:
- Permitiendo el acceso sólo mediante CloudFront. (Restingiendo mediante Origin Access Identity en la policy del bucket)
- Permitiendo el acceso mediante CloudFront y también directo mediante S3.
La segunda opción nos quita un poco de control, por qué en CloudFront entre otras cosas podemos configurar por ejemplo auditoría, https y muchas opciones que en S3 no podemos (además de obviamente la cdn propiamente dicha), y si los usuarios lo bypasean se las estarían salteando.
Hay diferentes maneras de solucionar esto:
RoutingRules en S3
La primera opción es editar las reglas de ruteo directamente en S3. Lo que le decimos a la config es que cuando devuelva un 404, lo redireccione a la raiz.
<RoutingRules>
<RoutingRule>
<Condition>
<HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
</Condition>
<Redirect>
<HostName>3ops.com</HostName>
<ReplaceKeyPrefixWith>#!/</ReplaceKeyPrefixWith>
</Redirect>
</RoutingRule>
</RoutingRules>
El problema de este método, es que cuando pasamos por Cloudfront y el S3 está restringido a únicamente CloudFront, no funciona. Devuelve un 403 (forbiden).
Custom Error Pages en CloudFront
La segunda opción es generar un Custom Error Page en CloudFront, y redireccionar el response 403 a /index.html o a la raiz.
A saber, Amazon S3 devuleve un 403 en vez de un 404 cuando no existe el archivo que se busca y no se tiene permiso de ListBucket.
Saludos!