diff --git a/src/Servers/HttpSys/src/DelegationRule.cs b/src/Servers/HttpSys/src/DelegationRule.cs
index e33997338c..70b85c7c22 100644
--- a/src/Servers/HttpSys/src/DelegationRule.cs
+++ b/src/Servers/HttpSys/src/DelegationRule.cs
@@ -13,6 +13,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys
public class DelegationRule : IDisposable
{
private readonly ILogger _logger;
+ private readonly UrlGroup _sourceQueueUrlGroup;
+ private bool _disposed;
///
/// The name of the Http.Sys request queue
///
@@ -23,8 +25,9 @@ namespace Microsoft.AspNetCore.Server.HttpSys
public string UrlPrefix { get; }
internal RequestQueue Queue { get; }
- internal DelegationRule(string queueName, string urlPrefix, ILogger logger)
+ internal DelegationRule(UrlGroup sourceQueueUrlGroup, string queueName, string urlPrefix, ILogger logger)
{
+ _sourceQueueUrlGroup = sourceQueueUrlGroup;
_logger = logger;
QueueName = queueName;
UrlPrefix = urlPrefix;
@@ -34,8 +37,20 @@ namespace Microsoft.AspNetCore.Server.HttpSys
///
public void Dispose()
{
- Queue.UrlGroup?.Dispose();
- Queue?.Dispose();
+ if (_disposed)
+ {
+ return;
+ }
+
+ _disposed = true;
+
+ try
+ {
+ _sourceQueueUrlGroup.UnSetDelegationProperty(Queue, throwOnError: false);
+ }
+ catch (ObjectDisposedException) { /* Server may have been shutdown */ }
+ Queue.UrlGroup.Dispose();
+ Queue.Dispose();
}
}
}
diff --git a/src/Servers/HttpSys/src/NativeInterop/UrlGroup.cs b/src/Servers/HttpSys/src/NativeInterop/UrlGroup.cs
index ea6c657813..d93d236477 100644
--- a/src/Servers/HttpSys/src/NativeInterop/UrlGroup.cs
+++ b/src/Servers/HttpSys/src/NativeInterop/UrlGroup.cs
@@ -83,6 +83,15 @@ namespace Microsoft.AspNetCore.Server.HttpSys
SetProperty(HttpApiTypes.HTTP_SERVER_PROPERTY.HttpServerDelegationProperty, new IntPtr(&propertyInfo), (uint)RequestPropertyInfoSize);
}
+ internal unsafe void UnSetDelegationProperty(RequestQueue destination, bool throwOnError = true)
+ {
+ var propertyInfo = new HttpApiTypes.HTTP_BINDING_INFO();
+ propertyInfo.Flags = HttpApiTypes.HTTP_FLAGS.NONE;
+ propertyInfo.RequestQueueHandle = destination.Handle.DangerousGetHandle();
+
+ SetProperty(HttpApiTypes.HTTP_SERVER_PROPERTY.HttpServerDelegationProperty, new IntPtr(&propertyInfo), (uint)RequestPropertyInfoSize, throwOnError);
+ }
+
internal void SetProperty(HttpApiTypes.HTTP_SERVER_PROPERTY property, IntPtr info, uint infosize, bool throwOnError = true)
{
Debug.Assert(info != IntPtr.Zero, "SetUrlGroupProperty called with invalid pointer");
diff --git a/src/Servers/HttpSys/src/ServerDelegationPropertyFeature.cs b/src/Servers/HttpSys/src/ServerDelegationPropertyFeature.cs
index d9066a3dd5..07041f08d2 100644
--- a/src/Servers/HttpSys/src/ServerDelegationPropertyFeature.cs
+++ b/src/Servers/HttpSys/src/ServerDelegationPropertyFeature.cs
@@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
public DelegationRule CreateDelegationRule(string queueName, string uri)
{
- var rule = new DelegationRule(queueName, uri, _logger);
+ var rule = new DelegationRule(_queue.UrlGroup, queueName, uri, _logger);
_queue.UrlGroup.SetDelegationProperty(rule.Queue);
return rule;
}
diff --git a/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs b/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs
index f94f0bf0be..de896ed679 100644
--- a/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs
+++ b/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs
@@ -161,6 +161,38 @@ namespace Microsoft.AspNetCore.Server.HttpSys.FunctionalTests
_ = await SendRequestAsync(delegatorAddress);
}
+ [ConditionalFact]
+ [DelegateSupportedCondition(true)]
+ public async Task UpdateDelegationRuleTest()
+ {
+ var queueName = Guid.NewGuid().ToString();
+ using var receiver = Utilities.CreateHttpServer(out var receiverAddress, async httpContext =>
+ {
+ await httpContext.Response.WriteAsync(_expectedResponseString);
+ },
+ options =>
+ {
+ options.RequestQueueName = queueName;
+ });
+
+ 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();
+ destination = delegationProperty.CreateDelegationRule(queueName, receiverAddress);
+ destination?.Dispose();
+ destination = delegationProperty.CreateDelegationRule(queueName, receiverAddress);
+ var responseString = await SendRequestAsync(delegatorAddress);
+ Assert.Equal(_expectedResponseString, responseString);
+ destination?.Dispose();
+ }
+
private async Task SendRequestAsync(string uri)
{
using var client = new HttpClient();