问题
I am using Laravel Event Broadcast and Pusher to utilize websockets both on my API and Web. If I try them individually, both work fine. What I mean is:
Broadcast::routes(['middleware' => 'web']); // this works for my Laravel website
Broadcast::routes(['middleware' => 'auth:api']); // this works for my api
However, if I want to use both at the same time like this:
Broadcast::routes(['middleware' => ['auth:api', 'web']]); // doesn't work
... it crashes for both, which I suspect that it is assuming I am trying to enable for both auth:api && web
middlewares.
Is there a way to use an OR kind of statement for this (auth::api || 'web')
? What if I want to use both at the same time and if it passes one middleware, it bypasses the middleware.
Please note that I am using Laravel Passport for my api.
Or is there a way to combine and creating a mixed middleware for both (which will essentially check for either api or web)? So I can use something like this maybe:
Broadcast::routes(['middleware' => 'broadcast']); // or auth:broadcast
Update:
As far as I understand, if I create a new Middleware called broadcast
, I can do:
class BroadcastMiddleware() {
public function handle() {
$web = Auth::guard('web')->user();
if ($web) {
return response()->json($web);
}
$api = Auth::guard('api')->user();
if ($api) {
return response()->json($api);
}
return response()->json('Unauthorized.', 500);
}
}
But then how do I change /broadcasting/auth
route? If I try this:
Route::post('/realtime/auth', function(){
return true;
})->middleware('broadcast');
This returns the user object info, however instead, it should return something like: auth:"374f7ff42b7da877aa35:c29addedec281b418331a61dc3cfc74da8b108222565fa4924a8..."
回答1:
Why not just use something like this in the BroadcastServiceProvider? This creates two separate endpoints with separate middleware assigned.
Broadcast::routes(['middleware' => 'web']);
Broadcast::routes(['prefix' => 'api', 'middleware' => 'api']);
回答2:
I finally figured out how to do it.
I am not sure if it is the best way of achieving this, and I'd highly appreciate any improvements.
How I achieved is created a new middleware for 'web' and left the other one as it it. Here are the steps.
1) In 'BroadcastServiceProvider', left only auth:api
guard for Broadcast::routes(['middleware' => 'auth:api']);
.
This way, Laravel's auth:api
method for authenticating broadcasting works as expected.
2) Created a middleware called "Broadcast" and mapped it in Kernel.php like so:
'broadcast' => \App\Http\Middleware\Broadcast::class
and the Broadcast.php
middleware looks like this:
public function handle($request, Closure $next)
{
$web = Auth::guard('web')->user();
if ($web) {
return response()->json(\Illuminate\Support\Facades\Broadcast::auth($request));
}
return response()->json('Unauthorized.', 500);
}
3) Created a unique route other than Laravel's /broadcasting/auth in my routes>web.php
Route::post('/guard/broadcast/auth', function(\Illuminate\Support\Facades\Request $req){
return true;
})->middleware('broadcast');
4) And then only on my blade, I use it like so:
<script>
let pusher = new Pusher("{{ env('PUSHER_APP_KEY') }}", {
cluster: 'us2',
encrypted: true,
auth: {
headers: {
'X-CSRF-TOKEN': "{{ csrf_token() }}"
}
},
authEndpoint: '{{ env('APP_URL') }}' + '/guard/broadcast/auth',
});
let channel = pusher.subscribe('private-channel.{{ Auth::user()->id }}');
channel.bind('my-event', addMessage);
function addMessage(data) {
console.log(data);
}
</script>
回答3:
I'm preferable just using middleware that extends to both auth:api
and web
middlewares.
like what I posted in here: https://github.com/tlaverdure/laravel-echo-server/issues/266#issuecomment-365599129. So, I just maintenance 1 middleware if I wanted to change it in the future
来源:https://stackoverflow.com/questions/48934892/laravel-broadcast-combining-multiple-middleware-web-authapi