Question

How to set up websockets for Laravel on an Ubuntu Apache server

Posted December 24, 2021 254 views
UbuntuApachePHPReactLaravel

I’m trying to set up websockets on Laravel running on Ubuntu Apache2 server with Laravel Echo Server. Right now, it appears that everything is working properly, but whenever I navigate to https://api.mysite.com/socket.io/?EIO=4&transport=websocket I’m getting an Internal Server Error and whenever I check the error log I’m getting this: [Fri Dec 24 21:36:52.883549 2021] [proxy:warn] [pid 622621] [client 99.10.81.95:63149] AH01144: No protocol handler was valid for the URL /socket.io/ (scheme ‘ws’). If you are using a DSO version of mod_proxy, make sure the proxy submodules are included in the configuration using LoadModule.

Is there still something that I need to add to my vhosts?

Here’s my laravel-echo-server.json file:

{
    "authHost": "api.mysite.com",
    "authEndpoint": "/broadcasting/auth",
    "clients": [],
    "database": "redis",
    "databaseConfig": {
        "redis": {},
        "sqlite": {
            "databasePath": "/database/laravel-echo-server.sqlite"
        }
    },
    "devMode": true,
    "host": null,
    "port": "6001",
    "protocol": "http",
    "socketio": {},
    "secureOptions": 67108864,
    "sslCertPath": "",
    "sslKeyPath": "",
    "sslCertChainPath": "",
    "sslPassphrase": "",
    "subscribers": {
        "http": true,
        "redis": true
    },
    "apiOriginAllow": {
        "allowCors": false,
        "allowOrigin": "",
        "allowMethods": "",
        "allowHeaders": ""
    }
}

Here’s what I’m getting back whenever I run my laravel-echo-server:

L A R A V E L  E C H O  S E R V E R

version 1.6.2

⚠ Starting server in DEV mode...

✔  Running at localhost on port 6001
✔  Channels are ready.
✔  Listening for http events...
✔  Listening for redis events...

Server ready!

Channel: chat.9255
Event: App\Events\LeagueChatCreated
Channel: chat.9255
Event: App\Events\LeagueChatCreated
Channel: chat.9255
Event: App\Events\LeagueChatCreated

So obviously the events are being logged.

Here’s my 000-default.conf file in sites-available:

<VirtualHost *:80>
        ServerName api.mysite.com
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html/public

        <Directory /var/www/html/public/>
            Options Indexes FollowSymLinks MultiViews
            AllowOverride All
            Order allow,deny
            allow from all
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        <IfModule mod_dir.c>
            DirectoryIndex index.php index.pl index.cgi index.html index.xhtml index.htm
        </IfModule>
RewriteEngine on
RewriteCond %{SERVER_NAME} =api.mysite.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

And here’s my 000-default-le-ssl.conf file in sites-available:

<IfModule mod_ssl.c>
<VirtualHost *:443 *:6001>
        ServerName api.mysite.com
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html/public

        <Directory /var/www/html/public/>
            Options Indexes FollowSymLinks MultiViews
            AllowOverride All
            Order allow,deny
            allow from all
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        <IfModule mod_dir.c>
            DirectoryIndex index.php index.pl index.cgi index.html index.xhtml index.htm
        </IfModule>

SSLCertificateFile /etc/letsencrypt/live/api.mysite.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/api.mysite.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf

RewriteEngine On
RewriteCond %{REQUEST_URI}  ^/socket.io            [NC]
RewriteCond %{QUERY_STRING} transport=websocket    [NC]
RewriteRule /(.*)           ws://127.0.0.1:6001/$1 [P,L]

ProxyRequests off
ProxyPreserveHost On
SSLProxyEngine on

<Proxy *>
    Require all granted
</Proxy>

ProxyPass        /socket.io http://127.0.0.1:6001/socket.io/
ProxyPassReverse /socket.io http://127.0.0.1:6001/socket.io/
</VirtualHost>
</IfModule>

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

×
Submit an Answer
1 answer

Hi there,

Usually, you should have the following 3 modules enabled:

a2enmod proxy
a2enmod proxy_http
a2enmod proxy_wstunnel

In your case it sounds like you might not have enabled the proxy_wstunnel Apache module.

Let me know how this goes once you’ve enabled it.

Best,
Bobby

  • Bobby, thanks for the reply. Looks like I have all of those enabled, then I ran sudo service apache2 restart and I’m still getting the same issue.

    • Hi there Peter,

      I could suggest also trying to add the following rewrite condition to the ws rewrite rule:

      RewriteEngine On
      RewriteCond %{HTTP:Upgrade} websocket [NC]
      RewriteCond %{REQUEST_URI}  ^/socket.io            [NC]
      RewriteCond %{QUERY_STRING} transport=websocket    [NC]
      RewriteRule /(.*)           ws://127.0.0.1:6001/$1 [P,L]
      

      Let me know how it goes!
      Best,
      Bobby

      • Thanks so much! That looks like it was the issue, but looks like I’m having a new issue of not being able to listen to the events on React correctly.

        Here’s my echo set up on the front end:

        import Echo from "laravel-echo/dist/echo";
        import socketio from "socket.io-client";
        
        const echo = new Echo({
            host: "https://api.mysite.com/socket.io",
            broadcaster: "socket.io",
            client: socketio
        });
        
        export default echo;
        
        

        And here’s where I’m listening

        useEffect(() => {
                if (leagueId !== "team" && leagueId !== "0") {
                    chat.request();
                }
        
                //register socket events
                echo.channel("chat." + leagueId).listen("LeagueChatCreated", (ev) => {
                    console.log("new request");
                });
        
                return () => {
                    echo.channel("chat." + leagueId).stopListening("LeagueChatCreated");
                };
            }, [leagueId]);
        

        And whenever the event fires, I’m still not seeing the console.log

        L A R A V E L  E C H O  S E R V E R
        
        version 1.6.2
        
        ⚠ Starting server in DEV mode...
        
        ✔  Running at localhost on port 6001
        ✔  Channels are ready.
        ✔  Listening for http events...
        ✔  Listening for redis events...
        
        Server ready!
        
        Channel: chat.9332
        Event: LeagueChatCreated
        

        Would you have any ideas?

        • Hi there,

          Happy to hear that this is working now!

          Regarding the second problem, at a first glance it looks all correct, do you see any errors in the error log or in your web console?

          • There’s no errors in the web console or in the error log from what I can see. I’m getting a 200 response back from all the websocket calls. Here’s an example of the response I’m getting back if that helps:

            96:0{"sid":"sN6qEza31zzm900JAACa","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":5000}2:40