How to use the Serverless Event Gateway: build a REST API and react to custom events

Aug 7, 2018

Last week, we announced the Serverless Platform Beta, a single toolkit that provides everything teams need to operationalize serverless development. The Serverless Platform is made of three components—the Serverless Framework for deploying applications, the Serverless Dashboard for visualizing your application, and the Event Gateway for routing events to compute.

I'm going to focus on the Event Gateway for this post. We'll learn about two use cases of the Event Gateway:

  • Building REST APIs
  • Reacting to custom events

Let's get started!

Event Gateway: when you should use it

We built the Event Gateway to be the centralized event hub for the serverless ecosystem. Rather than scattered point-to-point integrations across your infrastructure, all events will flow into a single Event Gateway.

You can then configure the Event Gateway to react to these events as you want, in multiple different ways. For example, if a new user signs up and a user.created event is emitted into the Event Gateway, your marketing team may have a subscribed function that sends them a welcome email, while your development team may have a function that inserts the new user into Elasticsearch to power search functionality in your application.

Getting set up with the Serverless Platform

The Event Gateway is an open-source project that you can run yourself on your own infrastructure. We also provide a hosted version of the Event Gateway with the Serverless Platform Beta for quickly getting started with the Event Gateway.

Note: This section assumes you have already installed the Serverless Framework and have configured your terminal with AWS credentials. If this is not true for you, check out our longer guide to getting started with the Serverless Platform.

You will need to sign up for a Serverless Platform account. If you already have the Serverless Framework installed, you can create a Serverless Platform account by entering the following command into your terminal:

serverless login

This will open a browser window to create a Serverless Platform account. Once your account is created, the proper credentials will be returned to your terminal for easy command-line deploys.

Once you've signed up for an account, create a new application in the Dashboard. You can do this by clicking the red + App button. When you create a new application, you will get an application URL in the form of <tenant>-<app> This is the URL to which you will emit your Event Gateway events.

Make sure you have your tenant name, app name, and application URL available as you will need them in the following sections.

Creating and deploying your first service

We will be using the code in the Event Gateway Getting Started repo. You can clone this service into your terminal with the following command:

serverless create --template-url --path event-gateway-getting-started

Then change into your service directory and install the dependencies:

cd event-gateway-getting-started
npm i

Open the serverless.yml file and edit the tenant and app values to be your Tenant and App name from the Serverless Platform:

# serverless.yml

tenant: <your-tenant-here>
app: <your-app-here>

Then, deploy your application:

serverless deploy

With your application deployed, it's time to interact with your service.

Using Event Gateway for a REST API

One of the more popular use cases for the Event Gateway is to create a REST API. REST APIs have grown in popularity recently with the advent of single-page apps and microservices.

Functions-as-a-service (FaaS) providers like AWS Lambda, Google Cloud Functions, and Azure Function have made it easier than ever to deploy compute to production. With the Event Gateway, you can connect an HTTP path and method to a serverless function for your REST API.

To see how this is done, look at your serverless.yml. There is a functions block that describes the functions your service will deploy to AWS Lambda. Look at the top two functions in particular, as shown below:

    handler: handler.getUser
      - eventgateway:
          type: sync
          eventType: http.request
          path: /users/:id
          method: GET
    handler: handler.createUser
      - eventgateway:
          type: sync
          eventType: http.request
          path: /users
          method: POST

For both getUser and createUser, the function's handler is defined. Then, the events to which we want these functions described are listed. You can think of it like "If this, then that"—"If an HTTP POST request arrives on the /users path, then call the createUser function in the Event Gateway."

You can test that your REST API works by issuing an HTTP request with curl in your terminal. The curl request should go to your application URL that you configured in your terminal, in the format of https://<tenant>-<app>

Run the following command to issue a POST request to /users to create a new user:

$ APP="https://<tenant>-<app>"
$ curl -X POST -H "Content-Type: application/json" ${APP}/users \
    --data '{
    	"id": "10",
    	"firstName": "Donald",
    	"lastName": "Duck",
    	"email": ""

# {"id":10,"firstName":"Donald","lastName":"Duck","email":""}

You should get a response returning the user that was created.

Your AWS Lambda function will receive an event object in CloudEvents format. CloudEvents is a CNCF hosted project for describing event data in a common way. In our request above, the event received by our Lambda function will look similar to the following:

{ "eventType": "http.request",
  "cloudEventsVersion": "0.1",
  "source": "",
  "eventID": "f2f6b58d-b20a-4d23-bc41-4c3388057752",
  "eventTime": "2018-08-04T17:50:05.573211588Z",
   { "eventgateway": { "transformation-version": "0.1", "transformed": "true" } },
  "contentType": "application/json",
   { "headers":
      { "Accept": "*/*",
        "Content-Length": "128",
        "Content-Type": "application/json",
        "User-Agent": "curl/7.54.0",
        "X-Amzn-Trace-Id": "Root=1-5b65e74d-5248534899080846fc9ac954",
        "X-Forwarded-For": "",
        "X-Forwarded-Port": "443",
        "X-Forwarded-Proto": "https" },
     "query": {},
      { "email": "",
        "firstName": "Donald",
        "id": "10",
        "lastName": "Duck" },
     "host": "",
     "path": "/users",
     "method": "POST",
     "params": {} 

In the data object, you can see all the parameters of our HTTP request, including the headers, body, and path. You can use this information in the business logic of your Lambda function.

You can then retrieve that user by issuing a GET request to the /users/10 path:

$ APP="<appURL>"
$ curl -X GET ${APP}/users/10

# {"id":"10","email":"","firstName":"Donald","lastName":"Duck"}

As you can see, the Event Gateway can easily be used to handle REST API workloads with pay-per-use, infinitely scalable serverless functions.

Using the Event Gateway with custom events

The REST API use case is a pattern with which most developers are familiar, and it's a great way to get started with the Event Gateway. However, my favorite part of the Event Gateway is using custom events to asynchronously react to events that are happening across my application architecture.

First, let's see an example in action. Then we'll talk about why it's so important.

In the previous section, we created a new user by making a POST request to our /users endpoint. If you look at the createUser function in the handler.js, you'll see the following snippet of code after the user is saved to the database:

    eventID: '1',
    eventType: 'user.created',
    cloudEventsVersion: '0.1',
    source: '/services/users',
    contentType: 'application/json',
    data: params.Item
  .then(() => console.log('Emitted user.created event'))

In this snippet, the function is using the emit() function in the Event Gateway SDK to emit a user.created event into our Event Gateway. This event contains the details of the user that was created.

Now take a look at the functions block of your serverless.yml again. The third function listed looks as follows:

    handler: handler.emailUser
      - eventgateway:
          type: async
          eventType: user.created

The emailUser function is subscribed to the user.created event type and reacts in an async manner. In this simple example, this could be your on-boarding team sending a "Welcome!" email to your application's new user.

This is a powerful pattern. One portion of your application emits events indicating that something happened—a new user was created, an IoT light went on, or a video was viewed—and other parts of your application can receive those events and react as needed, by sending an email, storing to an analytics database, or alerting an on-call engineer.

Event Gateway use cases

We're seeing more and more of this reactive, event-driven pattern using asynchronous communication. Microservices have allowed for teams to independently develop and scale their application components, while tools like Kafka help with asynchronous communication between microservices. For those of you that are front-end engineers, you might see Event Gateway custom events as similar to Redux actions and reducers but used in your application backend.

While the user.created event only has one subscription in this example, you can add any number of additional subscriptions. Do you want to insert this newly-created user into Elasticsearch to power discoverability in your application? Does your sales team want to get notified if the new user works for an enterprise company? You can add additional subscriptions without affecting existing subscriptions and without updating code for the original producer.

The Event Gateway is designed to democratize the accessibility of these events by connecting them to serverless functions. Just like FaaS democratized compute, the Event Gateway democratizes events.

How you can contribute

The Event Gateway is in active development, and we're looking to make it easier to import events from your existing infrastructure, such as Kafka, Kinesis, RabbitMQ, and more. If you're interested, check out the Event Gateway repository and get involved!

Subscribe to our newsletter to get the latest product updates, tips, and best practices!

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.