Ease the pain of Serverless AWS -How to return HTML from AWS API
Tags: html, aws, awslambda, api
Published: 2017-08-14 22:04:20

---
title: Ease the pain of Serverless AWS -How to return HTML from AWS API
published: true
description: Do you need to return an HTML page from your API Gateway & Lambda function? Are you rendering HTML for web crawlers to read? This article is for you.
tags: HTML, AWS, AWS Lambda, API
---

Posted before on <a href="https://kennbrodhagen.net/2016/01/31/how-to-return-html-from-aws-api-gateway-lambda/"> here.</a>

<h1>Why return HTML from API Gateway?</h1>

I was recently working with a client who needed to create custom html meta tags for social media. He has an AngularJS single-page application and we needed a quick way to create nice-looking social media cards for Facebook, Twitter, and Google Plus. Since the app was based in Angular we didn't have a server-side infrastructure we could easily leverage. We decided to create an API Gateway and Lambda function to serve our needs. Out of the box API Gateway really wants to work with application/json content so it needs a little bit of tweaking to work with a Lambda function that outputs HTML.

<h1>Overview</h1>

In this tuorial you'll first create a Lambda placeholder function that returns HTML and bind it to an API in API Gateway. The placeholder function will return a hard-coded HTML string. Once you have the skeleton in place you can replace this function with a more sophisticated version. 

<h1>The Lambda Placeholder</h1>

Create a simple Lambda function that returns an HTML string.

<ol>
<li>Log into to the AWS Console and navigate to the Lambda service.</li>
<li>Create a new Lambda function and select the hello-world template.</li>
<li>Name the function lambda-html.</li>
<li>Input the code block below to return some basic html.</li>
<li>Choose to create a new *Basic Execution Role or if you have created a Lambda before you should see lambda_basic_execution in the bottom of the list.</li>
<li>Leave the default Advanced Settings.</li>
<li>Save your function and continue to run the test. It doesn't matter what input you give it.</li>
</ol>


```
// Lambda Placeholder
console.log('Loading Lambda HTML');

exports.handler = function(event, context) {
    var html = '<html><head><title>HTML from API Gateway/Lambda</title></head>' + 
        '<body><h1>HTML from API Gateway/Lambda</h1></body></html>';
    
    context.succeed(html);
};
```
<span>Lambda function returning HTML</span>
<img src="https://thepracticaldev.s3.amazonaws.com/i/htbpz9mshfmjevd2tprc.jpg" />


<span>Lambda function returning HTML</span>
<img src="https://thepracticaldev.s3.amazonaws.com/i/uphosxexe2ro0y1190ae.jpg" />

<h1>API Gateway</h1>

Now move on to the API Gateway service to create our api and bind it to the Lambda function.

<h1>Create the new API</h1>
<ol>
<li>Navigate to the API Gateway service and create a new API called <code> html-response-api</code>.</li>
<li>Create a GET method on the root resource and bind it to your Lambda <code>lambda-html.</code></li>
</ol>

<span>Creating GET method</span>
<img src="https://thepracticaldev.s3.amazonaws.com/i/of0pwfnaughjemfrm1ny.jpg" />


<h1>Method Response</h1>
<ol>
<li>Navigate to the Method Response for the API's GET method.</li>
<li>Open up the 200 under HTTP Status and add a Response Header named <code> Content-Type </code>. Be sure to save it with the green check mark. If you try pressing enter to save it will clear the field and not save.</li>
<li>Delete the application/json Response Model for 200.</li>

<span>Add the Content-Type header and clear the Response Models</span>
<img src="https://thepracticaldev.s3.amazonaws.com/i/igd5upchy7yb1d45rghe.jpg" />


<h1>Integration Response</h1>
<ol>
  <li>Navigate to the Integration Response for the API's GET method.</li>
  <li>Open up the 200 Response, Header Mappings, and Mapping Templates.</li>
  <li>Edit the Response Header Content-Type and set the Mapping value to <code>'text/html'</code> (be sure to use single quotes). Don't forget to save it with the green checkmark icon.</li>
  <li>Delete the application/json Content-Type under Mapping Templates.</li>
  <li>Add the Content-Type <code>'text/html'</code> (no quotes this time).</li>
  <li>Select ***Mapping Template*** in the right-hand drop-down box.</li>
  <li>Set the value of Template to <code>input.path('$')</code> and save with the green checkmark.</li>
</ol>    
<span>Change Content-Type to text/html and map the Lambda's response string as the entire output.</span>
<img src="https://thepracticaldev.s3.amazonaws.com/i/mjwijtinhjq4yehvnknx.jpg">


<h1> Deploy & test the API</h1>

<ol>
  <li>Click the blue Deploy API button.</li>
  <li>Name the stage prod or anything you like.</li>
  <li>Click the URL to open a new browser tab and see your results.</li>
</ol>

<span>Deploy the API to the prod stage.</span>
<img src="https://thepracticaldev.s3.amazonaws.com/i/9kkoy3oeqo3w05kusmfz.jpg" >

<span>Your HTML from the Lambda successfully rendered.</span>
<img src="https://thepracticaldev.s3.amazonaws.com/i/wuzyxgnqkntnvfrqlvlb.jpg" >


<h1>Take it further</h1>

Now you can customize the Lambda function to perform your own business logic. Here are some ideas:
<ul>
  <li>Fetch results from a database or <a href="http:/mockapi.io">mockapi</a>.</li> 
  <li>Render your HTML from a template.</li>
  <li>Add a URL or query parameter to the API request and pass it to your Lambda function. See my article on passing URL and query parameters to Lambda if you need help. (Video: <a href="https://youtu.be/2Z-Utw_xl4c">https://youtu.be/2Z-Utw_xl4c</a> 17min)</li>
</ul>


I hope you enjoy it. Keep slapping the keyboard until something good happens.