0

I get this error, when sending a message from the Laravel Websockets dashboard. Laravel version is 8.9.0

this is how my composer.json file looks:

`{
    "name": "laravel/laravel",
    "type": "project",
    "description": "The Laravel Framework.",
    "keywords": [
        "framework",
        "laravel"
    ],
    "license": "MIT",
    "require": {
        "php": "^7.4",
        "ext-curl": "*",
        "ext-dom": "*",
        "ext-fileinfo": "*",
        "ext-json": "*",
        "ext-libxml": "*",
        "ext-pdo": "*",
        "ext-posix": "^7.3",
        "ext-zip": "*",
        "adoy/oauth2": "1.3.0",
        "beyondcode/laravel-websockets": "^1.13",
        "curl/curl": "2.2.0",
        "doctrine/dbal": "2.3.5",
        "facade/ignition": "^2.3.6",
        "fideloper/proxy": "^4.0",
        "guzzlehttp/guzzle": "^7.0",
        "intervention/image": "^2.4",
        "intervention/imagecache": "^2.3",
        "laravel/framework": "v8.9.0",
        "laravel/horizon": "v5.0",
        "laravel/passport": "^10.1",
        "laravel/tinker": "^2.0",
        "laravel/ui": "^3.0",
        "league/flysystem": "^1.0",
        "maatwebsite/excel": "^3.1",
        "php-ai/php-ml": "^0.9.0",
        "phpmailer/phpmailer": "^6.4",
        "predis/predis": "v1.1.6",
        "pusher/pusher-php-server": "^7.2",
        "spatie/laravel-permission": "^4.2",
        "tightenco/ziggy": "^1.4"
    },
    "require-dev": {
        "filp/whoops": "^2.0",
        "laravel/sail": "^1.5",
        "mockery/mockery": "^1.0",
        "nunomaduro/collision": "^4.1",
        "omniphx/forrest": "2.*",
        "phpunit/phpunit": "^9.0"
    },
    "config": {
        "optimize-autoloader": true,
        "preferred-install": "dist",
        "sort-packages": true,
        "platform": {
            "ext-pcntl": "7.4",
            "ext-posix": "7.4"
        }
    },
    "extra": {
        "laravel": {
            "dont-discover": []
        }
    },
    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Database\\Factories\\": "database/factories/",
            "Database\\Seeders\\": "database/seeders/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "scripts": {
        "post-autoload-dump": [
            "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
            "@php artisan package:discover --ansi"
        ],
        "post-root-package-install": [
            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
        ],
        "post-create-project-cmd": [
            "@php artisan key:generate --ansi"
        ],
        "post-update-cmd": [
            "@php artisan horizon:publish --ansi"
        ]
    }
}


Hallo

    

Broadcast_Driver in .env is pusher. My broadcasting.php has this pusher settings:

'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,
        'host' => '127.0.0.1',
        'port' => 6001,
        'scheme' => 'https',
       'curl_options' => [
            CURLOPT_SSL_VERIFYHOST => 0,
            CURLOPT_SSL_VERIFYPEER => 0,
        ]
    ],
],

My websockets.php

<?php

use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize;

return [

    /*
     * Set a custom dashboard configuration
     */
    'dashboard' => [
        'port' => env('LARAVEL_WEBSOCKETS_PORT', 6001),
    ],

    /*
     * This package comes with multi tenancy out of the box. Here you can
     * configure the different apps that can use the webSockets server.
     *
     * Optionally you specify capacity so you can limit the maximum
     * concurrent connections for a specific app.
     *
     * Optionally you can disable client events so clients cannot send
     * messages to each other via the webSockets.
     */
    
    'apps' => [
        [
            'id' => env('PUSHER_APP_ID'),
            'name' => env('APP_NAME'),
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            'enable_client_messages' => false,
            'enable_statistics' => false,
            'encrypted' => true,
        ],
    ],
    'ssl' => [
        'local_cert' => '/etc/letsencrypt/live/contento-demo2.net/fullchain.pem',
        'local_pk' => '/etc/letsencrypt/live/contento-demo2.net/privkey.pem',
        'passphrase' => null,
        'verify_peer' => false,
    ],

    /*
     * This class is responsible for finding the apps. The default provider
     * will use the apps defined in this config file.
     *
     * You can create a custom provider by implementing the
     * `AppProvider` interface.
     */
    'app_provider' => BeyondCode\LaravelWebSockets\Apps\ConfigAppProvider::class,

    /*
     * This array contains the hosts of which you want to allow incoming requests.
     * Leave this empty if you want to accept requests from all hosts.
     */
    'allowed_origins' => [
        //
    ],

    /*
     * The maximum request size in kilobytes that is allowed for an incoming WebSocket request.
     */
    'max_request_size_in_kb' => 250,

    /*
     * This path will be used to register the necessary routes for the package.
     */
    'path' => 'laravel-websockets',

    /*
     * Dashboard Routes Middleware
     *
     * These middleware will be assigned to every dashboard route, giving you
     * the chance to add your own middleware to this list or change any of
     * the existing middleware. Or, you can simply stick with this list.
     */
    'middleware' => [
        'web',
        Authorize::class,
    ],

    'statistics' => [
        /*
         * This model will be used to store the statistics of the WebSocketsServer.
         * The only requirement is that the model should extend
         * `WebSocketsStatisticsEntry` provided by this package.
         */
        'model' => \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry::class,

        /**
         * The Statistics Logger will, by default, handle the incoming statistics, store them
         * and then release them into the database on each interval defined below.
         */
        'logger' => BeyondCode\LaravelWebSockets\Statistics\Logger\HttpStatisticsLogger::class,

        /*
         * Here you can specify the interval in seconds at which statistics should be logged.
         */
        'interval_in_seconds' => 60,

        /*
         * When the clean-command is executed, all recorded statistics older than
         * the number of days specified here will be deleted.
         */
        'delete_statistics_older_than_days' => 60,

        /*
         * Use an DNS resolver to make the requests to the statistics logger
         * default is to resolve everything to 127.0.0.1.
         */
        'perform_dns_lookup' => false,
    ],

    /*
     * Define the optional SSL context for your WebSocket connections.
     * You can see all available options at: http://php.net/manual/en/context.ssl.php
     */

/*    'ssl' => [
        'local_cert' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT', null),
        'local_pk' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_PK', null),
        'passphrase' => env('LARAVEL_WEBSOCKETS_SSL_PASSPHRASE', null),
        'verify_peer' => false,
    ],*/

    /*
     * Channel Manager
     * This class handles how channel persistence is handled.
     * By default, persistence is stored in an array by the running webserver.
     * The only requirement is that the class should implement
     * `ChannelManager` interface provided by this package.
     */
    'channel_manager' => \BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers\ArrayChannelManager::class,
];


The error occurs, right after pusher->trigger is called, while the socket variable in payload is null:

    
/**
 * Broadcast the given event.
 *
 * @param  array  $channels
 * @param  string  $event
 * @param  array  $payload
 * @return void
 *
 * @throws \Illuminate\Broadcasting\BroadcastException
 */
public function broadcast(array $channels, $event, array $payload = [])
{
    $socket = Arr::pull($payload, 'socket');

    $response = $this->pusher->trigger(
        $this->formatChannels($channels), $event, $payload, $socket, true
    );

    if ((is_array($response) && $response['status'] >= 200 && $response['status'] <= 299)
        || $response === true) {
        return;
    }

    throw new BroadcastException(
        ! empty($response['body'])
            ? sprintf('Pusher error: %s.', $response['status'])
            : 'Failed to connect to Pusher.'
    );
}


I already know, there was a bug in Laravel version 7.x, so any hints in this direction are not helpful.

Any help is warmly welcomed, I've already spent 2 days with the problem and I need a solution.

1 Answers1

0

Fixed the error by downgrading pusher php server to version 5.0.1:

composer require pusher/pusher-php-server ^5.0.1

and following these instructions from github:

I had same problem, after my workaround, I solved it by restoring the pusher to the original, and creating a new workaround:

there is three problems for me when calling from laravel 8 when calling trigger function of Pusher.php

Here is the line 112: in ...Illuminate/Broadcasting..../PusherBroadcaster.php

$response = $this->pusher->trigger(
$this->formatChannels($channels), $event, $payload, $socket, true
);

the problems are

  1. $socket is set null instead of array,

  2. laravel sets $already_encoded variable true, but sending data as array not json I don't understand why, the parameter is set as array but anyway send true to the function.

  3. the function return just body instead of complete response

I'm avoiding to change the laravel PusherBroadcaster, so I changed the Pusher.php in order to correct that problems:

My workaround is like this:

1- Line 496 of Pusher.php changed from:

$data_encoded = $this->crypto->encrypt_payload($channels[0], $already_encoded ? $data : json_encode($data));

To:

$data_encoded = $this->crypto->encrypt_payload($channels[0], $already_encoded && !is_array( $data) ? $data : json_encode($data));

Line 499 of Pusher.php changed from:

$data_encoded = $already_encoded ? $data : json_encode($data);

To:

$data_encoded = $already_encoded && !is_array( $data) ? $data : json_encode($data);

2-Line 518 of Pusher.php changed from:

$all_params = array_merge($post_params, $params);

To:

$all_params = array_merge($post_params, is_array($params) ? $params:[]);

3- Line 542 of Pusher.php changed from:

return $result;

To:

return $response;

using that it works for me, and Im getting messages on the browser.

Many thanks to lisandrop05!

https://github.com/pusher/pusher-http-php/issues/288#issuecomment-787487210