Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,15 @@
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.

using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Steeltoe.Management.Endpoint.Actuators.CloudFoundry;

namespace Steeltoe.Management.Endpoint;

internal sealed class ConfigureActuatorsMiddlewareStartupFilter : IStartupFilter
{
private readonly ILogger<ConfigureActuatorsMiddlewareStartupFilter> _logger;

public ConfigureActuatorsMiddlewareStartupFilter(ILogger<ConfigureActuatorsMiddlewareStartupFilter> logger)
{
ArgumentNullException.ThrowIfNull(logger);

_logger = logger;
}

public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
{
ArgumentNullException.ThrowIfNull(next);
Expand All @@ -45,30 +33,9 @@ public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
app.UseCloudFoundrySecurity();
}

int? beforeMiddlewareCount = GetMiddlewareCount(app);
next.Invoke(app);
int? afterMiddlewareCount = GetMiddlewareCount(app);

if (beforeMiddlewareCount != afterMiddlewareCount)
{
_logger.LogWarning(
"Actuators were registered with automatic middleware setup, and at least one additional middleware was registered afterward. This combination is usually undesired. " +
"To remove this warning, either remove the additional middleware registration or set configureMiddleware to false when registering actuators.");
}

app.UseActuatorEndpoints();
};
}

private static int? GetMiddlewareCount(IApplicationBuilder app)
{
FieldInfo? componentsField = app.GetType().GetField("_components", BindingFlags.NonPublic | BindingFlags.Instance);
return componentsField?.GetValue(app) is List<Func<RequestDelegate, RequestDelegate>> components ? components.Count(IsMiddleware) : null;
}

private static bool IsMiddleware(Func<RequestDelegate, RequestDelegate> component)
{
// This type exists so that ASP.NET Core can identify where to inject UseRouting. It is not a real middleware.
return component.Target == null || component.Target.ToString() != "Microsoft.AspNetCore.Builder.WebApplicationBuilder+WireSourcePipeline";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors.Infrastructure;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Steeltoe.Common.TestResources;
using Steeltoe.Management.Endpoint.Actuators.All;
Expand Down Expand Up @@ -134,24 +132,4 @@ public async Task Does_not_register_duplicate_services(HostBuilderType hostBuild
host.Services.GetServices<InfoEndpointMiddleware>().Should().ContainSingle();
host.Services.GetServices<IEndpointMiddleware>().OfType<InfoEndpointMiddleware>().Should().ContainSingle();
}

[Fact]
public async Task Logs_warning_when_custom_middleware_is_registered_without_configureMiddleware_false()
{
using var capturingLoggerProvider = new CapturingLoggerProvider((_, logLevel) => logLevel >= LogLevel.Warning);

WebApplicationBuilder builder = TestWebApplicationBuilderFactory.Create();
builder.Logging.AddProvider(capturingLoggerProvider);
builder.Services.AddAllActuators();
await using WebApplication host = builder.Build();

host.UseRouting();
host.UseActuatorEndpoints();

await host.StartAsync(TestContext.Current.CancellationToken);

capturingLoggerProvider.GetAll().Should().Contain($"WARN {typeof(ConfigureActuatorsMiddlewareStartupFilter)}: " +
"Actuators were registered with automatic middleware setup, and at least one additional middleware was registered afterward. This combination is usually undesired. " +
"To remove this warning, either remove the additional middleware registration or set configureMiddleware to false when registering actuators.");
}
}