【问题标题】:CORS enabled but response for preflight has invalid HTTP status code 404 when POSTing JSON已启用 CORS,但在 POST JSON 时,预检响应的 HTTP 状态代码 404 无效
【发布时间】:2016-07-15 12:18:19
【问题描述】:

我已经彻底搜索,但在我的特定情况下找不到解决此问题的方法。

使用 Fiddler (POST) 的跨域服务调用正确执行并接收到数据。但是,通过浏览器 (Chrome) 我收到消息“预检有无效的 HTTP 状态代码 404”

我有一个 Web API 应用程序并安装了 CORS 并确保 web.config 文件中存在以下内容:

<system.webServer>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="Content-Type" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
      </customHeaders>
    </httpProtocol>
</system.webServer>

这里是 Ajax 调用:

var secretKey = 'difusod7899sdfiertwe08wepifdfsodifyosey',
    url = 'http://api.intrinsic.co.uk/api/v1/PTS/ActiveDrivers?api_key=098werolllfWnCbPGAuIXVOJidDHRfYcgxImMlxTXopuekXrSOqOWzEAIdeNTWGPQPpyHxgVGsFysGFKPzq';

  jQuery.ajax ({
      url: url,
      type: "POST",
      data: JSON.stringify({ secretKey: secretKey}),
      dataType: "json",
      contentType: "application/json; charset=utf-8",
      success: function(data){
          var content = "<table class=\"container\"><thead><tr><th>Driver Number</th><th>Timestamp</th><th>VRN</th><th>Latitude</th><th>Longitude</th><th>Track Link</th></tr></thead><tbody>";
          $.each(data.ActiveDrivers.DriverLocationStatus, function (index, element) {
              content += "<tr><td>" + element.DriverNumber + "</td>";
              content += "<td>" + dateFormat(element.Timestamp, "d/m/yy") + " " + dateFormat(element.Timestamp, "h:MM TT") + "</td>";
              content += "<td>" + element.VRN + "</td>";
              content += "<td>" + element.CurrentLatitude + "</td>";
              content += "<td>" + element.CurrentLongitude + "</td>";
              content += "<td><a href=\"https://www.google.co.uk/maps/place//@" + element.CurrentLatitude + "," + element.CurrentLongitude + ",15z/\" target='_blank'>Track &raquo;</a></td></tr>";
          });
          content += "</tbody></table>";
          $( "#result" ).html( content );
      }
  });

显然,可以完美地在同一个域上运行,并且如上所述,它可以使用 Fiddler。

我确定是浏览器的预检选项检查对于“应用程序/json”的内容类型失败,但我不确定如何修复它。

web.config 文件中是否缺少我应该添加的内容?

我已尝试删除“内容类型”而没有任何影响。

我曾希望this article 能解决问题(看起来很有希望),但遇到了同样的错误:

XMLHttpRequest cannot load [URL]. Response for preflight has invalid HTTP status code 404

【问题讨论】:

    标签: json ajax asp.net-web-api cors


    【解决方案1】:

    谢谢,但在上述配置更改后出现 405 错误。

    在 web api Global.asax 文件中添加以下代码后,它终于可以工作了

    protected void Application_BeginRequest(Object sender, EventArgs e)
        {
            //HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
            if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
            {
                HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
                HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
                HttpContext.Current.Response.End();
            }
        }
    

    【讨论】:

    • 为什么这还不是答案?
    【解决方案2】:

    我终于搞定了。

    这篇文章'WebAPI with CORS – IIS Intercepts OPTIONS Verb'告诉了我的想法。一张图片显示了 IIS 中 OPTIONS 处理程序映射出现的位置,以及为什么我们需要在 web.config 中删除它以确保 IIS 不会拦截。

    当我查看 IIS 时,那个处理程序并不存在。然后,我查看了链接文章“Can't set HttpHandler order using Web.Config unless a «clear» tag exists”,发现在本文中,删除 OPTION 处理程序后,它被显式添加到 web.config 中。

    因为我在 IIS 中看不到 OPTION 处理程序,所以我也将它添加到 web.config 文件中,然后突然就开始工作了。看来这个添加是需要的。

    最终的 web.config 处理程序部分如下所示(请注意,我决定保留最初的“删除”,以防万一将来我迁移到不同的 Web 服务器时出现问题)。

    <system.webServer>
        <handlers>
          <remove name="WebDAV"/>
          <remove name="OPTIONSVerbHandler"/>
          <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
          <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
          <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
          <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
          <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
          <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
          <add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="ProtocolSupportModule" requireAccess="None" responseBufferLimit="4194304" />
        </handlers>
        <httpProtocol>
          <customHeaders>
            <add name="Access-Control-Allow-Origin" value="*" />
            <add name="Access-Control-Allow-Headers" value="Content-Type" />
            <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS" />
          </customHeaders>
        </httpProtocol>
    </system.webServer>
    

    【讨论】:

    【解决方案3】:

    这对我有用。

    在 Global.asax 中

    protected void Application_BeginRequest(Object sender, EventArgs e)
    {
        //HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
        if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
        {
            HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
            HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
            HttpContext.Current.Response.End();
        }
    }
    

    在 Web.config 中

        <httpProtocol>
            <customHeaders>
    
        <add name="Access-Control-Allow-Origin" value="*"/>
        <add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS"/>
        <add name="Access-Control-Allow-Headers" value="Content-Type"/>
            </customHeaders>
        </httpProtocol>
    

    重建并嘿presto。

    【讨论】:

      【解决方案4】:

      当我试图让 CORS 在我的 Web 服务上运行时,我有一个类似的设置显示 404 错误和 500 错误。我的修复基本上使用了 Hussain 的解决方案,但是当我清理修复时,我注意到只需要一个响应行,并且我能够将原始 Web 处理程序保留在 web.config 中,并且不需要移动所有将响应处理程序放入代码中。

      基本上,我的修复在我的 ApplicationOnBeginRequest 处理程序中包含了这个 ONE MAJOR FIX

          private void ApplicationOnBeginRequest( object sender, EventArgs eventArgs )
              {
      ...
                  if ( context.Request.HttpMethod == "OPTIONS" )
                      response.End();
              }
      

      以及我的 web.config 中的这些处理程序:

      <system.webServer>
          <!--Other handlers/modules ...-->
          <httpProtocol>
              <customHeaders>
                  <clear />
                  <add name="Access-Control-Allow-Origin" value="*" />
                  <add name="Access-Control-Allow-Credentials" value="true" />
                  <add name="Access-Control-Allow-Headers" value="Content-Type,Accept" />
                  <add name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS" />
              </customHeaders>
          </httpProtocol>
         </system.webServer>
      

      抱歉,我无法将此笔记作为对 Hussain 回答的评论发送。

      【讨论】:

        【解决方案5】:

        对于使用 .NET Core 3.1 的用户,这里有一个完整的解决方案(前端到后端):

        我的问题:当我在我的 Web API 上启用 Windows 身份验证时,我无法从我的 react 应用程序获取调用到我的 .NET Core 3.1 Web API,CORS 吓坏了。使用匿名身份验证它可以工作,但在启用 Windows 身份验证时不能。

        1.launchSettings.json

        这将仅用于您的开发环境,请确保您的产品服务器上的 IIS 中也启用了 Windows 身份验证。

        {
          "iisSettings": {
            "windowsAuthentication": true,
            "anonymousAuthentication": false,
            "iisExpress": {
              "applicationUrl": "http://localhost:58747",
              "sslPort": 0
            }
          },
         {... more settings if any}
        }
        

        2.Startup.cs:

        CORS 政策在此处启用。方法的顺序在这里很重要。此外,您不需要在 web.config 中设置这些

        public void ConfigureServices(IServiceCollection services)
            {
                services.AddCors(options =>
                {
                    options.AddPolicy("CorsPolicy", //give it the name you want
                                   builder =>
                                   {
                                       builder.WithOrigins( "http://localhost:3000", //dev site
                                                            "production web site"
                                                           .AllowAnyHeader()
                                                           .AllowAnyMethod()
                                                           .AllowCredentials();
                                   });
                });
        
                //database services here
        
                services.AddControllers();
            }
        
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
        
                app.UseRouting();
        
                // global policy same name as in the ConfigureServices()
                app.UseCors("CorsPolicy");
        
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllers();
                });
            }
        

        3.控制器:

        using Microsoft.AspNetCore.Cors;
        ... your other usings
        
        namespace ProjectTest.Controllers
        {
            [ApiController]
            [EnableCors("CorsPolicy")] //THIS HERE needs to be the same name as set in your startup.cs
            [Route("[controller]")]
            public class FooController:Controller
            {
                [HttpGet("getTest")]
                public JsonResult GetTest()
                {
                    return Json("bar");
                }
            }
        }
        

        4.React Component fetch 调用示例:

        “凭据:'include'”是秘密

            await fetch('http://localhost:3000/Foo/getTest', {
                method: 'GET',
                credentials: 'include'
            }).then(resp => resp.json());
        

        【讨论】:

          【解决方案6】:

          对于 asp 核心,请在配置过程中的 Startup.cs 中使用此代码。我用的是 2.0 版本,但我认为它也应该适用于旧版本

          app.UseCors(builder => {
                          builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
                      });
          

          【讨论】:

            【解决方案7】:

            这对我也有帮助,我已经在 web.config 中配置了 CORS

            protected void Application_BeginRequest(Object sender, EventArgs e)
            {
                //HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
                if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
                {
                    HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
                    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
                    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
                    HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
                    HttpContext.Current.Response.End();
                }
            }
            

            【讨论】:

              猜你喜欢
              • 2017-06-28
              • 2017-09-26
              • 2016-02-13
              • 2018-04-25
              • 2018-07-01
              • 2016-01-22
              • 1970-01-01
              • 2016-05-21
              • 2018-09-30
              相关资源
              最近更新 更多