Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel WebSocket with Pusher Error when making POST Request

I'm trying to integrate web socket into my laravel project. I did all steps from here


composer require pusher/pusher-php-server
/Users/alpha/Sites/jdoe/config/broadcasting.php


https://dashboard.pusher.com/apps/888



app_id = "888"
key = "***"
secret = "333"
cluster = "us2"



|
V


BROADCAST_DRIVER=pusher
PUSHER_APP_ID=888
PUSHER_APP_KEY=***
PUSHER_APP_SECRET=333
PUSHER_APP_CLUSTER=us2


.env.example + .env 

npm install --save laravel-echo pusher-js


npm run watch 


---------------------------------------------------


php artisan make:event logEvent


<?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;

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

    private $data;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct($data)
    {
        $this->data = $data;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new Channel('logEventChannel');
    }

    public function broadcastWith()
    {
        return [
            'data' => $this->data
        ];
    }
}

---------------------------------------------------



/Users/alpha/Sites/jdoe/resources/js/app.js



require('./bootstrap');


Echo.channel('logEventChannel').listen('logEvent', (e) => {

    // console.log(typeof JSON.parse(JSON.stringify(e))) //object
    // console.log(typeof JSON.parse(JSON.stringify(e.data))) //string
    // console.log(JSON.parse(e.data)); //decode or parse it

    let data = JSON.parse(e.data);

    /*=============================
    =            Debug            =
    =============================*/

    console.log('data ===== ',data);

    

});




---------------------------------------------------

route



Route::post('ws/log', 'BroadcastController@logEvent');




---------------------------------------------------
Controller



<?php

namespace App\Http\Controllers;

use App\Events\LogEvent;
use Illuminate\Http\Request;

class BroadcastController extends Controller
{

    public function vnfevent(Request $request)
    {

        $body            = json_decode($request->getContent(),true);
        dd($body); 💥
        $json = json_encode($body);

        broadcast(new LogEvent($json));

        return response()->json($body,200);

    }

}


---------------------------------------------------
CSRF


/Users/alpha/Sites/jdoe/app/Http/Middleware/VerifyCsrfToken.php


protected $except = [
'/ws/log'
];



---------------------------------------------------
TEST

POSTman

ws/log


{
    "type": "poop"
}



place a dd in broadbast 


arrived !! 

array:1 [
  "type" => "poop"
]




ErrorException: array_merge(): Expected parameter 2 to be an array, null given in file

---------------------------------------------------
Debug the crashing line 

/Users/alpha/Sites/jdoe/vendor/pusher/pusher-php-server/src/Pusher.php


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




array:3 [â–¼
  "name" => "App\Events\logEvent"
  "data" => array:1 [â–¼
    "data" => "{"type":"poop"}"
  ]
  "channels" => array:1 [â–¼
    0 => "logEventChannel"
  ]
]


Look correct 


I tested making a post to my /ws/log

{
    "type": "poop"
}

I kept getting

ErrorException: array_merge(): Expected parameter 2 to be an array, null given in file /Users/alpha/Sites/jdoe/vendor/pusher/pusher-php-server/src/Pusher.php on line 518

I opened that file

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

$params some how = null

enter image description here

How do I continue to debug this further?


Edit

I removed my vendor/ and tried version 4.1 as suggested.

"require": {
    "php": "^7.2.5",
    "doctrine/dbal": "^2.10",
    "fideloper/proxy": "^4.2",
    "fruitcake/laravel-cors": "^1.0",
    "guzzlehttp/guzzle": "^6.3",
    "intervention/image": "^2.3",
    "laravel/framework": "^7.0",
    "laravel/tinker": "^2.0",
    "laravelcollective/html": "~6.0",
    "pusher/pusher-php-server":"^4.1"
},

I still face issue when making a POST to my route via POSTman.

enter image description here

like image 678
code-8 Avatar asked Mar 16 '21 19:03

code-8


1 Answers

So for this problem, in fact that was an issue in Laravel and it is solved now using (laravel 8.29.0) or higher versions.
So pusher-http-php library v5.0.1 and Laravel v8.29.0 will work fine for you.

Another Solution: is to downgrade pusher to version 4.1 on composer.json and this version seems to work fine with older laravel versions (older than 8.29.0).

If you want to solve the problem with your current installation:

The problem is that the calls for trigger function, at least on laravel 8 is not sending the right parameters, so in PusherBroadcaster.php and pusher-php-server/Pusher.php there are 2 calls for trigger function which are:

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

and

public function trigger($channels, $event, $data, $params = array(), $already_encoded = false)

You will need to change the Pusher only.

1- Change (Line 496).

$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));

2- Change (Line 499).

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

To:

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

3- Change (Line 518)

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

To:

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

4- Change (Line 542)

return $result;

To:

return $response;

and this will make it works for you fine.

Note: As I said it is resolved in v8.29.0 of Laravel. Link
Note: Or you can use composer require pusher/pusher-php-server ^4.1

Note that:
The main problem is that $param is null in this case and it didn't check if this value is array() so when the code tries to merge array() with null.

Resources:

Link_1 Link_2 Link_3

like image 68
Mohamed Bdr Avatar answered Oct 25 '22 22:10

Mohamed Bdr