I'm trying to make both a regular node http server work and a WebSocket server. the HTTP server (as in node) is working, but the WebSocket isn't.
I'm not sure what I'm doing wrong, maybe someone can point me into the correct direction?
On the front-end, I'm doing socket = new WebSocket('wss://sub.example.com:8080') which gives the following error: handle-chat.js:11 WebSocket connection to 'wss://sub.example.com:8080/' failed:
I'm running on https, with letsencrypt. I'm running on a VPS, with Apache I'm editing the vhost config for the :80 port, I'm trying to run the ws(s?) server on port 8080, and the http server on port 8000. My vhosts file mostly looks like this:
sub.example.com.conf
<VirtualHost *:80>
ServerName sub.example.com
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# ProxyPass for WebSocket server
ProxyPass "/wss/" "wss://localhost:8080/"
ProxyPassReverse "/wss/" "wss://localhost:8080/"
# ProxyPass for HTTP server
ProxyPass / http://localhost:8000/
ProxyPassReverse / http://localhost:8000/
</VirtualHost>
See, I'm not sure if and when it has to be ws or wss (proxyPass "/ws/" or "/wss/" or on "ws://localhost" or "wss://localhost"), or if I even can do it through the non ssl conf.
This is what the sub.example.com-le-ssl.conf looks like
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName sub.example.com
# ProxyPreserveHost On
ProxyPass / http://localhost:8000/
ProxyPassReverse / http://localhost:8000/
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLCertificateFile /etc/letsencrypt/live/sub.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/sub.example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
Or maybe it has something to do with ports.conf, which looks like this
# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default.conf
Listen 80
Listen 81
Listen 82
<IfModule ssl_module>
Listen 443
</IfModule>
<IfModule mod_gnutls.c>
Listen 443
</IfModule>
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
I did enable the required moduels
- proxy_module
- proxy_http_module
- proxy_wstunnel_module
And I'm also running proxy_fcgi_module, http2_module and even some more modules.
I think my back-end code is correct as well, it's basically just this:
import WebSocket, { WebSocketServer } from 'ws'
const wss = new WebSocketServer({
port: 8080
})
wss.on('connection', function connection(ws, req) {
ws.on('error', console.error)
ws.on('message', function message(data) {
console.log('received: %s', data)
})
ws.send('something')
})
Edit:
I am doing systemctl restart apache2 whenever I change the vhosts files
I did notice that when I go to http://sub.example.com:8080/ws/ whilst running the node app, it returns a response saying: Upgrade Required So something is definitely working correctly, but I assume the wss part is not working, or something.
This was when the vhosts file looks like
<VirtualHost *:80>
ServerName sub.example.com
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# ProxyPass for WebSocket server
ProxyPass "/ws/" "ws://localhost:8080/"
ProxyPassReverse "/ws/" "ws://localhost:8080/"
# ProxyPass for HTTP server
ProxyPass / http://localhost:8000/
ProxyPassReverse / http://localhost:8000/
</VirtualHost>
I also forgot to mention, I am running UFW on which I did allow the port: 8080
Thanks for reading :)
Well, I fixed it, using someone else's question.
Websocket only work with ws:// but not with wss://
The fix is basically setting it up on the vhost side so it looks like the following:
Sub.example.com.conf now looks like this:
sub.example.com-le-ssl.conf like this
What I did on the front-end was connect with the 8080 server, but you shouldn't. So now the front-end code looks like this:
The back-end code still looks the same.
Thanks :)