Formulario de contacto en un sitio estático6 min de lectura
Añade un formulario de contacto a un sitio web estático en Amazon S3
Los website endpoints de S3 solo aceptan GET y HEAD por HTTP plano, así que envía el formulario de contacto a un backend y configura bien las redirecciones con CloudFront.
Un website endpoint de S3 responde al POST de un formulario con 405 MethodNotAllowed, así que apunta el action del formulario a tu endpoint de Ikiform. Como el endpoint es http: plano, un _redirect de vuelta a él nunca se sigue; configura Redirect after submit en los ajustes del formulario, o pon CloudFront delante para tener https:. Con CloudFront delante del endpoint REST del bucket, redirige a un nombre de archivo completo como thanks.html, porque el default root object solo se aplica a la raíz.
Qué cambia en S3
Un bucket configurado para alojar un sitio web estático tiene su propio website endpoint, como http://www.example.com.s3-website-us-east-1.amazonaws.com. AWS documenta que solo admite peticiones GET y HEAD sobre objetos. El envío de un formulario recibe una página de error HTML:
<html>
<head><title>405 Method Not Allowed</title></head>
<body>
<h1>405 Method Not Allowed</h1>
<ul>
<li>Code: MethodNotAllowed</li>
<li>Message: The specified method is not allowed against this resource.</li>
<li>Method: POST</li>
<li>ResourceType: OBJECT</li>Otros tres rasgos de S3 condicionan el formulario de contacto:
| Rasgo de S3 | Qué significa para el formulario |
|---|---|
| Los website endpoints no admiten HTTPS | Ikiform solo sigue un _redirect a una URL https:, así que se ignora una redirección de vuelta al endpoint sin más |
| Las cabeceras de respuesta vienen de CloudFront, no del bucket | La Content-Security-Policy se define en una política de cabeceras de respuesta de CloudFront |
| El default root object de CloudFront solo se aplica a la raíz | Con un origen REST, https://example.com/thanks/ no carga thanks/index.html; redirige a thanks.html |
Para un sitio https:, AWS recomienda Amplify Hosting, que funciona sobre CloudFront, o CloudFront delante del bucket. El formulario funciona en ambos casos. Lo que cambia es dónde acaba el visitante después de enviar.
- En el website endpoint sin más, la página se sirve por http y envía a Ikiform.
- Ikiform guarda el mensaje, pero ignora un _redirect a una dirección http y muestra su página de agradecimiento alojada.
- Configurar Redirect after submit en el panel es la forma de evitarlo, porque acepta URL http.
- Detrás de CloudFront con tu propio dominio, la página es https.
- Ikiform sigue el _redirect a tu thanks.html, siempre que el dominio esté en Allowed domains.
Qué origen de CloudFront usar
CloudFront puede leer del bucket de dos formas, y la elección decide cómo debe ser tu URL de agradecimiento:
| Origen | Bucket | Páginas índice de carpetas | URL de agradecimiento |
|---|---|---|---|
| El website endpoint de S3, como origen personalizado | Debe ser de lectura pública | Funcionan: /thanks/ carga thanks/index.html | /thanks/ o /thanks.html |
| El endpoint REST, con origin access control | Sigue siendo privado, solo lo lee CloudFront | Solo la raíz, mediante el default root object | /thanks.html, un nombre de archivo completo |
Un nombre de archivo completo funciona con ambos, y por eso los ejemplos lo usan. Si prefieres no gestionar CloudFront tú, Amplify Hosting puede desplegar desde el bucket con https: y una CDN gestionada; ahí el formulario tampoco necesita cambios.
El formulario
Los sitios en S3 suelen ser sitios de empresa, así que este formulario pide un email de trabajo y el nombre de la empresa. Súbelo como contact.html junto a thanks.html:
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
<label for="name">Name</label>
<input id="name" name="name" autocomplete="name" required />
<label for="email">Work email</label>
<input id="email" name="email" type="email" autocomplete="email" required />
<label for="company">Company</label>
<input id="company" name="company" autocomplete="organization" />
<label for="message">How can we help?</label>
<textarea id="message" name="message" rows="6" minlength="10" required></textarea>
<input type="hidden" name="_redirect" value="https://www.example.com/thanks.html" />
<input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
<button type="submit">Send</button>
</form>- El
_redirectapunta al dominio de CloudFront, con un nombre de archivo. Solo se sigue cuandowww.example.comoexample.comestá en Allowed domains. - En el endpoint
http:sin más, quita el input_redirecty configura Redirect after submit con la página de agradecimiento. Ese ajuste acepta URLhttp:, porque solo tu equipo puede cambiarlo. - Mantén
emailcomo nombre del campo. Los emails de notificación lo usan como dirección de respuesta.
En un sitio de empresa, normalmente más de una persona lee la bandeja de contacto. Añade hasta 10 destinatarios de notificaciones confirmados al formulario; cada uno recibe el mensaje, y quien pulse Reply responde directamente al remitente. Si los mensajes también deben llegar a un canal compartido o a una cola de tickets, añade un webhook firmado y pásalo por Zapier o por tu propio código. El campo company llega como texto plano, listo para filtrar en cualquiera de los dos sitios.
Antes de subirlo, prueba la página desde un servidor local con localhost en Allowed domains. Los envíos desde localhost cuentan como pruebas, así que puedes dejar el formulario bien antes de que el bucket llegue a servirlo.
Sincroniza la carpeta con el bucket e invalida las páginas en CloudFront para que el nuevo formulario se sirva de inmediato:
aws s3 sync ./site s3://www.example.com --delete
aws cloudfront create-invalidation --distribution-id E1EXAMPLE --paths "/contact.html" "/thanks.html"Dominios permitidos en hosts de AWS
| Dónde se sirve la página | Añade |
|---|---|
| Website endpoint sin más | El host completo del endpoint del bucket, como www.example.com.s3-website-us-east-1.amazonaws.com |
| Dominio por defecto de CloudFront | El host exacto d111111abcdef8.cloudfront.net, mientras pruebas |
| Tu propio dominio | example.com, que también cubre www.example.com |
Nunca añadas amazonaws.com, un sufijo regional s3-website o cloudfront.net por sí solos. Coincidiría cualquier bucket o distribución del mundo. AWS registra los dominios de los website endpoints de S3 en la Public Suffix List por la misma razón: cada bucket es un sitio distinto.
Cabeceras a través de CloudFront
Los metadatos de objeto de S3 no pueden definir una Content-Security-Policy, así que defínela en una política de cabeceras de respuesta de CloudFront y asóciala al comportamiento de caché por defecto de la distribución. El valor de la cabecera está limitado a 1.783 caracteres:
{
"Name": "site-csp",
"SecurityHeadersConfig": {
"ContentSecurityPolicy": {
"Override": true,
"ContentSecurityPolicy": "default-src 'self'; form-action 'self' https://ikiform.com; connect-src 'self' https://ikiform.com"
}
}
}aws cloudfront create-response-headers-policy --response-headers-policy-config file://csp-policy.jsonOverride: true sustituye cualquier CSP que envíe el origen. Con un origen S3 sin más no hay ninguna, pero así la política sigue mandando si cambias de origen más adelante.Comprueba que funciona
- Añade los dominios de la tabla de arriba, más
localhostmientras pruebas. - Envía desde tu dominio de CloudFront. Deberías llegar a
thanks.htmlen tu propio dominio. - Si también mantienes público el website endpoint sin más, envía desde él y confirma que llegas a la página configurada en Redirect after submit.
- Abre Submissions en el panel. El nuevo envío está ahí con todos los campos que enviaste.
- Revisa la bandeja de entrada de cada destinatario de notificaciones. Cada uno recibe un email con los campos, y Reply va a quien envió el formulario cuando este tiene un campo
email. - ¿No llegó nada? Cambia el filtro de estado del panel a Spam. El spam recibe la misma respuesta de éxito que un envío real.
Problemas habituales
| Problema | Qué hacer |
|---|---|
405 Method Not Allowed con Code: MethodNotAllowed | El formulario envió al bucket. Puede que CloudFront aún sirva el contact.html antiguo; invalídalo. |
AccessDenied o 403 después de la redirección | La redirección apunta a una carpeta como /thanks/ en una distribución de CloudFront con origen REST. Apúntala a thanks.html. |
| El navegador llega a la página de agradecimiento de Ikiform en lugar de a la tuya | _redirect se ignora salvo que su dominio esté en Allowed domains y sea una URL https:. Añade el dominio, o configura Redirect after submit en los ajustes del formulario. |
403 origin_not_allowed, o todos los envíos acaban en spam | El dominio de la página no está en Allowed domains del formulario. Añádelo, más localhost para las pruebas locales. Los subdominios de un dominio de la lista están permitidos. |
Preguntas
No. Los website endpoints de S3 solo admiten peticiones GET y HEAD, así que un POST recibe 405 MethodNotAllowed. Apunta el formulario a un backend de formularios, o construye una API con Lambda.
No. El formulario también envía a Ikiform desde una página http. CloudFront te da https, lo que permite a Ikiform seguir un _redirect de vuelta a tu propia página de agradecimiento.
Funciona y lo mantiene todo en AWS, pero tienes que construir tú la validación, el filtrado de spam, el almacenamiento y los reintentos, y SES necesita un remitente verificado. Un backend de formularios da menos mantenimiento para un formulario de contacto.
Puede, hasta que caduque la copia en caché. Invalida contact.html después de cada cambio, o sube el HTML con un max-age de Cache-Control corto para que los formularios nuevos se publiquen rápido.
No, no hay plan gratuito. Probar es gratis: puedes enviar 50 envíos de prueba al mes desde localhost antes de pagar. Para pasar a producción, Pro empieza en 6 $/mes por 500 envíos, o puedes pagar una sola vez 10.000 envíos por 49 $ o 50.000 envíos por 149, $ con créditos que no caducan nunca.
¿Te atascaste en un paso o quieres una guía para tu caso? Escribe a hello@ikiform.com.