beyondcode / laravel-websockets

Websockets for Laravel. Done right.
https://beyondco.de/docs/laravel-websockets
MIT License
5.08k stars 630 forks source link

Can't Get it to work with React-Native #82

Closed jafar-albadarneh closed 5 years ago

jafar-albadarneh commented 5 years ago

I've setup a websocket server on my local machine and could get it to work with some events on a blade webpage. I am trying to connect to the server using React-Native and can't get that to work. I've used Pusher as a client to connect to my local server using ngrok.

Here is my code:

    let pusher = new Pusher("SomeRandomAppKey", {
        wsHost       : 'a731f023.ngrok.io',
        wsPort       : 6001,
        disableStats : true,
    });

    pusher.connection.bind('state_change', function(states) {
        console.log("Channels current state is " + states.current);
    });

The console log shows that the connection status is unavailable.

any one been through react-native integration with this package before. Thanks

stayallive commented 5 years ago

Two thing I notice about this snippet (might both be unrelated):

Looking at the Pusher docs:

State unavailable: The connection is temporarily unavailable. In most cases this means that there is no internet connection. It could also mean that Channels is down, or some intermediary is blocking the connection. In this state, Channels will automatically retry the connection every ten seconds. connecting_in events will still be triggered.

So also check your web inspector for any connection errors or other error messages that might give you an idea.

If your connection works in an blade webpage the same Pusher initialization code will also work in React, should be nothing special about that :)

jafar-albadarneh commented 5 years ago

@stayallive thanks a lot for sharing your thoughts, however i made sure that the origin a731f023.ngrok.io is http. For the auth endpoint, the inspector does not show any errors, except the one logged from the connection status listener.

I can't isolate the source of the problem. I just need something to pin point the source of the problem in order to fix it.

masterix21 commented 5 years ago

I'm using react-native, pusher and laravel-echo with success.

Have you imported Pusher from 'pusher-js/react-native'?

ghost commented 5 years ago

@masterix21 Could you show your configuration please? The Echo initialisation and joining/listening to a channel incluiding the pusher part? Or where did you find the solution? I'm having a hard time finding the way to do it with this stack "rn+echo+pusher" because i want to "listen" and interact with the server i did using laravel-websockets package

masterix21 commented 5 years ago
import React from 'react';
import PusherNative from 'pusher-js/react-native';
import Echo from 'laravel-echo';
import { PROTOCOL } from '../config/passport';

export default (host, token) => {
    let options = {
        encrypted: true,
        key: YOUR_KEY,
        wsHost: YOUR_HOST,
        wsPort: YOUR_PORT,
        disableStats: true,
        authEndpoint:  host +'/broadcasting/auth',
        logToConsole: true,
        auth: {
            headers: {
                'Authorization': 'Bearer ' + token,
            },
        }
    };

    let PusherClient = new PusherNative(options.key, options);
/*
    PusherClient.connection.bind( 'initialized', () => console.log('PusherClient::initialized', arguments));
    PusherClient.connection.bind( 'connecting', () => console.log('PusherClient::connecting', arguments));
    PusherClient.connection.bind( 'connected', () => console.log('PusherClient::connected', arguments));
    PusherClient.connection.bind( 'error', () => console.log('PusherClient::error', arguments));
    PusherClient.connection.bind( 'unavailable', () => console.log('PusherClient::unavailable', arguments));
    PusherClient.connection.bind( 'failed', () => console.log('PusherClient::failed', arguments));
    PusherClient.connection.bind( 'disconnected', () => console.log('PusherClient::disconnected', arguments));
*/
    return new Echo({
        broadcaster: 'pusher',
        client: PusherClient,
        ...options
    });
};
ghost commented 5 years ago

@masterix21 Thank you for the quick response! I'm still struggling to make it work, first of all, i'm still trying to make it work without authentication (i don't have a Bearer token) is that really required? I have the simple channel: Broadcast::channel('chat', function ($user) { return $user; });

And in the laravel project which is the server with the websockets running, using VueJS, i am successfully connecting by a simple Echo.join('chat')

What about csrf_token? Do i need any kind of auth?

In the RN part i used your code in a barebone project trying to get feedback in the console but nothing happens.

masterix21 commented 5 years ago

Your "simple" channel is an authorized channel: it means that you must have a bearer token.

From Laravel docs:

Private and presence broadcast channels authenticate the current user via your application's default authentication guard. If the user is not authenticated, channel authorization is automatically denied and the authorization callback is never executed.

ghost commented 5 years ago

@masterix21 Alright i got the auth part now, and it does "event":"pusher:connection_established"

but it doesn't do the event "pusher":"subscribe" so there's no communication although the connection was successful 😢

masterix21 commented 5 years ago

This is how i use the code of my past comment:

import echo from 'FILE_WITH_CODE_OF_PAST_COMMENT';

let client = new echo(YOUR_HOST, YOUR_ACCESS_TOKEN);

client.join('YOUR_CHANNEL').listen('YOUR_EVENT', () => console.log(arguments));
ghost commented 5 years ago

Yes i got that right, still no luck 😞 Thank you for your help! I will continue to search for a solution.

ElegantSoft commented 5 years ago

I have same problem I can't connect react native app to channel

ElegantSoft commented 5 years ago

Edit I have found solution now my code is

import React, { Component } from 'react'; import { Platform, StyleSheet, Text, View } from 'react-native'; import PusherNative from 'pusher-js/react-native'; import Echo from 'laravel-echo';

const instructions = Platform.select({ ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu', android: 'Double tap R on your keyboard to reload,\n' + 'Shake or press menu button for dev menu', });

type Props = {}; export default class App extends Component {

constructor(props) {

super(props);
let options = {
  encrypted: false,
  key: 'anyKey',
  wsHost: 'host',
  wsPort: '6001',
  disableStats: true,
  authEndpoint:  'host' +'/broadcasting/auth',
  logToConsole: true,

};

let PusherClient = new PusherNative(options.key, options);

let echo = new Echo({
  broadcaster: 'pusher',
  host: 'host:6001',  
  client: PusherClient,

}); echo.channel('DemoChannel').listen('WebSocketDemoEvent', (e) => { console.log(e) }); }

render() { return ( <View style = { styles.container } > <Text style = { styles.welcome } > Welcome to React Native! <Text style = { styles.instructions } > To get started, edit App.js <Text style = { styles.instructions } > { instructions }

  </View>
);

} }

const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, instructions: { textAlign: 'center', color: '#333333', marginBottom: 5, }, });

ghost commented 5 years ago

That's what i have, but i only get "event":"pusher:connection_established" on the websockets:serve command debug I think what is missing is event":"pusher:subscribe" where the websockets receive the token or something. But there's so little information about it i don't know what else to do.

ghost commented 5 years ago

If i do client.join('chat').whisper('typing', this.state.user) and it works! I don't know why the other methods like here, joining, leaving, listen, listenForWhisper don't work 😩

LPranulis commented 5 years ago

If i do client.join('chat').whisper('typing', this.state.user) and it works! I don't know why the other methods like here, joining, leaving, listen, listenForWhisper don't work 😩

It's because Presence and Private channels need an authentication. Just add this to your api.php or web.php in routes directory: Broadcast::routes(['middleware' => ['jwt.verify']]); if you are using JWT or just Broadcast::routes(['middleware' => ['auth:api']]);

It should work :)

chiragparekh commented 4 years ago

@masterix21 I am using the same setup as you mentioned above in react native and using pusher and laravel echo. I am keep getting "App key websocketkey not in this cluster. Did you forget to specify the cluster?" with code 4001.

chiragparekh commented 4 years ago

I managed to fix the issue by changing localhost IP address i.e 127.0.0.1 to my computer local IP address.

danfebraa commented 4 years ago

@chiragparekh

I managed to fix the issue by changing localhost IP address i.e 127.0.0.1 to my computer local IP address. Managed to solve mine using with these code block:

/**Note: I am using homestead and on my homestead file I add these lines
This will allow me to let me access my local machine within the network, 
and I can also access this via the emulator (Android)

- ssh into your homestead and do `ifconfig ` and get the `eth2` ip address, that would be your access.

*/

networks:
    - type: "public_network"
      bridge: "en1: Wi-Fi (AirPort)"
/**In your App.js*/
import Pusher from 'pusher-js/react-native';
import Echo from 'laravel-echo';

/**In your App.js, function App()*/
useEffect(() => {

        Pusher.logToConsole = true;

        let PusherClient = new Pusher('{YOUR_KEY}',{
            cluster: 'mt1',
            wsHost: '{YOUR_HOST}',
            wsPort: '6001',
            enabledTransports: ['ws'],
            forceTLS: false
        });

        let echo = new Echo({
            broadcaster: 'pusher',
            client: PusherClient
        });

        echo.channel('home').listen('NewMessage', (e) => {
            alert()
        });

    })
jyotipati commented 2 years ago

@jafar-albadarneh did you resolved your issue The console log shows that the connection status is unavailable. if issue is resolved could you please share with me because i am facing same issue