Trying to get Pusher working on my app but cannot get it to send any messages to Pusher itself.
I have an event that is fired when creating a 'booking':
event(new BookingCreated($booking));
This event:
<?php
namespace App\Events\Booking;
use App\Booking;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class BookingCreated implements ShouldBroadcast
{
use SerializesModels, InteractsWithSockets;
public $booking;
/**
* Create a new event instance.
*
* #param Booking $booking
* #return void
*/
public function __construct(Booking $booking)
{
$this->booking = $booking;
}
public function broadcastOn()
{
return ['teams.'.$this->booking->team_id.'.bookings'];
}
}
My env file has the following (with details):
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
My broadcasting config file has the pusher details set up as:
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => 'eu'
],
],
When looking in the Pusher dashboard I can see open connections, but no messages. I am running queue:listen which is showing that the events are being processed.
Anything I am missing?
This was a mistake on my behalf, I had changed the env file BROADCAST_DRIVER but hadn't restarted the queue listener so my events were broadcasting to the log.
Related
I am trying to implement a queue to send email in laravel. My .env file
MAIL_DRIVER = smtp
MAIL_HOST = smtp.gmail.com
MAIL_PORT = 587
MAIL_FROM_ADDRESS = from#gmail.com
MAIL_USERNAME = from
MAIL_PASSWORD = ********
MAIL_ENCRYPTION = tls
QUEUE_CONNECTION=database
My config/queue.php
'connections' => [
'database' => [
'driver' => 'database',
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 90,
'after_commit' => false,
],
]
config/mail.php
'mailers' => [
'smtp' => [
'transport' => 'smtp',
'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
'port' => env('MAIL_PORT', 587),
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
'username' => env('MAIL_USERNAME'),
'password' => env('MAIL_PASSWORD'),
'timeout' => null,
'local_domain' => env('MAIL_EHLO_DOMAIN'),
],
]
My Job file
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
class SendSampleMail implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
Mail::send(['text' => 'mail'], ['name' => 'TestUser'], function ($message) {
$message->to('to#mailinator.com', 'testUserName')->subject('Test Laravel email');
$message->from('from#gmail.com', 'Test Mail');
});
}
}
In the controller, I am calling it like
$job = new SendSampleMail();
$this->dispatch($job);
The mail.blade.php
<p>Sending Mail from Laravel.</p>
When I run
php artisan queue:work
The jobs are queued but email fails to be sent.
I need to fix that issue. Any help would be appreciated. Thanks in advance.
As per the laravel document, create the jobs table in the database.
Run the below two command for the creating the table
php artisan queue:table
php artisan migrate
I need to authenticate temporary users of a third party app. In addition, users only get a signed URL to login (there is no username/password). The temporary users get created on the fly and logged in after verifying the signed URL and some query params. Because I also have "traditional" users in my app I am using an additional database table called "clients", an additional provder 'clients' and an additional guard called 'vcs' for the authentication workflow.
The authentication workflow (user clicks on the signed URL, a new Client is created and saved to the database as well as logged in as new user) is working fine. The session is created correctly and send to the browser in the laravel_session cookie. The problem is, that all subsequent requests to my API seem to be unauthenticated.
config/auth.php:
<?php
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'vcs' => [
'driver' => 'session',
'provider' => 'clients',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'clients' => [
'driver' => 'eloquent',
'model' => App\Models\Client::class,
],
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
],
'password_timeout' => 10800,
];
My client model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Laravel\Sanctum\HasApiTokens;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Client extends Authenticatable
{
use HasFactory, HasApiTokens;
protected $guard = "vcs";
/**
* The primary key associated with the table.
*
* #var string
*/
protected $primaryKey = 'uuid';
/**
* Indicates if the model's ID is auto-incrementing.
*
* #var bool
*/
public $incrementing = false;
protected $keyType = 'string';
/**
* Get the route key for the model.
*
* #return string
*/
public function getRouteKeyName()
{
return 'uuid';
}
}
The clients get a signed URL which points to the following controller action. The action checks for a valid query parameter in the URL (simplified for this thread). After that a new Client model gets created and the new Client gets logged in using the 'vcs' guard:
<?php
namespace App\Http\Controllers\VCS;
use Illuminate\Http\Request;
use App\Models\Client;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Auth;
class AuthController extends Controller
{
public function redirectWithCookie(Request $request)
{
// reduced for the sake of simplicity here
$credential = $request->someURLParameter;
if ($credential) {
$client = new Client;
$client->uuid = Str::uuid()->toString();
$client->ip = $request->ip();
$client->status = 'pending';
$client->save();
Auth::guard('vcs')->login($client, $remember = true);
// this logs the authenticated user correctly!
Log::info('Authenticated User: ' . Auth::guard('vcs')->user());
$cookieValue = json_encode(array('uuid' => $client->uuid));
$cookie = cookie('mycookie', $cookieValue);
$redirectUrl = config('my.redirect.url');
return redirect()->away($redirectUrl)->withCookie($cookie);
}
return response(['message' => 'Invalid URL', 'error' => 'url'], 422);
}
}
routes/web.php:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\VCS\AuthController;
Route::get('/', function () {
return ['Laravel' => app()->version()];
});
Route::get('vcs/auth', [AuthController::class, 'redirectWithCookie'])->name('vcs.auth');
require __DIR__.'/auth.php';
routes/api.php:
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\VCS\RoomController;
Route::middleware(['auth:sanctum'])->get('/user', function (Request $request) {
return $request->user();
})->name('profile');
Route::middleware(['auth:vcs'])->group(function () {
Route::get('rooms', [RoomController::class, 'rooms']);
});
After the redirect I get a laravel_session as a cookie which should authenticate my subsequent requests. The problem is that I can't call any API routes with the custom guard and I am not authenticated anymore although the browser is sending my session cookie with the request. For example calling the /api/rooms GET-endpoint defined in the api.php results in a redirect to the login page.
I also see that the user is not authenticated in the auth-middleware:
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* #param \Illuminate\Http\Request $request
* #return string|null
*/
protected function redirectTo($request)
{
Log::info('Authenticated User: ' . Auth::guard('vcs')->user());
}
}
The Log just returns an empty string so the user is not authenticated:
[2022-11-06 13:44:30] local.INFO: Authenticated User:
So my question is: How can I use a custom guard for my API routes after manually logging new users in?
I also tried the same workflow using Insomnia as a REST Client:
Login by URL:
whichs gives me a sessions cookie.
Access some API Route:
Which results in an Unauthorized-Status-Code..
I have a Vue.js separated project from a Laravel backend in many tutorials I see a Laravel + Vue.js but I have a Vue.js SPA separated and I don`t know what I doing wrong.
I already make the configuration on front end, this is it:
const pusher = new Pusher(configMain.PUSHER_APP_KEY, {
cluster: configMain.PUSHER_APP_CLUSTER
});
const pusherChannel = pusher.subscribe('teste');
pusherChannel.bind('my-event', function(data) {
console.log(data);
});
When I use the debug console in PUSHER and send an event, it works fine I receive it. But when I try to send an event from my backend Laravel project it doesn`t work.
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=********
PUSHER_APP_KEY=********
PUSHER_APP_SECRET=********
PUSHER_APP_CLUSTER=********
I already set the keys and change the driver, in config broadcasting i have this:
'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'),
'encrypted' => true,
],
],
I created an event in Laravel that is this:
<?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 MyEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
private $message;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($message)
{
//
$this->message = $message;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('teste');
}
public function broadcastAs()
{
return 'my-event';
}
}
And when i execute this in my backend:
event(new MyEvent('hello world'));
dd("ENTROU");
My front doesn't receive it, I must do something that I don't see it?
I need to run a very time consuming task asynchronous in Laravel 5.8. This is the .env file
...
QUEUE_CONNECTION=sync
QUEUE_DRIVER=redis
...
The queue driver must be Redis because the website uses Laravel-Echo with redis and socket.io to broadcast messages and I can't change queue driver to database.
This is the job I created
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class BroadcastRepeatJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
sleep(30);
}
}
and this is the HomeController:
public function index()
{
BroadcastRepeatJob::dispatch()->onQueue("default");
dd(1);
...
}
and I also run the following artisan commands
php artisan queue:work
php artisan queue:listen
when I visit /index of HomeController I expect to see dd(1) immediately not after 30 seconds because the sleep(30) must be ran in a queue but this does not happen and I have to wait 30 seconds to see dd(1). How can I run the job in background asynchronous ?
Thanks in advance.
Try switching your QUEUE_CONNECTION to redis rather than sync
/*
|--------------------------------------------------------------------------
| Queue Connections
|--------------------------------------------------------------------------
|
| Here you may configure the connection information for each server that
| is used by your application. A default configuration has been added
| for each back-end shipped with Laravel. You are free to add more.
|
| Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"
|
*/
'connections' => [
'sync' => [
'driver' => 'sync',
],
'database' => [
'driver' => 'database',
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 90,
],
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 90,
'block_for' => null,
],
],
I have tried sereval tuto to try to setup Laravel Redis NodeJs Socket.
And it'is not working.
So far :
- my broadcast fires as I can see it in Laravel log
- my redis server works (I have added a call to Redis in my homecontroller and I can see the value in the log and in redis-cli monitor - I have also installed Horizon and I can see its call in Redis-cli monitor)
But when my broadcast fires I don't see anything in redis-cli monitor
I have already tried the obvious things (cache/ config clear / reboot / ...)
Help will be very apreciated !
Redis call in my homecontroller : working
Redis::set("foo","bar");
$value = Redis::get("foo");
Log::debug('Redis value :'.$value);
.Env
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=siview
DB_USERNAME=root
DB_PASSWORD=
QUEUE_DRIVER=sync
QUEUE_CONNECTION=sync
CACHE_DRIVER=file
SESSION_DRIVER=file
SESSION_LIFETIME=120
BROADCAST_DRIVER=redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
Database.php
'redis' => [
'client' => 'predis',
'default' => [
'host' => env('REDIS_HOST', 'localhost'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 0,
'read_write_timeout' => 60,
],
'cache' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_CACHE_DB', 1),
],
'pubsub' => [
'host' => env('REDIS_HOST', 'localhost'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 2,
],
],
Boadcasting.php
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Broadcaster
|--------------------------------------------------------------------------
|
| This option controls the default broadcaster that will be used by the
| framework when an event needs to be broadcast. You may set this to
| any of the connections defined in the "connections" array below.
|
| Supported: "pusher", "redis", "log", "null"
|
*/
'default' => env('BROADCAST_DRIVER', 'redis'),
/*
|--------------------------------------------------------------------------
| Broadcast Connections
|--------------------------------------------------------------------------
|
| Here you may define all of the broadcast connections that will be used
| to broadcast events to other systems or over websockets. Samples of
| each available type of connection are provided inside this array.
|
*/
'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'),
'encrypted' => true,
],
],
'redis' => [
'driver' => 'redis',
'connection' => 'pubsub',
],
'log' => [
'driver' => 'log',
],
'null' => [
'driver' => 'null',
],
],
];
Event
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use App\User;
class SendMessageEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
private $user;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('App.User.' . $this->user->id);
}
public function broadcastWith()
{
return ['message' => 'Salut ' . $this->user->name];
}
}
Route Channel
<?php
/*
|--------------------------------------------------------------------------
| Broadcast Channels
|--------------------------------------------------------------------------
|
| Here you may register all of the event broadcasting channels that your
| application supports. The given channel authorization callbacks are
| used to check if an authenticated user can listen to the channel.
|
*/
Broadcast::channel('App.User.{id}', function ($user, $id) {
return true;//(int) $user->id === (int) $id;
});
Route web
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Auth::routes();
Route::get('/send/{user}', function(\App\User $user){
event(new \App\Events\SendMessageEvent($user));
});
Route::get('/home', 'HomeController#index')->name('home');
Laravel.log showing my broascast
[2018-11-04 09:39:42] local.INFO: Broadcasting [App\Events\SendMessageEvent] on channels [private-App.User.1] with payload:
{
"message": "Salut nathalie",
"socket": null
}
redis-cli monitor showing my homecontroller test
1541324518.159040 [0 127.0.0.1:59334] "SELECT" "0"
1541324518.159776 [0 127.0.0.1:59334] "SET" "foo" "bar"
1541324518.160360 [0 127.0.0.1:59334] "GET" "foo"
I have found and it's a bit strange :
I am working on windows with wamp.
The wamp server was started by not the Laravel server.
Strangly everything seemed to work well (no errors, pages rendered, auth was working...)
I just started laravel with : php artisan serve
and now I can see in Redis-cli monitor :
1541328214.873429 [0 127.0.0.1:52962] "SELECT" "2"
1541328214.874260 [2 127.0.0.1:52962] "PUBLISH" "private-App.User.1" "{\"event\":\"App\\\\Events\\\\SendMessageEvent\",\"data\":{\"message\":\"Salut nathalie\",\"socket\":null},\"socket\":null}"
1541328661.366923 [0 127.0.0.1:53078] "SELECT" "2"
1541328661.367643 [2 127.0.0.1:53078] "PUBLISH" "private-App.User.1" "{\"event\":\"App\\\\Events\\\\SendMessageEvent\",\"data\":{\"message\":\"Salut nathalie\",\"socket\":null},\"socket\":null}"
1541328679.554077 [0 127.0.0.1:53083] "SELECT" "2"
1541328679.555197 [2 127.0.0.1:53083] "PUBLISH" "private-App.User.1" "{\"event\":\"App\\\\Events\\\\SendMessageEvent\",\"data\":{\"message\":\"Salut nathalie\",\"socket\":null},\"socket\":null}"
Make sure you have latest version of redis serve.
Laravel uses commands like eval that supported in latest version on redis server.
I used Redis 3.2.100 and issue was solved.
I found that same problem and after a lot of useless research it was as simple to update de redis server.
Download here:
https://redis.io/download
Or here for windows:
https://redislabs.com/ebook/appendix-a/a-3-installing-on-windows/a-3-2-installing-redis-on-window/