From 3e476d77f0375b71b64c3dfade829bfe4f73ad1a Mon Sep 17 00:00:00 2001 From: pixelead0 <735873+pixelead0@users.noreply.github.com> Date: Mon, 20 Oct 2025 14:41:55 -0600 Subject: [PATCH 1/5] =?UTF-8?q?fix(config):=20agregar=20use=5Fdirectory=5F?= =?UTF-8?q?urls=20para=20manejar=20URLs=20sin=20extensi=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Configurar use_directory_urls: true en mkdocs.yml - Permite que URLs como /meetups/ funcionen correctamente - Mantiene compatibilidad con estructura de directorios de MkDocs --- mkdocs.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mkdocs.yml b/mkdocs.yml index 117abe8..7bc91d9 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -11,6 +11,9 @@ repo_url: https://github.com/PythonMexico/pythonCDMX/ # Copyright copyright: Copyright © 2025 Python CDMX +# URL configuration +use_directory_urls: true + # Theme configuration theme: name: material From 88183a035449704a0de2cf7dddcad31963d9a93a Mon Sep 17 00:00:00 2001 From: pixelead0 <735873+pixelead0@users.noreply.github.com> Date: Mon, 20 Oct 2025 14:42:02 -0600 Subject: [PATCH 2/5] =?UTF-8?q?feat(infra):=20implementar=20CloudFront=20F?= =?UTF-8?q?unction=20para=20URLs=20sin=20extensi=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Agregar CloudFront Function url_rewrite para manejar URLs sin .html - Función redirige /meetups/ a /meetups/index.html automáticamente - Asociar función con todos los cache behaviors para consistencia - Soluciona problema de enlaces que no funcionan en producción --- terraform/cloudfront.tf | 49 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/terraform/cloudfront.tf b/terraform/cloudfront.tf index 8e7da3c..07b5178 100644 --- a/terraform/cloudfront.tf +++ b/terraform/cloudfront.tf @@ -7,6 +7,31 @@ resource "aws_cloudfront_origin_access_control" "website" { signing_protocol = "sigv4" } +# CloudFront Function to handle URLs without .html extension +resource "aws_cloudfront_function" "url_rewrite" { + name = "pythoncdmx-url-rewrite" + runtime = "cloudfront-js-1.0" + comment = "Rewrite URLs without .html extension" + publish = true + code = <<-EOT +function handler(event) { + var request = event.request; + var uri = request.uri; + + // If the URI ends with a slash, try to serve index.html + if (uri.endsWith('/')) { + request.uri = uri + 'index.html'; + } + // If the URI doesn't have an extension, try to add .html + else if (!uri.includes('.') && !uri.endsWith('/')) { + request.uri = uri + '.html'; + } + + return request; +} +EOT +} + # CloudFront distribution resource "aws_cloudfront_distribution" "website" { enabled = true @@ -42,6 +67,12 @@ resource "aws_cloudfront_distribution" "website" { default_ttl = 3600 # 1 hour max_ttl = 86400 # 24 hours compress = true + + # Associate CloudFront Function for URL rewriting + function_association { + event_type = "viewer-request" + function_arn = aws_cloudfront_function.url_rewrite.arn + } } # Cache behavior for static assets (images, CSS, JS) @@ -63,6 +94,12 @@ resource "aws_cloudfront_distribution" "website" { default_ttl = 86400 # 24 hours max_ttl = 31536000 # 1 year compress = true + + # Associate CloudFront Function for URL rewriting + function_association { + event_type = "viewer-request" + function_arn = aws_cloudfront_function.url_rewrite.arn + } } ordered_cache_behavior { @@ -83,6 +120,12 @@ resource "aws_cloudfront_distribution" "website" { default_ttl = 86400 # 24 hours max_ttl = 31536000 # 1 year compress = true + + # Associate CloudFront Function for URL rewriting + function_association { + event_type = "viewer-request" + function_arn = aws_cloudfront_function.url_rewrite.arn + } } ordered_cache_behavior { @@ -103,6 +146,12 @@ resource "aws_cloudfront_distribution" "website" { default_ttl = 604800 # 7 days max_ttl = 31536000 # 1 year compress = true + + # Associate CloudFront Function for URL rewriting + function_association { + event_type = "viewer-request" + function_arn = aws_cloudfront_function.url_rewrite.arn + } } # Custom error responses for SPA-like behavior From d419bba1713a63d9c7bccf85ea07e22dac3e1744 Mon Sep 17 00:00:00 2001 From: pixelead0 <735873+pixelead0@users.noreply.github.com> Date: Mon, 20 Oct 2025 14:42:08 -0600 Subject: [PATCH 3/5] =?UTF-8?q?docs:=20agregar=20documentaci=C3=B3n=20para?= =?UTF-8?q?=20fix=20de=20URLs=20sin=20extensi=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Documentar problema de URLs que no funcionan en producción - Explicar solución implementada con CloudFront Function - Incluir pasos de despliegue y verificación - Agregar notas técnicas sobre funcionamiento de la solución --- docs/URL_FIX_DOCUMENTATION.md | 85 +++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 docs/URL_FIX_DOCUMENTATION.md diff --git a/docs/URL_FIX_DOCUMENTATION.md b/docs/URL_FIX_DOCUMENTATION.md new file mode 100644 index 0000000..e441b37 --- /dev/null +++ b/docs/URL_FIX_DOCUMENTATION.md @@ -0,0 +1,85 @@ +# Fix para URLs sin extensión .html en producción + +## Problema +Los enlaces funcionaban correctamente en local pero no en producción. Por ejemplo: +- ❌ `https://pythoncdmx.org/meetups/` no funcionaba +- ✅ `https://pythoncdmx.org/meetups/index.html` sí funcionaba + +## Causa +El problema se debía a que CloudFront no estaba configurado para manejar URLs sin extensión `.html`. Cuando MkDocs genera el sitio con `use_directory_urls: true`, crea URLs como `/meetups/` que apuntan a `/meetups/index.html`, pero CloudFront no sabía cómo resolver estas URLs. + +## Solución Implementada + +### 1. Configuración en mkdocs.yml +```yaml +# URL configuration +use_directory_urls: true +``` + +### 2. CloudFront Function +Se agregó una función CloudFront que maneja automáticamente las URLs sin extensión: + +```javascript +function handler(event) { + var request = event.request; + var uri = request.uri; + + // If the URI ends with a slash, try to serve index.html + if (uri.endsWith('/')) { + request.uri = uri + 'index.html'; + } + // If the URI doesn't have an extension, try to add .html + else if (!uri.includes('.') && !uri.endsWith('/')) { + request.uri = uri + '.html'; + } + + return request; +} +``` + +### 3. Asociación con Cache Behaviors +La función se asoció con todos los cache behaviors de CloudFront para asegurar consistencia. + +## Archivos Modificados + +1. **mkdocs.yml**: Agregada configuración `use_directory_urls: true` +2. **terraform/cloudfront.tf**: + - Agregada CloudFront Function `url_rewrite` + - Asociada la función con todos los cache behaviors + +## Despliegue + +Para aplicar estos cambios: + +1. **Aplicar cambios de Terraform**: + ```bash + cd terraform + terraform plan + terraform apply + ``` + +2. **Desplegar el sitio**: + ```bash + # Los cambios se aplicarán automáticamente en el próximo deploy + git push origin main + ``` + +## Verificación + +Después del despliegue, verificar que funcionen: +- ✅ `https://pythoncdmx.org/meetups/` +- ✅ `https://pythoncdmx.org/meetups/index.html` +- ✅ `https://pythoncdmx.org/about/` +- ✅ `https://pythoncdmx.org/about/index.html` + +## Notas Técnicas + +- La CloudFront Function se ejecuta en el edge, por lo que tiene latencia mínima +- La función solo modifica la URI si es necesario, sin afectar assets estáticos +- Los cache behaviors mantienen sus configuraciones originales de TTL +- La solución es compatible con el comportamiento existente de MkDocs + +## Referencias + +- [MkDocs use_directory_urls documentation](https://www.mkdocs.org/user-guide/configuration/#use_directory_urls) +- [CloudFront Functions documentation](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-functions.html) From 11e3ffd4f88b5f08a926e579f011c6fb645a14bd Mon Sep 17 00:00:00 2001 From: pixelead0 <735873+pixelead0@users.noreply.github.com> Date: Tue, 21 Oct 2025 09:06:05 -0600 Subject: [PATCH 4/5] feat(infra): aplicar CloudFront Function a staging environment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Agregar función url_rewrite a todos los cache behaviors de staging - Reutilizar la misma CloudFront Function global para consistencia - Soluciona problema de URLs sin extensión en staging.pythoncdmx.org - Mantiene configuración de cache más agresiva para staging --- terraform/cloudfront-staging.tf | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/terraform/cloudfront-staging.tf b/terraform/cloudfront-staging.tf index 3504eb0..bbe7ba9 100644 --- a/terraform/cloudfront-staging.tf +++ b/terraform/cloudfront-staging.tf @@ -7,6 +7,9 @@ resource "aws_cloudfront_origin_access_control" "website_staging" { signing_protocol = "sigv4" } +# CloudFront Function for staging (reuse the same function as production) +# Note: CloudFront Functions are global, so we can reference the same function + # CloudFront distribution for staging resource "aws_cloudfront_distribution" "website_staging" { enabled = true @@ -42,6 +45,12 @@ resource "aws_cloudfront_distribution" "website_staging" { default_ttl = 300 # 5 minutes - shorter cache for staging max_ttl = 3600 # 1 hour - shorter cache for staging compress = true + + # Associate CloudFront Function for URL rewriting (same as production) + function_association { + event_type = "viewer-request" + function_arn = aws_cloudfront_function.url_rewrite.arn + } } # Cache behavior for static assets (CSS) - shorter cache for staging @@ -63,6 +72,12 @@ resource "aws_cloudfront_distribution" "website_staging" { default_ttl = 1800 # 30 minutes max_ttl = 7200 # 2 hours compress = true + + # Associate CloudFront Function for URL rewriting + function_association { + event_type = "viewer-request" + function_arn = aws_cloudfront_function.url_rewrite.arn + } } # Cache behavior for static assets (JS) - shorter cache for staging @@ -84,6 +99,12 @@ resource "aws_cloudfront_distribution" "website_staging" { default_ttl = 1800 # 30 minutes max_ttl = 7200 # 2 hours compress = true + + # Associate CloudFront Function for URL rewriting + function_association { + event_type = "viewer-request" + function_arn = aws_cloudfront_function.url_rewrite.arn + } } # Cache behavior for images - shorter cache for staging @@ -105,6 +126,12 @@ resource "aws_cloudfront_distribution" "website_staging" { default_ttl = 3600 # 1 hour max_ttl = 86400 # 24 hours compress = true + + # Associate CloudFront Function for URL rewriting + function_association { + event_type = "viewer-request" + function_arn = aws_cloudfront_function.url_rewrite.arn + } } # Custom error responses for SPA-like behavior From 1fb57675983976f600a6ab8309c750caf94c52bd Mon Sep 17 00:00:00 2001 From: pixelead0 <735873+pixelead0@users.noreply.github.com> Date: Tue, 21 Oct 2025 09:06:28 -0600 Subject: [PATCH 5/5] =?UTF-8?q?docs:=20actualizar=20documentaci=C3=B3n=20c?= =?UTF-8?q?on=20soporte=20para=20staging?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Agregar información sobre configuración de staging - Incluir URLs de verificación para ambos ambientes - Documentar que la misma CloudFront Function se reutiliza --- docs/URL_FIX_DOCUMENTATION.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/URL_FIX_DOCUMENTATION.md b/docs/URL_FIX_DOCUMENTATION.md index e441b37..d6eeb0f 100644 --- a/docs/URL_FIX_DOCUMENTATION.md +++ b/docs/URL_FIX_DOCUMENTATION.md @@ -43,9 +43,12 @@ La función se asoció con todos los cache behaviors de CloudFront para asegurar ## Archivos Modificados 1. **mkdocs.yml**: Agregada configuración `use_directory_urls: true` -2. **terraform/cloudfront.tf**: +2. **terraform/cloudfront.tf**: - Agregada CloudFront Function `url_rewrite` - Asociada la función con todos los cache behaviors +3. **terraform/cloudfront-staging.tf**: + - Aplicada la misma CloudFront Function a staging + - Asociada la función con todos los cache behaviors de staging ## Despliegue @@ -67,11 +70,19 @@ Para aplicar estos cambios: ## Verificación Después del despliegue, verificar que funcionen: + +### Producción - ✅ `https://pythoncdmx.org/meetups/` - ✅ `https://pythoncdmx.org/meetups/index.html` - ✅ `https://pythoncdmx.org/about/` - ✅ `https://pythoncdmx.org/about/index.html` +### Staging +- ✅ `https://staging.pythoncdmx.org/meetups/` +- ✅ `https://staging.pythoncdmx.org/meetups/index.html` +- ✅ `https://staging.pythoncdmx.org/about/` +- ✅ `https://staging.pythoncdmx.org/about/index.html` + ## Notas Técnicas - La CloudFront Function se ejecuta en el edge, por lo que tiene latencia mínima