Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c94c3b1

Browse files
authoredDec 19, 2022
Don't set the status code if the response has started (#45664)
- Middleware that writes then ends up at the terminal middleware ends up throwing an exception. This change doesn't set the status code if the response has started. - Added a test
1 parent f6fe473 commit c94c3b1

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed
 

‎src/Http/Http/src/Builder/ApplicationBuilder.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,10 @@ public RequestDelegate Build()
132132
throw new InvalidOperationException(message);
133133
}
134134

135-
context.Response.StatusCode = StatusCodes.Status404NotFound;
135+
if (!context.Response.HasStarted)
136+
{
137+
context.Response.StatusCode = StatusCodes.Status404NotFound;
138+
}
136139
return Task.CompletedTask;
137140
};
138141

‎src/Http/Http/test/ApplicationBuilderTests.cs

+46
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using Microsoft.AspNetCore.Http;
5+
using Microsoft.AspNetCore.Http.Features;
56

67
namespace Microsoft.AspNetCore.Builder.Internal;
78

@@ -19,6 +20,23 @@ public void BuildReturnsCallableDelegate()
1920
Assert.Equal(404, httpContext.Response.StatusCode);
2021
}
2122

23+
[Fact]
24+
public async Task BuildReturnDelegateThatDoesNotSetStatusCodeIfResponseHasStarted()
25+
{
26+
var builder = new ApplicationBuilder(null);
27+
var app = builder.Build();
28+
29+
var httpContext = new DefaultHttpContext();
30+
var responseFeature = new TestHttpResponseFeature();
31+
httpContext.Features.Set<IHttpResponseFeature>(responseFeature);
32+
httpContext.Response.StatusCode = 200;
33+
34+
responseFeature.HasStarted = true;
35+
36+
await app.Invoke(httpContext);
37+
Assert.Equal(200, httpContext.Response.StatusCode);
38+
}
39+
2240
[Fact]
2341
public void ServerFeaturesEmptyWhenNotSpecified()
2442
{
@@ -96,4 +114,32 @@ public void PropertiesDictionaryIsDistinctAfterNew()
96114

97115
Assert.Equal("value1", builder1.Properties["test"]);
98116
}
117+
118+
private class TestHttpResponseFeature : IHttpResponseFeature
119+
{
120+
private int _statusCode = 200;
121+
public int StatusCode
122+
{
123+
get => _statusCode;
124+
set
125+
{
126+
_statusCode = HasStarted ? throw new NotSupportedException("The response has already started") : value;
127+
}
128+
}
129+
public string ReasonPhrase { get; set; }
130+
public IHeaderDictionary Headers { get; set; }
131+
public Stream Body { get; set; } = Stream.Null;
132+
133+
public bool HasStarted { get; set; }
134+
135+
public void OnCompleted(Func<object, Task> callback, object state)
136+
{
137+
138+
}
139+
140+
public void OnStarting(Func<object, Task> callback, object state)
141+
{
142+
143+
}
144+
}
99145
}

0 commit comments

Comments
 (0)
Please sign in to comment.