Skip to content

Use Laravel Echo with API Gateway Websockets. Works with Bref.sh and Laravel Vapor.

License

Notifications You must be signed in to change notification settings

georgeboot/laravel-echo-api-gateway

Folders and files

NameName
Last commit message
Last commit date

Latest commit

944b0e0 · Jan 26, 2021

History

13 Commits
Jan 26, 2021
Jan 26, 2021
Jan 26, 2021
Jan 26, 2021
Jan 22, 2021
Jan 22, 2021
Jan 22, 2021
Jan 22, 2021
Jan 22, 2021
Jan 22, 2021
Jan 22, 2021
Jan 26, 2021
Jan 26, 2021
Jan 26, 2021
Jan 26, 2021
Jan 26, 2021
Jan 26, 2021
Jan 26, 2021
Jan 26, 2021
Jan 22, 2021

Repository files navigation

laravel-echo-api-gateway

This package enables you to use API Gateway‘s Websockets as a driver for Laravel Echo , so you don’t have to use services like Pusher or Socket.io.

It works by setting up a websocket API in API Gateway, and configure it to invoke a Lambda function, every time a message is sent to the websocket. This package includes and autoconfigures a handler to respond to these websocket messages. We also configure Laravel to use this connection as a broadcast driver.

This package currently only works if you deploy your app using Bref, but it could theoretically also be deployed alongside a Laravel Vapor project.

Requirements

In order to use this package, your project needs to meet the following criteria:

  • PHP 7.4 or 8.x
  • Laravel 6, 7 or 8
  • Uses bref to deploy to AWS
  • Has a working queue
  • Uses Laravel Mix or any other tool to bundle your assets

Installation

Installation of this package is fairly simply.

First we have to install both the composer and npm package:

composer require georgeboot/laravel-echo-api-gateway

yarn add georgeboot/laravel-echo-api-gateway
# or
npn install --save georgeboot/laravel-echo-api-gateway

Next, we have to add some elements to our serverless.yml file.

Add a new function that will handle websocket events (messages etc):

functions:
    # Add this function
    websocket:
        handler: handlers/websocket.php
        layers:
            - ${bref:layer.php-80}
        events:
            - websocket: $disconnect
            - websocket: $default

Add a resource to create and configure our DynamoDB table, where connections will be stored in:

resources:
    Resources:
        # Add this resource
        ConnectionsTable:
            Type: AWS::DynamoDB::Table
            Properties:
                TableName: connections
                AttributeDefinitions:
                    - AttributeName: connectionId
                      AttributeType: S
                    - AttributeName: channel
                      AttributeType: S
                KeySchema:
                    - AttributeName: connectionId
                      KeyType: HASH
                    - AttributeName: channel
                      KeyType: RANGE
                GlobalSecondaryIndexes:
                    - IndexName: lookup-by-channel
                      KeySchema:
                          - AttributeName: channel
                            KeyType: HASH
                      Projection:
                          ProjectionType: ALL
                    - IndexName: lookup-by-connection
                      KeySchema:
                          - AttributeName: connectionId
                            KeyType: HASH
                      Projection:
                          ProjectionType: ALL
                BillingMode: PAY_PER_REQUEST

Add the following iamRoleStatement to enable our Lambda function to access the table:

provider:
    name: aws

    iamRoleStatements:
        # Add this iamRoleStatement
        - Effect: Allow
          Action: [ dynamodb:GetItem, dynamodb:PutItem, dynamodb:UpdateItem, dynamodb:DeleteItem, dynamodb:Query ]
          Resource: !GetAtt ConnectionsTable.Arn

Add an environment variable to autogenerate our websocket URL:

provider:
    name: aws

    environment:
        # Add this line
        BROADCAST_API_GATEWAY_URL: !Join [ '', [ 'wss://', !Ref "WebsocketsApi", '.execute-api.', "${self:provider.region}", '.', !Ref "AWS::URLSuffix", '/', "${self:provider.stage}" ] ]

Next, create the PHP handler file in handlers/websocket.php

<?php

use Georgeboot\LaravelEchoApiGateway\Handler;
use Illuminate\Foundation\Application;

require __DIR__ . '/../vendor/autoload.php';

/** @var Application $app */
$app = require __DIR__ . '/../bootstrap/app.php';

$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
$kernel->bootstrap();

return $app->make(Handler::class);

Edit your .env:

BROADCAST_DRIVER=laravel-echo-api-gateway
MIX_BROADCAST_API_GATEWAY_URL="${BROADCAST_API_GATEWAY_URL}"

Add to your javascript file:

import Echo from 'laravel-echo';
import {broadcaster} from 'laravel-echo-api-gateway';

const echo = new Echo({
    broadcaster,
    host: process.env.MIX_BROADCAST_API_GATEWAY_URL,
});

Lastly, you have to generate your assets by running Laravel Mix. After this step, you should be up and running.