Formulaire de contact sur un site statique

Formulaire de contact sur un site statique6 min de lecture

Ajouter un formulaire de contact à un site statique Amazon S3

Les website endpoints S3 n'acceptent que GET et HEAD en HTTP simple : envoyez le formulaire à un backend et gérez bien les redirections avec CloudFront.

Preet SutharFondateur, Ikiform

Un website endpoint S3 répond à un POST de formulaire par 405 MethodNotAllowed : faites donc pointer l'action du formulaire vers votre endpoint Ikiform. Comme l'endpoint est en http: simple, un _redirect vers lui n'est jamais suivi ; définissez Redirect after submit dans les réglages du formulaire, ou placez CloudFront devant pour avoir du https:. Avec CloudFront devant le REST endpoint du bucket, redirigez vers un nom de fichier complet comme thanks.html, car l'objet racine par défaut ne s'applique qu'à la racine.

Ce qui change sur S3

Un bucket configuré pour l'hébergement de site statique a son propre website endpoint, comme http://www.example.com.s3-website-us-east-1.amazonaws.com. AWS indique qu'il ne prend en charge que les requêtes GET et HEAD sur les objets. Un envoi de formulaire reçoit une page d'erreur HTML :

Réponse à un POST
<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>

Trois autres particularités de S3 façonnent le formulaire de contact :

Particularité de S3Conséquence pour le formulaire
Les website endpoints ne prennent pas en charge HTTPSIkiform ne suit un _redirect que vers une URL https: : une redirection vers l'endpoint nu est donc ignorée
Les en-têtes de réponse viennent de CloudFront, pas du bucketUne Content-Security-Policy se définit dans une politique d'en-têtes de réponse CloudFront
L'objet racine par défaut de CloudFront ne s'applique qu'à la racineAvec une origine REST, https://example.com/thanks/ ne charge pas thanks/index.html ; redirigez vers thanks.html

Pour un site en https:, AWS recommande Amplify Hosting, qui repose sur CloudFront, ou CloudFront devant le bucket. Le formulaire fonctionne dans les deux cas. Ce qui change, c'est l'endroit où arrive le visiteur après l'envoi.

Où arrive le visiteur après l'envoi, avec et sans CloudFrontwebsite endpoint S3 nu, httpCloudFront et votre domaine, httpshttp://…s3-website…contact.htmlIkiformstocke, vous écritpage deremerciementd'Ikiform_redirect en httpignoréhttps://www.example.comcontact.htmlIkiformstocke, vous écritvotre thanks.html_redirect suiviPOST303POST303Où arrive le visiteur après l'envoi, avec et sans CloudFrontwebsite endpoint S3 nu, httpCloudFront et votre domaine, httpshttp://…s3-website…contact.htmlIkiformstocke, vous écritpage de remerciementd'Ikiform_redirect en http ignoréhttps://www.example.comcontact.htmlIkiformstocke, vous écritvotre thanks.html_redirect suiviPOST303POST303
  1. Sur le website endpoint nu, la page est servie en http et envoie à Ikiform.
  2. Ikiform stocke le message, mais ignore un _redirect vers une adresse http et affiche sa page de remerciement hébergée.
  3. Définir Redirect after submit dans le tableau de bord contourne ce problème, car ce réglage accepte les URL http.
  4. Derrière CloudFront avec votre propre domaine, la page est en https.
  5. Ikiform suit le _redirect vers votre thanks.html, tant que le domaine figure dans Allowed domains.
Le message est stocké dans les deux cas. Seule la dernière étape, la destination du navigateur, dépend de https.

Quelle origine CloudFront

CloudFront peut lire le bucket de deux façons, et ce choix détermine la forme de votre URL de remerciement :

OrigineBucketPages d'index de dossierURL de remerciement
Le website endpoint S3, comme origine personnaliséeDoit être lisible publiquementFonctionnent : /thanks/ charge thanks/index.html/thanks/ ou /thanks.html
Le REST endpoint, avec origin access controlReste privé, lu uniquement par CloudFrontSeulement la racine, via l'objet racine par défaut/thanks.html, un nom de fichier complet

Un nom de fichier complet fonctionne dans les deux cas, c'est pourquoi les exemples en utilisent un. Si vous préférez ne pas gérer CloudFront vous-même, Amplify Hosting peut déployer depuis le bucket avec https: et un CDN géré ; le formulaire n'y demande aucune modification non plus.

Le formulaire

Les sites S3 sont souvent des sites d'entreprise : ce formulaire demande donc un e-mail professionnel et le nom de l'entreprise. Téléversez-le sous le nom contact.html à côté de thanks.html :

contact.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>
  • Le _redirect pointe vers le domaine CloudFront, avec un nom de fichier. Il n'est suivi que si www.example.com ou example.com figure dans Allowed domains.
  • Sur l'endpoint http: nu, retirez l'input _redirect et réglez plutôt Redirect after submit sur la page de remerciement. Ce réglage accepte les URL http:, car seule votre équipe peut le modifier.
  • Gardez email comme nom de champ. Les e-mails de notification l'utilisent comme adresse de réponse.

Sur un site d'entreprise, plusieurs personnes lisent généralement la boîte de contact. Ajoutez jusqu'à 10 destinataires de notification confirmés au formulaire ; chacun reçoit le message, et celui qui clique sur Reply répond directement à l'expéditeur. Si les messages doivent aussi arriver dans un canal partagé ou une file de tickets, ajoutez un webhook signé et acheminez-le via Zapier ou votre propre code. Le champ company arrive en texte brut, prêt à être filtré dans l'un ou l'autre.

Avant de téléverser, testez la page depuis un serveur local avec localhost dans Allowed domains. Les envois depuis localhost comptent comme des tests : vous pouvez donc mettre le formulaire au point avant même que le bucket ne le serve.

Synchronisez le dossier avec le bucket, et invalidez les pages dans CloudFront pour que le nouveau formulaire soit servi tout de suite :

Terminal
aws s3 sync ./site s3://www.example.com --delete

aws cloudfront create-invalidation --distribution-id E1EXAMPLE --paths "/contact.html" "/thanks.html"

Domaines autorisés sur les hôtes AWS

Où la page est servieÀ ajouter
Website endpoint nuL'hôte complet de l'endpoint du bucket, comme www.example.com.s3-website-us-east-1.amazonaws.com
Domaine CloudFront par défautL'hôte exact d111111abcdef8.cloudfront.net, pendant vos tests
Votre propre domaineexample.com, qui couvre aussi www.example.com

N'ajoutez jamais seuls amazonaws.com, un suffixe régional s3-website ou cloudfront.net. Tous les buckets ou distributions du monde correspondraient. AWS inscrit les domaines des website endpoints S3 dans la Public Suffix List pour la même raison : chaque bucket est un site distinct.

Les en-têtes via CloudFront

Les métadonnées d'objet S3 ne peuvent pas définir de Content-Security-Policy : définissez-la dans une politique d'en-têtes de réponse CloudFront et associez-la au comportement de cache par défaut de la distribution. La valeur de l'en-tête est limitée à 1 783 caractères :

csp-policy.json
{
  "Name": "site-csp",
  "SecurityHeadersConfig": {
    "ContentSecurityPolicy": {
      "Override": true,
      "ContentSecurityPolicy": "default-src 'self'; form-action 'self' https://ikiform.com; connect-src 'self' https://ikiform.com"
    }
  }
}
Terminal
aws cloudfront create-response-headers-policy --response-headers-policy-config file://csp-policy.json
Override: true remplace toute CSP envoyée par l'origine. Avec une origine S3 nue, il n'y en a pas, mais cela garde la politique aux commandes si vous changez d'origine plus tard.

Vérifiez que tout fonctionne

  1. Ajoutez les domaines du tableau ci-dessus, plus localhost pendant vos tests.
  2. Envoyez depuis votre domaine CloudFront. Vous devez arriver sur thanks.html sur votre propre domaine.
  3. Si vous gardez aussi le website endpoint nu public, envoyez depuis celui-ci et vérifiez que vous arrivez sur la page définie dans Redirect after submit.
  4. Ouvrez Submissions dans le tableau de bord. La nouvelle soumission y est, avec tous les champs envoyés.
  5. Vérifiez la boîte de réception de chaque destinataire des notifications. Chacun reçoit un e-mail avec les champs, et Reply répond à l'expéditeur quand le formulaire a un champ email.
  6. Rien n'est arrivé ? Passez le filtre de statut du tableau de bord sur Spam. Le spam reçoit la même réponse de succès qu'une vraie soumission.

Pièges

ProblèmeQue faire
405 Method Not Allowed avec Code: MethodNotAllowedLe formulaire a envoyé vers le bucket. CloudFront sert peut-être encore l'ancien contact.html ; invalidez-le.
AccessDenied ou 403 après la redirectionLa redirection pointe vers un dossier comme /thanks/ sur une distribution CloudFront avec une origine REST. Faites-la pointer vers thanks.html.
Le navigateur arrive sur la page de remerciement d'Ikiform au lieu de la vôtre_redirect est ignoré sauf si son domaine figure dans Allowed domains et qu'il s'agit d'une URL https:. Ajoutez le domaine, ou définissez plutôt Redirect after submit dans les réglages du formulaire.
403 origin_not_allowed, ou tous les envois finissent en spamLe domaine de la page n'est pas dans les Allowed domains du formulaire. Ajoutez-le, plus localhost pour les tests en local. Les sous-domaines d'un domaine listé sont autorisés.

Questions

Une étape vous bloque, ou vous voulez un guide pour votre cas ? Écrivez à hello@ikiform.com.