Startup Clix: Pusher Presence Channels with AWS SAM
Tags: pushercontest, javascript
Published: 2018-05-06 15:03:31

---
title: Startup Clix: Pusher Presence Channels with AWS SAM
published: true
description: 
tags: pushercontest, javascript
series: [pusher contest]
---

[After I lined out some basic ideas](https://dev.to/kayis/pusher-contest-idea-javascript-game-3-2m1l) about the game I want to make, I finally had time to start some implementation.

## What happened

Not much actually... and I'm already sitting 8h on this thing.

Well, Pusher is easy going, but AWS SAM & Lambda & API-Gateway aren't that simple.

## Project Setup

First I created a [repo on GitHub](https://github.com/kay-is/startup-clix) in which I'm gonna version my game.

I split it up in back-end, which is a AWS SAM application, and front-end which is, at the moment a pile of garbage.

You need a server to handle authentication for Pusher presence channels, and I need them to keep track of players and distribute events to all players in a game. 

### Back-End

Currently it consist of 3 Lambda functions. The JavaScript in the `back-ed/functions` directory gets wired up via the `template.yaml`. [AWS SAM Local](https://github.com/awslabs/aws-sam-local) is used for deployment.

- `hello` gets called by CloudWatch every minute and publishes a test message to the only channel

This is how a Lambda Function looks with a 1 minute rate schedule event:

```yaml
  HelloFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: ./functions/hello
      Events:
        ScheduleOneMinuteEvent:
          Type: Schedule
          Properties:
            Schedule: rate(1 minute)
```

- `pusherAuth` gets called by the Pusher client to allow a client to joint a presence channel


This is how a Lambda Function looks with an API-Gateway POST event:

```yaml
  PusherAuthFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: ./functions/pusherAuth
      Events:
        pusherAuthEvent:
          Type: Api
          Properties:
            Path: /pusherauth
            Method: post
```

This is how my simple authentication code looks like at the moment:

```javascript
// Loading and initializing Pusher server API
// only on a cold start
const Pusher = require("pusher");
const pusher = new Pusher({
  appId: process.env.APP_ID,
  key: process.env.APP_KEY,
  secret: process.env.SECRET_KEY
});

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

  // the Pusher client doesn't send JSON, so I just crack it open manually
  const body = event.body.split("&");
  const socket_id = body[0].split("=")[1];
  const channel_name = body[1].split("=")[1];

  // some data Pusher will distribute to the clients on channel subscription
  const presenceData = {
    user_id: socket_id,
    user_info: {
      name: "Player " + Math.random()
    }
  };

  // checking if this is all good and well, hurr
  const auth = pusher.authenticate(socket_id, channel_name, presenceData);

  // API-Gateway wants its response it that format
  const response = {
    statusCode: 200,
    body: JSON.stringify(auth)
  };

  callback(null, response);
};
```

- `getGameChannel` gives the client a channel to join, later this gets more logic to check which games are open, not full, waiting for players etc.

### Front-End

Not much happening here. Got a Bootstrap theme, loaded the Pusher client and connected. 

The whole thing is hosted on Github Pages.


## Problems

- CORS setup seems to be a huge pain with AWS SAM, so I'm using [CORS Everywhere](https://addons.mozilla.org/de/firefox/addon/cors-everywhere/) until I get this fixed.

- Packaging of Lambda functions is needed. Currently I have to copy the `node_modules` directory into every function directory before packaging. Would be cool if I could simply install it in the `back-end` directory and it gets copied automatically.

- Some helper functions are needed too. The whole Lambda experience is very basic at the moment.