Reescribir paths con [email protected]

Cuaquiera de vosotros que tenga contenido estático alojado en AWS S3 y necesite servirlo seguramente use CloudFront. Yo también, y quería comentaros un caso que sirve como ejemplo acerca de de cómo utilizar [email protected]. Una característica de CloudFront que nos permite ejecutar funciones lambda en las edge locations.

https://i0.wp.com/stringfixer.com/files/179878.jpg?w=768&ssl=1

En mi caso tengo una serie de webs estáticas alojadas en S3. Para ello uso dos buckets. Uno que contiene el código HTML y JavaScript y otro donde están las imágenes, audios, vídeos, ficheros de Unity…

Las páginas se sirven a través de CloudFront con la siguiente configuración:

  • Origins:
    • BucketA (HTML y JavaScript)
    • BucketB (resources)
  • Behaviors:
    • 0 ➡️ **/resources/** ➡️ BucketB
    • 1 ➡️ Default(*) ➡️ BucketA

Visualmente:

Esta configuración produce resultados como los siguientes ejemplos. Dependiendo de la petición, la enviará a un bucket u otro y mientras los objectos estén en el lugar correcto, los servirá de forma transparente como si estuviesen en el mismo sitio.

PathBehaviourBucket
/mysite1/index.htmlDefaults3://BucketA/mysite1/index.html
/mysite2/index.htmlDefaults3://BucketA/mysite2/index.html
/mysite1/resources/images/some-image.pngResourcess3://BucketB/mysite1/resources/images/some-image.png
/mysite27/resources/sounds/dog.mp3Resourcess3://BucketB/mysite27/resources/sounds/dog.mp3

Estas webs tienen traducciones a varios idiomas que se activan usando una cadena de consulta. Por ejemplo:

https://my-domain.com/mysite1/index.html?lan=es

Sin embargo, una de ellas no funciona de la misma manera. Es una web más antigua, heredada y adaptada, cuyo código produce alguien externo y que yo no debo modificar. El resultado es que la versión original sigue el patrón de las otras y la traducción está en un subdirectorio.

IdiomaURL
Originalhttps://my-domain.com/mysite32/index.html
Traducciónhttps://my-domain.com/mysite32/lan/asubdirectory/index.html

Esto en sí mismo no es ningún problema. CloudFront sigue actuando como debe y buscando lo que necesita en el bucket correcto. El problema viene cuando buscamos los recursos, ya que la traducción espera que estén dentro de su subdirectorio.

Comparando la versión original con la traducida:

Original/mysite32/resources/
Traducción/mysite32/lan/asubdirectory/resources/


Esta esctructura no existe en el bucket. Nuestros recursos están en:

s3://BucketB/mysite32/resources/

y no en

s3://BucketB/mysite32/lan/asubdirectory/resources/

Los recursos que necesita cada versión de la web son exactamente los mismos, así que podemos compartirlos sin problema.

He de decir que la solución que busqué en este caso fue para no tener que pedir modificaciones del código a la gente externa que la mantiene. Posiblemente lo mejor es que se hubiese cambiado la forma en la que se referencia resources desde las traducciones, pero el objectivo era solucionar el asunto sin tener involucrar a otra gente y esperar por ellos.

Gracias a [email protected] esto puede solucionar rápidamente. Con una simple función lambda en Javascript podemos reescribir ese path y hacer que referencie el lugar correcto.

El código sería el siguiente. Lo único que hace es reemplazar el URI si coincide con la expresión regular ahí definida.

function handler(event) {
    var request = event.request;

    var regex =  new RegExp("/mysite32/(.*)/asubdirectory/resources/", 'g')
    var correctPath = '/mysite32/resources/'
    request.uri = request.uri.replace(regex, correctPath)

    return request;
}

Para activarlo tendríamos que ir a CloudFront, seleccionar Functions en el menú de la izquierda y después ir a Create funcion, a la derecha.


Después tendremos que darle un nombre y una descripción.

Y entonces pegaremos el código en el sitio correspondiente.

Podemos probarlo en la sección Test.

Configuración
Resultado. EL URI cambió a lo que queremos.


Ahora debemos asociar la función con nuestra distribución y publicarla. Para ello nos vamos a Publish/Associate. Tendremos que seleccionar el behavior correspondiente. En nuestro caso debemos asociarla con el que gestiona **/resources/**.

Luego le damos a Publish function.

Esperamos un poco a que nuestra distribución se actualice. Veremos que el estado de la función cambiará a Deployed.

A partir de aquí, cualquier petición que lleve la URI que queremos modificar será reescrita y el nuestro problema está solucionado.

¡Hasta otra vez!

Deja una respuesta

Tu dirección de correo electrónico no será publicada.