Skip to content

Instantly share code, notes, and snippets.

  • Save asim-altayb/36f64ee72b3d0edf3a257184b9626ef7 to your computer and use it in GitHub Desktop.
Save asim-altayb/36f64ee72b3d0edf3a257184b9626ef7 to your computer and use it in GitHub Desktop.
Laravel-websockets on Laravel API backend + Laravel Echo on Vue.js front end on different server/domain using private channel.md

These are my notes on how I got all the basics working end to end.

Laravel API backend and Vue.js frontend are 2 different servers on different public IP addresses and different domains. I am using pure Vue.js on the front end. Most instructions assume Laravel Vue.js is being used which is structured slightly different with different file names and directories.

  • Laravel API backend domain name (api.somedomain.com)
  • Vue.js frontend domain name (client.somedomain.com)

No database is needed for any of this to work using sync queue. That is only needed in production if/when you use a database queue.


Laravel API backend server (api.somedomain.com)

composer require beyondcode/laravel-websockets
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"

Make sure App\Providers\BroadcastServiceProvider::class is uncommented

config/app.php

'providers' => [
  ...
  App\Providers\BroadcastServiceProvider::class,
],

.env

BROADCAST_DRIVER=pusher
QUEUE_CONNECTION=sync
PUSHER_APP_ID=testapp
PUSHER_APP_KEY=websocketkey
PUSHER_APP_SECRET=somethingsecret
PUSHER_APP_CLUSTER=mt1

config/broadcasting.php

'connections' => [

    'pusher' => [
        'driver' => 'pusher',
        'key' => env('PUSHER_APP_KEY'),
        'secret' => env('PUSHER_APP_SECRET'),
        'app_id' => env('PUSHER_APP_ID'),
        'options' => [
            'cluster' => env('PUSHER_APP_CLUSTER'),
            //'useTLS' => false,
            'encrypted' => true,
            'host' => '127.0.0.1',
            'port' => 6001,
            'scheme' => 'http',
        ],
    ],
    ...

config/websockets.php

'apps' => [
      [
          'id' => env('PUSHER_APP_ID'),
          'name' => env('APP_NAME'),
          'key' => env('PUSHER_APP_KEY'),
          'secret' => env('PUSHER_APP_SECRET'),
          'path' => env('PUSHER_APP_PATH'),
          'capacity' => null,
          'enable_client_messages' => true,
          'enable_statistics' => true,
      ],
  ],

routes/api.php

Route::get('test', function () {
    event(new App\Events\Test());
    return "Event has been sent!";
});

routes/channels.php

// This is only for testing purposes
Broadcast::channel('testchannel', function ($user) {
    return true;
}); 

// This is probably closer to what most would use in production
Broadcast::channel('user.{id}', function ($user, $id) {
    //return true if api user is authenticated
    return (int) $user->id === (int) $id;
});

app/Http/Middelware/VerifyCsrfToken.php

protected $except = [
    'broadcasting/auth',
];

app/Events/Test.php

<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class Test implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public function __construct()
    {
      //
    }

    public function broadcastOn()
    {
        return new PrivateChannel('testchannel');
    }
}

Run websockets server on Laravel api backend

php artisan websockets:serve


Vue.js frontend (client.somedomain.com)

npm install --save laravel-echo pusher-js

.env Note: The variable MUST be prefixed with VUE_APP_ https://cli.vuejs.org/guide/mode-and-env.html#modes

VUE_APP_PUSHER_APP_KEY='websocketkey'

Add Echo globally. In laravel vue that file is usually called bootstrap.js. In pure Vue.js it is called main.js

main.js

import Echo from 'laravel-echo'
window.Pusher = require('pusher-js')

// This assumes you have already saved your bearer token in your browsers local storage
const token = localStorage.getItem('user-token')

window.Echo = new Echo({
  broadcaster: 'pusher',
  key: process.env.VUE_APP_MIX_PUSHER_APP_KEY,
  wsHost: 'api.somedomain.com',
  authEndpoint: 'http://api.somedomain.com/broadcasting/auth',
  encrypted: true,
  forceTLS: false,
  wsPort: 6001,
  wssPort: 6001,
  disableStats: true,
  enabledTransports: ['ws', 'wss'],
  auth: {
    headers: {
      authorization: 'Bearer ' + token,
    }
  }
})

Add the Echo channel to whichever *.vue file we want to test this on

src/App.vue

...
created() {
  window.Echo.private('testchannel')
      .listen('Test', (e) => {
          console.log('test successful ' + e)
  })

All done. Now open your src/App.vue Single Page App in a chrome/firefox browser with the developer/inspect console window opened.

In a separate browser tab/window browse to http://api.somedomain.com/test to fire the test event. You should see "test successful" showing up in your SPA page developer console.

The end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment