SignalR Core Apache WS意外的响应代码:200

时间:2019-08-20 04:32:59

标签: signalr apache2 kestrel-http-server asp.net-core-signalr kestrel

我目前正在Ubuntu Apache Web服务器上使用SignalR运行.Net Core应用程序。可以通过example.com/api路径访问此.Net Core应用。

我也有一个在网络服务器上运行的Vue JS应用程序。当我尝试建立与SignalR应用程序的websocket连接时,发生以下错误:

  

与'wss://example.com/api/mainHub?id = V3XZrhdsQDTTMIZvQ-8cbQ'的WebSocket连接失败:WebSocket握手期间出错:意外的响应代码:200

     

错误:无法启动传输'WebSockets':null

.Net Core应用程序的Apache配置如下:

#Main/Desired Path - https://example.com
<VirtualHost *:443>
        DocumentRoot /var/www/example.com/dist/spa
        ServerName example.com

#SSL Certs
        SSLEngine on
        SSLProtocol all -SSLv2
        SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:!RC4+RSA:+HIGH:+MEDIUM:!LOW:!RC4
        SSLCertificateFile /etc/apache2/ssl/example.crt
        SSLCertificateKeyFile /etc/apache2/ssl/server.key
        SSLCertificateChainFile /etc/apache2/ssl/example.ca-bundle

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

#Other specific directories
        ProxyPreserveHost On
        ProxyPass "/api" http://localhost:5000
        ProxyPassReverse "/api" http://localhost:5000

</VirtualHost>

我已经添加了RewriteEngine来升级websocket,但不确定是Apache还是.Net Core应用本身的配置问题。

.Net Core应用在startup.cs

中具有以下内容
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options => options.AddPolicy("CorsPolicy", builder =>
            {
                builder
                    .AllowAnyMethod()
                    .AllowAnyHeader()
                    .AllowCredentials()
                    .WithOrigins("*");
            }));
            services.AddSignalR();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            //first handle any websocket requests
            app.UseWebSockets();

            app.UseCors("CorsPolicy");
            app.UseSignalR(routes =>
            {
                routes.MapHub<mainHub>("/mainHub");
                routes.MapHub<accounthub>("/accountHub");
            });
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Hello World!");
            });
        }

在建立WebSocket连接时,startup.cs似乎在向客户端发送200响应的某些错误,或者Apache虚拟主机未正确升级WebSocket。

2 个答案:

答案 0 :(得分:1)

我在一个网站 ( http://shyammakwana.me/server/websockets-with-apache-reverse-proxy-with-ssl.html ) 上发现了这个,它似乎也对我有用。 给定站点的 apache 配置应该是这样的

<IfModule mod_ssl.c>
<VirtualHost *:443>
  RewriteEngine On
  ProxyPreserveHost On
  ProxyRequests Off

  # allow for upgrading to websockets
  RewriteEngine On
  RewriteCond %{HTTP:Upgrade} =websocket [NC]
  RewriteRule /(.*)           ws://localhost:5000/$1 [P,L]
  RewriteCond %{HTTP:Upgrade} !=websocket [NC]
  RewriteRule /(.*)           http://localhost:5000/$1 [P,L]


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

  ProxyPass "/chatHub" "ws://localhost:5000/chatHub"
  ProxyPassReverse "/chatHub" "ws://localhost:5000/chatHub"

  ServerName site.com
  
SSLCertificateFile /etc/letsencrypt/live/site.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/site.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

您还应该启用这些模块:

a2enmod   proxy
a2enmod   proxy_wstunnel

答案 1 :(得分:0)

在将ASP.NET Core 3.1 Blazor服务器端应用程序部署到运行Apache2的Ubuntu 18.04服务器时,我也遇到此错误。

结合此错误,尝试从Linux服务器访问静态资源(.css文件,图像和脚本)时,我也遇到404错误,但在IIS环境中一切正常。我还注意到,当我发布应用程序时,解决方案中WWWRoot文件夹的内容似乎未复制到linux服务器。我正在使用发布的FolderProfile方法,然后通过SFTP将发布文件夹的内容复制到linux服务器。

样板启动时唯一的“真实”更改。配置类(来自VS2019中的New Blazor-Server Web App模板)我所做的就是添加UseForwardHeaders指令,如https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-apache?view=aspnetcore-3.1

中所述

我还向该应用程序添加了身份验证和授权,但是再一次,整个过程可以在IIS上完美运行,但是一旦测试完成,就需要将其安装在生产Linux服务器上。

我的Startup.Configure如下:

public int CompareTo(QueueEntryElement obj)
        {
            if (obj == null) return 1;
            QueueEntryElement otherQueueEntryElement = obj as QueueEntryElement;
            if (otherQueueEntryElement != null)
            {
                if (Priority.CompareTo(otherQueueEntryElement.Priority) == 0)
                {
                    return OrderId.CompareTo(otherQueueEntryElement.OrderId);
                }
                return 0;
            }
            else
                throw new ArgumentException("Object is not a QueueEntryElement");
        }

此外,在Linux端,虚拟主机配置文件如下所示:

 public static void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {

            app.UseForwardedHeaders(new ForwardedHeadersOptions
            {
                ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
            });

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            // Enable SyncFusion Community Edition License
            Syncfusion.Licensing.SyncfusionLicenseProvider
                .RegisterLicense("Key-Removed");

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();


            // Use Authentication and Authorisation providers in the application
            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
            });
        }

请注意,我已经注释掉了前三行,因为我无法使该表达式正常工作-Apache无法以我尝试的第二行的每个变体开头。我相信这可能与我的问题有关,但是我不确定该怎么办。

我还想强调一点,该应用程序仅供内部使用,并且Web服务器仅在我们的Intranet上可见-没有面向外部/ Internet的服务器或站点,并且只能通过物理访问来访问极少数人到服务器以及受限制的固定IP地址,因此我完全不关心使用SSL。

对此提供的任何帮助将不胜感激。我一直在努力使它运行一个星期,并且只剩下一个星期才必须在Linux测试环境中进行。