laravel / lumen-framework

The Laravel Lumen Framework.
https://lumen.laravel.com
MIT License
1.48k stars 419 forks source link

Auth routes for broadcasting #744

Closed chimit closed 5 years ago

chimit commented 6 years ago

Description:

I'm trying to use broadcasting in Lumen. Everything works fine except private channels. I can't setup auth routes.

Got an error:

[2018-03-16 11:06:12] lumen.ERROR: Symfony\Component\Debug\Exception\FatalThrowableError: Call to undefined method Laravel\Lumen\Application::routesAreCached() in /home/vagrant/Code/project/vendor/illuminate/broadcasting/BroadcastManager.php:61
Stack trace:
#0 /home/vagrant/Code/project/vendor/illuminate/support/Facades/Facade.php(221): Illuminate\Broadcasting\BroadcastManager->routes()
#1 /home/vagrant/Code/project/app/Providers/BroadcastServiceProvider.php(17): Illuminate\Support\Facades\Facade::__callStatic('routes', Array)
#2 [internal function]: App\Providers\BroadcastServiceProvider->boot()
#3 /home/vagrant/Code/project/vendor/illuminate/container/BoundMethod.php(29): call_user_func_array(Array, Array)
#4 /home/vagrant/Code/project/vendor/illuminate/container/BoundMethod.php(87): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
#5 /home/vagrant/Code/project/vendor/illuminate/container/BoundMethod.php(31): Illuminate\Container\BoundMethod::callBoundMethod(Object(Laravel\Lumen\Application), Array, Object(Closure))
#6 /home/vagrant/Code/project/vendor/illuminate/container/Container.php(549): Illuminate\Container\BoundMethod::call(Object(Laravel\Lumen\Application), Array, Array, NULL)
#7 /home/vagrant/Code/project/vendor/laravel/lumen-framework/src/Application.php(197): Illuminate\Container\Container->call(Array)
#8 /home/vagrant/Code/project/bootstrap/app.php(92): Laravel\Lumen\Application->register(Object(App\Providers\BroadcastServiceProvider))
#9 /home/vagrant/Code/project/public/index.php(14): require('/home/vagrant/C...')
#10 {main}  

Steps To Reproduce:

I copied a app\Providers\BroadcastServiceProvider.php file from Laravel and put it into the same place in Lumen and added:

$app->register(App\Providers\BroadcastServiceProvider::class);

into the bootstrap\app.php.

Apparently, it's because of different routes packages in Laravel and Lumen. So how to bypass this problem?

mattdalmau commented 6 years ago

Try to read that, it could help: https://laracasts.com/discuss/channels/lumen/setting-up-event-broadcasting-for-lumen-app-using-log-driver-initially

chimit commented 6 years ago

I've seen that. The author told he didn't have any success with it: https://github.com/laravel/lumen-framework/issues/602#issuecomment-373957256

mattdalmau commented 6 years ago

He says that:

I finally figured this out. It turns out that you shouldn't register BroadcastServiceProvider and configure broadcasting.php yourself in bootstrap/app.php. This is already done automatically in the Lumen source. Doing this yourself messes things up. Placing broadcasting.php in the config folder is all you need to do.

I find this quite confusing, as I've noticed that for other things (e.g. placing an auth.php in config or using MailServiceProvider) it is necessary to do the registering/configuring yourself in bootstrap/app.php. I wish the Lumen documentation would be a little more clear on this...

but I see that you did register BroadcastServiceProvider

chimit commented 6 years ago

Yes, I've already done this. This part works. Broadcasting in general works perfect. The problem is in auth routes for private channels. I don't know how to register them in Lumen.

dunhamjared commented 6 years ago

May be related to issue #746

Moutaz-homsi commented 6 years ago

@chimit , i have the same issue , did you found any solution for this ?

dunhamjared commented 6 years ago

A quick dirty hack is to overwrite the function it's trying to call in the service provider.

So in your class AppServiceProviderExample extends ServiceProvider class, add:

//@TODO Remove me when a fix is implemented
public function loadRoutesFrom($location){
    return $location;
}

It's trying to call the routesAreCached function from Illuminate\Foundation\Application but $this->app is in Laravel\Lumen\Application.

samlau15 commented 6 years ago

You can simply recreate the broadcasting/auth route by yourself.

Create a BroadcastController.php in Http\Controllers

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Broadcast;

class BroadcastController extends Controller {

    public function authenticate(Request $request)
    {
        return Broadcast::auth($request);
    }
}

Then, create a BroadcastServiceProvider.php in Providers and don't include Broadcast::routes() this time.

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class BroadcastServiceProvider extends ServiceProvider
{
    public function boot()
    {
        require base_path('routes/channels.php');
    }
}

Register your provider in bootstrap/app.php.

$app->register(App\Providers\BroadcastServiceProvider::class);

Create a channels.php in routes and define your authentication rules for your private channels as usual.

<?php

use Illuminate\Support\Facades\Broadcast;

Broadcast::channel('order.{orderId}', function ($user, $orderId) {
    return $user->id === Order::findOrNew($orderId)->user_id;
});

In routes/web.php, simply recreate the broadcasting/auth route.

$app->group(['middleware' => 'auth'], function () use ($app) {
    $app->post('broadcasting/auth', ['uses' => 'BroadcastController@authenticate']);
});

Also, don't forget to config your broadcast and queue drivers as mentioned in document.

driesvints commented 6 years ago

The routesAreCached issue should be resolved in 5.7

chimit commented 6 years ago

@driesvints the problem was not solved. In Lumen 5.7 auth routes don't work as well:

[2018-10-22 08:07:17] local.ERROR: Symfony\Component\Debug\Exception\FatalThrowableError: Call to undefined method Laravel\Lumen\Routing\Router::match() in /home/vagrant/code/project/vendor/illuminate/broadcasting/BroadcastManager.php:68
Stack trace:
#0 [internal function]: Illuminate\Broadcasting\BroadcastManager->Illuminate\Broadcasting\{closure}(Object(Laravel\Lumen\Routing\Router))
#1 /home/vagrant/code/project/vendor/laravel/lumen-framework/src/Routing/Router.php(62): call_user_func(Object(Closure), Object(Laravel\Lumen\Routing\Router))
#2 /home/vagrant/code/project/vendor/illuminate/broadcasting/BroadcastManager.php(72): Laravel\Lumen\Routing\Router->group(Array, Object(Closure))
#3 /home/vagrant/code/project/vendor/illuminate/support/Facades/Facade.php(223): Illuminate\Broadcasting\BroadcastManager->routes()
#4 /home/vagrant/code/project/app/Providers/BroadcastServiceProvider.php(17): Illuminate\Support\Facades\Facade::__callStatic('routes', Array)
#5 [internal function]: App\Providers\BroadcastServiceProvider->boot()
#6 /home/vagrant/code/project/vendor/illuminate/container/BoundMethod.php(29): call_user_func_array(Array, Array)
#7 /home/vagrant/code/project/vendor/illuminate/container/BoundMethod.php(87): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
#8 /home/vagrant/code/project/vendor/illuminate/container/BoundMethod.php(31): Illuminate\Container\BoundMethod::callBoundMethod(Object(Laravel\Lumen\Application), Array, Object(Closure))
#9 /home/vagrant/code/project/vendor/illuminate/container/Container.php(572): Illuminate\Container\BoundMethod::call(Object(Laravel\Lumen\Application), Array, Array, NULL)
#10 /home/vagrant/code/project/vendor/laravel/lumen-framework/src/Application.php(237): Illuminate\Container\Container->call(Array)
#11 /home/vagrant/code/project/vendor/laravel/lumen-framework/src/Application.php(222): Laravel\Lumen\Application->bootProvider(Object(App\Providers\BroadcastServiceProvider))
#12 [internal function]: Laravel\Lumen\Application->Laravel\Lumen\{closure}(Object(App\Providers\BroadcastServiceProvider), 'App\\Providers\\B...')
#13 /home/vagrant/code/project/vendor/laravel/lumen-framework/src/Application.php(223): array_walk(Array, Object(Closure))
#14 /home/vagrant/code/project/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(159): Laravel\Lumen\Application->boot()
#15 /home/vagrant/code/project/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(108): Laravel\Lumen\Application->dispatch(NULL)
#16 /home/vagrant/code/project/public/index.php(28): Laravel\Lumen\Application->run()
#17 {main} {"exception":"[object] (Symfony\\Component\\Debug\\Exception\\FatalThrowableError(code: 0): Call to undefined method Laravel\\Lumen\\Routing\\Router::match() at /home/vagrant/code/project/vendor/illuminate/broadcasting/BroadcastManager.php:68)
[stacktrace]
#0 [internal function]: Illuminate\\Broadcasting\\BroadcastManager->Illuminate\\Broadcasting\\{closure}(Object(Laravel\\Lumen\\Routing\\Router))
#1 /home/vagrant/code/project/vendor/laravel/lumen-framework/src/Routing/Router.php(62): call_user_func(Object(Closure), Object(Laravel\\Lumen\\Routing\\Router))
#2 /home/vagrant/code/project/vendor/illuminate/broadcasting/BroadcastManager.php(72): Laravel\\Lumen\\Routing\\Router->group(Array, Object(Closure))
#3 /home/vagrant/code/project/vendor/illuminate/support/Facades/Facade.php(223): Illuminate\\Broadcasting\\BroadcastManager->routes()
#4 /home/vagrant/code/project/app/Providers/BroadcastServiceProvider.php(17): Illuminate\\Support\\Facades\\Facade::__callStatic('routes', Array)
#5 [internal function]: App\\Providers\\BroadcastServiceProvider->boot()
#6 /home/vagrant/code/project/vendor/illuminate/container/BoundMethod.php(29): call_user_func_array(Array, Array)
#7 /home/vagrant/code/project/vendor/illuminate/container/BoundMethod.php(87): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()
#8 /home/vagrant/code/project/vendor/illuminate/container/BoundMethod.php(31): Illuminate\\Container\\BoundMethod::callBoundMethod(Object(Laravel\\Lumen\\Application), Array, Object(Closure))
#9 /home/vagrant/code/project/vendor/illuminate/container/Container.php(572): Illuminate\\Container\\BoundMethod::call(Object(Laravel\\Lumen\\Application), Array, Array, NULL)
#10 /home/vagrant/code/project/vendor/laravel/lumen-framework/src/Application.php(237): Illuminate\\Container\\Container->call(Array)
#11 /home/vagrant/code/project/vendor/laravel/lumen-framework/src/Application.php(222): Laravel\\Lumen\\Application->bootProvider(Object(App\\Providers\\BroadcastServiceProvider))
#12 [internal function]: Laravel\\Lumen\\Application->Laravel\\Lumen\\{closure}(Object(App\\Providers\\BroadcastServiceProvider), 'App\\\\Providers\\\\B...')
#13 /home/vagrant/code/project/vendor/laravel/lumen-framework/src/Application.php(223): array_walk(Array, Object(Closure))
#14 /home/vagrant/code/project/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(159): Laravel\\Lumen\\Application->boot()
#15 /home/vagrant/code/project/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(108): Laravel\\Lumen\\Application->dispatch(NULL)
#16 /home/vagrant/code/project/public/index.php(28): Laravel\\Lumen\\Application->run()
#17 {main}
"} 
jensdenies commented 5 years ago

@driesvints Can we reopen this issue? I can reproduce this.

driesvints commented 5 years ago

Done

jensdenies commented 5 years ago

@driesvints @chimit Instead of copying the app\Providers\BroadcastServiceProvider.php file from Laravel, you should register the routes yourself in Lumen. The Broadcast::routes(); method calls certain methods which are incompatible with Lumen. However, this method is more of a helper than a necessity, since you can just manually register the routes.

Therefore, we can assume that this feature works as expected and is not necessarily a bug, but it just requires a little more configuration.

driesvints commented 5 years ago

Okay, gonna close this then again.

knifesk commented 5 years ago

I've been working with lumen for a year and more. I hadn't had to enable the facades until now. Why? Because the Broadcasting module is not designed to function without them. Broadcast::routes() leads to

image

So I stopped relying on the routes method and registered the routes manually in my routes.php file(very nasty hack)

$router->get('/broadcasting/auth', '\\'.BroadcastController::class.'@authenticate');
$router->post('/broadcasting/auth', '\\'.BroadcastController::class.'@authenticate');

But then if I disable the facades, at the moment of the authentication I get an error about image

and if I enable them everything works as expected. I tracked the error down to the Illuminate\Broadcasting\BroadcastController class

class BroadcastController extends Controller
{
    /**
     * Authenticate the request for channel access.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function authenticate(Request $request)
    {
        if ($request->hasSession()) {
            $request->session()->reflash();
        }

        return Broadcast::auth($request);
    }
}

which is relying on the Broadcast facade and then is when it fails to handle the call. If I edit the controller to

namespace Illuminate\Broadcasting;

use Illuminate\Contracts\Broadcasting\Broadcaster;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Broadcast;

class BroadcastController extends Controller
{
    /**
     * Authenticate the request for channel access.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  Illuminate\Contracts\Broadcasting\Broadcaster $broadcaster
     * @return \Illuminate\Http\Response
     */
    public function authenticate(Request $request, Broadcaster $broadcaster)
    {
        if ($request->hasSession()) {
            $request->session()->reflash();
        }

        return $broadcaster->auth($request);
    }
}

and my channels.php to

$broadcast = app(Illuminate\Contracts\Broadcasting\Broadcaster::class);

$broadcast->channel('channel', .....)

then I'm back on business... I don't think this is a bug, but a oversight about the controller and channels depending directly on the Facades. I guess for Laravel is no problem, but for lumen there's some of us out there that don't like the Facades and we try to not enable them.

Oh, and btw I'm using lumen 5.7, but I checked on the 5.8 branch if the controller changed and is still the same, so I think the error is still there.

For now I'm going to implement my own Controller to avoid using the one that depends on the Facades, but I think this is easily fixable.

Cheers! Martin

driesvints commented 5 years ago

@knifesk it's best that you just upgrade to the Laravel framework if you want to use broadcasting.

knifesk commented 5 years ago

@driesvints thanks for the reply! I'm using broadcasting with redis and a separate app that uses laravel-echo-server to handle the Socket.io connections. The front-end is an entire separated Vue project that is being develop by another team. This is a REST API and it doesn't rely on sessions. Also we're using Auth0 for the authentication with JWTs.

Why do you recommend using Laravel? Lumen is doing just fine for me, the only issue is that I have the Facades disabled and I bumped into this issue. Lumen could support Broadcasting and Notifications just fine if the module weren't designed with facades enabled in mind. Or is there any other reason that I'm not aware of?

driesvints commented 5 years ago

We don't support using the broadcast module with Lumen.

knifesk commented 5 years ago

Ohh I see... That explains why I had such a hard time making it work and the documentation of Lumen said nothing about it haahah. Well, I'm happy with what I achieved. I guess that in the future I could migrate to Laravel if the need arises. For now I'll stick to Lumen because deadlines are pretty close haha.

Thank you!

On Tue, Jul 9, 2019 at 11:24 AM Dries Vints notifications@github.com wrote:

We don't support using the broadcast module with Lumen.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/laravel/lumen-framework/issues/744?email_source=notifications&email_token=AACRO3DBA7BIHYJODGBC733P6SNSHA5CNFSM4EV3CJ32YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODZQNW3A#issuecomment-509664108, or mute the thread https://github.com/notifications/unsubscribe-auth/AACRO3D6HVNY7OKEZQK4DV3P6SNSHANCNFSM4EV3CJ3Q .

fahmiegerton commented 4 years ago

is it supported now?

maxcotech commented 4 years ago

I wish I knew lumen doesn't support broadcasting before using it, right now am really stuck.

driesvints commented 4 years ago

If you need broadcasting please use Laravel.