Fermer

mai 2, 2018

Création d'un formulaire de contact sans serveur pour votre site statique


Les générateurs de sites statiques fournissent une alternative simple et rapide aux systèmes de gestion de contenu (CMS) comme WordPress . Il n'y a pas de configuration de serveur ou de base de données, juste un processus de construction et de simples HTML, CSS et JavaScript. Malheureusement, sans serveur, il est facile d'atteindre rapidement ses limites. Par exemple, en ajoutant un formulaire de contact.

Avec la montée de l'architecture sans serveur ajouter un formulaire de contact à votre site statique n'a pas besoin d'être la raison pour basculer vers un CMS. Il est possible d'obtenir le meilleur des deux mondes: un site statique avec un back-end sans serveur pour le formulaire de contact (que vous n'avez pas besoin de maintenir). Peut-être le meilleur de tous, dans les sites à faible trafic, comme les portefeuilles, les limites élevées de nombreux fournisseurs sans serveur rendent ces services complètement gratuits!

Dans cet article, vous apprendrez les bases d'Amazon Web Services (AWS) Lambda et Simple Email Service (SES) API pour créer votre propre expéditeur de site statique sur le Serverless Framework . Le service complet prendra en charge les données soumises à partir d'une requête AJAX, atteindra le point de terminaison Lambda, analysera les données pour construire les paramètres SES, enverra l'adresse e-mail et retournera une réponse à nos utilisateurs. Je vous guiderai tout au long de la première installation de Serverless pour la première fois. Cela devrait prendre moins d'une heure, alors commençons!

Configuration

La mise en route de la technologie sans serveur nécessite peu de prérequis. Pour nos besoins, il s'agit simplement d'un nœud environnement avec Fil le Serverless Framework et un compte AWS . The Project


 Le site Web du serveur sans serveur. Utile pour l'installation et la documentation.
Le site web de Serverless Framework. Utile pour l'installation et la documentation.

Nous utilisons Yarn pour installer le Framework sans serveur dans un répertoire local

  1. Créez un nouveau répertoire pour héberger le projet
  2. Accédez au répertoire dans votre interface de ligne de commande.
  3. Run yarn init pour créer un fichier package.json pour ce projet
  4. Exécuter yarn add serverless pour installer le framework localement.
  5. Exécuter yarn serverless create - -template aws-nodejs --nom static-site-mailer pour créer un template de service Node et nommez-le static-site-mailer .

Notre projet est configuré mais nous ne serons pas capable de faire quoi que ce soit jusqu'à ce que nous configurions nos services AWS.

Configuration d'un compte Amazon Web Services, informations d'identification et service de messagerie simple


 La ​​page d'inscription Amazon Web Services, qui inclut un niveau gratuit généreux pour être entièrement gratuit.
La page d'inscription Amazon Web Services, qui inclut un niveau gratuit généreux, permettant o Votre projet est entièrement gratuit.

Le Framework Serverless a enregistré une [1959030] vidéo-étape pour la configuration des informations d'identification AWS, mais j'ai également listé les étapes ici.

  1. S'inscrire pour un compte AWS ] ou connectez-vous si vous en avez déjà un
  2. Dans la barre de recherche AWS, recherchez "IAM".
  3. Sur la page IAM, cliquez sur "Utilisateurs" dans la barre latérale, puis sur "Ajouter utilisateur".
  4. Sur la page Ajouter un utilisateur, donnez un nom à l'utilisateur – quelque chose comme "sans serveur" est approprié. Cochez "Accès par programme" sous Type d'accès puis cliquez sur Suivant.
  5. Sur l'écran des autorisations, cliquez sur l'onglet "Attacher les politiques existantes", recherchez "AdministratorAccess" dans la liste, cochez-le et cliquez sur Suivant. Sur l'écran de révision, vous devriez voir votre nom d'utilisateur, avec "Accès par programme", et "AdministratorAccess", puis créer l'utilisateur.
  6. L'écran de confirmation affiche l'utilisateur "Access key ID" et "Secret access key" J'en ai besoin pour fournir l'accès au Framework sans serveur. Dans votre CLI, tapez yarn sls config informations d'identification --provider aws --key VOTRE_ACCESS_KEY_ID --secret YOUR_SECRET_ACCESS_KEY en remplacement de YOUR_ACCESS_KEY_ID et YOUR_SECRET_ACCESS_KEY avec les clés sur la confirmation screen

Vos identifiants sont configurés maintenant, mais tant que nous sommes dans la console AWS, configurons Simple Email Service.

  1. Cliquez sur Console Home dans le coin supérieur gauche pour retourner à la maison.
  2. Sur la page d'accueil, Dans la barre de recherche AWS, recherchez "Simple Email Service".
  3. Sur la page d'accueil de SES, cliquez sur "Email Addresses" dans la barre latérale.
  4. Sur la page Adresses email, cliquez sur "Verify a New Email Bouton "Adresse"
  5. Dans la boîte de dialogue, tapez votre adresse e-mail, puis cliquez sur "Vérifier cette adresse e-mail".
  6. Vous recevrez un email contenant un lien pour vérifier l'adresse. Cliquez sur le lien pour terminer le processus

Maintenant que nos comptes sont créés, jetons un coup d'œil aux fichiers modèles Serverless.

Configuration de la structure sans serveur

Exécution de serverless create crée deux fichiers: handler.js qui contient la fonction Lambda, et serverless.yml qui est le fichier de configuration pour l'ensemble de l'architecture sans serveur. Dans le fichier de configuration, vous pouvez spécifier autant de gestionnaires que vous le souhaitez, et chacun va correspondre à une nouvelle fonction qui peut interagir avec d'autres fonctions. Dans ce projet, nous ne créerons qu'un seul gestionnaire, mais dans une architecture sans serveur complète, vous aurez plusieurs des différentes fonctions du service.


 La ​​structure de fichier par défaut générée à partir du Framework sans serveur contenant handler.js et serverless.yml.
Structure de fichier par défaut générée à partir du Framework sans serveur contenant handler.js et serverless.yml .

Dans handler.js vous verrez une seule fonction exportée nommée bonjour . C'est actuellement la fonction principale (et unique). Il, avec tous les gestionnaires de nœuds, prend trois paramètres:

  • événement
    Cela peut être considéré comme les données d'entrée pour la fonction.
  • objet de contexte
    Ceci contient le runtime information de la fonction Lambda
  • callback
    Paramètre facultatif pour renvoyer des informations à l'appelant.
 // handler.js

'use strict';

module.exports.hello = (événement, contexte, rappel) => {
  Réponse de const = {
    statusCode: 200,
    corps: JSON.stringify ({
      message: 'Go Serverless v1.0! Votre fonction a été exécutée avec succès! ',
      entrée: événement,
    }),
  }

  callback (null, réponse);
}

Au bas de bonjour il y a un rappel. C'est un argument optionnel pour renvoyer une réponse, mais si ce n'est pas explicitement appelé, il retournera implicitement avec null . Le rappel prend deux paramètres :

  • Erreur d'erreur
    Pour fournir des informations d'erreur lorsque le Lambda lui-même tombe en panne. Lorsque le Lambda réussit, null doit être passé dans ce paramètre
  • Résultat de l'objet
    Pour fournir un objet de réponse. Il doit être compatible avec JSON.stringify . S'il y a un paramètre dans le champ d'erreur, ce champ est ignoré

Notre site statique enverra les données de notre formulaire dans le corps de l'événement et le rappel retournera une réponse à notre utilisateur.

Dans serverless .yml vous verrez le nom du service, les informations sur le fournisseur et les fonctions.

 # serverless.yml

service: static-site-mailer

fournisseur:
  nom: aws
  runtime: nodejs6.10

les fonctions:
  Bonjour:
    gestionnaire: handler.hello

 Comment les noms de fonction dans serverless.yml correspondent à handler.js.
Comment les noms de fonctions dans serverless.yml correspondent à handler.js .

Notez le mappage entre la fonction Hello et le gestionnaire? Nous pouvons nommer notre fichier et tout fonctionner et tant qu'il est mappé à la configuration, cela fonctionnera. Renommons notre fonction en staticSiteMailer .

 # serverless.yml

les fonctions:
  staticSiteMailer:
    gestionnaire: handler.staticSiteMailer
 // handler.js

module.exports.staticSiteMailer = (événement, contexte, rappel) => {
  ...
}

Les fonctions Lambda nécessitent l'autorisation d'interagir avec d'autres infrastructures AWS. Avant de pouvoir envoyer un e-mail, nous devons autoriser SES à le faire. Dans serverless.yml sous provider.iamRoleStatements ajoutez la permission.

 # serverless.yml

fournisseur:
  nom: aws
  runtime: nodejs6.10
  iamRoleStatements:
    - Effet: "Autoriser"
      Action:
        - "ses: SendEmail"
      Ressource: ["*"]

Comme nous avons besoin d'une URL pour notre action de formulaire, nous devons ajouter des événements HTTP à notre fonction. Dans serverless.yml nous créons un chemin, spécifions la méthode comme post et définissons CORS comme vrai pour la sécurité.
  staticSiteMailer:
    gestionnaire: handler.staticSiteMailer
    événements:
      – http:
          méthode: post
          chemin: static-site-mailer
          cors: vrai

Nos fichiers mis à jour serverless.yml et handler.js devraient ressembler à:

 # serverless.yml

service: static-site-mailer

fournisseur:
  nom: aws
  runtime: nodejs6.10

les fonctions:
  staticSiteMailer:
    gestionnaire: handler.staticSiteMailer
    événements:
      - http:
          méthode: post
          chemin: static-site-mailer
          cors: vrai

fournisseur:
  nom: aws
  runtime: nodejs6.10
  iamRoleStatements:
    - Effet: "Autoriser"
      Action:
        - "ses: SendEmail"
      Ressource: ["*"]
 // handler.js

'use strict';

module.exports.staticSiteMailer = (événement, contexte, rappel) => {
  Réponse de const = {
    statusCode: 200,
    corps: JSON.stringify ({
      message: 'Go Serverless v1.0! Votre fonction a été exécutée avec succès! ',
      entrée: événement,
    }),
  }

  callback (null, réponse);
}

Notre architecture sans serveur est configurée, alors déployons-la et testons-la. Vous obtiendrez une réponse JSON simple.

 SLS fil déploie --verbose
fil sls invoquer --fonction staticSiteMailer

{
    "statusCode": 200,
    "body": "{" message  ": " Go Serverless v1.0! Votre fonction a été exécutée avec succès!  ", " Input  ": {}}"
}

 La réponse de retour d'invoquer notre toute nouvelle fonction sans serveur.
La réponse de retour d'invoquer notre toute nouvelle fonction sans serveur.

Création du formulaire HTML

Notre entrée de fonction Lambda et la sortie de formulaire doivent correspondre, donc avant de construire la fonction, nous allons construire le formulaire et capturer sa sortie. Nous restons simples avec le nom, l'email, et les champs de message. Nous ajouterons l'action de formulaire une fois que nous aurons déployé notre architecture sans serveur et aurons obtenu notre URL, mais nous savons qu'il s'agira d'une demande POST. Nous pouvons donc ajouter cela à la fin du formulaire. des messages de réponse à l'utilisateur que nous mettrons à jour lors du rappel de soumission.

Pour capturer la sortie, nous ajoutons un gestionnaire de soumission au formulaire, transformons nos paramètres de formulaire en un objet et envoyons un JSON stringifié à notre fonction Lambda. Dans la fonction Lambda, nous utilisons JSON.parse () pour lire nos données. Vous pouvez également utiliser Serialize ou query-string de jQuery pour envoyer et analyser les paramètres de formulaire en tant que chaîne de requête mais JSON.stringify () et JSON.parse () sont natifs.

 (() => {
  const form = document.querySelector ('formulaire');
  const formResponse = document.querySelector ('js-form-response');

  form.onsubmit = e => {
    e.preventDefault ();

    // Prépare les données à envoyer
    const données = {};
    const formElements = Array.from (formulaire);
    formElements.map (input => (data [input.name] = input.value));

    // Consigne ce que notre fonction lambda recevra
    console.log (JSON.stringify (données));
  }
}) ();

Allez-y et soumettez votre formulaire puis capturez la sortie de la console. Nous allons l'utiliser dans notre fonction Lambda suivante


 Capture des données de formulaire dans un journal de console
Capture des données de formulaire dans un journal de console.

Invoquer des fonctions lambda

Surtout pendant le développement, nous devons tester notre fonction fait ce que nous attendons. Le Framework Serverless fournit la commande invoke et invoke local pour déclencher votre fonction depuis les environnements live et development respectivement. Les deux commandes requièrent le nom de la fonction passée, dans notre cas staticSiteMailer .

 ysls appelle la fonction locale staticSiteMailer

Pour passer des données fantaisie dans notre fonction, créez un nouveau fichier nommé data.json avec la sortie de la console capturée sous une clé body dans un objet JSON. Cela devrait ressembler à quelque chose comme:

 // data.json

{
  "body": "{" name  ": " Nom de l'expéditeur  ", " reply_to  ": " sender@email.com  ", " message  ": " Message de l'expéditeur  "}"
}

Pour appeler la fonction avec les données locales, transmettez l'argument - path avec le chemin d'accès au fichier.

 sls de fil invoquent la fonction locale staticSiteMailer --path data.json

 Une réponse de retour mise à jour de notre fonction sans serveur lorsque nous lui transmettons des données JSON
Une réponse de retour mise à jour de notre fonction sans serveur lorsque nous lui transmettons des données JSON.

Vous verrez une réponse similaire à avant, mais la touche d'entrée contiendra l'événement dont nous nous sommes moqués. Utilisons nos données fictives pour envoyer un email en utilisant le service de courriel simple!

Envoyer un courriel avec un simple service de courriel

Nous allons remplacer la fonction staticSiteMailer par un appel privé ] sendEmail fonction. Pour l'instant, vous pouvez commenter ou supprimer le code du modèle et le remplacer par:

 // hander.js

Fonction sendEmail (formData, callback) {
  // Construire les paramètres SES
  // Envoyer l'email
}

module.exports.staticSiteMailer = (événement, contexte, rappel) => {
  const formData = JSON.parse (event.body);

  sendEmail (formData, function (err, data) {
    if (err) {
      console.log (err, err.stack);
    } autre {
      console.log (données);
    }
  });
}

Tout d'abord, nous analysons l'événement .body pour capturer les données du formulaire, puis nous passons à une fonction privée sendEmail . sendEmail est responsable de l'envoi de l'e-mail et la fonction de rappel renvoie une erreur ou une réponse de succès avec les données err ou . Dans notre cas, nous pouvons simplement enregistrer l'erreur ou les données car nous allons remplacer cela par le rappel Lambda dans un instant.

Amazon fournit un SDK pratique, aws-sdk pour connecter leurs services avec des fonctions Lambda. Beaucoup de leurs services, y compris SES, en font partie. Nous l'ajoutons au projet avec yarn add aws-sdk et l'importons en haut du fichier gestionnaire

 // handler.js

const AWS = require ('aws-sdk');
const SES = nouveau AWS.SES ();

Dans notre fonction privée sendEmail nous construisons les paramètres SES.sendEmail à partir des données du formulaire analysé et utilisons le rappel pour renvoyer une réponse à l'appelant. Les paramètres requièrent ce qui suit en tant qu'objet:

  • Source
    L'adresse électronique SES envoie depuis .
  • ReplyToAddresses
    Un tableau d'adresses électroniques ajouté à la réponse à le champ dans l'email.
  • Destination
    Un objet qui doit contenir au moins un ToAddresses CcAddresses ou BccAddresses . Chaque champ prend un tableau d'adresses e-mail correspondant respectivement aux champs à cc et bcc .
  • Message
    An objet qui contient le Corps et Objet .

Depuis formData est un objet que nous pouvons appeler nos champs de formulaire directement comme formData.message construire nos paramètres, et l'envoyer. Nous transmettons votre adresse courriel vérifiée par SES à Source et Destination.ToAddresses . Tant que l'e-mail est vérifié, vous pouvez passer n'importe quoi ici, y compris les différentes adresses e-mail. Nous récupérons notre reply_to message et nom de notre objet formData pour remplir le ReplyToAddresses et Champs Message.Body.Text.Data .

 // handler.js
Fonction sendEmail (formData, callback) {
  const emailParams = {
    Source: 'your_email@example.com', // SES ENVOI EMAIL
    ReplyToAddresses: [formData.reply_to],
    Destination: {
      ToAddresses: ['your_email@example.com']// SES RECEVOIR UN EMAIL
    },
    Message: {
      Corps: {
        Texte: {
          Jeu de caractères: 'UTF-8',
          Données: `$ {formData.message}  n  nNom: $ {formData.name}  nEmail: $ {formData.reply_to}`,
        },
      },
      Sujet: {
        Jeu de caractères: 'UTF-8',
        Données: "Nouveau message de your_site.com",
      },
    },
  }

  SES.sendEmail (emailParams, callback);
}

SES.sendEmail enverra l'email et notre callback retournera une réponse. L'appel de la fonction locale enverra un e-mail à votre adresse vérifiée.

 ys sl appelle la fonction locale testMailer --path data.json

 Réponse de SES.sendEmail en cas de succès
Réponse de SES.sendEmail en cas de succès.

Retour d'une réponse du gestionnaire

Notre fonction envoie un courriel en utilisant la ligne de commande, mais ce n'est pas ainsi que nos utilisateurs interagiront avec elle. Nous devons retourner une réponse à notre soumission de formulaire AJAX. Si cela échoue, nous devrions retourner un statuscode approprié ainsi que le err.message . Quand il réussit, le 200 statusCode est suffisant, mais nous allons également renvoyer la réponse mailer dans le corps. Dans staticSiteMailer nous construisons nos données de réponse et remplaçons notre fonction de rappel sendEmail avec le rappel Lambda.

 // handler.js

module.exports.staticSiteMailer = (événement, contexte, rappel) => {
  const formData = JSON.parse (event.body);

  sendEmail (formData, function (err, data) {
    Réponse de const = {
      statusCode: err? 500: 200,
      en-têtes: {
        'Content-Type': 'application / json',
        'Access-Control-Allow-Origin': 'https://votre-domaine.com',
      },
      corps: JSON.stringify ({
        message: err? err.message: données,
      }),
    }

    callback (null, réponse);
  });
}

Notre rappel Lambda renvoie maintenant les messages de succès et d'échec de SES.sendEmail . Nous construisons la réponse avec des vérifications si err est présent afin que notre réponse soit cohérente. La fonction de rappel Lambda elle-même transmet null dans le champ d'argument d'erreur et la réponse dans la seconde. Nous voulons transmettre les erreurs, mais si le Lambda lui-même échoue, son rappel sera implicitement appelé avec la réponse d'erreur.

Dans les en-têtes vous devrez remplacer Access-Control-Allow-Origin avec votre propre domaine. Cela empêchera tout autre domaine d'utiliser votre service et potentiellement accumuler une facture AWS à votre nom! Et je ne le couvre pas dans cet article, mais il est possible de configurer Lambda pour utiliser votre propre domaine. Vous devez avoir un certificat SSL / TLS téléchargé sur Amazon. L'équipe du Framework Serverless a écrit un tutoriel fantastique sur la façon de procéder

L'appel de la fonction locale va maintenant envoyer un email et renvoyer la réponse appropriée.

 ys sl appelle la fonction locale testMailer - -path data.json

 La réponse de retour de notre fonction sans serveur, contenant la réponse de retour de SES.sendEmail dans le corps.
La réponse de retour de notre fonction sans serveur, contenant la réponse de retour de SES.sendEmail dans le corps.

Appel de la fonction lambda à partir de la forme

Notre service est complet! Pour le déployer, exécutez sls de fil déployer -v . Une fois qu'il est déployé, vous obtiendrez une URL qui ressemble à quelque chose comme https://r4nd0mh45h.execute-api.us-east-1.amazonaws.com/dev/static-site-mailer que vous pouvez ajouter à l'action de formulaire. Ensuite, nous créons la requête AJAX et renvoyons la réponse à l'utilisateur.

 (() => {
  const form = document.querySelector ('formulaire');
  const formResponse = document.querySelector ('js-form-response');

  form.onsubmit = e => {
    e.preventDefault ();

    // Prépare les données à envoyer
    const données = {};
    const formElements = Array.from (formulaire);
    formElements.map (input => (data [input.name] = input.value));

    // Consigne ce que notre fonction lambda recevra
    console.log (JSON.stringify (données));

    // Construire une requête HTTP
    var xhr = new XMLHttpRequest ();
    xhr.open (form.method, form.action, true);
    xhr.setRequestHeader ('Accepter', 'application / json; jeu de caractères = utf-8');
    xhr.setRequestHeader ('Content-Type', 'application / json; jeu de caractères = UTF-8');

    // Envoie les données collectées en JSON
    xhr.send (JSON.stringify (data));

    // Fonction de rappel
    xhr.onloadend = réponse => {
      if (response.target.status === 200) {
        // La soumission du formulaire a été réussie
        form.reset ();
        formResponse.innerHTML = 'Merci pour le message. Je serai en contact sous peu. ';
      } autre {
        // La soumission du formulaire a échoué
        formResponse.innerHTML = 'Quelque chose s'est mal passé';
        console.error (JSON.parse (response.target.response) .message);
      }
    }
  }
}) ();

Dans le rappel AJAX, nous vérifions le code d'état avec response.target.status . Si c'est quelque chose d'autre que 200 nous pouvons montrer un message d'erreur à l'utilisateur, sinon faites-lui savoir que le message a été envoyé. Puisque notre Lambda renvoie un JSON stringifié, nous pouvons analyser le message du corps avec JSON.parse (response.target.response) .message . Il est particulièrement utile de consigner l'erreur.

Vous devriez pouvoir soumettre votre formulaire entièrement à partir de votre site statique!

 Formulaire de site statique, envoyant le message au point de terminaison Lambda et retournant une réponse à l'utilisateur. [19659136] Le formulaire de site statique, envoyant le message au point de terminaison Lambda et renvoyant une réponse à l'utilisateur.</figcaption data-recalc-dims=

Next Steps

L'ajout d'un formulaire de contact à votre static est facile avec le Framework Serverless et AWS. Il y a place à amélioration dans notre code, comme ajouter une validation de forme avec un honeypot empêcher les appels AJAX pour les formulaires invalides et améliorer l'UX si la réponse, mais c'est suffisant pour commencer. Vous pouvez voir certaines de ces améliorations dans le [1959095] dépôt de site Web statique que j'ai créé. J'espère que je vous ai inspiré pour essayer vous-même Serverless!

 Éditorial Smashing (lf, ra, il)




Source link