Lesson 15—Netlify functions

In this section, we will learn:

Background

Netlify’s AWS Lambda functions bring the backend to your frontend workflow | Netlify

Netlify Lambda Functions Tutorial

Netlify gives us have a generous free tier limit, with up to 125.000 function invocations and a total of 100 hours of run time every month. Functions have 128MB of memory and each can execute for up to 10 seconds. For normal needs, this is more than enough.

Internally, Netlify runs this function on AWS Lambda, abstracting away all the complexity of AWS for you.

exports.handler = (event, context, callback) => {
  //functionality
}

Creating our first hello world lambda functions

A simple example

exports.handler = function(event, context, callback) {
    callback(null, {
      statusCode: 200,
      body: "Hello, World. This is from server-side."
    });
}

We can access the function via /.netlify/functions/FUNCTION_FILE_NAME. Our file is hello.js file.

fetch('/.netlify/functions/hello')
.then(response => response.text())
.then(data => console.log(data));

Using events

We can get the form data from the events.

{
  "path": "Path parameter",
  "httpMethod": "Incoming request's method name"
  "headers": {Incoming request headers}
  "queryStringParameters": {query string parameters }
  "body": "A JSON string of the request payload."
  "isBase64Encoded": "A boolean flag to indicate if the applicable request payload is Base64-encode"
}

We can inspect the events by creating a function that prints the output.

exports.handler = (event, context, callback) => {
  // accesscode
  console.log("---Event---");
  console.log(event);

  console.log("---Context---");
  console.log(context);

  console.log("---Form Data---");
  console.log(event.body)

  callback(null, {
    statusCode: 200,
    body: "Response from login"
  });
}

Here is a sample event and context.

4:58:03 PM: 2020-06-26T08:58:03.113Z ab2451c6-3ac5-4cc5-a8af-efe7141e1f42 INFO ---Event---
4:58:03 PM: 2020-06-26T08:58:03.116Z ab2451c6-3ac5-4cc5-a8af-efe7141e1f42 INFO {
path: '/.netlify/functions/login',
httpMethod: 'POST',
headers: {
accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'accept-encoding': 'br, gzip',
'accept-language': 'en-US,en;q=0.5',
'cache-control': 'no-cache',
'client-ip': '205.215.28.95',
connection: 'keep-alive',
'content-length': '15',
'content-type': 'application/x-www-form-urlencoded',
origin: 'https://11ty-demo.netlify.app',
pragma: 'no-cache',
referer: 'https://11ty-demo.netlify.app/login/',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:77.0) Gecko/20100101 Firefox/77.0',
via: 'https/2 Netlify[eec88f0c-fdc7-4e25-80c4-4ee885567b1a] (ApacheTrafficServer/7.1.11)',
'x-bb-ab': '0.977694',
'x-bb-client-request-uuid': 'eec88f0c-fdc7-4e25-80c4-4ee885567b1a-1073900',
'x-bb-ip': '205.215.28.95',
'x-bb-loop': '1',
'x-cdn-domain': 'www.bitballoon.com',
'x-country': 'MO',
'x-datadog-parent-id': '3100576936310270153',
'x-datadog-sampling-priority': '0',
'x-datadog-trace-id': '8619131124679011560',
'x-forwarded-for': '205.215.28.95',
'x-forwarded-proto': 'https',
'x-language': 'en,en;q=0.5',
'x-nf-client-connection-ip': '205.215.28.95'
},
multiValueHeaders: {
Accept: [
'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
],
'Accept-Encoding': [ 'br, gzip' ],
'Accept-Language': [ 'en-US,en;q=0.5' ],
'Cache-Control': [ 'no-cache' ],
'Client-Ip': [ '205.215.28.95' ],
Connection: [ 'keep-alive' ],
'Content-Length': [ '15' ],
'Content-Type': [ 'application/x-www-form-urlencoded' ],
Origin: [ 'https://11ty-demo.netlify.app' ],
Pragma: [ 'no-cache' ],
Referer: [ 'https://11ty-demo.netlify.app/login/' ],
'Upgrade-Insecure-Requests': [ '1' ],
'User-Agent': [
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:77.0) Gecko/20100101 Firefox/77.0'
],
Via: [
'https/2 Netlify[eec88f0c-fdc7-4e25-80c4-4ee885567b1a] (ApacheTrafficServer/7.1.11)'
],
'X-Bb-Ab': [ '0.977694' ],
'X-Bb-Client-Request-Uuid': [ 'eec88f0c-fdc7-4e25-80c4-4ee885567b1a-1073900' ],
'X-Bb-Ip': [ '205.215.28.95' ],
'X-Bb-Loop': [ '1' ],
'X-Cdn-Domain': [ 'www.bitballoon.com' ],
'X-Country': [ 'MO' ],
'X-Datadog-Parent-Id': [ '3100576936310270153' ],
'X-Datadog-Sampling-Priority': [ '0' ],
'X-Datadog-Trace-Id': [ '8619131124679011560' ],
'X-Forwarded-For': [ '205.215.28.95' ],
'X-Forwarded-Proto': [ 'https' ],
'X-Language': [ 'en,en;q=0.5' ],
'X-Nf-Client-Connection-Ip': [ '205.215.28.95' ]
},
queryStringParameters: {},
multiValueQueryStringParameters: {},
body: 'accesscode=demo',
isBase64Encoded: false
}
4:58:03 PM: 2020-06-26T08:58:03.116Z ab2451c6-3ac5-4cc5-a8af-efe7141e1f42 INFO ---Context---
4:58:03 PM: 2020-06-26T08:58:03.116Z ab2451c6-3ac5-4cc5-a8af-efe7141e1f42 INFO {
callbackWaitsForEmptyEventLoop: [Getter/Setter],
succeed: [Function],
fail: [Function],
done: [Function],
functionVersion: '$LATEST',
functionName: '10f17193d13d181aecadf7700782cb9186b8b7b9c6fb271c00ae85bbc1d7c648',
memoryLimitInMB: '1024',
logGroupName: '/aws/lambda/10f17193d13d181aecadf7700782cb9186b8b7b9c6fb271c00ae85bbc1d7c648',
logStreamName: '2020/06/26/[$LATEST]5f371446a61f4d66a24eacaa2e81c7e4',
clientContext: {
custom: {
netlify: 'eyJzaXRlX3VybCI6Imh0dHBzOi8vMTF0eS1kZW1vLm5ldGxpZnkuYXBwIn0='
}
},
identity: undefined,
invokedFunctionArn: 'arn:aws:lambda:us-east-1:922855128030:function:10f17193d13d181aecadf7700782cb9186b8b7b9c6fb271c00ae85bbc1d7c648',
awsRequestId: 'ab2451c6-3ac5-4cc5-a8af-efe7141e1f42',
getRemainingTimeInMillis: [Function: getRemainingTimeInMillis]
}
4:58:03 PM: 2020-06-26T08:58:03.116Z ab2451c6-3ac5-4cc5-a8af-efe7141e1f42 INFO ---Form Data---
4:58:03 PM: 2020-06-26T08:58:03.116Z ab2451c6-3ac5-4cc5-a8af-efe7141e1f42 INFO accesscode=demo
---
layout: layout
---

Please login to access gated content.

<form id="login" action="/.netlify/functions/login" method="POST">
  <input type="text" name="accesscode" id="accesscode">
  <input type="submit">
</form>

Making the gated content work

exports.handler = (event, context, callback) => {

  result = "/"

  if (event.body == "accesscode=demo") {
    result = "/super-long-url-here-to-hide-the-gated-content/"
  }

  callback(null, {
    statusCode: 200,
    body: result
  });
}
---
layout: layout
---

Please login to access gated content.

<form id="login" action="/.netlify/functions/login" method="POST">
  <input type="text" name="accesscode" id="accesscode">
  <input type="submit">
</form>

<script>
let accessCode = document.getElementById("accesscode").value;
document.getElementById("login").addEventListener("submit", function(event) {
  fetch('/.netlify/functions/login', {method: "POST", body:"accesscode="+accessCode})
  .then(response => response.text())
  .then(data => location.href=data);
  event.preventDefault();
});

</script>

A glimpse of what we can do with Netlify functions

Netlify Function Examples


Comments