dotnet/aspnetcore

Setting an invalid Transfer-Encoding response header sometimes kills the connection instead of responding with a 500 status

Open

#4,382 建立於 2018年12月4日

在 GitHub 查看
 (3 留言) (1 反應) (0 負責人)C# (37,933 star) (10,653 fork)batch import
affected-very-fewarea-networkingbugfeature-kestrelhelp wantedseverity-nice-to-have

描述

Describe the bug

Setting a Transfer-Encoding response header which is invalid for a given request or response (e.g. 204/205/304 responses and HEAD requests) without manually writing to or flushing the response body kills the connection instead of responding with a 500 status code.

To Reproduce

Steps to reproduce the behavior:

  1. Targeting ASP.NET Core 2.2 (though this bug likely existed earlier), add the following middleware:
app.Run(context =>
{
    context.Response.StatusCode = 204;
    context.Response.Headers["Transfer-Encoding"] = "chunked";
    return Task.CompletedTask;
});
  1. Run the app and test the endpoint by making a GET request. If you have a project reference to Kestrel.Core, make sure you run the app in release mode to avoid a Debug.Assert.
  2. See a connection reset error.

Expected behavior

A 500 response. This can be observed if you make a slight change to the above middleware to manually flush the response body:

app.Run(context =>
{
    context.Response.StatusCode = 204;
    context.Response.Headers["Transfer-Encoding"] = "chunked";
    return context.Response.Body.FlushAsync();
});

Additional context

Here are what the server logs look like when this bug is hit:

dbug: Microsoft.AspNetCore.Server.Kestrel[1]
      Connection id "0HLIPIMQJ59NK" started.
dbug: Microsoft.AspNetCore.Server.Kestrel[1]
      Connection id "0HLIPIMQJ59NL" started.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/
fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HLIPIMQJ59NK", Request id "0HLIPIMQJ59NK:00000001": An unhandled exception was thrown by the application.
System.InvalidOperationException: Setting the header Transfer-Encoding is not allowed on responses with status code 204.
warn: Microsoft.AspNetCore.Server.Kestrel[0]
      Connection processing ended abnormally.
System.InvalidOperationException: StatusCode cannot be set because the response has already started.
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ThrowResponseAlreadyStartedException(String value) in C:\dev\aspnet\AspNetCore\src\Servers\Kestrel\Core\src\Internal\Http\HttpProtocol.cs:line 1209
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.set_StatusCode(Int32 value) in C:\dev\aspnet\AspNetCore\src\Servers\Kestrel\Core\src\Internal\Http\HttpProtocol.cs:line 207
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.SetErrorResponseHeaders(Int32 statusCode) in C:\dev\aspnet\AspNetCore\src\Servers\Kestrel\Core\src\Internal\Http\HttpProtocol.cs:line 1245
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.CreateResponseHeader(Boolean appCompleted) in C:\dev\aspnet\AspNetCore\src\Servers\Kestrel\Core\src\Internal\Http\HttpProtocol.cs:line 1171
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProduceEndAwaited()
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application) in C:\dev\aspnet\AspNetCore\src\Servers\Kestrel\Core\src\Internal\Http\HttpProtocol.cs:line 597
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequestsAsync[TContext](IHttpApplication`1 application) in C:\dev\aspnet\AspNetCore\src\Servers\Kestrel\Core\src\Internal\Http\HttpProtocol.cs:line 465
dbug: Microsoft.AspNetCore.Server.Kestrel[10]
      Connection id "0HLIPIMQJ59NK" disconnecting.
dbug: Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets[7]
      Connection id "0HLIPIMQJ59NK" sending FIN because: "The Socket transport's send loop completed gracefully."
dbug: Microsoft.AspNetCore.Server.Kestrel[2]

貢獻者指南