amazon web services - archivos - ¿Cómo se configura un objeto raíz predeterminado para subdirectorios para un sitio web alojado estáticamente en Cloudfront?
amazon s3 (8)
¿Cómo se configura un objeto raíz predeterminado para subdirectorios en un sitio web alojado estáticamente en Cloudfront?
Específicamente, me gustaría que se sirva
www.example.com/subdir/index.html
cada vez que el usuario solicite
www.example.com/subdir
.
Tenga en cuenta que esto es para entregar un sitio web estático contenido en un depósito S3.
Además, me gustaría usar una identidad de acceso de origen para restringir el acceso al depósito S3 solo a Cloudfront.
Ahora, soy consciente de que Cloudfront funciona de manera diferente a los estados S3 y Amazon specifically :
El comportamiento de los objetos raíz predeterminados de CloudFront es diferente del comportamiento de los documentos de índice de Amazon S3. Cuando configura un depósito de Amazon S3 como un sitio web y especifica el documento de índice, Amazon S3 devuelve el documento de índice incluso si un usuario solicita un subdirectorio en el depósito. (Debe aparecer una copia del documento de índice en cada subdirectorio). Para obtener más información sobre cómo configurar buckets de Amazon S3 como sitios web y sobre documentos de índice, consulte el capítulo Sitios web de alojamiento en Amazon S3 en la Guía para desarrolladores de Amazon Simple Storage Service.
Como tal, aunque Cloudfront nos permite especificar un objeto raíz predeterminado, esto solo funciona para
www.example.com
y no para
www.example.com/subdir
.
Para evitar esta dificultad, podemos cambiar el nombre del dominio de origen para que apunte al punto final del sitio web proporcionado por S3.
Esto funciona muy bien y permite que los objetos raíz se especifiquen de manera uniforme.
Desafortunadamente, esto no parece ser compatible con
las identidades de acceso de origen
.
Específicamente, los enlaces anteriores indican:
Cambiar al modo de edición:
Distribuciones web: haga clic en la pestaña Orígenes, haga clic en el origen que desea editar y haga clic en Editar. Solo puede crear una identidad de acceso de origen para los orígenes para los que el Tipo de origen es S3 Origin.
Básicamente, para establecer el objeto raíz predeterminado correcto, utilizamos el punto final del sitio web S3 y no el depósito del sitio web en sí. Esto no es compatible con el uso de la identidad de acceso de origen. Como tal, mis preguntas se reducen a
-
¿Es posible especificar un objeto raíz predeterminado para todos los subdirectorios para un sitio web alojado estáticamente en Cloudfront?
-
¿Es posible configurar una identidad de acceso de origen para el contenido servido desde Cloudfront donde el origen es un punto final del sitio web S3 y no un depósito S3?
Activar el alojamiento S3 significa que tienes que abrir el cubo al mundo. En mi caso, necesitaba mantener el depósito privado y usar la funcionalidad de identidad de acceso de origen para restringir el acceso solo a Cloudfront. Como sugirió @Juissi, una función Lambda puede corregir los redireccionamientos:
''use strict'';
/**
* Redirects URLs to default document. Examples:
*
* /blog -> /blog/index.html
* /blog/july/ -> /blog/july/index.html
* /blog/header.png -> /blog/header.png
*
*/
let defaultDocument = ''index.html'';
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request;
if(request.uri != "/") {
let paths = request.uri.split(''/'');
let lastPath = paths[paths.length - 1];
let isFile = lastPath.split(''.'').length > 1;
if(!isFile) {
if(lastPath != "") {
request.uri += "/";
}
request.uri += defaultDocument;
}
console.log(request.uri);
}
callback(null, request);
};
Después de publicar su función, vaya a su distribución en la nube en la consola de AWS.
Vaya a
Behaviors
, luego elija
Origin Request
en
Lambda Function Associations
y finalmente pegue el ARN en su nueva función.
Hay otra forma de obtener un archivo predeterminado en un subdirectorio, como
example.com/subdir/
.
En realidad, puede (programáticamente) almacenar un archivo con la clave
subdir/
en el depósito.
Este archivo
no
aparecerá en la consola de administración S3, pero en realidad existe, y CloudFront lo servirá.
Hay una aws.amazon.com/blogs/compute/… que recomienda configurar una función Lambda @ Edge activada por su distribución CloudFront:
Por supuesto, es una mala experiencia de usuario esperar que los usuarios escriban siempre index.html al final de cada URL (o incluso sepan que debería estar allí). Hasta ahora, no ha habido una manera fácil de proporcionar estas URL más simples (equivalentes a la Directiva DirectoryIndex en una configuración de Servidor Web Apache) a los usuarios a través de CloudFront. No, si aún desea poder restringir el acceso al origen S3 utilizando un OAI. Sin embargo, con el lanzamiento de Lambda @ Edge, puede usar una función de JavaScript que se ejecuta en los nodos de Edge de CloudFront para buscar estos patrones y solicitar la clave de objeto adecuada desde el origen S3.
Solución
En este ejemplo, utiliza la potencia de cálculo en el borde de CloudFront para inspeccionar la solicitud a medida que llega desde el cliente. Luego, vuelva a escribir la solicitud para que CloudFront solicite un objeto de índice predeterminado (index.html en este caso) para cualquier URI de solicitud que termine en ''/''.
Cuando se realiza una solicitud en un servidor web, el cliente especifica el objeto a obtener en la solicitud. Puede usar este URI y aplicarle una expresión regular para que estos URI se resuelvan en un objeto de índice predeterminado antes de que CloudFront solicite el objeto desde el origen. Utiliza el siguiente código:
''use strict'';
exports.handler = (event, context, callback) => {
// Extract the request from the CloudFront event that is sent to Lambda@Edge
var request = event.Records[0].cf.request;
// Extract the URI from the request
var olduri = request.uri;
// Match any ''/'' that occurs at the end of a URI. Replace it with a default index
var newuri = olduri.replace(///$/, ''//index.html'');
// Log the URI as received by CloudFront and the new URI to be used to fetch from origin
console.log("Old URI: " + olduri);
console.log("New URI: " + newuri);
// Replace the received URI with the URI that includes the index page
request.uri = newuri;
// Return to CloudFront
return callback(null, request);
};
Siga la guía vinculada anteriormente para ver todos los pasos necesarios para configurar esto, incluido el bucket S3, la distribución de CloudFront y la creación de la función Lambda@Edge .
Hay una manera de hacer esto. En lugar de apuntarlo a su depósito seleccionándolo en el menú desplegable (www.example.com.s3.amazonaws.com), apúntelo al dominio estático de su depósito (por ejemplo, www.example.com.s3-website-us -west-2.amazonaws.com):
Gracias a este hilo del foro de AWS
La solución para el problema es utilizar lambda @ edge para reescribir las solicitudes. Uno solo necesita configurar el lambda para el evento de solicitud del visor de la distribución de CloudFront y reescribir todo lo que termina con ''/'' Y no es igual a ''/'' con el documento raíz predeterminado, por ejemplo, index.html.
Otra alternativa al uso de lambda @ edge es usar las páginas de error de CloudFront. Configure una respuesta de error personalizada para enviar todos los 403 a un archivo específico. Luego agregue javascript a ese archivo para agregar index.html a las URL que terminan en /. Código de muestra:
if ((window.location.href.endsWith("/") && !window.location.href.endsWith(".com/"))) {
window.location.href = window.location.href + "index.html";
}
else {
document.write("<Your 403 error message here>");
}
Sé que esta es una vieja pregunta, pero yo mismo luché con esto.
En última instancia, mi objetivo era menos establecer un archivo predeterminado en un directorio y más para obtener el resultado final de un archivo que se sirvió sin
.html
al final.
Terminé eliminando
.html
del nombre de archivo y programáticamente / manualmente configuré el tipo mime en
text/html
.
No es la forma tradicional, pero parece funcionar y satisface mis requisitos para las URL bonitas sin sacrificar los beneficios de la formación en la nube.
Establecer el tipo mime es molesto, pero en mi opinión, un pequeño precio a pagar por los beneficios
ACTUALIZACIÓN: ¡Parece que estaba incorrecto! Vea la respuesta de JBaczuk, que debería ser la respuesta aceptada en este hilo.
Lamentablemente, la respuesta a ambas preguntas es no.
1. ¿Es posible especificar un objeto raíz predeterminado para todos los subdirectorios para un sitio web alojado estáticamente en Cloudfront?
No. Como se indica en los documentos de AWS CloudFront ...
... Si define un objeto raíz predeterminado, una solicitud del usuario final para un subdirectorio de su distribución no devuelve el objeto raíz predeterminado. Por ejemplo, supongamos que
index.html
es su objeto raíz predeterminado y que CloudFront recibe una solicitud del usuario final para el directorio de instalación en su distribución de CloudFront:http://d111111abcdef8.cloudfront.net/install/
CloudFront no devolverá el objeto raíz predeterminado, incluso si aparece una copia de
index.html
en el directorio de instalación....
El comportamiento de los objetos raíz predeterminados de CloudFront es diferente del comportamiento de los documentos de índice de Amazon S3. Cuando configura un depósito de Amazon S3 como un sitio web y especifica el documento de índice, Amazon S3 devuelve el documento de índice incluso si un usuario solicita un subdirectorio en el depósito. (Una copia del documento de índice debe aparecer en cada subdirectorio).
2. ¿Es posible configurar una identidad de acceso de origen para el contenido servido desde Cloudfront donde el origen es un punto final del sitio web S3 y no un depósito S3?
No directamente. Sus opciones para los orígenes con CloudFront son cubos S3 o su propio servidor.
Sin embargo, es esa segunda opción la que abre algunas posibilidades interesantes. Probablemente esto anule el propósito de lo que está intentando hacer, pero podría configurar su propio servidor cuyo único trabajo es ser un servidor de origen CloudFront.
Cuando llega una solicitud para
http://d111111abcdef8.cloudfront.net/install/
, CloudFront reenviará esta solicitud a su servidor de origen, solicitando
/install
.
Puede configurar su servidor de origen como lo desee, incluso para servir
index.html
en este caso.
O podría escribir una pequeña aplicación web que simplemente atienda esta llamada y la obtenga directamente de S3 de todos modos.
Pero me doy cuenta de que configurar su propio servidor y preocuparse por escalarlo puede frustrar el propósito de lo que está tratando de hacer en primer lugar.