发送HTTP标头后,服务器无法设置状态 - web api CORS

时间:2015-04-17 21:16:25

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

好吧,我一直在抨击这个人的血腥......

设置:

  • 我设置了基本身份验证的Web Api 2.0项目。
  • 我在web.config
  • 中启用了CORS
  • 我有ELMAH记录错误
  • 我有一个处理传入请求的DelegatingHandler - (下面的代码)
  • 我有一个非常具体的数据结构,所以我没有使用Microsoft的会员资格或身份。
  • 我正在刷新使用OPTIONS动词的每个请求

问题:

我在每个经过身份验证的请求中收到以下错误:

System.Web.HttpException (0x80004005): Server cannot set status after HTTP headers have been sent.
   at System.Web.HttpResponse.set_StatusCode(Int32 value)
   at System.Web.HttpResponseWrapper.set_StatusCode(Int32 value)
   at System.Web.Http.WebHost.HttpControllerHandler.<CopyResponseStatusAndHeadersAsync>d__31.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at System.Web.Http.WebHost.HttpControllerHandler.<CopyResponseAsync>d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at System.Web.Http.WebHost.HttpControllerHandler.<ProcessRequestAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at System.Web.TaskAsyncHelper.EndTask(IAsyncResult ar)
   at System.Web.HttpTaskAsyncHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
   at System.Web.HttpApplication.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar)

到目前为止进行的调查:

上面列出的错误只发生于OPTIONS动词。

错误表示标题已在被要求设置其状态代码之前已发送。

只出现1条错误记录 - 在elmah中,“SendAsync”方法被击中两次 - 一次用于OPTIONS飞行前,一次用于GET或POST。这告诉我这只发生在一个请求 - OPTIONS请求。

为了超越飞行前,我正在使用:(global.asax)

protected void Application_BeginRequest()
{
  if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
    {
        Response.Flush();
    }
}

这会将响应传递给我的处理程序,但它也会将OPTIONS动词传递给此代码,我认为它应该:

//Capture incoming request by overriding SendAsync method

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    //validate credentials, set CurrentPrincipal and Current.User if valid
    if (ValidateCredentials(request.Headers.Authorization))
    {
        Thread.CurrentPrincipal = new MyPrincipal(_userName);
        HttpContext.Current.User = new MyPrincipal(_userName);
    }


    // Execute base.SendAsync to execute default actions
    // and once it is completed, capture the response object and add
    // WWW-Authenticate header if the request was marked as (401) unauthorized.

    return base.SendAsync(request, cancellationToken).ContinueWith(task =>
    {
        HttpResponseMessage response = task.Result;
        if (response.StatusCode == HttpStatusCode.Unauthorized && !response.Headers.Contains("WWW-Authenticate"))
        {
            response.Headers.Add("WWW-Authenticate", "Basic");
        }
        return response;
    });

}

现在在调试器中,我看到OPTIONS通过并触发了一个不允许的405方法,但是当它出现在elmah时它是一个500错误 - 服务器无法在发送HTTP头后设置状态。 / p>

我没有把OPTIONS放在我的任何控制器上,所以这可能解释了405 - 但请求不应该那么远。

所以 - 这听起来像配置的东西?困惑。

我的cors配置是:

<!-- BEGIN: Enable CORS -->
<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Headers" value="accept, authorization, origin, content-type" />
    <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
  </customHeaders>
</httpProtocol>

<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="OPTIONSVerbHandler" />
  <remove name="TRACEVerbHandler" />
  <remove name="WebDAV"/>
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<!-- END: Enable CORS -->

到目前为止我的想法

错误不是“FatalError”,程序仍然会触发,因为预检请求不会影响我所知道的任何内容 - 错误也会被忽略?好吧,不!这是一个错误!

现在 - 通过我已经完成的研究,似乎这是一个漏洞进入我的应用程序的IIS,我可以通过配置停止 - 但是如何?

如果那不是它那么到底是什么造成的呢?它来自哪里?我该如何解决?不知道......

所以我依靠Stack Overflow上同伴们的勇敢智慧......

HELP !!!!!!!

1 个答案:

答案 0 :(得分:21)

Response.End();

之后加Response.Flush();

因此,您应该对预检请求进行空响应。​​

至少这为我解决了这个问题。