laravel-websockets icon indicating copy to clipboard operation
laravel-websockets copied to clipboard

Duplicate websocket messages.

Open faizan-glowlogix opened this issue 4 years ago • 3 comments

My channel listen query is here. when i chat with more than one person. using websockets it shows duplicate messages on receiver side. these person are in different tab. One user is open in chrome ,second is in chrome incognito mode and third is in firefox. when i send message from second and third to first user duplication in message is shown. I am using laravel 7.x and vue 2.5.17

// join channel query

Echo.join('chat-' + this.user.id + '-' + this.authUser.id)
                    .listen('MessageSent',(event) => {
                        this.messages.push(event.message);
                    })

//send Message

sendMessage() {
                this.messages.push({
                    sender_id: this.authUser.id,
                    receiver_id: this.user.id,
                    message: this.newMessage
                });

                axios.post('/messages/send', {
                    sender_id: this.authUser.id,
                    receiver_id: this.user.id,
                    message: this.newMessage,
                });
            }

//Controller

message = Message::create([
      'sender_id' => $request->input('sender_id'),
      'receiver_id' => $request->input('receiver_id'),
      'message' => $request->input('message'),
      'status' => $status,
    ]);
    broadcast(new MessageSent($message))->toOthers();

faizan-glowlogix avatar Jul 23 '20 07:07 faizan-glowlogix

@faizan-glowlogix By default Laravel Echo will bind a request interceptor to set the X-Socket-ID header, which is used in the toOthers method to identify the sending socket. However if you create your own axios instance you have to pass the X-Socket-ID header to laravel yourself. Which might be your issue.

Please check to see if the X-Socket-ID header is sent with your POST message.

// New axios instance, not intercepted by laravel Echo
const instance = axios.create();

// We need to bind the interceptors ourselves to use laravel's ->toOthers() feature
instance.interceptors.request.use((config) => {
            const socketId = broadcasting.echo.socketId();

            if (socketId) {
                config.headers['X-Socket-Id'] = socketId;
            }

            return config;
        });

reneheijnemans avatar Sep 15 '20 08:09 reneheijnemans

Have anyone found a reason? I get duplicate messages issue in random order. SocketsId sends correctly.

slavarazum avatar May 27 '21 07:05 slavarazum

May be late, but as I found several issues for this withour answers, here is how I solved in my project, which does note use Axios.

The laravel-websockets demo uses Axios. Axios automatically send the header X-Socket-ID in your requests to the API. With it, the API knows whom not to send the event.

The request you must include the header is the one you are sending the payload that will be broadcast. For example, in the demo you would have to include the header in the sendMessage() methods request. To the POST request to /messages would have the header included along with the message.

Done this, the "duplicated" event stopped.

alexandre-da-costa avatar May 26 '22 17:05 alexandre-da-costa

Here is a solution to avoid redeclaring the headers on each API call.

In resources/js/bootstrap.js

import axios from 'axios';
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';

axios.defaults.headers.common['Access-Control-Allow-Origin'] = '*';
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
axios.defaults.withCredentials = true;

window.Pusher = Pusher;

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: import.meta.env.VITE_PUSHER_APP_KEY,
    wsHost: window.location.hostname,
    wsPort: 6001,
    wssPort: 6001,
    forceTLS: false,
    disableStats: true,
});

In another file, before/after listening to your events


//Here is the line to add once Echo is joined to a channel
axios.defaults.headers.common['X-Socket-ID'] = Echo.socketId();

cariboufute avatar Nov 17 '22 21:11 cariboufute