Estoy usando S3 para alojar una aplicación de JavaScript que usará HTML5 pushStates. El problema es que si el usuario marca alguna de las URL, no se resolverá en nada. Lo que necesito es la capacidad de tomar todas las solicitudes de URL y servir el index.html raíz en mi bucket de S3, en lugar de simplemente hacer una redirección completa. Entonces mi aplicación javascript podría analizar la URL y mostrar la página adecuada.
¿Hay alguna forma de decirle a S3 que sirva index.html para todas las solicitudes de URL en lugar de hacer redirecciones? Esto sería similar a configurar apache para manejar todas las solicitudes entrantes al servir un solo index.html como en este ejemplo: https://stackoverflow.com/a/10647521/1762614 . Realmente me gustaría evitar ejecutar un servidor web solo para manejar estas rutas. Hacer todo desde S3 es muy atractivo.
Respuestas:
Es muy fácil resolverlo sin trucos de URL, con la ayuda de CloudFront.
fuente
La forma en que pude hacer que esto funcionara es la siguiente:
En la sección Editar reglas de redireccionamiento de la consola S3 para su dominio, agregue las siguientes reglas:
Esto redirigirá todas las rutas que den como resultado un 404 no encontrado a su dominio raíz con una versión hash-bang de la ruta. Entonces http://yourdomainname.com/posts redirigirá a http://yourdomainname.com/#!/posts siempre que no haya un archivo en / posts.
Sin embargo, para usar HTML5 PushStates, debemos tomar esta solicitud y establecer manualmente el pushState adecuado en función de la ruta hash-bang. Agregue esto al principio de su archivo index.html:
Esto toma el hash y lo convierte en un HTML5 pushState. A partir de este momento, puede usar pushStates para tener rutas que no sean hash-bang en su aplicación.
fuente
<script language="javascript"> if (typeof(window.history.pushState) == 'function') { window.history.pushState(null, "Site Name", window.location.hash.substring(2)); } else { window.location.hash = window.location.hash.substring(2); } </script>
react-router
esa solución usando HTML5 pushStates y<ReplaceKeyPrefixWith>#/</ReplaceKeyPrefixWith>
Hay pocos problemas con el enfoque basado en S3 / Redirect mencionado por otros.
La solucion es:
Configure las reglas de la página de error para su instancia de Cloudfront. En las reglas de error especifique:
Código de respuesta HTTP: 200
Configure una instancia EC2 y configure un servidor nginx.
Puedo ayudar con más detalles con respecto a la configuración de nginx, solo deje una nota. Lo he aprendido por las malas.
Una vez que la distribución de la distribución frontal de la nube. Invalide su caché de Cloudfront una vez para estar en el modo prístino. Pulse la url en el navegador y todo debería estar bien.
fuente
If-Modified-Since
solicitud GET al origen); puede ser una consideración útil para las personas que no desean configurar un servidor como en el paso 5.Es tangencial, pero aquí hay un consejo para aquellos que usan la biblioteca React Router de Rackt con el historial del navegador (HTML5) que desean alojar en S3.
Supongamos que un usuario visita
/foo/bear
su sitio web estático alojado en S3. Dada la sugerencia anterior de David , las reglas de redireccionamiento los enviarán a/#/foo/bear
. Si su aplicación está construida utilizando el historial del navegador, esto no servirá de mucho. Sin embargo, su aplicación se carga en este momento y ahora puede manipular el historial.Al incluir el historial de Rackt en nuestro proyecto (consulte también Uso de historiales personalizados del proyecto React Router), puede agregar un oyente que conozca las rutas del historial de hash y reemplazar la ruta según corresponda, como se ilustra en este ejemplo:
Recordar:
/foo/bear
a/#/foo/bear
.#/foo/bear
historial detectará la notación del historial.Link
Las etiquetas funcionarán como se espera, al igual que todas las demás funciones del historial del navegador. El único inconveniente que he notado es la redirección intersticial que ocurre en la solicitud inicial.Esto fue inspirado por una solución para AngularJS , y sospecho que podría adaptarse fácilmente a cualquier aplicación.
fuente
browserHistory.listen
Veo 4 soluciones a este problema. Los primeros 3 ya estaban cubiertos en respuestas y el último es mi contribución.
Establezca el documento de error en index.html.
Problema : el cuerpo de la respuesta será correcto, pero el código de estado será 404, lo que perjudica al SEO.
Establece las reglas de redireccionamiento.
Problema : URL contaminada
#!
y la página parpadea cuando se carga.Configurar CloudFront.
Problema : todas las páginas devolverán 404 desde el origen, por lo que debe elegir si no almacenará en caché nada (TTL 0 como se sugiere) o si almacenará en caché y tendrá problemas al actualizar el sitio.
Presta todas las páginas.
Problema : trabajo adicional para renderizar páginas, especialmente cuando las páginas cambian con frecuencia. Por ejemplo, un sitio web de noticias.
Mi sugerencia es utilizar la opción 4. Si prescribe todas las páginas, no habrá errores 404 para las páginas esperadas. La página se cargará bien y el marco tomará el control y actuará normalmente como un SPA. También puede configurar el documento de error para que muestre una página genérica error.html y una regla de redirección para redirigir los errores 404 a una página 404.html (sin el hashbang).
Con respecto a los errores prohibidos 403, no dejo que sucedan en absoluto. En mi aplicación, considero que todos los archivos dentro del depósito de host son públicos y configuro esto con la opción de todos con el permiso de lectura . Si su sitio tiene páginas privadas, permitir que el usuario vea el diseño HTML no debería ser un problema. Lo que necesita proteger son los datos y esto se hace en el backend.
Además, si tiene activos privados, como fotos de usuario, puede guardarlos en otro depósito. Porque los activos privados necesitan el mismo cuidado que los datos y no se pueden comparar con los archivos de activos que se utilizan para alojar la aplicación.
fuente
Me encontré con el mismo problema hoy, pero la solución de @ Mark-Nutter estaba incompleta para eliminar el hashbang de mi aplicación angularjs.
De hecho, debe ir a Editar permisos , hacer clic en Agregar más permisos y luego agregar la Lista correcta en su bucket a todos. Con esta configuración, AWS S3 ahora podrá devolver el error 404 y luego la regla de redireccionamiento captará correctamente el caso.
Así como así:
Y luego puede ir a Editar reglas de redireccionamiento y agregar esta regla:
Aquí puede reemplazar HostName subdominio.domain.fr con su dominio y KeyPrefix #! / Si no utiliza el método hashbang para fines de SEO.
Por supuesto, todo esto solo funcionará si ya ha configurado html5mode en su aplicación angular.
fuente
La solución más fácil para hacer que la aplicación Angular 2+ sirva desde Amazon S3 y que funcionen las URL directas es especificar index.html como documentos de índice y error en la configuración del bucket de S3.
fuente
body
la respuesta. El código de estado será 404 y dañará el SEO.body
si tienes scripts que importas enhead
ellos, no funcionarán cuando golpees directamente cualquiera de las subrutas en tu sitio webDado que el problema sigue ahí, pensé en agregar otra solución. Mi caso fue que quería implementar automáticamente todas las solicitudes de extracción en s3 para realizar pruebas antes de combinarlas y hacerlas accesibles en [mydomain] / pull-request / [pr number] /
(ej. Www.example.com/pull-requests/822/ )
Que yo sepa, los escenarios de reglas no s3 permitirían tener múltiples proyectos en un solo cubo usando el enrutamiento html5, por lo que si bien la sugerencia más votada funciona para un proyecto en la carpeta raíz, no lo hace para múltiples proyectos en sus propias subcarpetas.
Así que señalé mi dominio a mi servidor donde el siguiente trabajo de configuración nginx hizo el trabajo
intenta obtener el archivo y, si no lo encuentra, supone que es la ruta html5 y lo intenta. Si tiene una página angular 404 para rutas no encontradas, nunca llegará a @not_found y obtendrá la página angular 404 devuelta en lugar de archivos no encontrados, lo que podría solucionarse con alguna regla en @get_routes o algo así.
Tengo que decir que no me siento muy cómodo en el área de configuración de nginx y el uso de expresiones regulares para el caso, conseguí que funcione con alguna prueba y error, así que mientras esto funciona, estoy seguro de que hay margen de mejora y por favor comparta sus pensamientos .
Nota : elimine las reglas de redireccionamiento s3 si las tenía en la configuración S3.
y por cierto funciona en Safari
fuente
Estaba buscando el mismo tipo de problema. Terminé usando una mezcla de las soluciones sugeridas descritas anteriormente.
Primero, tengo un cubo s3 con múltiples carpetas, cada carpeta representa un sitio web react / redux. También uso cloudfront para la invalidación de caché.
Así que tuve que usar Reglas de enrutamiento para admitir 404 y redirigirlas a una configuración hash:
En mi código js, necesitaba manejarlo con una
baseName
configuración para react-router. En primer lugar, asegúrese de que sus dependencias sean interoperables, yahistory==4.0.0
que las instalé con las que no era compatiblereact-router==3.0.1
.Mis dependencias son:
He creado un
history.js
archivo para cargar el historial:Este código permite manejar el 404 enviado por el servidor con un hash y reemplazarlo en el historial para cargar nuestras rutas.
Ahora puede usar este archivo para configurar su tienda y su archivo raíz.
Espero eso ayude. Notarás que con esta configuración utilizo el inyector redux y un inyector de sagas homebrew para cargar JavaScript de forma asincrónica a través del enrutamiento. No importa con estas líneas.
fuente
Ahora puede hacer esto con Lambda @ Edge para reescribir las rutas
Aquí hay una función lambda @ Edge que funciona:
En sus comportamientos frente a la nube, los editará para agregar una llamada a esa función lambda en "Solicitud de visor"
Tutorial completo: https://aws.amazon.com/blogs/compute/implementing-default-directory-indexes-in-amazon-s3-backed-amazon-cloudfront-origins-using-lambdaedge/
fuente
return callback(null, request);
Si aterrizó aquí buscando una solución que funcione con React Router y AWS Amplify Console, ya sabe que no puede usar las reglas de redirección de CloudFront directamente, ya que Amplify Console no expone CloudFront Distribution para la aplicación.
Sin embargo, la solución es muy simple: solo necesita agregar una regla de redireccionamiento / reescritura en Amplify Console de esta manera:
Consulte los siguientes enlaces para obtener más información (y una regla fácil de copiar de la captura de pantalla):
fuente
Estaba buscando una respuesta a esto yo mismo. Parece que S3 solo admite redireccionamientos, no puede simplemente reescribir la URL y devolver silenciosamente un recurso diferente. Estoy considerando usar mi script de compilación para simplemente hacer copias de mi index.html en todas las ubicaciones de ruta requeridas. Quizás eso también funcione para ti.
fuente
Solo para poner la respuesta extremadamente simple. Solo use la estrategia de ubicación hash para el enrutador si está alojando en S3.
export const AppRoutingModule: ModuleWithProviders = RouterModule.forRoot (rutas, {useHash: true, scrollPositionRestoration: 'enabled'});
fuente