"Unexpected token H in JSON at position 0" Apache Web 服务器上的 SignalR 核心和 Kestrel

"Unexpected token H in JSON at position 0" SignalR Core and Kestrel on Apache Web Server

我目前是 运行 Ubuntu 上的 apache2 网络服务器。此 Web 服务器正在托管一个 Vue.js Web 应用程序,该应用程序连接到一个 .Net Core 应用程序(也在同一 linux 服务器上),使用 SignalR 创建一个 websocket。

.Net Core 应用 运行 使用 Kestrel。下面是重新路由域的 apache 配置。com/api 到端口 5000 上的 .Net Core 应用程序 运行。

<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/ [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>

当 Vue.js 应用程序尝试创建到示例的 websocket 连接时。com/api/mainHub 发生以下错误:

Failed to complete negotiation with the server: SyntaxError: Unexpected token H in JSON at position 0

似乎正在向正确的URL发送请求,https://example.com/api/mainHub但无法建立连接。

我在 Linux 服务器上注意到的一件事是 POST 在路径中不包含 /api。

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1] Request starting HTTP/1.1 POST http://example.com//mainHub/negotiate text/plain;charset=UTF-8 0

这是我的 apache2 配置如何将请求路由到 /api 目录的问题吗?

编辑 我已经更改了我的 apache 配置以删除 localhost:5000 末尾的额外 / - 这允许外部连接到达正确的 API 路径。

<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 [P]
  RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
  RewriteRule /(.*) https://localhost:5000 [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>

现在的问题似乎与安全的 websocket 升级有关。我尝试将 ws 升级更改为 wss,但仍然有问题。当客户端尝试建立 wss 连接时,出现以下错误:

WebSocket connection to 'wss://example.com/api/mainHub?id=k1-_KxspgAQgIAhKroQBpQ' failed: Error during WebSocket handshake: Unexpected response code: 502

我认为我的虚拟主机使用 HTTPS 升级 websocket 连接的方式有问题。

Error: Failed to start the transport 'WebSockets': null

如果您的 .Net Core 应用正在侦听 /api/ 端口 5000,请将其添加到 ProxyPass 指令中:

ProxyPass "/api" http://localhost:5000/api
ProxyPassReverse "/api" http://localhost:5000/api

编辑:尝试

RewriteEngine on
  RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
  RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
  RewriteRule /(.*) ws://localhost:5000/ [P]

ProxyPreserveHost On
ProxyPass "/api" http://localhost:5000
ProxyPassReverse "/api" http://localhost:5000