I can't find a solution for more than a week. Everything works fine on the dev server, but not on production. I have no strength, I appeal to you, colleagues :)
I'm using Laravel-echo-server on Socket.io using CloudFlare. When trying to connect, I get an error:
WebSocketError: Unexpected status code received (502 Bad Gateway)
Ubuntu 16.04.7 LTS, Laravel Echo Server: 1.6.1, NodeJs: v12.19.0
laravel-echo-server.json:
{
"authHost": "http://localhost",
"authEndpoint": "/broadcasting/auth",
"clients": [
{
"appId": "...",
"key": "..."
}
],
"database": "redis",
"databaseConfig": {
"redis": {
"password": "...",
"port": "...",
"db": 0
},
"sqlite": {}
},
"devMode": true,
"host": "",
"port": "6001",
"protocol": "http",
"socketio": {
"transports": ["websocket", "polling"]
},
"secureOptions": 67108864,
"sslCertPath": "",
"sslKeyPath": "",
"sslCertChainPath": "",
"sslPassphrase": "",
"subscribers": {
"http": true,
"redis": true
},
"apiOriginAllow": {
"allowCors": true,
"allowOrigin": "*",
"allowMethods": "GET, POST",
"allowHeaders": "Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id"
}
}
Nginx host:
server {
listen 8443 ssl;
server_name domain.tld;
ssl_certificate /etc/nginx/ssl/my.crt;
ssl_certificate_key /etc/nginx/ssl/my.key;
error_log /var/log/nginx/domain.tld/ws.log info;
location /ws {
proxy_pass http://127.0.0.1:6001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
After start EchoServer i see:
L A R A V E L E C H O S E R V E R
version 1.6.1
⚠ Starting server in DEV mode...
✔ Running at localhost on port 6001
✔ Channels are ready.
✔ Listening for http events...
✔ Listening for redis events...
Server ready!
Ok, next:
$ curl 127.0.0.1:6001
> OK
Next:
websocat wss://domain.tld:8443/ws
And I get the error:
websocat: WebSocketError: Received unexpected status code (502 Bad Gateway)
Laravel echo server is running, I can see its events. Tried changing the host in laravel-echo-server.json (127.0.0.1, localhost, null, 0.0.0.0), in nginx proxy to localhost, 127.0.0.1 - nothing helps. I tried to add upstreams in nginx host, it doesn't help.
This information also did not help: https://github.com/tlaverdure/laravel-echo-server/issues/273
Please, help :)
I don't know what the problem is, but I found a solution.
I've updated a lot: updated Nginx to 1.19.1, possibly installed some additional modules. Installed npm not globally, but locally.
And it worked ...
Attention: this only works if you write location /socket.io.
That was not the point for sure: "authHost": "http://localhost"
I assume this is your issue.
{
"authHost": "http://localhost" // This should be your domain name
}
Related
I use laravel echo server and socket.io-client and running at localhost is work at port 6001 and I config at server and use port 8443. Events and laravel echo server work but when client side connect, got 200 success and Remote Address: ip:443 instead of ip:8443.
laravel 7.0
laravel-echo-server 1.6.3
socket.io-client 2.3.0
NginxConfig
location /abc/projectpath{
proxy_pass https://blah.com/abc/projectpath:8443;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
root /var/www/html/abc/projectpath/public;
index index.php;
try_files $uri $uri/ /abc/projectpath/server.php$is_args$args;
#limit_conn conn_limit_per_ip 5;
}
Laravel Echo Server
{
"authHost": "https://blah.com/abc/projectpath",
"authEndpoint": "/broadcasting/auth",
"clients": [],
"database": "redis",
"databaseConfig": {
"redis": {},
"sqlite": {
"databasePath": "/database/laravel-echo-server.sqlite"
}
},
"devMode": true,
"host": null,
"port": "8443",
"protocol": "https",
"socketio": {},
"secureOptions": 67108864,
"sslCertPath": "sslpath",
"sslKeyPath": "sslkeypath",
"sslCertChainPath": "",
"sslPassphrase": "",
"subscribers": {
"http": true,
"redis": true
},
"apiOriginAllow": {
"allowCors": false,
"allowOrigin": "",
"allowMethods": "",
"allowHeaders": ""
}
client side
window.io = require('socket.io-client')
window.Echo = new Echo({
broadcaster: 'socket.io',
path: '/abc/projectpath:8443/socket.io',
host: 'https://blah.com'
})
To start with, I have a real-time chat app (Vue as frontend, Laravel as backend)
On localhost it works perfectly, but not on production.
I've noticed that I do receive events, but I've never been able to join any channel.
Here is all the information, I hope you have any ideas on how to solve it. Thanks!
Main.js (laravel-echo / socket.io connection):
import Echo from "laravel-echo"
window.io = require('socket.io-client')
window.Echo = new Echo({
broadcaster: 'socket.io',
host: 'https://example.com/socket.io',
auth: {
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
}
}
});
Chat component (listener):
window.Echo.private(`chat.${this.user.id}`)
.listen('NewMessage', (e) => {
console.log(e.message);
});
Nginx config:
server {
server_name example.com www.example.com;
root /var/www/html/example/api/public/;
index index.html index.php;
location / {
root /var/www/html/example/web/dist/;
try_files $uri $uri/ /index.html;
}
location /socket.io {
proxy_pass http://localhost:6001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location /api {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.0-fpm.sock;
}
}
Laravel-echo config:
{
"authHost": "https://example.com/api",
"authEndpoint": "/broadcasting/auth",
"clients": [
{
"appId": "xxx",
"key": "xxxxxxx"
}
],
"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": true,
"allowOrigin": "*",
"allowMethods": "GET, POST",
"allowHeaders": "Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id"
}
}
As it's working in local but not in production, you need to check if socket.io path on your domain is proxied to laravel echo server. To check this path run this path in browser and it must return an array. if it's not proxied you will be redirected according to laravel rules.
https://example.com/socket.io must return:
{"code":0,"message":"Transport unknown"}
I am having trouble getting my Laravel Echo Server to work in a staging/production environment. It works great in my local but not sure why I can't get things going on my Debian 10 VPS. Here is my configuration.
I have no firewall configured yet so there should be no issue with ports being blocked
What I see in the browser console
GET https://dev.domain.com:6001/socket.io/?EIO=3&transport=polling&t=NGLF-O_ net::ERR_CONNECTION_TIMED_OUT
Services are running via Supervisor
root#vultr:/var/www/html/website/storage/logs# supervisorctl status
echo-sever:echo-sever_00 RUNNING pid 28148, uptime 0:22:44
laravel-worker:laravel-worker_00 RUNNING pid 28140, uptime 0:22:44
laravel-worker:laravel-worker_01 RUNNING pid 28141, uptime 0:22:44
laravel-worker:laravel-worker_02 RUNNING pid 28142, uptime 0:22:44
laravel-worker:laravel-worker_03 RUNNING pid 28143, uptime 0:22:44
laravel-worker:laravel-worker_04 RUNNING pid 28144, uptime 0:22:44
laravel-worker:laravel-worker_05 RUNNING pid 28145, uptime 0:22:44
laravel-worker:laravel-worker_06 RUNNING pid 28146, uptime 0:22:44
laravel-worker:laravel-worker_07 RUNNING pid 28147, uptime 0:22:44
peerjs-sever:peerjs-sever_00 RUNNING pid 28149, uptime 0:22:44
Output of Laravel Echo 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!
NGINX CONFIG
server {
#only use default_server if only its the only site running
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html/website/public;
index index.php index.html index.htm index.nginx-debian.html;
server_name dev.domain.com;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
}
location ~* \.io {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy false;
proxy_pass http://localhost:6001;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location ~ /\.ht {
deny all;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/dev.domain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/dev.domain.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
laravel-echo-server.json
{
"authHost": "https://dev.domain.com",
"authEndpoint": "/broadcasting/auth",
"clients": [
{
"appId": "my-app-id",
"key": "my-app-key"
}
],
"database": "redis",
"databaseConfig": {
"redis": {
"host": "my-redis-ip",
"port": "6379",
"password": "my-redis-pass"
},
"sqlite": {
"databasePath": "/database/laravel-echo-server.sqlite"
}
},
"devMode": true,
"host": null,
"port": "6001",
"protocol": "https",
"socketio": {},
"secureOptions": 67108864,
"sslCertPath": "/etc/letsencrypt/live/dev.domain.com/fullchain.pem",
"sslKeyPath": "/etc/letsencrypt/live/dev.domain.com/privkey.pem",
"sslCertChainPath": "",
"sslPassphrase": "",
"subscribers": {
"http": true,
"redis": true
},
"apiOriginAllow": {
"allowCors": true,
"allowOrigin": "https://dev.domain.com",
"allowMethods": "GET, POST",
"allowHeaders": "Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id"
}
}
SNIPPET of relevant APP.JS
import Echo from "laravel-echo";
window.io = require("socket.io-client");
window.Echo = new Echo({
broadcaster: "socket.io",
host: "https://dev.domain.com:6001"
});
EDIT:
Forgot to mention, not sure if this is relevant, but I am using Cloudflare with SSL encryption set to FULL and I'm using LetsEncrypt to generate the certificate on the server which can be seen in my Nginx configuration
Not sure what the problem is, but I found a solution.
I've updated a lot: Nginx to 1.19.1, possibly installed additional modules. Installed npm not globally, but locally.
And at some point, it started working as it should. I still don't understand what's the matter)
Note: this only works if you write location /socket.io.
YES !!!!!, i made this working, i am using aws lightsail and in the networking section all you need to do is to allow that port to work,
Here is some of the configuration which I've used to make it work,
resources/js/bootstrap.js
window._ = require('lodash');
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
window.axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
window.axios.defaults.headers.common.crossDomain = true;
window.axios.defaults.baseURL = '/';
let token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
console.error('CSRF token not found: https://adonisjs.com/docs/4.1/csrf');
}
/**
* We'll load the axios HTTP library which allows us to easily issue requests
* to our Laravel back-end. This library automatically handles sending the
* CSRF token as a header based on the value of the "XSRF" token cookie.
*/
import Echo from "laravel-echo";
if (typeof window.io !== "undefined") {
window.Echo = new Echo({
broadcaster: "socket.io",
host: window.location.hostname + ":6001",
auth: {
headers: {
Accept: 'application/json',
Authorization: 'Bearer ' + token
}
},
wsPort: 80,
wssPort: 443,
disableStats: true,
encrypted: true,
forceTLS: true,
transports: ['websocket', 'polling', 'flashsocket'],
enabledTransports: ['ws', 'wss']
});
}
blade file
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.1.2/socket.io.js"></script>
<script src="//{{ Request::getHost() }}:{{env('LARAVEL_ECHO_PORT')}}/socket.io/socket.io.js"></script>
<script src="{{ mix('/js/laravel-echo-setup.js') }}" type="text/javascript"></script>
laravel-echo-server.json
{
"authHost": "http://ip-address-or-domain-name",
"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": true,
"allowOrigin": "http://ip-address-or-domain-name",
"allowMethods": "GET, POST",
"allowHeaders": "Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id"
}
}
I need to host a laravel application that utilizes laravel-echo-server over a HTTPS server.
I want to use Apache's reverse proxy to redirect my /socket.io url polls to 127.0.0.1 on port 6001 which is where laravel-echo-server is running on within the same domain url.
For example over https://example.com when my laravel-echo-server sends url polls to https://example.com/socket.io apache should redirect it to http://127.0.0.1:6001 within that same domain.
NOTICE
I'm not hosting my laravel app at the root directory but in a subdirectory within my cpanel.
My server is a VPS and I am hosting from a sub domain host that runs on a separate IP address from that of the main server host.
Let's say my main host is host.mydomain.com with a unique IP address pointing to the /home/... directory. This runs on http
I now have a domestic.mydomain.com with a unique IP address pointing to the /home/domestic/... directory and this is where I'm hosting my laravel app from. This runs on https.
But my cpanel login is from the host.mydomain.com IP address where i access the domestic.mydomain.com file manager
What my laravel-echo-server.json looks like:
{
"authHost": "https://example.com",
"authEndpoint": "/broadcasting/auth",
"clients": [
{
"appId": "xxxx",
"key": "xxxxxxxx"
}
],
"database": "redis",
"databaseConfig": {
"redis": {},
"sqlite": {
"databasePath": "/database/laravel-echo-server.sqlite"
}
},
"devMode": false,
"host": "127.0.0.1",
"port": "6001",
"protocol": "http",
"socketio": {},
"sslCertPath": "",
"sslKeyPath": "",
"sslCertChainPath": "",
"sslPassphrase": "",
"subscribers": {
"http": true,
"redis": true
},
"apiOriginAllow": {
"allowCors": false,
"allowOrigin": "",
"allowMethods": "",
"allowHeaders": ""
}
}
How I deploy my laravel-echo:
import Echo from "laravel-echo";
window.io = require('socket.io-client');
// Have this in case you stop running your laravel echo server
if (typeof io !== 'undefined') {
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname,
});
window.Echo.channel('session-expired')
.listen('sessionExpired', (e) => {
setTimeout(location.reload(), 3000);
});
}
And when I run laravel-echo-server start It successfully initialises and shows running on 127.0.0.1 on port 6001
Then here is my apache reverse proxy config /etc/httpd/conf/httpd.conf:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
# mod_proxy setup.
ProxyRequests Off
ProxyPass /socket.io http://127.0.0.1:6001
ProxyPassReverse /socket.io http://127.0.0.1:6001
<Location "/socket.io">
Order allow,deny
Allow from all
</Location>
My problem is when I open my website the polls return a set of OK and 404 responses simultaneously, but it doesn't join any channels within my socket.io. After lots of testing i figured that the proxy does redirect but i doubt it's hitting the particular one I want.
Heres the HTML responses for my 404, which is not my server's configured 404 response:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot POST /</pre>
</body>
</html>
It runs perfectly on my local server but I need to make it run on my production server.
Finally got it.
While my website must still bear an SSL, the solution is to get Apache to redirect /socket.io to http://localhost:6001/socket.io already configured for redis. Then use 2.2.3 version of socket io.
So my laravel-echo-server.json isn't configured for SSL.
Heres my laravel-echo-server.json:
{
"authHost": "https://domainName.com",
"authEndpoint": "/broadcasting/auth",
"clients": [
{
"appId": "xxxxxxx",
"key": "xxxxxxxxxxx"
}
],
"database": "redis",
"databaseConfig": {
"redis": {},
"sqlite": {
"databasePath": "/database/laravel-echo-server.sqlite"
}
},
"devMode": false,
"host": null,
"port": "6001",
"protocol": "http",
"socketio": {},
"sslCertPath": "",
"sslKeyPath": "",
"sslCertChainPath": "",
"sslPassphrase": "",
"subscribers": {
"http": true,
"redis": true
},
"apiOriginAllow": {
"allowCors": true,
"allowOrigin": "*",
"allowMethods": "GET, POST",
"allowHeaders": "Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id"
}
}
How I utitlizes laravel-echo-server.json:
import Echo from "laravel-echo";
window.io = require('socket.io-client');
// Have this in case you stop running your laravel echo server
if (typeof io !== 'undefined') {
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname,
});
}
And my apaxhe config within my SSL virtualhost for my domain:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/socket.io [NC]
RewriteCond %{QUERY_STRING} transport=websocket [NC]
RewriteRule /(.*) ws://localhost:6001/$1 [P,L]
ProxyPass /socket.io http://localhost:6001/socket.io
ProxyPassReverse /socket.io http://localhost:6001/socket.io
In addition it would require a Node js process manager to keep the laravel-echo-server running. So I created echo-server.json and placed the following code.
{
"name": "apps",
"script": "laravel-echo-server",
"args": "start"
}
Next, I install pm2 process manager. npm install pm2 -g and started my service pm2 start echo-server.json --name="apps".
Lastly I use pm2 list to view all my services and pm2 startup to keep my services running.
I followed the documentation provided, and it seems that the server isn't accepting the connection:
(failed)
net::ERR_CONNECTION_CLOSED
I am using Laravel Horizon, and it appears to be running fine.
If I manually use the redis-cli command to access the server, and
apply the 'ping' command, I get a 'pong' response.
Server appears to be up and running after applying the laravel-echo-server start command:
L A R A V E L E C H O S E R V E R
version 1.3.6
⚠ Starting server in DEV mode...
✔ Running at localhost on port 6001
✔ Channels are ready.
✔ Listening for http events...
✔ Listening for redis events...
Server ready!
bootstrap.js:
import Echo from 'laravel-echo'
window.io = require('socket.io-client');
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':6001',
});
.env:
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=redis
REDIS_HOST=localhost
REDIS_PASSWORD=null
REDIS_PORT=6379
laravel-echo-server.json
{
"authHost": "http://dialfy.local",
"authEndpoint": "/broadcasting/auth",
"clients": [
{
"appId": "dd4d563e7e81f442",
"key": "1627b6fd226c7f3c866ca209f78779b6"
}
],
"database": "redis",
"databaseConfig": {
"redis": {},
"sqlite": {
"databasePath": "/database/laravel-echo-server.sqlite"
}
},
"devMode": true,
"host": null,
"port": "6001",
"protocol": "http",
"socketio": {},
"sslCertPath": "",
"sslKeyPath": "",
"sslCertChainPath": "",
"sslPassphrase": "",
"apiOriginAllow": {
"allowCors": false,
"allowOrigin": "",
"allowMethods": "",
"allowHeaders": ""
}
}
Any idea on what the issue may be, or where I could start looking? I imagine it is a configuration issue, but I can't seem to put my finger on it.
For anyone else who runs into a similar problem: the reason was because my app was running on https locally, and I did not configure laravel-echo-server to do the same.