How did I re-architect my web application to serve dynamic forms serverless
Tags: aws, serverless, lambda, s3
Published: 2020-08-31 13:06:43

This use case is useful for the "contact us" or " feedback" section for most of the websites. Instead of having the entire website running on web server and supporting DB, the proposed architecture really helps to have the same functionality without having to manage any servers.

I want to touch on how I changed existing setup for my Web application that typically had my web portfolio on it. Web site has fairly static content and only a form data that was more of dynamic in nature which when someone contacts will push the contact form data to database.

This is the current architecture:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/21qsp85wnii0abzdt8y2.PNG)

This has two problems:

Even though the contents are all static except form data , this need to go on a server as we need to handle the form data. My web portfolio:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/kvolou1myydci86niu14.PNG)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/73x3uynk2cfbhocl72s0.PNG)



The server is always up and running, we end up paying the cost for the server even if it is serving only static content or limited form data.

Solution:

If there is only form data that needs to be handled, the above solution can be changed as below and still have same functionality but without server. Proposed architecture :


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/i0c08edmofw7wmzhccy2.JPG)


The solution is achieved through following steps:

Host the static content from S3.
Create an API gateway
Create Lambda that would get the form data from API gateway ( json data)
Use the json data and send an email or
Push the json data to Dynamo DB.
Implementation:

In this implementation I would dwell on points 1 to 4 since implementing 5 is fairly similar as that of sending SES.

Hosting static website on S3. This is straight forward, the documentation from AWS is very clear on how you can host. 

https://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html

Only call out here is I had to adjust my contact page HTML to embed with the following java-script to handle the form data and send it to the API gateway. SendtoAPI is the function that actually triggers when send button is clicked on web page.

```Javascript

<script>
	function sendToAPI(e) {
	e.preventDefault();
	var URL = "<API Gateway URL here > ";

	var email = document.getElementById("email").value;
	var subject = document.getElementById("subject").value;
	var body = document.getElementById("body").value;
	if (email=="" || subject =="" ||body=="" )
	{
	alert("Please Fill All Required Field");
	return false;
	}
	
	var data = {
	email : email,
	subject : subject,
	body : body,
	
	};
	

	var xmlhttp = new XMLHttpRequest();
	xmlhttp.open("<API Gateway URL here >");
	xmlhttp.setRequestHeader("Content-Type", "application/json");
	xmlhttp.send(JSON.stringify(data));
	xmlhttp.onreadystatechange = function() {
	if (xmlhttp.readyState === 4) {
	var response = JSON.parse(xmlhttp.responseText);
	if (xmlhttp.status === 200 ) {
	console.log('successful');
	document.getElementById("contact-form").innerHTML = "<h1>Thank you for your message <br> I will get back to you soon!</h1>";
	} else {
	console.log('failed');
	}
	}
	}
	
	document.getElementById('contact-form').reset();
	
```

Contact page html :
```
<div class="col-md-7">
	<div class="form-group">
	<input name="email" type="email" class="form-control" id="email" placeholder="Email">
	</div>
	<div class="form-group">
	<input name="subject" type="text" class="form-control" id="subject" placeholder="Subject">
	</div>
	<div class="form-group">
	<textarea name="textmessage" class="form-control" rows="5" " id="body" placeholder="Enter your message"></textarea>
	</div>
	<button type="submit" onClick​="sendToAPI(event)" class="btn btn-default btn-lg">Send</button>
	</div>

```
2. Creating Lambda function:

This Lambda will run on nodejs runtime. Be sure to verify your email on SES, otherwise this will throw error for email verification.

```
var AWS = require('aws-sdk');
var ses = new AWS.SES();
 
var RECEIVER = 'email@address';
var SENDER = 'email@address';


var response = {
 "isBase64Encoded": false,
 "headers": { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'},
 "statusCode": 200,
 "body": "{\"result\": \"Success.\"}"
 };


exports.handler = function (event, context) {
    console.log('Received event:', event);
    sendEmail(event, function (err, data) {
        context.done(err, null);
    });
};
 
function sendEmail (event, done) {
    var params = {
        Destination: {
            ToAddresses: [
                RECEIVER
            ]
        },
        Message: {
            Body: {
                Text: {
                    Data: 'email ' + event.email + '\n subject ' + event.subject+ '\n body ' + event.body ,
                    Charset: 'UTF-8'
                }
            },
            Subject: {
                Data: 'Someone contacted you on your contact form ' + event.name,
                Charset: 'UTF-8'
            }
        },
        Source: SENDER
    };
    ses.sendEmail(params, done);

```

3. API Gateway:

API and Lambda go hand in hand. Integrating API gateway to trigger lambda is key for any serverless implementation. Be sure to enable CORS on API gateway otherwise the data cannot be reached to API gateway and Deploy your API.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/fb389euh7b9b2j4b5vwn.JPG)

Integrating everything:

If everything is setup in a right way, when we put some content in the contact page , the contents will be passed to API gateway which will trigger Lambda and which will in turn send email all the contents to the email verified.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/q62nq62yva9xssuxzd1m.JPG)

When we click send, it should return us another HTML page and send the same contents to our email.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/bjgwebbvyzm0a75icd4s.JPG)

Email:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/n50t78pe51vvbwxo39a9.JPG)

Similar flow can be redirected to have the contents posted to DynamoDB at the back if there is need to store the details. But we have everything now running full managed and serverless.

GitHub link:

https://github.com/durga533/serverless

References:


https://aws.amazon.com/blogs/architecture/create-dynamic-contact-forms-for-s3-static-websites-using-aws-lambda-amazon-api-gateway-and-amazon-ses/