ASP核心并发请求在CORS预检中被阻止

时间:2018-08-11 16:56:12

标签: c# asp.net-core cors

我有一个脚本,可以对包含JSON的端点进行多次POST。目前,该脚本可能同时从本地主机发出100多个POST。在请求所有POST之前,不会调用该路由的方法。在此之前,仅发送HTTP OPTIONS(CORS预检)作为响应。脚本停止发出POST请求后,服务器才开始调用route方法。

当然,让脚本同时发出100个以上POST请求将被更改,但是我担心这将如何影响许多用户的生产使用。

在调试中,我发现直到该批次中的所有POST请求都完成后,我的过滤器/代码才运行。

我不知所措。 CPU和内存甚至都没有接近极限,更改过滤器顺序没有任何效果,并且优化route方法也没有任何效果,因为直到所有请求都发出后才调用它。

我正在使用IIS Express 10上的Visual Studio在开发机上对此进行测试。我正在使用ASP.NET Core 2.0。

应用配置:

    public void ConfigureServices(IServiceCollection services)
    {
        services
            .AddMvc()
            .AddJsonOptions(opt =>
            {
                opt.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
            })
            .AddMvcOptions(opt =>
            {
                opt.Filters.Add(new IPLoggingInterceptionAttribute());
            });

        services.AddCors(options =>
        {
            options.AddPolicy("AllOrigins", builder =>
            {
                builder.AllowAnyHeader();
                builder.AllowAnyMethod();
                builder.AllowAnyOrigin();
            });
        });

        services
            .AddScoped<RequireAuthAttribute>();

        String connectionString = Configuration.GetConnectionString("Vault");
        services.AddDbContext<VaultContext>(options => options.UseNpgsql(connectionString));
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseCors("AllOrigins");

        app.UseForwardedHeaders(new ForwardedHeadersOptions
        {
            ForwardedHeaders = ForwardedHeaders.All,
            RequireHeaderSymmetry = false
        });

        app.UseMvc();
    }

路由响应方法(如果相关):

    [HttpPost("{villageId}/army/current")]
    public async Task<IActionResult> PostCurrentArmy(long villageId, [FromBody]JSON.ArmySet currentArmySetJson)
    {
        if (!ModelState.IsValid)
            return ValidationProblem(ModelState);

        //  [Note that 'CurrentWorldId' is a blocking property on first read]
        //  Get or make CurrentVillage
        Scaffold.CurrentVillage currentVillage =
            await context.CurrentVillage
                .FromWorld(CurrentWorldId)
                .Where(v => v.VillageId == villageId)
                .FirstOrDefaultAsync();

        currentVillage = currentVillage ?? (await context.AddAsync(new Scaffold.CurrentVillage())).Entity;
        currentVillage.WorldId = CurrentWorldId;

        if (currentVillage.PlayerId == null)
        {
            var modelVillage = await (
                    from village in context.Village.FromWorld(CurrentWorldId)
                    where village.VillageId == villageId
                    select village
                ).FirstOrDefaultAsync();

            if (modelVillage != null)
            {
                currentVillage.VillageId = modelVillage.VillageId;
                currentVillage.PlayerId = modelVillage.PlayerId;
                currentVillage.Points = modelVillage.Points;
                currentVillage.VillageName = modelVillage.VillageName;
                currentVillage.X = modelVillage.X.Value;
                currentVillage.Y = modelVillage.Y.Value;
            }
        }

        if (!Configuration.Security.AllowUploadArmyForNonOwner
                && currentVillage.PlayerId != CurrentUser.PlayerId)
        {
            await context.InvalidDataRecord.AddAsync(MakeInvalidDataRecord(
                JsonConvert.SerializeObject(currentArmySetJson),
                $"Attempted to upload current army to village {villageId} but that village is not owned by the requestor"
            ));
            await context.SaveChangesAsync();
            return Unauthorized();
        }

        var fullArmy = currentArmySetJson.Stationed + currentArmySetJson.Traveling + currentArmySetJson.Supporting;
        currentVillage.ArmyOwned     = ArmyConvert.JsonToArmy(fullArmy, currentVillage.ArmyOwned, context);
        currentVillage.ArmyStationed = ArmyConvert.JsonToArmy(currentArmySetJson.Stationed, currentVillage.ArmyStationed, context);
        currentVillage.ArmyTraveling = ArmyConvert.JsonToArmy(currentArmySetJson.Traveling, currentVillage.ArmyTraveling, context);


        await context.SaveChangesAsync();
        return Ok();
    }

2 个答案:

答案 0 :(得分:0)

@Tseng指出,请在IIS服务器(非开发人员)上尝试。在继续执行此操作之前,您应该能够快速通过几件事来排除您的应用不是引起关注的原因。

  1. 您是否100%确定请求没有达到您的netcore应用程序?你是否可以 检查IIS日志并关联时间戳?最好有Fiddler 在您再次尝试以确保请求是 实际上马上就打您的应用,而没有排队 大爆炸?

  2. 也尝试使用其他浏览器。通过所有优化浏览器     这些天用客户端代码来做,有些怪癖或     您发出请求的方式使其以您的方式行为     如上所述(排队请求立即执行)。

如果不是以上两种情况,并且您可以确认所有请求都立即到达应用程序,那么我怀疑某种类型的阻止和/或资源锁定会阻止所有请求排队。

让我们知道您的发现。祝好运。

答案 1 :(得分:0)

@Tseng是正确的-问题出在浏览器上,它似乎一直保持POST请求,直到脚本完成为止,但没有保持OPTIONS请求。