WebSocket握手期间出错:意外的响应代码400

时间:2019-03-14 19:30:31

标签: c# angular web asp.net-core

我为他准备了Web API和Angular应用。

我在Web API端启用了cors策略:

services.AddCors(options =>
            {
                options.AddPolicy("CorsPolicy", b =>
                    {
                        b.AllowAnyOrigin()
                            .AllowAnyMethod()
                            .AllowAnyHeader()
                            .AllowCredentials();
                    }
                );
            });

app.UseCors("CorsPolicy");

我这样从Angular发送get请求:

this._httpClient.get(`WebApi link`);

但捕获错误:

  

WebSocket握手过程中的错误:意外的响应代码400

我在做什么错了?

此链接在PostMan中完美工作,我得到了结果。

Web API使用Win身份验证。

UPD

Web API端在Startup.cs中具有此设置:

public class Startup
{
    private readonly ILoggerFactory _loggerFactory;  
    public Startup(IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        AutomapperConfig.Init();

        _loggerFactory = loggerFactory;
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddEnvironmentVariables();
        Configuration = builder.Build();
    }   
    public IConfigurationRoot Configuration { get; }

    /// <summary>
    /// This method gets called by the runtime. Use this method to add services to the container.
    /// </summary>
    /// <param name="services"></param>
    /// <returns></returns>
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        services.AddResponseCompression();
        services.AddMvc();
        services.AddAuthentication(HttpSysDefaults.AuthenticationScheme);
        services.AddAuthorization(options =>
        {
            foreach (var action in Action.All)
                options.AddPolicy(action.Name, policy =>
                    policy.Requirements.Add(new AssemblyStorageRequirement(action)));
        });
        services.AddSingleton<IAuthorizationHandler, AssemblyStorageRequirementHandler>();

        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy", b =>
                {
                    b.AllowAnyOrigin()
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .AllowCredentials();
                }
            );
        });

        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
            var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
            var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
            c.IncludeXmlComments(xmlPath);
        });
        services.AddOptions();   
        services.AddSingleton(Configuration);   // IConfigurationRoot
        services.AddSingleton<IConfiguration>(Configuration);       // IConfiguration explicitly                          
        return services.AddDiConfig(Configuration);
    }

    /// <summary>
    /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    /// </summary>
    /// <param name="app"></param>
    /// <param name="env"></param>
    /// <param name="loggerFactory"></param>
    /// <param name="appLifetime"></param>
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime appLifetime)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();
        loggerFactory.AddLog4Net();
        app.UseSwagger();
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
        });
        app.UseAuthentication();
        app.UseResponseCompression();
        app.UseCors("CorsPolicy");
        app.UseMvc();

        app.UseForwardedHeaders(new ForwardedHeadersOptions
        {
            ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
        });   
        appLifetime.ApplicationStopped.Register(DiConfig.DisposeContainer);
    }
}

Angular端在Startup.cs中具有此设置:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        // In production, the Angular files will be served from this directory
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/dist";
        });
        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy", b =>
                {
                    b.AllowAnyOrigin()
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .AllowCredentials();
                }
            );
        });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }
        app.UseCors("CorsPolicy");
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseSpaStaticFiles();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller}/{action=Index}/{id?}");
        });

        app.UseSpa(spa =>
        {
            // To learn more about options for serving an Angular SPA from ASP.NET Core,
            // see https://go.microsoft.com/fwlink/?linkid=864501

            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                spa.UseAngularCliServer(npmScript: "start");
            }
        });
    }
}
  

请求标头:GET   wss:// localhost:44391 / sockjs-node / 616 / kjiu00aa / websocket HTTP / 1.1   主机:localhost:44391连接:升级语法:无缓存   缓存控制:无缓存升级:websocket来源:   https://localhost:44391 Sec-WebSocket版本:13用户代理:   Mozilla / 5.0(Windows NT 6.1; Win64; x64)AppleWebKit / 537.36(KHTML,   Chrome / 72.0.3626.121 Safari / 537.36 Accept-Encoding:gzip,   放气,br接受语言:ru-RU,ru; q = 0.9,en-US; q = 0.8,en; q = 0.7   Sec-WebSocket密钥:Ia0VO1G8 + d52FJG74UvsQw == Sec-WebSocket扩展:   放气放气client_max_window_bits

     

响应标题:

     

HTTP / 1.1 400错误的请求传输编码:分块的Vary:原始   服务器:Kestrel访问控制允许凭据:true   Access-Control-Allow-Origin:https://localhost:44391 X-​​SourceFiles:   =?UTF-8 2 B 4 RTpcUHJvamVjdHNcVEZTXE9jdG9wdXNTZXJ2aWNlc1xBc3NlbWJseVN0b3JhZ2VcQXNzZW1ibHlTdG9yYWdlV2ViU2l0ZVxBc3NlbWJseVN0b3JhZ2VXZWJTaXRlXHNvY2tqcy1ub2RlXDYxNlxraml1MDBhYVx3ZWJzb2NrZXQ =?=   X-Powered-By:ASP.NET Date:Fri,15 Mar 2019 08:03:32 GMT

     

常规:

     

请求URL:wss:// localhost:44391 / sockjs-node / 616 / kjiu00aa / websocket   请求方法:GET状态码:400错误请求

UPD

如果我注释掉代码中使用HttpClient的唯一位置,那么错误仍然显示...

因此问题不在WebApi中

2 个答案:

答案 0 :(得分:0)

你能这样尝试吗?

log.warn("shutdown event received {}", event.getSource().toString());
log.warn("/ping will respond 404, Main thread will sleep for 20 seconds to allow pending tasks to complete");

isShuttingDown = true;
try {
    Thread.sleep(SLEEP_BEFORE_SHUTDOWN_MILLIS);
} catch (InterruptedException e) {
    log.error("sleep before shutdown interrupted", e);
}

log.warn("Shutting down now, daemon threads will continue work");
releaseResources(); 

log.info("{} {} on {} stopped.", NAME, VERSION, HOSTNAME);

答案 1 :(得分:0)

一切都很简单...

至少对我来说,这个错误是没有用的。

我不知道观察者是不是很懒,所以请求没有通过

UPD:

将Angular的版本从5更新到7后,不会显示此错误。