Add reset support for IIS (#24552)

This commit is contained in:
Justin Kotalik 2020-08-07 11:08:40 -07:00 committed by GitHub
parent 8ba7c7b457
commit 6020fdef0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 759 additions and 18 deletions

View File

@ -589,4 +589,16 @@ http_response_set_trailer(
IHttpResponse4* pHttpResponse = (IHttpResponse4*)pInProcessHandler->QueryHttpContext()->GetResponse();
return pHttpResponse->SetTrailer(pszHeaderName, pszHeaderValue, usHeaderValueLength, fReplace);
}
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
VOID
http_reset_stream(
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
ULONG errorCode
)
{
IHttpResponse4* pHttpResponse = (IHttpResponse4*)pInProcessHandler->QueryHttpContext()->GetResponse();
pHttpResponse->ResetStream(errorCode);
}
// End of export

View File

@ -33,7 +33,8 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
ITlsConnectionFeature,
IHttpBodyControlFeature,
IHttpMaxRequestBodySizeFeature,
IHttpResponseTrailersFeature
IHttpResponseTrailersFeature,
IHttpResetFeature
{
// NOTE: When feature interfaces are added to or removed from this HttpProtocol implementation,
// then the list of `implementedFeatures` in the generated code project MUST also be updated.
@ -394,6 +395,33 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
set => ResponseTrailers = value;
}
internal IHttpResetFeature GetResetFeature()
{
// Check version is above 2.
if (HttpVersion >= System.Net.HttpVersion.Version20 && NativeMethods.HttpSupportTrailer(_pInProcessHandler))
{
return this;
}
return null;
}
void IHttpResetFeature.Reset(int errorCode)
{
if (errorCode < 0)
{
throw new ArgumentOutOfRangeException("'errorCode' cannot be negative");
}
SetResetCode(errorCode);
AbortIO(clientDisconnect: false);
}
internal unsafe void SetResetCode(int errorCode)
{
NativeMethods.HttpResetStream(_pInProcessHandler, (ulong)errorCode);
}
void IHttpResponseBodyFeature.DisableBuffering()
{
NativeMethods.HttpDisableBuffering(_pInProcessHandler);

View File

@ -29,6 +29,7 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
private static readonly Type IServerVariablesFeature = typeof(global::Microsoft.AspNetCore.Http.Features.IServerVariablesFeature);
private static readonly Type IHttpMaxRequestBodySizeFeature = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpMaxRequestBodySizeFeature);
private static readonly Type IHttpResponseTrailersFeature = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpResponseTrailersFeature);
private static readonly Type IHttpResetFeature = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpResetFeature);
private object _currentIHttpRequestFeature;
private object _currentIHttpResponseFeature;
@ -50,6 +51,7 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
private object _currentIServerVariablesFeature;
private object _currentIHttpMaxRequestBodySizeFeature;
private object _currentIHttpResponseTrailersFeature;
private object _currentIHttpResetFeature;
private void Initialize()
{
@ -66,6 +68,7 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
_currentIHttpMaxRequestBodySizeFeature = this;
_currentITlsConnectionFeature = this;
_currentIHttpResponseTrailersFeature = GetResponseTrailersFeature();
_currentIHttpResetFeature = GetResetFeature();
}
internal object FastFeatureGet(Type key)
@ -154,6 +157,10 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
{
return _currentIHttpResponseTrailersFeature;
}
if (key == IHttpResetFeature)
{
return _currentIHttpResetFeature;
}
return ExtraFeatureGet(key);
}
@ -260,6 +267,10 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
{
_currentIHttpResponseTrailersFeature = feature;
}
if (key == IHttpResetFeature)
{
_currentIHttpResetFeature = feature;
}
if (key == IISHttpContextType)
{
throw new InvalidOperationException("Cannot set IISHttpContext in feature collection");
@ -349,6 +360,10 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
{
yield return new KeyValuePair<Type, object>(IHttpResponseTrailersFeature, _currentIHttpResponseTrailersFeature as global::Microsoft.AspNetCore.Http.Features.IHttpResponseTrailersFeature);
}
if (_currentIHttpResetFeature != null)
{
yield return new KeyValuePair<Type, object>(IHttpResponseTrailersFeature, _currentIHttpResetFeature as global::Microsoft.AspNetCore.Http.Features.IHttpResetFeature);
}
if (MaybeExtra != null)
{

View File

@ -59,6 +59,13 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
// Dispose
}
if (!success && HasResponseStarted)
{
// HTTP/2 INTERNAL_ERROR = 0x2 https://tools.ietf.org/html/rfc7540#section-7
// Otherwise the default is Cancel = 0x8.
SetResetCode(2);
}
if (_onCompleted != null)
{
await FireOnCompleted();

View File

@ -146,6 +146,9 @@ namespace Microsoft.AspNetCore.Server.IIS
[DllImport(AspNetCoreModuleDll)]
private static extern unsafe int http_response_set_trailer(IntPtr pInProcessHandler, byte* pszHeaderName, byte* pszHeaderValue, ushort usHeaderValueLength, bool replace);
[DllImport(AspNetCoreModuleDll)]
private static extern unsafe int http_reset_stream(IntPtr pInProcessHandler, ulong errorCode);
[DllImport(AspNetCoreModuleDll)]
private static extern unsafe int http_response_set_known_header(IntPtr pInProcessHandler, int headerId, byte* pHeaderValue, ushort length, bool fReplace);
@ -318,6 +321,11 @@ namespace Microsoft.AspNetCore.Server.IIS
Validate(http_response_set_trailer(pInProcessHandler, pHeaderName, pHeaderValue, length, false));
}
internal static unsafe void HttpResetStream(IntPtr pInProcessHandler, ulong errorCode)
{
Validate(http_reset_stream(pInProcessHandler, errorCode));
}
internal static unsafe bool HttpSupportTrailer(IntPtr pInProcessHandler)
{
bool supportsTrailers;

View File

@ -0,0 +1,413 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http2Cat;
using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities;
using Microsoft.AspNetCore.Server.IntegrationTesting.Common;
using Microsoft.AspNetCore.Server.IntegrationTesting.IIS;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2;
using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
using Xunit;
namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests
{
[Collection(PublishedSitesCollection.Name)]
public class ResetTests : IISFunctionalTestBase
{
public ResetTests(PublishedSitesFixture fixture) : base(fixture)
{
}
private static readonly Version Win10_Regressed_DataFrame = new Version(10, 0, 20145, 0);
public static readonly IEnumerable<KeyValuePair<string, string>> Headers = new[]
{
new KeyValuePair<string, string>(HeaderNames.Method, "GET"),
new KeyValuePair<string, string>(HeaderNames.Scheme, "https"),
new KeyValuePair<string, string>(HeaderNames.Authority, "localhost:443"),
new KeyValuePair<string, string>("user-agent", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:54.0) Gecko/20100101 Firefox/54.0"),
new KeyValuePair<string, string>("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"),
new KeyValuePair<string, string>("accept-language", "en-US,en;q=0.5"),
new KeyValuePair<string, string>("accept-encoding", "gzip, deflate, br"),
new KeyValuePair<string, string>("upgrade-insecure-requests", "1"),
};
public static readonly IEnumerable<KeyValuePair<string, string>> PostRequestHeaders = new[]
{
new KeyValuePair<string, string>(HeaderNames.Method, "POST"),
new KeyValuePair<string, string>(HeaderNames.Scheme, "https"),
new KeyValuePair<string, string>(HeaderNames.Authority, "localhost:80"),
};
[ConditionalFact]
[MinimumOSVersion(OperatingSystems.Windows, WindowsVersions.Win10, SkipReason = "Http2 requires Win10")]
public async Task AppException_BeforeResponseHeaders_500()
{
var deploymentParameters = GetHttpsDeploymentParameters();
var deploymentResult = await DeployAsync(deploymentParameters);
await new HostBuilder()
.UseHttp2Cat(deploymentResult.ApplicationBaseUri, async h2Connection =>
{
await h2Connection.InitializeConnectionAsync();
h2Connection.Logger.LogInformation("Initialized http2 connection. Starting stream 1.");
await h2Connection.StartStreamAsync(1, GetHeaders("/AppException_BeforeResponseHeaders_500"), endStream: true);
await h2Connection.ReceiveHeadersAsync(1, decodedHeaders =>
{
Assert.Equal("500", decodedHeaders[HeaderNames.Status]);
});
var dataFrame = await h2Connection.ReceiveFrameAsync();
if (Environment.OSVersion.Version >= Win10_Regressed_DataFrame)
{
// TODO: Remove when the regression is fixed.
// https://github.com/dotnet/aspnetcore/issues/23164#issuecomment-652646163
Http2Utilities.VerifyDataFrame(dataFrame, 1, endOfStream: false, length: 0);
dataFrame = await h2Connection.ReceiveFrameAsync();
}
Http2Utilities.VerifyDataFrame(dataFrame, 1, endOfStream: true, length: 0);
h2Connection.Logger.LogInformation("Connection stopped.");
})
.Build().RunAsync();
}
[ConditionalFact]
[MinimumOSVersion(OperatingSystems.Windows, WindowsVersions.Win10, SkipReason = "Http2 requires Win10")]
[MaximumOSVersion(OperatingSystems.Windows, WindowsVersions.Win10_20H1, SkipReason = "This is last version without custom Reset support")]
public async Task AppException_AfterHeaders_PriorOSVersions_ResetCancel()
{
var deploymentParameters = GetHttpsDeploymentParameters();
var deploymentResult = await DeployAsync(deploymentParameters);
await new HostBuilder()
.UseHttp2Cat(deploymentResult.ApplicationBaseUri + "AppException_AfterHeaders_PriorOSVersions_ResetCancel", async h2Connection =>
{
await h2Connection.InitializeConnectionAsync();
h2Connection.Logger.LogInformation("Initialized http2 connection. Starting stream 1.");
await h2Connection.StartStreamAsync(1, GetHeaders("/AppException_AfterHeaders_PriorOSVersions_ResetCancel"), endStream: true);
await h2Connection.ReceiveHeadersAsync(1, decodedHeaders =>
{
Assert.Equal("200", decodedHeaders[HeaderNames.Status]);
});
var resetFrame = await h2Connection.ReceiveFrameAsync();
Http2Utilities.VerifyResetFrame(resetFrame, expectedStreamId: 1, Http2ErrorCode.CANCEL);
h2Connection.Logger.LogInformation("Connection stopped.");
})
.Build().RunAsync();
}
[ConditionalFact]
[MinimumOSVersion(OperatingSystems.Windows, "10.0.19529", SkipReason = "Custom Reset support was added in Win10_20H2.")]
public async Task AppException_AfterHeaders_ResetInternalError()
{
var deploymentParameters = GetHttpsDeploymentParameters();
var deploymentResult = await DeployAsync(deploymentParameters);
await new HostBuilder()
.UseHttp2Cat(deploymentResult.ApplicationBaseUri, async h2Connection =>
{
await h2Connection.InitializeConnectionAsync();
h2Connection.Logger.LogInformation("Initialized http2 connection. Starting stream 1.");
await h2Connection.StartStreamAsync(1, GetHeaders("/AppException_AfterHeaders_ResetInternalError"), endStream: true);
await h2Connection.ReceiveHeadersAsync(1, decodedHeaders =>
{
Assert.Equal("200", decodedHeaders[HeaderNames.Status]);
});
var frame = await h2Connection.ReceiveFrameAsync();
if (Environment.OSVersion.Version >= Win10_Regressed_DataFrame)
{
// TODO: Remove when the regression is fixed.
// https://github.com/dotnet/aspnetcore/issues/23164#issuecomment-652646163
Http2Utilities.VerifyDataFrame(frame, 1, endOfStream: false, length: 0);
frame = await h2Connection.ReceiveFrameAsync();
}
Http2Utilities.VerifyResetFrame(frame, expectedStreamId: 1, Http2ErrorCode.INTERNAL_ERROR);
h2Connection.Logger.LogInformation("Connection stopped.");
})
.Build().RunAsync();
}
[ConditionalFact]
public async Task Reset_Http1_NotSupported()
{
var deploymentParameters = GetHttpsDeploymentParameters();
var deploymentResult = await DeployAsync(deploymentParameters);
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
using HttpClient client = new HttpClient(handler);
client.DefaultRequestVersion = HttpVersion.Version11;
var response = await client.GetStringAsync(deploymentResult.ApplicationBaseUri + "Reset_Http1_NotSupported");
Assert.Equal("Hello World", response);
}
[ConditionalFact]
[MinimumOSVersion(OperatingSystems.Windows, WindowsVersions.Win10, SkipReason = "Http2 requires Win10")]
[MaximumOSVersion(OperatingSystems.Windows, WindowsVersions.Win10_20H1, SkipReason = "This is last version without Reset support")]
public async Task Reset_PriorOSVersions_NotSupported()
{
var deploymentParameters = GetHttpsDeploymentParameters();
var deploymentResult = await DeployAsync(deploymentParameters);
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
using HttpClient client = new HttpClient(handler);
client.DefaultRequestVersion = HttpVersion.Version20;
var response = await client.GetStringAsync(deploymentResult.ApplicationBaseUri);
Assert.Equal("Hello World", response);
}
[ConditionalFact]
[MinimumOSVersion(OperatingSystems.Windows, "10.0.19529", SkipReason = "Reset support was added in Win10_20H2.")]
public async Task Reset_BeforeResponse_Resets()
{
var deploymentParameters = GetHttpsDeploymentParameters();
var deploymentResult = await DeployAsync(deploymentParameters);
await new HostBuilder()
.UseHttp2Cat(deploymentResult.ApplicationBaseUri, async h2Connection =>
{
await h2Connection.InitializeConnectionAsync();
h2Connection.Logger.LogInformation("Initialized http2 connection. Starting stream 1.");
await h2Connection.StartStreamAsync(1, GetHeaders("/Reset_BeforeResponse_Resets"), endStream: true);
var resetFrame = await h2Connection.ReceiveFrameAsync();
Http2Utilities.VerifyResetFrame(resetFrame, expectedStreamId: 1, expectedErrorCode: (Http2ErrorCode)1111);
// Any app errors?
var client = CreateClient();
var response = await client.GetAsync(deploymentResult.ApplicationBaseUri + "/Reset_BeforeResponse_Resets_Complete");
Assert.True(response.IsSuccessStatusCode);
h2Connection.Logger.LogInformation("Connection stopped.");
})
.Build().RunAsync();
}
[ConditionalFact]
[MinimumOSVersion(OperatingSystems.Windows, "10.0.19529", SkipReason = "Reset support was added in Win10_20H2.")]
public async Task Reset_BeforeResponse_Zero_Resets()
{
var deploymentParameters = GetHttpsDeploymentParameters();
var deploymentResult = await DeployAsync(deploymentParameters);
await new HostBuilder()
.UseHttp2Cat(deploymentResult.ApplicationBaseUri, async h2Connection =>
{
await h2Connection.InitializeConnectionAsync();
h2Connection.Logger.LogInformation("Initialized http2 connection. Starting stream 1.");
await h2Connection.StartStreamAsync(1, GetHeaders("/Reset_BeforeResponse_Zero_Resets"), endStream: true);
var resetFrame = await h2Connection.ReceiveFrameAsync();
Http2Utilities.VerifyResetFrame(resetFrame, expectedStreamId: 1, expectedErrorCode: (Http2ErrorCode)0);
// Any app errors?
var client = CreateClient();
var response = await client.GetAsync(deploymentResult.ApplicationBaseUri + "/Reset_BeforeResponse_Zero_Resets_Complete");
Assert.True(response.IsSuccessStatusCode);
h2Connection.Logger.LogInformation("Connection stopped.");
})
.Build().RunAsync();
}
[ConditionalFact]
[MinimumOSVersion(OperatingSystems.Windows, "10.0.19529", SkipReason = "Reset support was added in Win10_20H2.")]
public async Task Reset_AfterResponseHeaders_Resets()
{
var deploymentParameters = GetHttpsDeploymentParameters();
var deploymentResult = await DeployAsync(deploymentParameters);
await new HostBuilder()
.UseHttp2Cat(deploymentResult.ApplicationBaseUri, async h2Connection =>
{
await h2Connection.InitializeConnectionAsync();
h2Connection.Logger.LogInformation("Initialized http2 connection. Starting stream 1.");
await h2Connection.StartStreamAsync(1, GetHeaders("/Reset_AfterResponseHeaders_Resets"), endStream: true);
// Any app errors?
var client = CreateClient();
var response = await client.GetAsync(deploymentResult.ApplicationBaseUri + "/Reset_AfterResponseHeaders_Resets_Complete");
Assert.True(response.IsSuccessStatusCode);
await h2Connection.ReceiveHeadersAsync(1, decodedHeaders =>
{
Assert.Equal("200", decodedHeaders[HeaderNames.Status]);
});
var dataFrame = await h2Connection.ReceiveFrameAsync();
Http2Utilities.VerifyDataFrame(dataFrame, expectedStreamId: 1, endOfStream: false, length: 0);
var resetFrame = await h2Connection.ReceiveFrameAsync();
Http2Utilities.VerifyResetFrame(resetFrame, expectedStreamId: 1, expectedErrorCode: (Http2ErrorCode)1111);
h2Connection.Logger.LogInformation("Connection stopped.");
})
.Build().RunAsync();
}
[ConditionalFact]
[MinimumOSVersion(OperatingSystems.Windows, "10.0.19529", SkipReason = "Reset support was added in Win10_20H2.")]
public async Task Reset_DuringResponseBody_Resets()
{
var deploymentParameters = GetHttpsDeploymentParameters();
var deploymentResult = await DeployAsync(deploymentParameters);
await new HostBuilder()
.UseHttp2Cat(deploymentResult.ApplicationBaseUri, async h2Connection =>
{
await h2Connection.InitializeConnectionAsync();
h2Connection.Logger.LogInformation("Initialized http2 connection. Starting stream 1.");
await h2Connection.StartStreamAsync(1, GetHeaders("/Reset_DuringResponseBody_Resets"), endStream: true);
// This is currently flaky, can either receive header or reset at this point
var headerOrResetFrame = await h2Connection.ReceiveFrameAsync();
Assert.True(headerOrResetFrame.Type == Http2FrameType.HEADERS || headerOrResetFrame.Type == Http2FrameType.RST_STREAM);
if (headerOrResetFrame.Type == Http2FrameType.HEADERS)
{
var dataFrame = await h2Connection.ReceiveFrameAsync();
Http2Utilities.VerifyDataFrame(dataFrame, 1, endOfStream: false, length: 11);
var resetFrame = await h2Connection.ReceiveFrameAsync();
Http2Utilities.VerifyResetFrame(resetFrame, expectedStreamId: 1, expectedErrorCode: (Http2ErrorCode)1111);
}
else
{
Http2Utilities.VerifyResetFrame(headerOrResetFrame, expectedStreamId: 1, expectedErrorCode: (Http2ErrorCode)1111);
}
h2Connection.Logger.LogInformation("Connection stopped.");
})
.Build().RunAsync();
}
[ConditionalFact]
[MinimumOSVersion(OperatingSystems.Windows, "10.0.19529", SkipReason = "Reset support was added in Win10_20H2.")]
public async Task Reset_BeforeRequestBody_Resets()
{
var deploymentParameters = GetHttpsDeploymentParameters();
var deploymentResult = await DeployAsync(deploymentParameters);
await new HostBuilder()
.UseHttp2Cat(deploymentResult.ApplicationBaseUri, async h2Connection =>
{
await h2Connection.InitializeConnectionAsync();
h2Connection.Logger.LogInformation("Initialized http2 connection. Starting stream 1.");
await h2Connection.StartStreamAsync(1, GetPostHeaders("/Reset_BeforeRequestBody_Resets"), endStream: false);
// Any app errors?
//Assert.Equal(0, await appResult.Task.DefaultTimeout());
var resetFrame = await h2Connection.ReceiveFrameAsync();
Http2Utilities.VerifyResetFrame(resetFrame, expectedStreamId: 1, expectedErrorCode: (Http2ErrorCode)1111);
h2Connection.Logger.LogInformation("Connection stopped.");
})
.Build().RunAsync();
}
[ConditionalFact]
[MinimumOSVersion(OperatingSystems.Windows, "10.0.19529", SkipReason = "Reset support was added in Win10_20H2.")]
public async Task Reset_DuringRequestBody_Resets()
{
var deploymentParameters = GetHttpsDeploymentParameters();
var deploymentResult = await DeployAsync(deploymentParameters);
await new HostBuilder()
.UseHttp2Cat(deploymentResult.ApplicationBaseUri, async h2Connection =>
{
await h2Connection.InitializeConnectionAsync();
h2Connection.Logger.LogInformation("Initialized http2 connection. Starting stream 1.");
await h2Connection.StartStreamAsync(1, GetPostHeaders("/Reset_DuringRequestBody_Resets"), endStream: false);
await h2Connection.SendDataAsync(1, new byte[10], endStream: false);
// Any app errors?
//Assert.Equal(0, await appResult.Task.DefaultTimeout());
var resetFrame = await h2Connection.ReceiveFrameAsync();
Http2Utilities.VerifyResetFrame(resetFrame, expectedStreamId: 1, expectedErrorCode: (Http2ErrorCode)1111);
h2Connection.Logger.LogInformation("Connection stopped.");
})
.Build().RunAsync();
}
private static List<KeyValuePair<string, string>> GetHeaders(string path)
{
var headers = Headers.ToList();
var kvp = new KeyValuePair<string, string>(HeaderNames.Path, path);
headers.Add(kvp);
return headers;
}
private static List<KeyValuePair<string, string>> GetPostHeaders(string path)
{
var headers = PostRequestHeaders.ToList();
var kvp = new KeyValuePair<string, string>(HeaderNames.Path, path);
headers.Add(kvp);
return headers;
}
private IISDeploymentParameters GetHttpsDeploymentParameters()
{
var port = TestPortHelper.GetNextSSLPort();
var deploymentParameters = Fixture.GetBaseDeploymentParameters();
deploymentParameters.ApplicationBaseUriHint = $"https://localhost:{port}/";
deploymentParameters.AddHttpsToServerConfig();
return deploymentParameters;
}
private static HttpClient CreateClient()
{
var handler = new HttpClientHandler();
handler.MaxResponseHeadersLength = 128;
handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var client = new HttpClient(handler);
return client;
}
}
}

View File

@ -5,6 +5,7 @@
<TestGroupName>IIS.FunctionalTests</TestGroupName>
<DisableFastUpToDateCheck>True</DisableFastUpToDateCheck>
<SkipTests Condition=" '$(SkipIISTests)' == 'true' ">true</SkipTests>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<Import Project="../FunctionalTest.props" />
@ -19,13 +20,30 @@
<ItemGroup>
<Compile Include="..\Common.FunctionalTests\**\*.cs" />
<Compile Include="..\IIS.Shared.FunctionalTests\**\*.cs" />
<Compile Include="$(SharedSourceRoot)Http2cat\**\*.cs" LinkBase="Shared\Http2cat" />
<Compile Include="$(SharedSourceRoot)runtime\Http2\**\*.cs" LinkBase="Shared\Http2\" />
<Compile Include="$(SharedSourceRoot)runtime\IHttpHeadersHandler.cs" LinkBase="Shared\IHttpHeadersHandler.cs" />
<Compile Include="$(SharedSourceRoot)runtime\SR.cs" LinkBase="Shared\SR.cs" />
<Compile Include="$(SharedSourceRoot)ServerInfrastructure\**\*.cs" LinkBase="Shared\" />
<Compile Include="$(SharedSourceRoot)TaskToApm.cs" Link="Shared\TaskToApm.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Hosting" />
<Reference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets" />
<Reference Include="Microsoft.Extensions.Logging" />
<Reference Include="System.Diagnostics.EventLog" />
<Reference Include="System.Net.Http.WinHttpHandler" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="$(SharedSourceRoot)ServerInfrastructure\SharedStrings.resx" Link="Shared\SharedStrings.resx">
<ManifestResourceName>Microsoft.AspNetCore.Server.SharedStrings</ManifestResourceName>
<Generator></Generator>
</EmbeddedResource>
<EmbeddedResource Include="$(SharedSourceRoot)runtime\SR.resx" Link="Shared\runtime\SR.resx">
<ManifestResourceName>System.Net.Http.SR</ManifestResourceName>
<Generator></Generator>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@ -5,6 +5,7 @@
<TestGroupName>IISNewHandler.FunctionalTests</TestGroupName>
<DisableFastUpToDateCheck>True</DisableFastUpToDateCheck>
<SkipTests Condition=" '$(SkipIISNewHandlerTests)' == 'true' ">true</SkipTests>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<Import Project="../FunctionalTest.props" />
@ -12,6 +13,12 @@
<ItemGroup>
<Compile Include="..\Common.FunctionalTests\**\*.cs" />
<Compile Include="..\IIS.Shared.FunctionalTests\**\*.cs" />
<Compile Include="$(SharedSourceRoot)Http2cat\**\*.cs" LinkBase="Shared\Http2cat" />
<Compile Include="$(SharedSourceRoot)runtime\Http2\**\*.cs" LinkBase="Shared\Http2\" />
<Compile Include="$(SharedSourceRoot)runtime\IHttpHeadersHandler.cs" LinkBase="Shared\IHttpHeadersHandler.cs" />
<Compile Include="$(SharedSourceRoot)runtime\SR.cs" LinkBase="Shared\SR.cs" />
<Compile Include="$(SharedSourceRoot)ServerInfrastructure\**\*.cs" LinkBase="Shared\" />
<Compile Include="$(SharedSourceRoot)TaskToApm.cs" Link="Shared\TaskToApm.cs" />
</ItemGroup>
<ItemGroup>
@ -30,10 +37,22 @@
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Hosting" />
<Reference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets" />
<Reference Include="Microsoft.Extensions.Logging" />
<Reference Include="System.Diagnostics.EventLog" />
<Reference Include="System.Net.WebSockets.WebSocketProtocol" />
<Reference Include="System.Net.Http.WinHttpHandler" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="$(SharedSourceRoot)ServerInfrastructure\SharedStrings.resx" Link="Shared\SharedStrings.resx">
<ManifestResourceName>Microsoft.AspNetCore.Server.SharedStrings</ManifestResourceName>
<Generator></Generator>
</EmbeddedResource>
<EmbeddedResource Include="$(SharedSourceRoot)runtime\SR.resx" Link="Shared\runtime\SR.resx">
<ManifestResourceName>System.Net.Http.SR</ManifestResourceName>
<Generator></Generator>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@ -5,6 +5,7 @@
<TestGroupName>IISNewShim.FunctionalTests</TestGroupName>
<DisableFastUpToDateCheck>True</DisableFastUpToDateCheck>
<SkipTests Condition=" '$(SkipIISNewShimTests)' == 'true' ">true</SkipTests>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<Import Project="../FunctionalTest.props" />
@ -21,13 +22,30 @@
<ItemGroup>
<Compile Include="..\Common.FunctionalTests\**\*.cs" />
<Compile Include="..\IIS.Shared.FunctionalTests\**\*.cs" />
<Compile Include="$(SharedSourceRoot)Http2cat\**\*.cs" LinkBase="Shared\Http2cat" />
<Compile Include="$(SharedSourceRoot)runtime\Http2\**\*.cs" LinkBase="Shared\Http2\" />
<Compile Include="$(SharedSourceRoot)runtime\IHttpHeadersHandler.cs" LinkBase="Shared\IHttpHeadersHandler.cs" />
<Compile Include="$(SharedSourceRoot)runtime\SR.cs" LinkBase="Shared\SR.cs" />
<Compile Include="$(SharedSourceRoot)ServerInfrastructure\**\*.cs" LinkBase="Shared\" />
<Compile Include="$(SharedSourceRoot)TaskToApm.cs" Link="Shared\TaskToApm.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Hosting" />
<Reference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets" />
<Reference Include="Microsoft.Extensions.Logging" />
<Reference Include="System.Diagnostics.EventLog" />
<Reference Include="System.Net.Http.WinHttpHandler" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="$(SharedSourceRoot)ServerInfrastructure\SharedStrings.resx" Link="Shared\SharedStrings.resx">
<ManifestResourceName>Microsoft.AspNetCore.Server.SharedStrings</ManifestResourceName>
<Generator></Generator>
</EmbeddedResource>
<EmbeddedResource Include="$(SharedSourceRoot)runtime\SR.resx" Link="Shared\runtime\SR.resx">
<ManifestResourceName>System.Net.Http.SR</ManifestResourceName>
<Generator></Generator>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@ -7,6 +7,7 @@
<DisableFastUpToDateCheck>True</DisableFastUpToDateCheck>
<TestGroupName>IISExpress.FunctionalTests</TestGroupName>
<SkipTests Condition=" '$(SkipIISExpressTests)' == 'true' ">true</SkipTests>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
@ -23,13 +24,31 @@
<ItemGroup>
<Compile Include="..\Common.FunctionalTests\**\*.cs" />
<Compile Include="$(SharedSourceRoot)Http2cat\**\*.cs" LinkBase="Shared\Http2cat" />
<Compile Include="$(SharedSourceRoot)runtime\Http2\**\*.cs" LinkBase="Shared\Http2\" />
<Compile Include="$(SharedSourceRoot)runtime\IHttpHeadersHandler.cs" LinkBase="Shared\IHttpHeadersHandler.cs" />
<Compile Include="$(SharedSourceRoot)runtime\SR.cs" LinkBase="Shared\SR.cs" />
<Compile Include="$(SharedSourceRoot)ServerInfrastructure\**\*.cs" LinkBase="Shared\" />
<Compile Include="$(SharedSourceRoot)TaskToApm.cs" Link="Shared\TaskToApm.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Hosting" />
<Reference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets" />
<Reference Include="Microsoft.Extensions.Logging" />
<Reference Include="System.Diagnostics.EventLog" />
<Reference Include="System.Net.Http.WinHttpHandler" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="$(SharedSourceRoot)ServerInfrastructure\SharedStrings.resx" Link="Shared\SharedStrings.resx">
<ManifestResourceName>Microsoft.AspNetCore.Server.SharedStrings</ManifestResourceName>
<Generator></Generator>
</EmbeddedResource>
<EmbeddedResource Include="$(SharedSourceRoot)runtime\SR.resx" Link="Shared\runtime\SR.resx">
<ManifestResourceName>System.Net.Http.SR</ManifestResourceName>
<Generator></Generator>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@ -1033,7 +1033,7 @@ namespace TestSite
return Task.CompletedTask;
}
#if !FORWARDCOMPAT
#if !FORWARDCOMPAT
public Task ResponseTrailers_HTTP2_TrailersAvailable(HttpContext context)
{
Assert.Equal("HTTP/2", context.Request.Protocol);
@ -1135,6 +1135,191 @@ namespace TestSite
return Task.FromResult(0);
}
public Task AppException_BeforeResponseHeaders_500(HttpContext context)
{
throw new Exception("Application exception");
}
public async Task AppException_AfterHeaders_PriorOSVersions_ResetCancel(HttpContext httpContext)
{
await httpContext.Response.Body.FlushAsync();
throw new Exception("Application exception");
}
public async Task AppException_AfterHeaders_ResetInternalError(HttpContext httpContext)
{
await httpContext.Response.Body.FlushAsync();
throw new Exception("Application exception");
}
public Task Reset_PriorOSVersions_NotSupported(HttpContext httpContext)
{
Assert.Equal("HTTP/2", httpContext.Request.Protocol);
var feature = httpContext.Features.Get<IHttpResetFeature>();
Assert.Null(feature);
return httpContext.Response.WriteAsync("Hello World");
}
public Task Reset_Http1_NotSupported(HttpContext httpContext)
{
Assert.Equal("HTTP/1.1", httpContext.Request.Protocol);
var feature = httpContext.Features.Get<IHttpResetFeature>();
Assert.Null(feature);
return httpContext.Response.WriteAsync("Hello World");
}
private TaskCompletionSource<object> _resetBeforeResponseResetsCts = new TaskCompletionSource<object>();
public Task Reset_BeforeResponse_Resets(HttpContext httpContext)
{
try
{
Assert.Equal("HTTP/2", httpContext.Request.Protocol);
var feature = httpContext.Features.Get<IHttpResetFeature>();
Assert.NotNull(feature);
feature.Reset(1111); // Custom
_resetBeforeResponseResetsCts.SetResult(0);
}
catch (Exception ex)
{
_resetBeforeResponseResetsCts.SetException(ex);
}
return Task.FromResult(0);
}
public async Task Reset_BeforeResponse_Resets_Complete(HttpContext httpContext)
{
await _resetBeforeResponseResetsCts.Task;
}
private TaskCompletionSource<object> _resetBeforeResponseZeroResetsCts = new TaskCompletionSource<object>();
public Task Reset_BeforeResponse_Zero_Resets(HttpContext httpContext)
{
try
{
Assert.Equal("HTTP/2", httpContext.Request.Protocol);
var feature = httpContext.Features.Get<IHttpResetFeature>();
Assert.NotNull(feature);
feature.Reset(0); // Zero should be an allowed errorCode
_resetBeforeResponseZeroResetsCts.SetResult(0);
}
catch (Exception ex)
{
_resetBeforeResponseZeroResetsCts.SetException(ex);
}
return Task.FromResult(0);
}
public async Task Reset_BeforeResponse_Resets_Zero_Complete(HttpContext httpContext)
{
await _resetBeforeResponseZeroResetsCts.Task;
}
private TaskCompletionSource<object> _resetAfterResponseHeadersResetsCts = new TaskCompletionSource<object>();
public async Task Reset_AfterResponseHeaders_Resets(HttpContext httpContext)
{
try
{
Assert.Equal("HTTP/2", httpContext.Request.Protocol);
var feature = httpContext.Features.Get<IHttpResetFeature>();
Assert.NotNull(feature);
await httpContext.Response.Body.FlushAsync();
feature.Reset(1111); // Custom
_resetAfterResponseHeadersResetsCts.SetResult(0);
}
catch (Exception ex)
{
_resetAfterResponseHeadersResetsCts.SetException(ex);
}
}
public async Task Reset_AfterResponseHeaders_Resets_Complete(HttpContext httpContext)
{
await _resetAfterResponseHeadersResetsCts.Task;
}
private TaskCompletionSource<object> _resetDuringResponseBodyResetsCts = new TaskCompletionSource<object>();
public async Task Reset_DuringResponseBody_Resets(HttpContext httpContext)
{
try
{
Assert.Equal("HTTP/2", httpContext.Request.Protocol);
var feature = httpContext.Features.Get<IHttpResetFeature>();
Assert.NotNull(feature);
await httpContext.Response.WriteAsync("Hello World");
await httpContext.Response.Body.FlushAsync();
feature.Reset(1111); // Custom
_resetDuringResponseBodyResetsCts.SetResult(0);
}
catch (Exception ex)
{
_resetDuringResponseBodyResetsCts.SetException(ex);
}
}
public async Task Reset_DuringResponseBody_Resets_Complete(HttpContext httpContext)
{
await _resetDuringResponseBodyResetsCts.Task;
}
private TaskCompletionSource<object> _resetBeforeRequestBodyResetsCts = new TaskCompletionSource<object>();
public async Task Reset_BeforeRequestBody_Resets(HttpContext httpContext)
{
try
{
Assert.Equal("HTTP/2", httpContext.Request.Protocol);
var feature = httpContext.Features.Get<IHttpResetFeature>();
Assert.NotNull(feature);
var readTask = httpContext.Request.Body.ReadAsync(new byte[10], 0, 10);
feature.Reset(1111);
await Assert.ThrowsAsync<IOException>(() => readTask);
_resetBeforeRequestBodyResetsCts.SetResult(0);
}
catch (Exception ex)
{
_resetBeforeRequestBodyResetsCts.SetException(ex);
}
}
public async Task Reset_BeforeRequestBody_Resets_Complete(HttpContext httpContext)
{
await _resetBeforeRequestBodyResetsCts.Task;
}
private TaskCompletionSource<object> _resetDuringRequestBodyResetsCts = new TaskCompletionSource<object>();
public async Task Reset_DuringRequestBody_Resets(HttpContext httpContext)
{
try
{
Assert.Equal("HTTP/2", httpContext.Request.Protocol);
var feature = httpContext.Features.Get<IHttpResetFeature>();
Assert.NotNull(feature);
var read = await httpContext.Request.Body.ReadAsync(new byte[10], 0, 10);
Assert.Equal(10, read);
var readTask = httpContext.Request.Body.ReadAsync(new byte[10], 0, 10);
feature.Reset(1111);
await Assert.ThrowsAsync<IOException>(() => readTask);
_resetDuringRequestBodyResetsCts.SetResult(0);
}
catch (Exception ex)
{
_resetDuringRequestBodyResetsCts.SetException(ex);
}
}
public async Task Reset_DuringRequestBody_Resets_Complete(HttpContext httpContext)
{
await _resetDuringRequestBodyResetsCts.Task;
}
internal static readonly HashSet<(string, StringValues, StringValues)> NullTrailers = new HashSet<(string, StringValues, StringValues)>()
{
("NullString", (string)null, (string)null),

View File

@ -1,30 +1,29 @@
{
{
"solution": {
"path": "..\\..\\..\\AspNetCore.sln",
"projects" : [
"src\\Servers\\IIS\\IISIntegration\\src\\Microsoft.AspNetCore.Server.IISIntegration.csproj",
"src\\Servers\\IIS\\IIS\\test\\IISExpress.FunctionalTests\\IISExpress.FunctionalTests.csproj",
"src\\Servers\\IIS\\IIS\\samples\\NativeIISSample\\NativeIISSample.csproj",
"src\\Servers\\IIS\\IIS\\src\\Microsoft.AspNetCore.Server.IIS.csproj",
"projects": [
"src\\Servers\\IIS\\AspNetCoreModuleV2\\AspNetCore\\AspNetCore.vcxproj",
"src\\Servers\\IIS\\AspNetCoreModuleV2\\CommonLibTests\\CommonLibTests.vcxproj",
"src\\Servers\\IIS\\AspNetCoreModuleV2\\CommonLib\\CommonLib.vcxproj",
"src\\Servers\\IIS\\AspNetCoreModuleV2\\IISLib\\IISLib.vcxproj",
"src\\Servers\\IIS\\IIS\\benchmarks\\IIS.Performance\\IIS.Performance.csproj",
"src\\Servers\\IIS\\AspNetCoreModuleV2\\InProcessRequestHandler\\InProcessRequestHandler.vcxproj",
"src\\Servers\\IIS\\AspNetCoreModuleV2\\OutOfProcessRequestHandler\\OutOfProcessRequestHandler.vcxproj",
"src\\Servers\\IIS\\AspNetCoreModuleV2\\RequestHandlerLib\\RequestHandlerLib.vcxproj",
"src\\Servers\\IIS\\AspNetCoreModuleV2\\Symbols\\Microsoft.AspNetCore.ANCMSymbols.csproj",
"src\\Servers\\IIS\\AspNetCoreModuleV2\\gtest\\gtest.vcxproj",
"src\\Servers\\IIS\\IISIntegration\\samples\\IISSample\\IISSample.csproj",
"src\\Servers\\IIS\\IISIntegration\\src\\Microsoft.AspNetCore.Server.IISIntegration.csproj",
"src\\Servers\\IIS\\IISIntegration\\test\\Tests\\Microsoft.AspNetCore.Server.IISIntegration.Tests.csproj",
"src\\Servers\\IIS\\IIS\\benchmarks\\IIS.Performance\\IIS.Performance.csproj",
"src\\Servers\\IIS\\IIS\\samples\\NativeIISSample\\NativeIISSample.csproj",
"src\\Servers\\IIS\\IIS\\src\\Microsoft.AspNetCore.Server.IIS.csproj",
"src\\Servers\\IIS\\IIS\\test\\IIS.FunctionalTests\\IIS.FunctionalTests.csproj",
"src\\Servers\\IIS\\IIS\\test\\IIS.Tests\\IIS.Tests.csproj",
"src\\Servers\\IIS\\IIS\\test\\testassets\\IIS.Common.TestLib\\IIS.Common.TestLib.csproj",
"src\\Servers\\IIS\\IIS\\test\\IIS.NewHandler.FunctionalTests\\IIS.NewHandler.FunctionalTests.csproj",
"src\\Servers\\IIS\\IIS\\test\\IIS.NewShim.FunctionalTests\\IIS.NewShim.FunctionalTests.csproj",
"src\\Servers\\IIS\\IIS\\test\\testassets\\TestTasks\\TestTasks.csproj",
"src\\Servers\\IIS\\IIS\\test\\IIS.Tests\\IIS.Tests.csproj",
"src\\Servers\\IIS\\IIS\\test\\IISExpress.FunctionalTests\\IISExpress.FunctionalTests.csproj",
"src\\Servers\\IIS\\IIS\\test\\testassets\\InProcessWebSite\\InProcessWebSite.csproj",
"src\\Servers\\IIS\\IISIntegration\\test\\Tests\\Microsoft.AspNetCore.Server.IISIntegration.Tests.csproj",
"src\\Servers\\IIS\\IntegrationTesting.IIS\\src\\Microsoft.AspNetCore.Server.IntegrationTesting.IIS.csproj",
"src\\Servers\\IIS\\AspNetCoreModuleV2\\CommonLibTests\\CommonLibTests.vcxproj",
"src\\Servers\\IIS\\IISIntegration\\samples\\IISSample\\IISSample.csproj",
"src\\Servers\\IIS\\AspNetCoreModuleV2\\gtest\\gtest.vcxproj"
"src\\Servers\\IIS\\IntegrationTesting.IIS\\src\\Microsoft.AspNetCore.Server.IntegrationTesting.IIS.csproj"
]
}
}
}