I'm currently running an apache2 webserver on Ubuntu. This web server is hosting a Vue.js web app that connects to a .Net Core app (also on the same linux server) with SignalR to create a websocket.
The .Net Core app is ran using Kestrel. Below is the apache config to reroute the domain.com/api to the .Net Core app running on port 5000.
<VirtualHost *:80>
ServerName example.com
Redirect permanent / https://www.example.com/
</VirtualHost>
<VirtualHost _default_:443>
DocumentRoot /var/www/example.com/dist/spa
ServerName www.example.com
ServerAlias example.com
ProxyPreserveHost On
ProxyPass "/api" http://localhost:5000/
ProxyPassReverse "/api" http://localhost:5000/
RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
RewriteRule /(.*) ws://localhost:5000/$1 [P]
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:!RC4+RSA:+HIGH:+MEDIUM:!LOW:!RC4
SSLCertificateFile /etc/apache2/ssl/example_com.crt
SSLCertificateKeyFile /etc/apache2/ssl/server.key
SSLCertificateChainFile /etc/apache2/ssl/example_com.ca-bundle
ErrorLog ${APACHE_LOG_DIR}example-error.log
CustomLog ${APACHE_LOG_DIR}example.log common
</VirtualHost>
When the Vue.js app attempts to create a websocket connection to the example.com/api/mainHub the following error occurs:
Failed to complete negotiation with the server: SyntaxError: Unexpected token H in JSON at position 0
It seems to be sending the request to the correct URL, https://example.com/api/mainHub but fails to establish the connection.
One thing I noticed on the Linux server, is the POST does not include the /api in the path.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1] Request starting HTTP/1.1 POST http://example.com//mainHub/negotiate text/plain;charset=UTF-8 0
Is this an issue with how my apache2 config is routing the requests to the /api directory?
Edit
I've since changed my apache config to remove the extra /
at the end of the localhost:5000 - This allowed the outside connection to reach the correct API path.
<VirtualHost *:80>
ServerName example.com
Redirect permanent / https://www.example.com/
</VirtualHost>
<VirtualHost _default_:443>
DocumentRoot /var/www/example.com/dist/spa
ServerName www.example.com
ServerAlias example.com
RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteRule /(.*) wss://localhost:5000$1 [P]
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
RewriteRule /(.*) https://localhost:5000$1 [P]
ProxyPreserveHost On
ProxyPass "/api" http://localhost:5000
ProxyPassReverse "/api" http://localhost:5000
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:!RC4+RSA:+HIGH:+MEDIUM:!LOW:!RC4
SSLCertificateFile /etc/apache2/ssl/example_com.crt
SSLCertificateKeyFile /etc/apache2/ssl/server.key
SSLCertificateChainFile /etc/apache2/ssl/example_com.ca-bundle
ErrorLog ${APACHE_LOG_DIR}example-error.log
CustomLog ${APACHE_LOG_DIR}example.log common
</VirtualHost>
The issue now seems to be with the secure websocket upgrade. I tried changing the ws upgrade to wss, but something is still wrong. When the client attempts to make the wss connection, the following error occurs:
WebSocket connection to 'wss://example.com/api/mainHub?id=k1-_KxspgAQgIAhKroQBpQ' failed: Error during WebSocket handshake: Unexpected response code: 502
I believe something is wrong with how my virtual host is upgrading the websocket connection with HTTPS.
Error: Failed to start the transport 'WebSockets': null
If your .Net Core app is listening at /api/
on port 5000, then add that to ProxyPass directives:
ProxyPass "/api" http://localhost:5000/api
ProxyPassReverse "/api" http://localhost:5000/api
Edit: Try
RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
RewriteRule /(.*) ws://localhost:5000/$1 [P]
ProxyPreserveHost On
ProxyPass "/api" http://localhost:5000
ProxyPassReverse "/api" http://localhost:5000