Skip to content

Commit

Permalink
Enable forwarded headers middleware when publishing projects by default
Browse files Browse the repository at this point in the history
Fixes #290
  • Loading branch information
DamianEdwards committed Mar 9, 2024
1 parent a2a7c31 commit 0e7eade
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;

namespace Aspire.Hosting.ApplicationModel;

[DebuggerDisplay("Type = {GetType().Name,nq}")]
internal sealed class DisableForwardedHeadersAnnotation : IResourceAnnotation
{

}
28 changes: 26 additions & 2 deletions src/Aspire.Hosting/Extensions/ProjectResourceBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ namespace Aspire.Hosting;
/// </summary>
public static class ProjectResourceBuilderExtensions
{
private const string AspNetCoreForwaredHeadersEnabledVariableName = "ASPNETCORE_FORWARDEDHEADERS_ENABLED";

/// <summary>
/// Adds a .NET project to the application model. By default, this will exist in a Projects namespace. e.g. Projects.MyProject.
/// If the project is not in a Projects namespace, make sure a project reference is added from the AppHost project to the target project.
Expand Down Expand Up @@ -92,6 +94,19 @@ private static IResourceBuilder<ProjectResource> WithProjectDefaults(this IResou
builder.WithOtlpExporter();
builder.ConfigureConsoleLogs();

var projectResource = builder.Resource;

if (builder.ApplicationBuilder.ExecutionContext.IsPublishMode)
{
builder.WithEnvironment(context =>
{
if (!projectResource.Annotations.OfType<DisableForwardedHeadersAnnotation>().Any())
{
context.EnvironmentVariables[AspNetCoreForwaredHeadersEnabledVariableName] = "true";
}
});
}

if (excludeLaunchProfile)
{
builder.WithAnnotation(new ExcludeLaunchProfileAnnotation());
Expand All @@ -103,8 +118,6 @@ private static IResourceBuilder<ProjectResource> WithProjectDefaults(this IResou
builder.WithAnnotation(new LaunchProfileAnnotation(launchProfileName));
}

var projectResource = builder.Resource;

if (builder.ApplicationBuilder.ExecutionContext.IsRunMode)
{
// Automatically add EndpointAnnotation to project resources based on ApplicationUrl set in the launch profile.
Expand Down Expand Up @@ -208,6 +221,17 @@ public static IResourceBuilder<ProjectResource> ExcludeLaunchProfile(this IResou
throw new InvalidOperationException("This API is replaced by the AddProject overload that accepts a launchProfileName. Null means exclude launch profile. Method will be removed by GA.");
}

/// <summary>
/// Configures the project to disable forwarded headers when being published.
/// </summary>
/// <param name="builder">The project resource builder.</param>
/// <returns>A reference to the <see cref="IResourceBuilder{T}"/>.</returns>
public static IResourceBuilder<ProjectResource> DisableForwadedHeadersOnPublish(this IResourceBuilder<ProjectResource> builder)
{
builder.WithAnnotation<DisableForwardedHeadersAnnotation>(ResourceAnnotationMutationBehavior.Replace);
return builder;
}

private static bool IsKestrelHttp2ConfigurationPresent(ProjectResource projectResource)
{
var projectMetadata = projectResource.GetProjectMetadata();
Expand Down
44 changes: 44 additions & 0 deletions tests/Aspire.Hosting.Tests/ManifestGenerationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,50 @@ public void ExcludeLaunchProfileOmitsBindings()
"Service has no bindings because they weren't populated from the launch profile.");
}

[Fact]
public void ProjectResourceEmitsForwardedHeadersEnvironmentVariableByDefault()
{
var appBuilder = DistributedApplication.CreateBuilder(new DistributedApplicationOptions
{ Args = GetManifestArgs(), DisableDashboard = true, AssemblyName = typeof(ManifestGenerationTests).Assembly.FullName });

appBuilder.AddProject<Projects.ServiceA>("servicea", launchProfileName: null);

appBuilder.Services.AddKeyedSingleton<IDistributedApplicationPublisher, JsonDocumentManifestPublisher>("manifest");

var program = appBuilder.Build();
var publisher = program.Services.GetManifestPublisher();

program.Run();

var resources = publisher.ManifestDocument.RootElement.GetProperty("resources");

Assert.Equal("true",
resources.GetProperty("servicea").GetProperty("env").GetProperty("ASPNETCORE_FORWARDEDHEADERS_ENABLED").GetString());
}

[Fact]
public void DisableForwardedHeadersOmitsEnvironmentVariable()
{
var appBuilder = DistributedApplication.CreateBuilder(new DistributedApplicationOptions
{ Args = GetManifestArgs(), DisableDashboard = true, AssemblyName = typeof(ManifestGenerationTests).Assembly.FullName });

appBuilder.AddProject<Projects.ServiceA>("servicea", launchProfileName: null)
.DisableForwadedHeadersOnPublish();

appBuilder.Services.AddKeyedSingleton<IDistributedApplicationPublisher, JsonDocumentManifestPublisher>("manifest");

var program = appBuilder.Build();
var publisher = program.Services.GetManifestPublisher();

program.Run();

var resources = publisher.ManifestDocument.RootElement.GetProperty("resources");

Assert.False(
resources.GetProperty("servicea").GetProperty("env").TryGetProperty("ASPNETCORE_FORWARDEDHEADERS_ENABLED", out _),
"Service has no ASPNETCORE_FORWARDEDHEADERS_ENABLED environment variable because it was disabled.");
}

[Fact]
public void EnsureContainerWithEndpointsEmitsContainerPort()
{
Expand Down
3 changes: 2 additions & 1 deletion tests/Aspire.Hosting.Tests/ProjectResourceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ public async Task VerifyManifest()
"path": "net8.0/another-path",
"env": {
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true",
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true"
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true",
"ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true"
},
"bindings": {
"http": {
Expand Down

0 comments on commit 0e7eade

Please sign in to comment.