diff --git a/AspNetCore.sln b/AspNetCore.sln index 813c654076b8..2cfc85e4fc35 100644 --- a/AspNetCore.sln +++ b/AspNetCore.sln @@ -1656,6 +1656,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.App.Co EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.App.Analyzers.Test", "src\Framework\AspNetCoreAnalyzers\test\Microsoft.AspNetCore.App.Analyzers.Test.csproj", "{B739B8B6-94F5-4F05-9497-28A7C6EBBC03}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.HttpSys.NonHelixTests", "src\Servers\HttpSys\test\NonHelixTests\Microsoft.AspNetCore.Server.HttpSys.NonHelixTests.csproj", "{37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DelegationSite", "src\Servers\HttpSys\test\testassets\DelegationSite\DelegationSite.csproj", "{14217994-9F24-4E14-87B6-58367ED0413B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -7907,6 +7911,30 @@ Global {B739B8B6-94F5-4F05-9497-28A7C6EBBC03}.Release|x64.Build.0 = Release|Any CPU {B739B8B6-94F5-4F05-9497-28A7C6EBBC03}.Release|x86.ActiveCfg = Release|Any CPU {B739B8B6-94F5-4F05-9497-28A7C6EBBC03}.Release|x86.Build.0 = Release|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Debug|x64.ActiveCfg = Debug|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Debug|x64.Build.0 = Debug|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Debug|x86.ActiveCfg = Debug|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Debug|x86.Build.0 = Debug|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Release|Any CPU.Build.0 = Release|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Release|x64.ActiveCfg = Release|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Release|x64.Build.0 = Release|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Release|x86.ActiveCfg = Release|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Release|x86.Build.0 = Release|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Debug|x64.ActiveCfg = Debug|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Debug|x64.Build.0 = Debug|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Debug|x86.ActiveCfg = Debug|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Debug|x86.Build.0 = Debug|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Release|Any CPU.Build.0 = Release|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Release|x64.ActiveCfg = Release|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Release|x64.Build.0 = Release|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Release|x86.ActiveCfg = Release|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -8727,6 +8755,8 @@ Global {636B73F6-9EED-435D-9DA8-EB3C7FDFAB1C} = {23C56C5B-9D3F-4069-88C4-87ACCFE05DBC} {78D9A5AF-6089-44F4-93AB-F7E96925E4FD} = {23C56C5B-9D3F-4069-88C4-87ACCFE05DBC} {B739B8B6-94F5-4F05-9497-28A7C6EBBC03} = {12541C41-58FB-46F4-BA0F-0D56B5B45A18} + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1} = {C3722C5D-E159-4AB3-AF60-769185B31B47} + {14217994-9F24-4E14-87B6-58367ED0413B} = {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,