How to store and use HTML templates in serverless application on AWS Lambda (using AWS SAM)?
Asked Answered
P

1

11

Instead of

  • (A) following a more traditional route for running a web application on AWS (e.g., using Ruby/Sinatra or Python/Flask on AWS EC2 or Beanstalk), or

  • (C) creating static HTML and JavaScript files in S3 and dynamic API endpoints in AWS Lambda (sending JSON data to those static web pages that use/interpret that data via JavaScript),

I want to reach a middle ground:

  • (B) create HTTP endpoints in AWS Lambda (e.g., in Python) that read and use HTML templates for generating complete HTML responses to the client.

That setup will result in a serverless web application where the AWS Lambda functions deliver server-side (the irony is not lost on me) generated HTML output.

In Python code for AWS Lambda functions, it is possible to include HTML code snippets, modify that (populate with data) in the function, and return the HTML as text/html output to the client. The drawback of that approach is that the HTML template is then 'embedded' in the Python code, and not external in a separate file.

Q1: How can I refer to a HTML template file somewhere in the code package - the template should be part of the package - have that read by the Python function, and generate the HMTL page by variable substitution in the template?

Q2: How can I specify / include / link to a set of HTML template files in my project using AWS Serverless Application Model (AWS SAM)?

Phebe answered 22/10, 2018 at 8:30 Comment(3)
Here is something that might be useful in serving static files (your templates) using serverless AWS lambda. :github.com/activescott/serverless-aws-static-file-handler I had always wanted to try this out, but didn't get a chance. Nonetheless, it is an interesting endeavour!Buenrostro
On adding the "python" tag: accepted, but it's not core to the question. Python is just an example language for programming the AWS Lambda functions, and could have been Node.js/JavaScript, Java, Go or C# as well.Phebe
In Node.js, I normally use Handlebars to achieve the same result: handlebarsjs.comMonocyte
M
9

I'm not sure where you are starting from here, so I'll start from the beginning.

  1. Create the YAML Config file referencing the handlers and the Event Resources and put in a deployment folder.

  2. For Templating, use "Mustashe for Python" pystashe.

  3. Create the parameterised HTML Template within your Python project/Virtualenv:

    <html>
    <head>
        <title>Customer: {{name}}</title>
    </head>
    <body>
        <div>
            <h2>Customer Name: {{name}}</h2> 
            <h4>Phone Number: {{phone}}</h4>
        </div>
    </body>
    </html>
    
  4. Create the data object to populate the parameterised template:

    {
      "name": "Tom Thumb",
      "phone": "0123456789"
    }
    
  5. Load the template from the location in the project

    template = file('%s/mypath/template.html'%py_root).read()
    
  6. Render the page from the data object:

    myhtml = pystache.render(template, data)
    
  7. Return the rendered html to the client:

    response = {
        "statusCode": 200,
        "body": myhtml,
        "headers": {
            'Content-Type': 'text/html',
        }
    }
    
  8. Zip the python code, site-packages, and html files and put in the deployment folder.

  9. From the deployment folder, package the SAM Project, which prepares and uploads to S3:

    aws cloudformation package --template-file myservice.yml --output-template-file deploy-myservice.yml --s3-bucket myserverless-deploy
    
  10. From the deployment folder, deploy the SAM Project to AWS:

    aws cloudformation deploy --template-file deploy-myservice.yml --stack-name mycontext-myservice-dev --capabilities CAPABILITY_IAM
    

For the record, I prefer option C, with NodeJS... :)

Monocyte answered 25/10, 2018 at 13:25 Comment(8)
That could work, thanks. Following this... how can I arrange that mypath/template.html is part of the package stored in/with the Lambda function handlers? Or is that done automatically when ZIPping the package? Then, does AWS Lambda accept that other non-Python files are part of the deployment, and can those be referenced from the function handler code?Phebe
"For the record, I prefer option C, with NodeJS." I've done option (C) a couple of times, writing static HTML files with JavaScript consuming Node.js-powered or AWS Lambda-provided API endpoints. A Node.js applications requires a web server (which is more costly than practically zero for AWS Lambda functions). Creating AWS Lambda API endpoints is fine, but then application logic is in two locations: JavaScript client-side, and AWS Lambda server-side. Approach (B) aims to bring all logic to just 'server-side': AWS Lambda functions, with the additional advantage of a low-cost solution.Phebe
The Lambda service unzips the zip file into the Lambda Container, so whatever structure you have in the zip file will be the same as the folder structure in the container. That includes anything, like images, binaries, libraries, etc.Monocyte
I guess that's the solution then I had in mind for option (B). Thanks! /me accepting your answerPhebe
@JochemSchulenklopper Great post - Would this work with Jinja2 templates for python?Monthly
(The post was by @MattD. The original question was mine.) I don't see why it would not work with another template system. You only need to change steps 2, 3, and 6.Phebe
How we can iterate over the data in the template on step 3, does it accept any for-loop?Abiogenesis
I'd start by understanding "Mustashe for Python" a little more, have a look at pystashe docs: github.com/defunkt/pystacheMonocyte

© 2022 - 2024 — McMap. All rights reserved.