diff --git a/AspNetCore.sln b/AspNetCore.sln index 2ad398116849..09c4747213c6 100644 --- a/AspNetCore.sln +++ b/AspNetCore.sln @@ -1716,6 +1716,10 @@ Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "WindowsHostingBundle", "src EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServerComparison.TestSites", "src\Servers\testassets\ServerComparison.TestSites\ServerComparison.TestSites.csproj", "{56DFE643-7F0F-40C8-9F7F-8EA5357781EF}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DelegationSite", "src\Servers\HttpSys\test\testassets\DelegationSite\DelegationSite.csproj", "{E0BE6B86-F8DB-405D-AC05-78C8C9D3857D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.HttpSys.NonHelixTests", "src\Servers\HttpSys\test\NonHelixTests\Microsoft.AspNetCore.Server.HttpSys.NonHelixTests.csproj", "{8EB0B983-8851-4565-B92F-366F1B126E61}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -9990,44 +9994,42 @@ Global {6D365C86-3158-49F5-A21D-506C1E06E870}.Release|x86.Build.0 = Release|Any CPU {2A150BE3-D7DC-4E2A-8399-6EBAB77DEF00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2A150BE3-D7DC-4E2A-8399-6EBAB77DEF00}.Debug|Any CPU.Build.0 = Debug|Any CPU - {564CABB8-1B3F-4D9E-909D-260EF2B8614A}.Debug|arm64.ActiveCfg = Debug|Any CPU - {564CABB8-1B3F-4D9E-909D-260EF2B8614A}.Debug|arm64.Build.0 = Debug|Any CPU + {2A150BE3-D7DC-4E2A-8399-6EBAB77DEF00}.Debug|arm64.ActiveCfg = Debug|Any CPU {2A150BE3-D7DC-4E2A-8399-6EBAB77DEF00}.Debug|x64.ActiveCfg = Debug|Any CPU {2A150BE3-D7DC-4E2A-8399-6EBAB77DEF00}.Debug|x64.Build.0 = Debug|Any CPU {2A150BE3-D7DC-4E2A-8399-6EBAB77DEF00}.Debug|x86.ActiveCfg = Debug|Any CPU {2A150BE3-D7DC-4E2A-8399-6EBAB77DEF00}.Debug|x86.Build.0 = Debug|Any CPU {2A150BE3-D7DC-4E2A-8399-6EBAB77DEF00}.Release|Any CPU.ActiveCfg = Release|Any CPU {2A150BE3-D7DC-4E2A-8399-6EBAB77DEF00}.Release|Any CPU.Build.0 = Release|Any CPU - {564CABB8-1B3F-4D9E-909D-260EF2B8614A}.Release|arm64.ActiveCfg = Release|Any CPU - {564CABB8-1B3F-4D9E-909D-260EF2B8614A}.Release|arm64.Build.0 = Release|Any CPU + {2A150BE3-D7DC-4E2A-8399-6EBAB77DEF00}.Release|arm64.ActiveCfg = Release|Any CPU {2A150BE3-D7DC-4E2A-8399-6EBAB77DEF00}.Release|x64.ActiveCfg = Release|Any CPU {2A150BE3-D7DC-4E2A-8399-6EBAB77DEF00}.Release|x64.Build.0 = Release|Any CPU {2A150BE3-D7DC-4E2A-8399-6EBAB77DEF00}.Release|x86.ActiveCfg = Release|Any CPU {2A150BE3-D7DC-4E2A-8399-6EBAB77DEF00}.Release|x86.Build.0 = Release|Any CPU {D5F4D764-887D-4EB3-8D00-FCBE23FFDBBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D5F4D764-887D-4EB3-8D00-FCBE23FFDBBC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CF4CEC18-798D-46EC-B0A0-98D97496590F}.Debug|arm64.ActiveCfg = Debug|Any CPU - {CF4CEC18-798D-46EC-B0A0-98D97496590F}.Debug|arm64.Build.0 = Debug|Any CPU + {D5F4D764-887D-4EB3-8D00-FCBE23FFDBBC}.Debug|arm64.ActiveCfg = Debug|Any CPU {D5F4D764-887D-4EB3-8D00-FCBE23FFDBBC}.Debug|x64.ActiveCfg = Debug|Any CPU {D5F4D764-887D-4EB3-8D00-FCBE23FFDBBC}.Debug|x64.Build.0 = Debug|Any CPU {D5F4D764-887D-4EB3-8D00-FCBE23FFDBBC}.Debug|x86.ActiveCfg = Debug|Any CPU {D5F4D764-887D-4EB3-8D00-FCBE23FFDBBC}.Debug|x86.Build.0 = Debug|Any CPU {D5F4D764-887D-4EB3-8D00-FCBE23FFDBBC}.Release|Any CPU.ActiveCfg = Release|Any CPU {D5F4D764-887D-4EB3-8D00-FCBE23FFDBBC}.Release|Any CPU.Build.0 = Release|Any CPU - {CF4CEC18-798D-46EC-B0A0-98D97496590F}.Release|arm64.ActiveCfg = Release|Any CPU - {CF4CEC18-798D-46EC-B0A0-98D97496590F}.Release|arm64.Build.0 = Release|Any CPU + {D5F4D764-887D-4EB3-8D00-FCBE23FFDBBC}.Release|arm64.ActiveCfg = Release|Any CPU {D5F4D764-887D-4EB3-8D00-FCBE23FFDBBC}.Release|x64.ActiveCfg = Release|Any CPU {D5F4D764-887D-4EB3-8D00-FCBE23FFDBBC}.Release|x64.Build.0 = Release|Any CPU {D5F4D764-887D-4EB3-8D00-FCBE23FFDBBC}.Release|x86.ActiveCfg = Release|Any CPU {D5F4D764-887D-4EB3-8D00-FCBE23FFDBBC}.Release|x86.Build.0 = Release|Any CPU {40F493E2-FE59-4787-BE44-3AED39D585BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {40F493E2-FE59-4787-BE44-3AED39D585BF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {40F493E2-FE59-4787-BE44-3AED39D585BF}.Debug|arm64.ActiveCfg = Debug|Any CPU {40F493E2-FE59-4787-BE44-3AED39D585BF}.Debug|x64.ActiveCfg = Debug|Any CPU {40F493E2-FE59-4787-BE44-3AED39D585BF}.Debug|x64.Build.0 = Debug|Any CPU {40F493E2-FE59-4787-BE44-3AED39D585BF}.Debug|x86.ActiveCfg = Debug|Any CPU {40F493E2-FE59-4787-BE44-3AED39D585BF}.Debug|x86.Build.0 = Debug|Any CPU {40F493E2-FE59-4787-BE44-3AED39D585BF}.Release|Any CPU.ActiveCfg = Release|Any CPU {40F493E2-FE59-4787-BE44-3AED39D585BF}.Release|Any CPU.Build.0 = Release|Any CPU + {40F493E2-FE59-4787-BE44-3AED39D585BF}.Release|arm64.ActiveCfg = Release|Any CPU {40F493E2-FE59-4787-BE44-3AED39D585BF}.Release|x64.ActiveCfg = Release|Any CPU {40F493E2-FE59-4787-BE44-3AED39D585BF}.Release|x64.Build.0 = Release|Any CPU {40F493E2-FE59-4787-BE44-3AED39D585BF}.Release|x86.ActiveCfg = Release|Any CPU @@ -10128,10 +10130,16 @@ Global {B2D7BD12-5BDF-47F5-A55B-4A09D705731F}.Release|x64.Build.0 = Release|Any CPU {B2D7BD12-5BDF-47F5-A55B-4A09D705731F}.Release|x86.ActiveCfg = Release|Any CPU {B2D7BD12-5BDF-47F5-A55B-4A09D705731F}.Release|x86.Build.0 = Release|Any CPU + {FD819B29-9EFE-4102-BD0A-375A63051458}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FD819B29-9EFE-4102-BD0A-375A63051458}.Debug|arm64.ActiveCfg = Debug|Any CPU {FD819B29-9EFE-4102-BD0A-375A63051458}.Debug|arm64.Build.0 = Debug|Any CPU + {FD819B29-9EFE-4102-BD0A-375A63051458}.Debug|x64.ActiveCfg = Debug|Any CPU + {FD819B29-9EFE-4102-BD0A-375A63051458}.Debug|x86.ActiveCfg = Debug|Any CPU + {FD819B29-9EFE-4102-BD0A-375A63051458}.Release|Any CPU.ActiveCfg = Release|Any CPU {FD819B29-9EFE-4102-BD0A-375A63051458}.Release|arm64.ActiveCfg = Release|Any CPU {FD819B29-9EFE-4102-BD0A-375A63051458}.Release|arm64.Build.0 = Release|Any CPU + {FD819B29-9EFE-4102-BD0A-375A63051458}.Release|x64.ActiveCfg = Release|Any CPU + {FD819B29-9EFE-4102-BD0A-375A63051458}.Release|x86.ActiveCfg = Release|Any CPU {53EA8180-8942-4D16-B92A-C5D3813D47CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {53EA8180-8942-4D16-B92A-C5D3813D47CE}.Debug|Any CPU.Build.0 = Debug|Any CPU {53EA8180-8942-4D16-B92A-C5D3813D47CE}.Debug|arm64.ActiveCfg = Debug|Any CPU @@ -10336,6 +10344,38 @@ Global {56DFE643-7F0F-40C8-9F7F-8EA5357781EF}.Release|x64.Build.0 = Release|x64 {56DFE643-7F0F-40C8-9F7F-8EA5357781EF}.Release|x86.ActiveCfg = Release|x86 {56DFE643-7F0F-40C8-9F7F-8EA5357781EF}.Release|x86.Build.0 = Release|x86 + {E0BE6B86-F8DB-405D-AC05-78C8C9D3857D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E0BE6B86-F8DB-405D-AC05-78C8C9D3857D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E0BE6B86-F8DB-405D-AC05-78C8C9D3857D}.Debug|arm64.ActiveCfg = Debug|Any CPU + {E0BE6B86-F8DB-405D-AC05-78C8C9D3857D}.Debug|arm64.Build.0 = Debug|Any CPU + {E0BE6B86-F8DB-405D-AC05-78C8C9D3857D}.Debug|x64.ActiveCfg = Debug|Any CPU + {E0BE6B86-F8DB-405D-AC05-78C8C9D3857D}.Debug|x64.Build.0 = Debug|Any CPU + {E0BE6B86-F8DB-405D-AC05-78C8C9D3857D}.Debug|x86.ActiveCfg = Debug|Any CPU + {E0BE6B86-F8DB-405D-AC05-78C8C9D3857D}.Debug|x86.Build.0 = Debug|Any CPU + {E0BE6B86-F8DB-405D-AC05-78C8C9D3857D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E0BE6B86-F8DB-405D-AC05-78C8C9D3857D}.Release|Any CPU.Build.0 = Release|Any CPU + {E0BE6B86-F8DB-405D-AC05-78C8C9D3857D}.Release|arm64.ActiveCfg = Release|Any CPU + {E0BE6B86-F8DB-405D-AC05-78C8C9D3857D}.Release|arm64.Build.0 = Release|Any CPU + {E0BE6B86-F8DB-405D-AC05-78C8C9D3857D}.Release|x64.ActiveCfg = Release|Any CPU + {E0BE6B86-F8DB-405D-AC05-78C8C9D3857D}.Release|x64.Build.0 = Release|Any CPU + {E0BE6B86-F8DB-405D-AC05-78C8C9D3857D}.Release|x86.ActiveCfg = Release|Any CPU + {E0BE6B86-F8DB-405D-AC05-78C8C9D3857D}.Release|x86.Build.0 = Release|Any CPU + {8EB0B983-8851-4565-B92F-366F1B126E61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8EB0B983-8851-4565-B92F-366F1B126E61}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8EB0B983-8851-4565-B92F-366F1B126E61}.Debug|arm64.ActiveCfg = Debug|Any CPU + {8EB0B983-8851-4565-B92F-366F1B126E61}.Debug|arm64.Build.0 = Debug|Any CPU + {8EB0B983-8851-4565-B92F-366F1B126E61}.Debug|x64.ActiveCfg = Debug|Any CPU + {8EB0B983-8851-4565-B92F-366F1B126E61}.Debug|x64.Build.0 = Debug|Any CPU + {8EB0B983-8851-4565-B92F-366F1B126E61}.Debug|x86.ActiveCfg = Debug|Any CPU + {8EB0B983-8851-4565-B92F-366F1B126E61}.Debug|x86.Build.0 = Debug|Any CPU + {8EB0B983-8851-4565-B92F-366F1B126E61}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8EB0B983-8851-4565-B92F-366F1B126E61}.Release|Any CPU.Build.0 = Release|Any CPU + {8EB0B983-8851-4565-B92F-366F1B126E61}.Release|arm64.ActiveCfg = Release|Any CPU + {8EB0B983-8851-4565-B92F-366F1B126E61}.Release|arm64.Build.0 = Release|Any CPU + {8EB0B983-8851-4565-B92F-366F1B126E61}.Release|x64.ActiveCfg = Release|Any CPU + {8EB0B983-8851-4565-B92F-366F1B126E61}.Release|x64.Build.0 = Release|Any CPU + {8EB0B983-8851-4565-B92F-366F1B126E61}.Release|x86.ActiveCfg = Release|Any CPU + {8EB0B983-8851-4565-B92F-366F1B126E61}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -11186,6 +11226,8 @@ Global {5244BC49-2568-4701-80A6-EAB8950AB5FA} = {31854B06-DC6B-4416-97C3-559CC390B8B4} {6F1B115C-1903-40CB-837D-7961AB610F4E} = {5E46DC83-C39C-4E3A-B242-C064607F4367} {56DFE643-7F0F-40C8-9F7F-8EA5357781EF} = {3CBC4802-E9B8-48B7-BC8C-B0AFB9EEC643} + {E0BE6B86-F8DB-405D-AC05-78C8C9D3857D} = {C3722C5D-E159-4AB3-AF60-769185B31B47} + {8EB0B983-8851-4565-B92F-366F1B126E61} = {C3722C5D-E159-4AB3-AF60-769185B31B47} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3E8720B3-DBDD-498C-B383-2CC32A054E8F} diff --git a/src/Hosting/Server.IntegrationTesting/src/Deployers/SelfHostDeployer.cs b/src/Hosting/Server.IntegrationTesting/src/Deployers/SelfHostDeployer.cs index 7acf196b4a75..ccc2063b8fee 100644 --- a/src/Hosting/Server.IntegrationTesting/src/Deployers/SelfHostDeployer.cs +++ b/src/Hosting/Server.IntegrationTesting/src/Deployers/SelfHostDeployer.cs @@ -150,7 +150,7 @@ public override async Task DeployAsync() HostProcess.EnableRaisingEvents = true; HostProcess.OutputDataReceived += (sender, dataArgs) => { - if (string.Equals(dataArgs.Data, ApplicationStartedMessage)) + if (!string.IsNullOrEmpty(dataArgs.Data) && dataArgs.Data.Contains(ApplicationStartedMessage)) { started.TrySetResult(); } diff --git a/src/Servers/HttpSys/HttpSysServer.slnf b/src/Servers/HttpSys/HttpSysServer.slnf index 62fd45d3320f..3990e33925cb 100644 --- a/src/Servers/HttpSys/HttpSysServer.slnf +++ b/src/Servers/HttpSys/HttpSysServer.slnf @@ -31,7 +31,9 @@ "src\\Servers\\HttpSys\\samples\\TestClient\\TestClient.csproj", "src\\Servers\\HttpSys\\src\\Microsoft.AspNetCore.Server.HttpSys.csproj", "src\\Servers\\HttpSys\\test\\FunctionalTests\\Microsoft.AspNetCore.Server.HttpSys.FunctionalTests.csproj", + "src\\Servers\\HttpSys\\test\\NonHelixTests\\Microsoft.AspNetCore.Server.HttpSys.NonHelixTests.csproj", "src\\Servers\\HttpSys\\test\\Tests\\Microsoft.AspNetCore.Server.HttpSys.Tests.csproj", + "src\\Servers\\HttpSys\\test\\testassets\\DelegationSite\\DelegationSite.csproj", "src\\Servers\\IIS\\IISIntegration\\src\\Microsoft.AspNetCore.Server.IISIntegration.csproj", "src\\Servers\\IIS\\IIS\\src\\Microsoft.AspNetCore.Server.IIS.csproj", "src\\Servers\\Kestrel\\Core\\src\\Microsoft.AspNetCore.Server.Kestrel.Core.csproj", diff --git a/src/Servers/HttpSys/src/MessagePump.cs b/src/Servers/HttpSys/src/MessagePump.cs index fde21e41dcd0..2d4df374e534 100644 --- a/src/Servers/HttpSys/src/MessagePump.cs +++ b/src/Servers/HttpSys/src/MessagePump.cs @@ -55,7 +55,7 @@ public MessagePump(IOptions options, ILoggerFactory loggerFactor _serverAddresses = new ServerAddressesFeature(); Features.Set(_serverAddresses); - if (HttpApi.IsFeatureSupported(HttpApiTypes.HTTP_FEATURE_ID.HttpFeatureDelegateEx)) + if (HttpApi.SupportsDelegation) { var delegationProperty = new ServerDelegationPropertyFeature(Listener.RequestQueue, _logger); Features.Set(delegationProperty); diff --git a/src/Servers/HttpSys/src/Microsoft.AspNetCore.Server.HttpSys.csproj b/src/Servers/HttpSys/src/Microsoft.AspNetCore.Server.HttpSys.csproj index 5ef4637d0772..dff0c5861c71 100644 --- a/src/Servers/HttpSys/src/Microsoft.AspNetCore.Server.HttpSys.csproj +++ b/src/Servers/HttpSys/src/Microsoft.AspNetCore.Server.HttpSys.csproj @@ -28,4 +28,9 @@ + + + + + diff --git a/src/Servers/HttpSys/src/NativeInterop/HttpApi.cs b/src/Servers/HttpSys/src/NativeInterop/HttpApi.cs index 83d56d3cfc8a..d371721197cd 100644 --- a/src/Servers/HttpSys/src/NativeInterop/HttpApi.cs +++ b/src/Servers/HttpSys/src/NativeInterop/HttpApi.cs @@ -125,6 +125,7 @@ internal static HTTP_API_VERSION ApiVersion internal static bool SupportsTrailers { get; private set; } [MemberNotNullWhen(true, nameof(HttpSetRequestProperty))] internal static bool SupportsReset { get; private set; } + internal static bool SupportsDelegation { get; private set; } static HttpApi() { @@ -136,7 +137,7 @@ private static void InitHttpApi(ushort majorVersion, ushort minorVersion) version.HttpApiMajorVersion = majorVersion; version.HttpApiMinorVersion = minorVersion; - var statusCode = HttpInitialize(version, (uint)HTTP_FLAGS.HTTP_INITIALIZE_SERVER, null); + var statusCode = HttpInitialize(version, (uint)(HTTP_FLAGS.HTTP_INITIALIZE_SERVER | HTTP_FLAGS.HTTP_INITIALIZE_CONFIG), null); supported = statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS; @@ -144,10 +145,9 @@ private static void InitHttpApi(ushort majorVersion, ushort minorVersion) { HttpApiModule = SafeLibraryHandle.Open(HTTPAPI); HttpSetRequestProperty = HttpApiModule.GetProcAddress("HttpSetRequestProperty", throwIfNotFound: false); - SupportsReset = HttpSetRequestProperty != null; - // Trailers support was added in the same release as Reset, but there's no method we can export to check it directly. - SupportsTrailers = SupportsReset; + SupportsTrailers = IsFeatureSupported(HTTP_FEATURE_ID.HttpFeatureResponseTrailers); + SupportsDelegation = IsFeatureSupported(HTTP_FEATURE_ID.HttpFeatureDelegateEx); } } @@ -160,7 +160,7 @@ internal static bool Supported } } - internal static bool IsFeatureSupported(HTTP_FEATURE_ID feature) + private static bool IsFeatureSupported(HTTP_FEATURE_ID feature) { try { diff --git a/src/Servers/HttpSys/src/Properties/AssemblyInfo.cs b/src/Servers/HttpSys/src/Properties/AssemblyInfo.cs deleted file mode 100644 index c33e8da68ef0..000000000000 --- a/src/Servers/HttpSys/src/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,6 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.HttpSys.FunctionalTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] \ No newline at end of file diff --git a/src/Servers/HttpSys/src/StandardFeatureCollection.cs b/src/Servers/HttpSys/src/StandardFeatureCollection.cs index 9c79d2938a4c..c5eb1be5e577 100644 --- a/src/Servers/HttpSys/src/StandardFeatureCollection.cs +++ b/src/Servers/HttpSys/src/StandardFeatureCollection.cs @@ -48,7 +48,7 @@ static StandardFeatureCollection() _featureFuncLookup[typeof(ITlsHandshakeFeature)] = ctx => ctx.GetTlsHandshakeFeature(); } - if (HttpApi.IsFeatureSupported(HttpApiTypes.HTTP_FEATURE_ID.HttpFeatureDelegateEx)) + if (HttpApi.SupportsDelegation) { _featureFuncLookup[typeof(IHttpSysRequestDelegationFeature)] = _identityFunc; } diff --git a/src/Servers/HttpSys/test/FunctionalTests/DelegateSupportedConditionAttribute.cs b/src/Servers/HttpSys/test/FunctionalTests/DelegateSupportedConditionAttribute.cs index 2a0d65bc2138..625dea9a27a3 100644 --- a/src/Servers/HttpSys/test/FunctionalTests/DelegateSupportedConditionAttribute.cs +++ b/src/Servers/HttpSys/test/FunctionalTests/DelegateSupportedConditionAttribute.cs @@ -1,13 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Microsoft.AspNetCore.Testing; -using static Microsoft.AspNetCore.HttpSys.Internal.HttpApiTypes; namespace Microsoft.AspNetCore.Server.HttpSys.FunctionalTests { @@ -17,14 +11,8 @@ public class DelegateSupportedConditionAttribute : Attribute, ITestCondition private readonly bool _isSupported; public DelegateSupportedConditionAttribute(bool isSupported) => _isSupported = isSupported; - private readonly Lazy _isDelegateSupported = new Lazy(CanDelegate); - public bool IsMet => (_isDelegateSupported.Value == _isSupported); + public bool IsMet => HttpApi.SupportsDelegation == _isSupported; public string SkipReason => $"Http.Sys does {(_isSupported ? "not" : "")} support delegating requests"; - - private static bool CanDelegate() - { - return HttpApi.IsFeatureSupported(HTTP_FEATURE_ID.HttpFeatureDelegateEx); - } } } diff --git a/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs b/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs index e8db9c6e77a6..ca9dcf3a0736 100644 --- a/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs +++ b/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs @@ -148,6 +148,9 @@ public async Task DelegateAfterRequestBodyReadShouldThrow() [DelegateSupportedCondition(false)] public async Task DelegationFeaturesAreNull() { + // Testing the DelegateSupportedCondition + Assert.True(Environment.OSVersion.Version < new Version(10, 0, 22000), "This should be supported on Win 11."); + using var delegator = Utilities.CreateHttpServer(out var delegatorAddress, httpContext => { var delegateFeature = httpContext.Features.Get(); diff --git a/src/Servers/HttpSys/test/NonHelixTests/DelegateOutOfProcTests.cs b/src/Servers/HttpSys/test/NonHelixTests/DelegateOutOfProcTests.cs new file mode 100644 index 000000000000..16b229d1e2e3 --- /dev/null +++ b/src/Servers/HttpSys/test/NonHelixTests/DelegateOutOfProcTests.cs @@ -0,0 +1,70 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Net.Http; +using Microsoft.AspNetCore.Server.IntegrationTesting; +using Microsoft.AspNetCore.Testing; +using Xunit.Abstractions; + +namespace Microsoft.AspNetCore.Server.HttpSys.NonHelixTests +{ + public class DelegateOutOfProcTests : LoggedTest + { + public DelegateOutOfProcTests(ITestOutputHelper output) : base(output) { } + + [ConditionalFact] + [DelegateSupportedCondition(true)] + public async Task CanDelegateOutOfProcess() + { + using var _ = StartLog(out var loggerFactory); + + var logger = loggerFactory.CreateLogger("CanDelegateOutOfProcess"); + + // https://github.com/dotnet/aspnetcore/issues/8247 +#pragma warning disable 0618 + var applicationPath = Path.Combine(TestPathUtilities.GetSolutionRootDirectory("HttpSysServer"), "test", "testassets", + "DelegationSite"); +#pragma warning restore 0618 + + var deploymentParameters = new DeploymentParameters( + applicationPath, + ServerType.HttpSys, + RuntimeFlavor.CoreClr, + RuntimeArchitecture.x64) + { + EnvironmentName = "Testing", + TargetFramework = Tfm.Default, + ApplicationType = ApplicationType.Portable, + PublishApplicationBeforeDeployment = true, + StatusMessagesEnabled = true + }; + + var queueName = Guid.NewGuid().ToString(); + deploymentParameters.EnvironmentVariables["queue"] = queueName; + + using var deployer = new SelfHostDeployer(deploymentParameters, loggerFactory); + var deploymentResult = await deployer.DeployAsync().DefaultTimeout(); + + // Make sure the deployment really worked + var responseString = await deploymentResult.HttpClient.GetStringAsync("").DefaultTimeout(); + Assert.Equal("Hello from delegatee", responseString); + + DelegationRule destination = default; + using var delegator = Utilities.CreateHttpServer(out var delegatorAddress, httpContext => + { + var delegateFeature = httpContext.Features.Get(); + delegateFeature.DelegateRequest(destination); + return Task.CompletedTask; + }); + + var delegationProperty = delegator.Features.Get(); + using (destination = delegationProperty.CreateDelegationRule(queueName, deploymentResult.ApplicationBaseUri)) + { + // Send a request to the delegator that gets transfered to the delegatee in the other process. + using var client = new HttpClient(); + responseString = await client.GetStringAsync(delegatorAddress).DefaultTimeout(); + Assert.Equal("Hello from delegatee", responseString); + } + } + } +} diff --git a/src/Servers/HttpSys/test/NonHelixTests/DelegateSupportedConditionAttribute.cs b/src/Servers/HttpSys/test/NonHelixTests/DelegateSupportedConditionAttribute.cs new file mode 100644 index 000000000000..668c02485c41 --- /dev/null +++ b/src/Servers/HttpSys/test/NonHelixTests/DelegateSupportedConditionAttribute.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.AspNetCore.Testing; + +namespace Microsoft.AspNetCore.Server.HttpSys.NonHelixTests +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + public class DelegateSupportedConditionAttribute : Attribute, ITestCondition + { + private readonly bool _isSupported; + public DelegateSupportedConditionAttribute(bool isSupported) => _isSupported = isSupported; + + public bool IsMet => HttpApi.SupportsDelegation == _isSupported; + + public string SkipReason => $"Http.Sys does {(_isSupported ? "not" : "")} support delegating requests"; + } +} diff --git a/src/Servers/HttpSys/test/NonHelixTests/DummyApplication.cs b/src/Servers/HttpSys/test/NonHelixTests/DummyApplication.cs new file mode 100644 index 000000000000..55d6313ed5c0 --- /dev/null +++ b/src/Servers/HttpSys/test/NonHelixTests/DummyApplication.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.AspNetCore.Hosting.Server; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; + +namespace Microsoft.AspNetCore.Server.HttpSys +{ + internal class DummyApplication : IHttpApplication + { + private readonly RequestDelegate _requestDelegate; + + public DummyApplication() : this(context => Task.CompletedTask) { } + + public DummyApplication(RequestDelegate requestDelegate) + { + _requestDelegate = requestDelegate; + } + + public HttpContext CreateContext(IFeatureCollection contextFeatures) + { + return new DefaultHttpContext(contextFeatures); + } + + public void DisposeContext(HttpContext httpContext, Exception exception) + { + + } + + public async Task ProcessRequestAsync(HttpContext httpContext) + { + await _requestDelegate(httpContext); + } + } +} diff --git a/src/Servers/HttpSys/test/NonHelixTests/Microsoft.AspNetCore.Server.HttpSys.NonHelixTests.csproj b/src/Servers/HttpSys/test/NonHelixTests/Microsoft.AspNetCore.Server.HttpSys.NonHelixTests.csproj new file mode 100644 index 000000000000..58ca1a4d3baa --- /dev/null +++ b/src/Servers/HttpSys/test/NonHelixTests/Microsoft.AspNetCore.Server.HttpSys.NonHelixTests.csproj @@ -0,0 +1,30 @@ + + + + $(DefaultNetCoreTargetFramework) + HttpSys.NonHelixTests + true + + + + false + + + + + + + + + + + + 214124cd-d05b-4309-9af9-9caa44b2b74a + + + + + + + + diff --git a/src/Servers/HttpSys/test/NonHelixTests/Properties/AssemblyInfo.cs b/src/Servers/HttpSys/test/NonHelixTests/Properties/AssemblyInfo.cs new file mode 100644 index 000000000000..c590df52068d --- /dev/null +++ b/src/Servers/HttpSys/test/NonHelixTests/Properties/AssemblyInfo.cs @@ -0,0 +1,9 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.AspNetCore.Testing; +using Xunit; + +[assembly: OSSkipCondition(OperatingSystems.MacOSX)] +[assembly: OSSkipCondition(OperatingSystems.Linux)] +[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file diff --git a/src/Servers/HttpSys/test/NonHelixTests/Utilities.cs b/src/Servers/HttpSys/test/NonHelixTests/Utilities.cs new file mode 100644 index 000000000000..301547ac25bb --- /dev/null +++ b/src/Servers/HttpSys/test/NonHelixTests/Utilities.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Hosting.Server; +using Microsoft.AspNetCore.Hosting.Server.Features; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Microsoft.AspNetCore.Server.HttpSys +{ + internal static class Utilities + { + internal static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(15); + internal static readonly int WriteRetryLimit = 1000; + + // Minimum support for Windows 7 is assumed. + internal static readonly bool IsWin8orLater; + + static Utilities() + { + var win8Version = new Version(6, 2); + IsWin8orLater = (Environment.OSVersion.Version >= win8Version); + } + + internal static IServer CreateHttpServer(out string baseAddress, RequestDelegate app) + { + string root; + return CreateDynamicHttpServer(string.Empty, out root, out baseAddress, options => { }, app); + } + + internal static MessagePump CreatePump(ILoggerFactory loggerFactory = null) + => new MessagePump(Options.Create(new HttpSysOptions()), loggerFactory ?? new LoggerFactory(), new AuthenticationSchemeProvider(Options.Create(new AuthenticationOptions()))); + + internal static MessagePump CreatePump(Action configureOptions, ILoggerFactory loggerFactory = null) + { + var options = new HttpSysOptions(); + configureOptions(options); + return new MessagePump(Options.Create(options), loggerFactory ?? new LoggerFactory(), new AuthenticationSchemeProvider(Options.Create(new AuthenticationOptions()))); + } + + internal static IServer CreateDynamicHttpServer(string basePath, out string root, out string baseAddress, Action configureOptions, RequestDelegate app) + { + var prefix = UrlPrefix.Create("http", "localhost", "0", basePath); + + var server = CreatePump(configureOptions); + server.Features.Get().Addresses.Add(prefix.ToString()); + server.StartAsync(new DummyApplication(app), CancellationToken.None).Wait(); + + prefix = server.Listener.Options.UrlPrefixes.First(); // Has new port + root = prefix.Scheme + "://" + prefix.Host + ":" + prefix.Port; + baseAddress = prefix.ToString(); + + return server; + } + } +} diff --git a/src/Servers/HttpSys/test/testassets/DelegationSite/DelegationSite.csproj b/src/Servers/HttpSys/test/testassets/DelegationSite/DelegationSite.csproj new file mode 100644 index 000000000000..e125cecc1622 --- /dev/null +++ b/src/Servers/HttpSys/test/testassets/DelegationSite/DelegationSite.csproj @@ -0,0 +1,14 @@ + + + + $(DefaultNetCoreTargetFramework) + Exe + + + + + + + + + diff --git a/src/Servers/HttpSys/test/testassets/DelegationSite/Program.cs b/src/Servers/HttpSys/test/testassets/DelegationSite/Program.cs new file mode 100644 index 000000000000..cf029c3beafb --- /dev/null +++ b/src/Servers/HttpSys/test/testassets/DelegationSite/Program.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace DelegationSite; + +public static class Program +{ + public static void Main(string[] args) + { + var builder = Host.CreateDefaultBuilder(args) + .ConfigureWebHost(webHostBuilder => + { + webHostBuilder.UseHttpSys(options => + { + options.RequestQueueName = Environment.GetEnvironmentVariable("queue"); + }) + .Configure(app => + { + app.Run(context => + { + return context.Response.WriteAsync("Hello from delegatee"); + }); + }); + }); + + using var host = builder.Build(); + host.Run(); + } +} + diff --git a/src/Servers/HttpSys/test/testassets/DelegationSite/Properties/launchSettings.json b/src/Servers/HttpSys/test/testassets/DelegationSite/Properties/launchSettings.json new file mode 100644 index 000000000000..454cdfd0b4c5 --- /dev/null +++ b/src/Servers/HttpSys/test/testassets/DelegationSite/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "DelegationSite": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:5000" + } + } +} diff --git a/src/Servers/HttpSys/test/testassets/Directory.Build.props b/src/Servers/HttpSys/test/testassets/Directory.Build.props new file mode 100644 index 000000000000..b49282fb6f94 --- /dev/null +++ b/src/Servers/HttpSys/test/testassets/Directory.Build.props @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/Shared/HttpSys/NativeInterop/HttpApiTypes.cs b/src/Shared/HttpSys/NativeInterop/HttpApiTypes.cs index 60c8a2e11da0..2ecb2dac84cc 100644 --- a/src/Shared/HttpSys/NativeInterop/HttpApiTypes.cs +++ b/src/Shared/HttpSys/NativeInterop/HttpApiTypes.cs @@ -84,10 +84,10 @@ internal enum HTTP_DELEGATE_REQUEST_PROPERTY_ID : uint internal enum HTTP_FEATURE_ID { - HttpFeatureUnknown = 0, - HttpFeatureResponseTrailers = 1, - HttpFeatureApiTimings = 2, - HttpFeatureDelegateEx = 3, + HttpFeatureUnknown, + HttpFeatureResponseTrailers, + HttpFeatureApiTimings, + HttpFeatureDelegateEx, } [StructLayout(LayoutKind.Sequential, Pack = 4)] @@ -655,6 +655,7 @@ internal enum HTTP_FLAGS : uint HTTP_SEND_REQUEST_FLAG_MORE_DATA = 0x00000001, HTTP_PROPERTY_FLAG_PRESENT = 0x00000001, HTTP_INITIALIZE_SERVER = 0x00000001, + HTTP_INITIALIZE_CONFIG = 0x00000002, HTTP_INITIALIZE_CBT = 0x00000004, HTTP_SEND_RESPONSE_FLAG_OPAQUE = 0x00000040, HTTP_SEND_RESPONSE_FLAG_GOAWAY = 0x00000100,