Statik Siteniz İçin Sunucusuz Bir İletişim Formu Oluşturma

Yayınlanan: 2022-03-10
Kısa özet ↬ Bu makalenin yardımıyla, sonunda, Serverless Framework üzerinde kendi statik site posta gönderinizi oluşturmanıza yardımcı olacak Amazon Web Services (AWS) Lambda ve Simple Email Service (SES) API'lerinin temellerini öğrenebileceksiniz. Başlayalım!

Statik site oluşturucular, WordPress gibi İçerik Yönetim Sistemlerine (CMS) hızlı ve basit bir alternatif sunar. Sunucu veya veritabanı kurulumu yoktur, yalnızca bir oluşturma işlemi ve basit HTML, CSS ve JavaScript vardır. Ne yazık ki, bir sunucu olmadan, sınırlarını hızla aşmak kolaydır. Örneğin, bir iletişim formu eklerken.

Sunucusuz mimarinin yükselişiyle birlikte, statik sitenize bir iletişim formu eklemenin artık bir CMS'ye geçme nedeni olması gerekmiyor. Her iki dünyanın da en iyisini elde etmek mümkündür: iletişim formu için sunucusuz bir arka uca sahip statik bir site (korumanız gerekmeyen). Belki de en iyisi, portföyler gibi düşük trafikli sitelerde, birçok sunucusuz sağlayıcının yüksek limitleri bu hizmetleri tamamen ücretsiz hale getirir!

Bu makalede, Serverless Framework üzerinde kendi statik site posta gönderinizi oluşturmak için Amazon Web Services (AWS) Lambda ve Simple Email Service (SES) API'lerinin temellerini öğreneceksiniz. Tam hizmet, bir AJAX isteğinden gönderilen form verilerini alacak, Lambda uç noktasına ulaşacak, SES parametrelerini oluşturmak için verileri ayrıştıracak, e-posta adresini gönderecek ve kullanıcılarımız için bir yanıt döndürecektir. Dağıtım yoluyla ilk kez Sunucusuz kurulumu gerçekleştirme konusunda size rehberlik edeceğim. Tamamlanması bir saatten az sürer, o yüzden başlayalım!

Statik site formu, mesajı Lambda uç noktasına gönderme ve kullanıcıya yanıt döndürme.
Statik site formu, mesajı Lambda uç noktasına gönderme ve kullanıcıya yanıt döndürme.
Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓

Kurulum

Sunucusuz teknolojiyi kullanmaya başlamanın minimum önkoşulları vardır. Bizim amaçlarımız için, sadece Yarn, Sunucusuz Çerçeve ve bir AWS hesabı içeren bir Düğüm Ortamıdır.

Projeyi Kurmak

Sunucusuz Çerçeve web sitesi. Kurulum ve dokümantasyon için kullanışlıdır.
Sunucusuz Çerçeve web sitesi. Kurulum ve dokümantasyon için kullanışlıdır.

Serverless Framework'ü yerel bir dizine kurmak için Yarn kullanıyoruz.

  1. Projeyi barındırmak için yeni bir dizin oluşturun.
  2. Komut satırı arayüzünüzdeki dizine gidin.
  3. Bu proje için bir package.json dosyası oluşturmak için thread yarn init çalıştırın.
  4. Çerçeveyi yerel olarak kurmak için yarn add serverless çalıştırın.
  5. Bir Düğüm hizmeti şablonu oluşturmak için yarn serverless create --template aws-nodejs --name static-site-mailer çalıştırın ve bunu static-site-mailer olarak adlandırın.

Projemiz kuruldu ancak AWS hizmetlerimizi kurana kadar hiçbir şey yapamayacağız.

Bir Amazon Web Hizmetleri Hesabı, Kimlik Bilgileri ve Basit E-posta Hizmeti Oluşturma

Cömert bir ücretsiz katman içeren ve projemizin tamamen ücretsiz olmasını sağlayan Amazon Web Services kayıt sayfası.
Cömert bir ücretsiz katman içeren ve projemizin tamamen ücretsiz olmasını sağlayan Amazon Web Services kayıt sayfası.

Sunucusuz Çerçeve, AWS kimlik bilgilerini ayarlamak için bir video incelemesi kaydetti, ancak adımları burada da listeledim.

  1. Bir AWS hesabına kaydolun veya zaten varsa oturum açın.
  2. AWS arama çubuğunda “IAM” arayın.
  3. IAM sayfasında, kenar çubuğundaki "Kullanıcılar"ı ve ardından "Kullanıcı ekle" düğmesini tıklayın.
  4. Kullanıcı ekle sayfasında, kullanıcıya bir ad verin - "sunucusuz" gibi bir şey uygundur. Erişim türü altında “Programatik erişim”i işaretleyin ve ardından ileriyi tıklayın.
  5. İzinler ekranında, "Mevcut ilkeleri doğrudan ekle" sekmesine tıklayın, listede "Yönetici Erişimi"ni arayın, kontrol edin ve ileri'ye tıklayın.
  6. İnceleme ekranında “Programatik erişim” ve “Yönetici Erişimi” ile kullanıcı adınızı görmeli ve ardından kullanıcıyı oluşturmalısınız.
  7. Onay ekranı, "Erişim anahtarı kimliği" ve "Gizli erişim anahtarı" kullanıcısını gösterir, Sunucusuz Çerçeveye erişim sağlamak için bunlara ihtiyacınız olacaktır. CLI'nize, YOUR_ACCESS_KEY_ID ve YOUR_SECRET_ACCESS_KEY onay ekranındaki tuşlarla değiştirerek, yarn sls config credentials --provider aws --key YOUR_ACCESS_KEY_ID --secret YOUR_SECRET_ACCESS_KEY .

Kimlik bilgileriniz şimdi yapılandırıldı, ancak biz AWS konsolundayken Basit E-posta Hizmeti ayarlayalım.

  1. Eve gitmek için sol üst köşedeki Konsol Ana Sayfası'na tıklayın.
  2. Ana sayfada, AWS arama çubuğunda “Basit E-posta Hizmeti”ni arayın.
  3. SES Ana sayfasında, kenar çubuğundaki “E-posta Adresleri”ne tıklayın.
  4. E-posta Adresleri listeleme sayfasında, "Yeni Bir E-posta Adresini Doğrula" düğmesini tıklayın.
  5. İletişim penceresinde e-posta adresinizi yazın ve ardından "Bu E-posta Adresini Doğrula"yı tıklayın.
  6. Birkaç dakika içinde adresi doğrulamak için bir bağlantı içeren bir e-posta alacaksınız. İşlemi tamamlamak için bağlantıya tıklayın.

Artık hesaplarımız yapıldığına göre Serverless şablon dosyalarına bir göz atalım.

Sunucusuz Çerçeveyi Ayarlama

Serverless serverless create çalıştırıldığında iki dosya oluşturulur: Lambda işlevini içeren handler.js ve tüm Sunucusuz Mimari için yapılandırma dosyası olan serverless.yml. Yapılandırma dosyasında istediğiniz kadar işleyici belirtebilirsiniz ve her biri diğer işlevlerle etkileşime girebilecek yeni bir işlevle eşlenir. Bu projede yalnızca tek bir işleyici oluşturacağız, ancak tam bir Sunucusuz Mimaride, hizmetin çeşitli işlevlerine sahip olacaksınız.

handler.js ve serverless.yml içeren Serverless Framework'ten oluşturulan varsayılan dosya yapısı.
handler.js ve serverless.yml içeren Serverless Framework'ten oluşturulan varsayılan dosya yapısı.

handler.js'de, hello adında dışa aktarılan tek bir işlev göreceksiniz. Bu şu anda ana (ve yalnızca) işlevdir. Tüm Düğüm işleyicileriyle birlikte üç parametre alır:

  • event
    Bu, işlev için giriş verileri olarak düşünülebilir.
  • context object
    Bu, Lambda işlevinin çalışma zamanı bilgilerini içerir.
  • callback
    Arayan kişiye bilgi döndürmek için isteğe bağlı bir parametre.
 // handler.js 'use strict'; module.exports.hello = (event, context, callback) => { const response = { statusCode: 200, body: JSON.stringify({ message: 'Go Serverless v1.0! Your function executed successfully!', input: event, }), }; callback(null, response); };

hello altında bir geri arama var. Bir yanıt döndürmek isteğe bağlı bir argümandır, ancak açıkça çağrılmazsa, örtük olarak null ile dönecektir. Geri arama iki parametre alır:

  • Hata hatası
    Lambda'nın kendisinin ne zaman arızalanacağına ilişkin hata bilgisi sağlamak için. Lambda başarılı olduğunda, bu parametreye null geçirilmelidir.
  • nesne sonucu
    Bir yanıt nesnesi sağlamak için. JSON.stringify uyumlu olmalıdır. Hata alanında bir parametre varsa bu alan yok sayılır.

Statik sitemiz, form verilerimizi olay gövdesine gönderecek ve geri arama, kullanıcımızın görmesi için bir yanıt döndürecektir.

serverless.yml'de hizmetin adını, sağlayıcı bilgilerini ve işlevleri göreceksiniz.

 # serverless.yml service: static-site-mailer provider: name: aws runtime: nodejs6.10 functions: hello: handler: handler.hello 
serverless.yml dosyasındaki işlev adları handler.js ile nasıl eşlenir?
serverless.yml dosyasındaki işlev adları handler.js ile nasıl eşlenir?

Merhaba işlevi ile işleyici arasındaki eşlemeye dikkat edin? Dosyamızı adlandırabilir ve her şeyi çalıştırabiliriz ve çalışacağı konfigürasyonla eşleştiği sürece. Fonksiyonumuzu staticSiteMailer olarak yeniden adlandıralım.

 # serverless.yml functions: staticSiteMailer: handler: handler.staticSiteMailer
 // handler.js module.exports.staticSiteMailer = (event, context, callback) => { ... };

Lambda işlevlerinin diğer AWS altyapısıyla etkileşime girebilmesi için izne ihtiyacı vardır. Bir e-posta gönderebilmemiz için önce SES'in bunu yapmasına izin vermemiz gerekiyor. serverless.yml dosyasında, provider.iamRoleStatements altında izni ekleyin.

 # serverless.yml provider: name: aws runtime: nodejs6.10 iamRoleStatements: - Effect: "Allow" Action: - "ses:SendEmail" Resource: ["*"]

Form eylemimiz için bir URL'ye ihtiyacımız olduğundan, işlevimize HTTP olayları eklememiz gerekiyor. serverless.yml'de bir yol oluşturuyoruz, yöntemi post olarak belirledik ve güvenlik için CORS'u true olarak ayarladık.

 functions: staticSiteMailer: handler: handler.staticSiteMailer events: - http: method: post path: static-site-mailer cors: true

Güncellenen serverless.yml ve handler.js dosyalarımız şöyle görünmelidir:

 # serverless.yml service: static-site-mailer provider: name: aws runtime: nodejs6.10 functions: staticSiteMailer: handler: handler.staticSiteMailer events: - http: method: post path: static-site-mailer cors: true provider: name: aws runtime: nodejs6.10 iamRoleStatements: - Effect: "Allow" Action: - "ses:SendEmail" Resource: ["*"]
 // handler.js 'use strict'; module.exports.staticSiteMailer = (event, context, callback) => { const response = { statusCode: 200, body: JSON.stringify({ message: 'Go Serverless v1.0! Your function executed successfully!', input: event, }), }; callback(null, response); };

Sunucusuz Mimarimiz kuruldu, bu yüzden dağıtalım ve test edelim. Basit bir JSON yanıtı alacaksınız.

 yarn sls deploy --verbose yarn sls invoke --function staticSiteMailer { "statusCode": 200, "body": "{\"message\":\"Go Serverless v1.0! Your function executed successfully!\",\"input\":{}}" } 
Yepyeni sunucusuz işlevimizi çağırmanın geri dönüşü.
Yepyeni sunucusuz işlevimizi çağırmanın geri dönüşü.

HTML Formu Oluşturma

Lambda işlevi girdimiz ve form çıktımızın eşleşmesi gerekir, bu nedenle işlevi oluşturmadan önce formu oluşturup çıktısını yakalayacağız. Ad, e-posta ve mesaj alanlarıyla bunu basit tutuyoruz. Sunucusuz mimarimizi dağıttıktan ve URL'mizi aldıktan sonra form eylemini ekleyeceğiz, ancak bunun bir POST isteği olacağını biliyoruz, bu yüzden onu ekleyebilmemiz için. Formun sonuna, görüntülemek için bir paragraf etiketi ekliyoruz. Gönderim geri aramasında güncelleyeceğimiz kullanıcıya yanıt mesajları.

 <form action="{{ SERVICE URL }}" method="POST"> <label> Name <input type="text" name="name" required> </label> <label> Email <input type="email" name="reply_to" required> </label> <label> Message: <textarea name="message" required></textarea> </label> <button type="submit">Send Message</button> </form> <p></p>

Çıktıyı yakalamak için forma bir gönderme işleyicisi ekliyoruz, form parametrelerimizi bir nesneye dönüştürüyoruz ve dizili JSON'u Lambda işlevimize gönderiyoruz. Lambda işlevinde verilerimizi okumak için JSON.parse() kullanıyoruz. Alternatif olarak, form parametrelerini bir sorgu dizesi olarak göndermek ve ayrıştırmak için jQuery'nin Serileştirme veya sorgu dizesini kullanabilirsiniz, ancak JSON.stringify() ve JSON.parse() yereldir.

 (() => { const form = document.querySelector('form'); const formResponse = document.querySelector('js-form-response'); form.onsubmit = e => { e.preventDefault(); // Prepare data to send const data = {}; const formElements = Array.from(form); formElements.map(input => (data[input.name] = input.value)); // Log what our lambda function will receive console.log(JSON.stringify(data)); }; })();

Devam edin ve formunuzu gönderin, ardından konsol çıktısını alın. Bundan sonra Lambda işlevimizde kullanacağız.

Bir konsol günlüğünde form verilerini yakalama.
Bir konsol günlüğünde form verilerini yakalama.

Lambda İşlevlerini Çağırma

Özellikle geliştirme sırasında, fonksiyonumuzun beklediğimiz şeyi yaptığını test etmemiz gerekiyor. Sunucusuz Çerçeve, işlevinizi sırasıyla canlı ve geliştirme ortamlarından tetiklemek için yerel invoke ve invoke local komutunu sağlar. Her iki komut da, bizim durumumuzda staticSiteMailer iletilen işlev adını gerektirir.

 yarn sls invoke local --function staticSiteMailer

Sahte verileri işlevimize iletmek için, bir JSON nesnesi içindeki bir body anahtarının altında yakalanan konsol çıktısıyla data.json adlı yeni bir dosya oluşturun. Şunun gibi görünmelidir:

 // data.json { "body": "{\"name\": \"Sender Name\",\"reply_to\": \"[email protected]\",\"message\": \"Sender message\"}" }

İşlevi yerel verilerle çağırmak için, dosya yolu ile birlikte --path argümanını iletin.

 yarn sls invoke local --function staticSiteMailer --path data.json 
JSON verilerini ilettiğimizde sunucusuz işlevimizden güncellenmiş bir dönüş yanıtı.
JSON verilerini ilettiğimizde sunucusuz işlevimizden güncellenmiş bir dönüş yanıtı.

Öncekine benzer bir yanıt göreceksiniz, ancak input anahtarı, alay ettiğimiz olayı içerecek. Basit E-posta Hizmetini kullanarak bir e-posta göndermek için sahte verilerimizi kullanalım!

Basit E-posta Hizmetiyle E-posta Gönderme

staticSiteMailer işlevini özel bir sendEmail işlevi çağrısıyla değiştireceğiz. Şimdilik, şablon kodunu yorumlayabilir veya kaldırabilir ve şununla değiştirebilirsiniz:

 // hander.js function sendEmail(formData, callback) { // Build the SES parameters // Send the email } module.exports.staticSiteMailer = (event, context, callback) => { const formData = JSON.parse(event.body); sendEmail(formData, function(err, data) { if (err) { console.log(err, err.stack); } else { console.log(data); } }); };

İlk olarak, form verilerini yakalamak için event.body ayrıştırırız, sonra onu özel bir sendEmail işlevine geçiririz. sendEmail , e-postayı göndermekten sorumludur ve geri arama işlevi, err veya data ile bir başarısızlık veya başarı yanıtı döndürür. Bizim durumumuzda, bir an sonra bunu Lambda geri aramasıyla değiştireceğimiz için hatayı veya verileri basitçe kaydedebiliriz.

Amazon, hizmetlerini Lambda işlevlerine bağlamak için uygun bir SDK ( aws-sdk ) sağlar. SES de dahil olmak üzere hizmetlerinin çoğu bunun bir parçasıdır. yarn add aws-sdk ile projeye ekliyoruz ve işleyici dosyasının en üstüne import ediyoruz.

 // handler.js const AWS = require('aws-sdk'); const SES = new AWS.SES();

Özel sendEmail işlevimizde, ayrıştırılmış form verilerinden SES.sendEmail parametrelerini oluşturuyoruz ve arayana bir yanıt döndürmek için geri aramayı kullanıyoruz. Parametreler, bir nesne olarak aşağıdakileri gerektirir:

  • Kaynak
    SES'in gönderdiği e-posta adresi .
  • Adresleri Yanıtla
    E-postadaki alana verilen yanıta eklenen bir dizi e-posta adresi.
  • Hedef
    En az bir ToAddresses , CcAddresses veya BccAddresses içermesi gereken bir nesne. Her alan, sırasıyla to , cc ve bcc alanlarına karşılık gelen bir dizi e-posta adresi alır.
  • İleti
    Gövde ve Özneyi içeren bir nesne.

formData bir nesne olduğu için form alanlarımızı doğrudan formData.message gibi çağırabilir, parametrelerimizi oluşturabilir ve gönderebiliriz. SES tarafından doğrulanmış e- postanızı Source ve Destination.ToAddresses adresine iletiriz. E-posta doğrulandığı sürece, farklı e-posta adresleri de dahil olmak üzere her şeyi buraya iletebilirsiniz. ReplyToAddresses ve Message.Body.Text.Data alanlarını doldurmak için answer_to , message ve reply_to formData name alıyoruz.

 // handler.js function sendEmail(formData, callback) { const emailParams = { Source: '[email protected]', // SES SENDING EMAIL ReplyToAddresses: [formData.reply_to], Destination: { ToAddresses: ['[email protected]'], // SES RECEIVING EMAIL }, Message: { Body: { Text: { Charset: 'UTF-8', Data: `${formData.message}\n\nName: ${formData.name}\nEmail: ${formData.reply_to}`, }, }, Subject: { Charset: 'UTF-8', Data: 'New message from your_site.com', }, }, }; SES.sendEmail(emailParams, callback); }

SES.sendEmail e-postayı gönderecek ve geri aramamız bir yanıt verecektir. Yerel işlevi çağırmak, doğrulanmış adresinize bir e-posta gönderir.

 yarn sls invoke local --function staticSiteMailer --path data.json 
Başarılı olduğunda SES.sendEmail'den gelen dönüş yanıtı.
Başarılı olduğunda SES.sendEmail gelen dönüş yanıtı.

İşleyiciden Yanıt Döndürme

İşlevimiz komut satırını kullanarak bir e-posta gönderir, ancak kullanıcılarımız onunla bu şekilde etkileşime girmez. AJAX form gönderimimize bir yanıt göndermemiz gerekiyor. Başarısız olursa, statusCode ile birlikte uygun bir err.message . Başarılı olduğunda, 200 statusCode yeterlidir, ancak posta yanıtını gövdede de döndürürüz. staticSiteMailer yanıt verilerimizi oluşturuyoruz ve sendEmail geri arama işlevimizi Lambda geri aramasıyla değiştiriyoruz.

 // handler.js module.exports.staticSiteMailer = (event, context, callback) => { const formData = JSON.parse(event.body); sendEmail(formData, function(err, data) { const response = { statusCode: err ? 500 : 200, headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': 'https://your-domain.com', }, body: JSON.stringify({ message: err ? err.message : data, }), }; callback(null, response); }); };

Lambda geri SES.sendEmail hem başarı hem de başarısızlık mesajları döndürüyor. Yanıtımızın tutarlı olması için err olup olmadığını kontrol ederek yanıtı oluştururuz. Lambda geri çağırma işlevinin kendisi, hata bağımsız değişkeni alanında null ve ikinci olarak yanıtı geçer. Hataları iletmek istiyoruz, ancak Lambda'nın kendisi başarısız olursa, geri çağrısı dolaylı olarak hata yanıtıyla çağrılır.

headers , Access-Control-Allow-Origin kendi alanınızla değiştirmeniz gerekir. Bu, diğer etki alanlarının hizmetinizi kullanmasını ve potansiyel olarak adınıza bir AWS faturası oluşturmasını önleyecektir! Ve bu makalede ele almıyorum, ancak Lambda'yı kendi alanınızı kullanacak şekilde ayarlamak mümkündür. Amazon'a yüklenmiş bir SSL/TLS sertifikasına sahip olmanız gerekir. Serverless Framework ekibi, bunun nasıl yapılacağına dair harika bir eğitim yazdı.

Yerel işlevi çağırmak artık bir e-posta gönderecek ve uygun yanıtı döndürecektir.

 yarn sls invoke local --function staticSiteMailer --path data.json 
Gövdede SES.sendEmail dönüş yanıtını içeren sunucusuz işlevimizden gelen dönüş yanıtı.
Gövdede SES.sendEmail dönüş yanıtını içeren sunucusuz işlevimizden gelen dönüş yanıtı.

Formdan Lambda İşlevini Çağırma

Hizmetimiz tamamlandı! Bunu dağıtmak için yarn sls deploy -v . Dağıtıldıktan sonra, form eylemine ekleyebileceğiniz https://r4nd0mh45h.execute-api.us-east-1.amazonaws.com/dev/static-site-mailer gibi görünen bir URL alırsınız. Ardından, AJAX isteğini oluşturuyoruz ve yanıtı kullanıcıya geri gönderiyoruz.

 (() => { const form = document.querySelector('form'); const formResponse = document.querySelector('js-form-response'); form.onsubmit = e => { e.preventDefault(); // Prepare data to send const data = {}; const formElements = Array.from(form); formElements.map(input => (data[input.name] = input.value)); // Log what our lambda function will receive console.log(JSON.stringify(data)); // Construct an HTTP request var xhr = new XMLHttpRequest(); xhr.open(form.method, form.action, true); xhr.setRequestHeader('Accept', 'application/json; charset=utf-8'); xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); // Send the collected data as JSON xhr.send(JSON.stringify(data)); // Callback function xhr.onloadend = response => { if (response.target.status === 200) { // The form submission was successful form.reset(); formResponse.innerHTML = 'Thanks for the message. I'll be in touch shortly.'; } else { // The form submission failed formResponse.innerHTML = 'Something went wrong'; console.error(JSON.parse(response.target.response).message); } }; }; })();

AJAX geri aramasında, durum kodunu response.target.status ile kontrol ediyoruz. 200 farklı bir şeyse, kullanıcıya bir hata mesajı gösterebiliriz, aksi takdirde mesajın gönderildiğini onlara bildirin. Lambda'mız dizilmiş JSON döndürdüğü için, gövde mesajını JSON.parse(response.target.response).message ile ayrıştırabiliriz. Hatayı günlüğe kaydetmek özellikle yararlıdır.

Formunuzu tamamen statik sitenizden gönderebilmelisiniz!

Statik site formu, mesajı Lambda uç noktasına gönderme ve kullanıcıya yanıt döndürme.
Statik site formu, mesajı Lambda uç noktasına gönderme ve kullanıcıya yanıt döndürme.

Sonraki adımlar

Sunucusuz Çerçeve ve AWS ile statiğinize bir iletişim formu eklemek kolaydır. Kodumuzda, bal küpü ile form doğrulama eklemek, geçersiz formlar için AJAX çağrılarını önlemek ve yanıt verilirse UX'i iyileştirmek gibi iyileştirmeler için yer var, ancak bu başlamak için yeterlidir. Bu iyileştirmelerden bazılarını, oluşturduğum statik site posta deposu deposunda görebilirsiniz. Umarım Sunucusuz'u kendiniz denemeniz için size ilham vermişimdir!