Skip to content

Commit 0646bb9

Browse files
authored
Call Flush With fMoreData=false when response isn't allowed to have body (#4403)
1 parent 1733aa0 commit 0646bb9

File tree

11 files changed

+46
-17
lines changed

11 files changed

+46
-17
lines changed

src/IISIntegration/IISIntegration.NoV1.sln

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{7E80C58E
3838
build\applicationhost.iis.config = build\applicationhost.iis.config
3939
build\Build.Settings = build\Build.Settings
4040
build\Config.Definitions.Props = build\Config.Definitions.Props
41-
build\dependencies.props = build\dependencies.props
4241
build\functional-test-assets.targets = build\functional-test-assets.targets
4342
build\Key.snk = build\Key.snk
4443
build\launchSettings.json = build\launchSettings.json
@@ -116,7 +115,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IIS.BackwardsCompatibility.
116115
EndProject
117116
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IIS.ForwardsCompatibility.FunctionalTests", "test\IIS.ForwardsCompatibility.FunctionalTests\IIS.ForwardsCompatibility.FunctionalTests.csproj", "{D1EA5D99-28FD-4197-81DE-17098846B38B}"
118117
EndProject
119-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InProcessForwardsCompatWebSite", "test\WebSites\InProcessForwardsCompatWebSite\InProcessWebSite.csproj", "{BBBC85B2-5D7A-4D09-90B1-8DBCC9059493}"
118+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InProcessWebSite", "test\WebSites\InProcessForwardsCompatWebSite\InProcessWebSite.csproj", "{BBBC85B2-5D7A-4D09-90B1-8DBCC9059493}"
120119
EndProject
121120
Global
122121
GlobalSection(SolutionConfigurationPlatforms) = preSolution

src/IISIntegration/src/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,13 +288,13 @@ EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
288288
HRESULT
289289
http_flush_response_bytes(
290290
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
291+
_In_ BOOL fMoreData,
291292
_Out_ BOOL* pfCompletionExpected
292293
)
293294
{
294295
IHttpResponse *pHttpResponse = (IHttpResponse*)pInProcessHandler->QueryHttpContext()->GetResponse();
295296

296297
BOOL fAsync = TRUE;
297-
BOOL fMoreData = TRUE;
298298
DWORD dwBytesSent = 0;
299299

300300
HRESULT hr = pHttpResponse->Flush(

src/IISIntegration/src/Microsoft.AspNetCore.Server.IIS/Core/IISHttpContext.IO.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ private async Task WriteBody(bool flush = false)
158158

159159
if (flush)
160160
{
161-
await AsyncIO.FlushAsync();
161+
await AsyncIO.FlushAsync(moreData: true);
162162
flush = false;
163163
}
164164
}

src/IISIntegration/src/Microsoft.AspNetCore.Server.IIS/Core/IISHttpContext.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,12 +243,12 @@ private async Task ProduceStart(bool flushHeaders)
243243
SetResponseHeaders();
244244

245245
EnsureIOInitialized();
246-
246+
var canHaveNonEmptyBody = StatusCodeCanHaveBody();
247247
if (flushHeaders)
248248
{
249249
try
250250
{
251-
await AsyncIO.FlushAsync();
251+
await AsyncIO.FlushAsync(canHaveNonEmptyBody);
252252
}
253253
// Client might be disconnected at this point
254254
// don't leak the exception
@@ -258,7 +258,20 @@ private async Task ProduceStart(bool flushHeaders)
258258
}
259259
}
260260

261-
_writeBodyTask = WriteBody(!flushHeaders);
261+
if (!canHaveNonEmptyBody)
262+
{
263+
_bodyOutput.Dispose();
264+
}
265+
else
266+
{
267+
_writeBodyTask = WriteBody(!flushHeaders);
268+
}
269+
}
270+
271+
private bool StatusCodeCanHaveBody()
272+
{
273+
return StatusCode != 204
274+
&& StatusCode != 304;
262275
}
263276

264277
private void InitializeRequestIO()

src/IISIntegration/src/Microsoft.AspNetCore.Server.IIS/Core/IO/AsyncIOEngine.Flush.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,23 @@ internal class AsyncFlushOperation : AsyncIOOperation
1212
private readonly AsyncIOEngine _engine;
1313

1414
private IntPtr _requestHandler;
15+
private bool _moreData;
1516

1617
public AsyncFlushOperation(AsyncIOEngine engine)
1718
{
1819
_engine = engine;
1920
}
2021

21-
public void Initialize(IntPtr requestHandler)
22+
public void Initialize(IntPtr requestHandler, bool moreData)
2223
{
2324
_requestHandler = requestHandler;
25+
_moreData = moreData;
2426
}
2527

2628
protected override bool InvokeOperation(out int hr, out int bytes)
2729
{
2830
bytes = 0;
29-
hr = NativeMethods.HttpFlushResponseBytes(_requestHandler, out var fCompletionExpected);
31+
hr = NativeMethods.HttpFlushResponseBytes(_requestHandler, _moreData, out var fCompletionExpected);
3032

3133
return !fCompletionExpected;
3234
}
@@ -36,6 +38,7 @@ protected override void ResetOperation()
3638
base.ResetOperation();
3739

3840
_requestHandler = default;
41+
_moreData = false;
3942
_engine.ReturnOperation(this);
4043
}
4144
}

src/IISIntegration/src/Microsoft.AspNetCore.Server.IIS/Core/IO/AsyncIOEngine.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ private void Run(AsyncIOOperation ioOperation)
9090
}
9191

9292

93-
public ValueTask FlushAsync()
93+
public ValueTask FlushAsync(bool moreData)
9494
{
9595
var flush = GetFlushOperation();
96-
flush.Initialize(_handler);
96+
flush.Initialize(_handler, moreData);
9797
Run(flush);
9898
return new ValueTask(flush, 0);
9999
}

src/IISIntegration/src/Microsoft.AspNetCore.Server.IIS/Core/IO/IAsyncIOEngine.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ internal interface IAsyncIOEngine: IDisposable
1111
{
1212
ValueTask<int> ReadAsync(Memory<byte> memory);
1313
ValueTask<int> WriteAsync(ReadOnlySequence<byte> data);
14-
ValueTask FlushAsync();
14+
ValueTask FlushAsync(bool moreData);
1515
void NotifyCompletion(int hr, int bytes);
1616
}
1717
}

src/IISIntegration/src/Microsoft.AspNetCore.Server.IIS/Core/IO/WebSocketsAsyncIOEngine.Initialize.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public void Initialize(IntPtr requestHandler)
2525

2626
protected override bool InvokeOperation(out int hr, out int bytes)
2727
{
28-
hr = NativeMethods.HttpFlushResponseBytes(_requestHandler, out var completionExpected);
28+
hr = NativeMethods.HttpFlushResponseBytes(_requestHandler, fMoreData: true, out var completionExpected);
2929
bytes = 0;
3030
return !completionExpected;
3131
}

src/IISIntegration/src/Microsoft.AspNetCore.Server.IIS/Core/IO/WebSocketsAsyncIOEngine.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public ValueTask<int> WriteAsync(ReadOnlySequence<byte> data)
5656
}
5757
}
5858

59-
public ValueTask FlushAsync()
59+
public ValueTask FlushAsync(bool moreData)
6060
{
6161
lock (_contextLock)
6262
{

src/IISIntegration/src/Microsoft.AspNetCore.Server.IIS/NativeMethods.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ private static extern int register_callbacks(IntPtr pInProcessApplication,
6767
private static extern unsafe int http_write_response_bytes(IntPtr pInProcessHandler, HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks, int nChunks, out bool fCompletionExpected);
6868

6969
[DllImport(AspNetCoreModuleDll)]
70-
private static extern int http_flush_response_bytes(IntPtr pInProcessHandler, out bool fCompletionExpected);
70+
private static extern int http_flush_response_bytes(IntPtr pInProcessHandler, bool fMoreData, out bool fCompletionExpected);
7171

7272
[DllImport(AspNetCoreModuleDll)]
7373
private static extern unsafe HttpApiTypes.HTTP_REQUEST_V2* http_get_raw_request(IntPtr pInProcessHandler);
@@ -171,9 +171,9 @@ public static unsafe int HttpWriteResponseBytes(IntPtr pInProcessHandler, HttpAp
171171
return http_write_response_bytes(pInProcessHandler, pDataChunks, nChunks, out fCompletionExpected);
172172
}
173173

174-
public static int HttpFlushResponseBytes(IntPtr pInProcessHandler, out bool fCompletionExpected)
174+
public static int HttpFlushResponseBytes(IntPtr pInProcessHandler, bool fMoreData, out bool fCompletionExpected)
175175
{
176-
return http_flush_response_bytes(pInProcessHandler, out fCompletionExpected);
176+
return http_flush_response_bytes(pInProcessHandler, fMoreData, out fCompletionExpected);
177177
}
178178

179179
public static unsafe HttpApiTypes.HTTP_REQUEST_V2* HttpGetRawRequest(IntPtr pInProcessHandler)

src/IISIntegration/test/Common.FunctionalTests/Inprocess/ResponseHeaderTests.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4+
using System;
45
using System.Linq;
56
using System.Net;
7+
using System.Net.Http;
68
using System.Threading.Tasks;
79
using Microsoft.AspNetCore.Testing.xunit;
810
using Microsoft.Net.Http.Headers;
@@ -75,6 +77,18 @@ public async Task CustomErrorCodeWorks(int code, string reason, string expectedR
7577
Assert.Equal(body ?? string.Empty, await response.Content.ReadAsStringAsync());
7678
}
7779

80+
[ConditionalTheory]
81+
[RequiresNewHandler]
82+
[InlineData(204, "GET")]
83+
[InlineData(304, "GET")]
84+
public async Task TransferEncodingNotSetForStatusCodes(int code, string method)
85+
{
86+
var request = new HttpRequestMessage(new HttpMethod(method), _fixture.Client.BaseAddress + $"SetCustomErorCode?code={code}");
87+
var response = await _fixture.Client.SendAsync(request);
88+
Assert.Equal((HttpStatusCode)code, response.StatusCode);
89+
Assert.DoesNotContain(response.Headers, h => h.Key.Equals("transfer-encoding", StringComparison.InvariantCultureIgnoreCase));
90+
}
91+
7892
[ConditionalFact]
7993
public async Task ServerHeaderIsOverriden()
8094
{

0 commit comments

Comments
 (0)