Skip to content

Commit 9dc120c

Browse files
authored
Move HttpApplication middleware into UseSystemWebAdapters (#407)
This was initially moved into the startup filter to be added early on in the request pipeline because it was thought it was needed there for output caching. However, that does not seem to be the case (test has been added for that). So, now it can be moved into the standard `UseSystemWebAdapters()` so that it will be only added on requests that needed it (i.e. if the pipeline has been branched and `UseSystemWebAdapters()` is not added).
1 parent 9bec0c7 commit 9dc120c

File tree

3 files changed

+129
-6
lines changed

3 files changed

+129
-6
lines changed

src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/HttpApplication/HttpApplicationExtensions.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,18 @@ public static ISystemWebAdapterBuilder AddHttpApplication(this ISystemWebAdapter
4242
return builder;
4343
}
4444

45+
public static ISystemWebAdapterBuilder AddHttpApplication<TApp>(this ISystemWebAdapterBuilder builder)
46+
{
47+
ArgumentNullException.ThrowIfNull(builder);
48+
49+
builder.AddHttpApplication(options =>
50+
{
51+
options.ApplicationType = typeof(TApp);
52+
});
53+
54+
return builder;
55+
}
56+
4557
public static ISystemWebAdapterBuilder AddHttpApplication<TApp>(this ISystemWebAdapterBuilder builder, Action<HttpApplicationOptions> configure)
4658
where TApp : HttpApplication
4759
{

src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/SystemWebAdaptersExtensions.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,21 @@ internal static void UseSystemWebAdapterFeatures(this IApplicationBuilder app)
6262
return;
6363
}
6464

65+
if (app.AreHttpApplicationEventsRequired())
66+
{
67+
app.UseMiddleware<HttpApplicationMiddleware>();
68+
}
69+
6570
app.UseMiddleware<PreBufferRequestStreamMiddleware>();
6671
app.UseMiddleware<BufferResponseStreamMiddleware>();
6772
app.UseMiddleware<SetDefaultResponseHeadersMiddleware>();
6873
app.UseMiddleware<SingleThreadedRequestMiddleware>();
6974
app.UseMiddleware<CurrentPrincipalMiddleware>();
75+
76+
if (app.AreHttpApplicationEventsRequired())
77+
{
78+
app.UseHttpApplicationEvent(ApplicationEvent.BeginRequest);
79+
}
7080
}
7181

7282
public static void UseSystemWebAdapters(this IApplicationBuilder app)
@@ -136,12 +146,6 @@ public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
136146
builder.UseMiddleware<SetHttpContextTimestampMiddleware>();
137147
builder.UseMiddleware<RegisterAdapterFeaturesMiddleware>();
138148

139-
if (builder.AreHttpApplicationEventsRequired())
140-
{
141-
builder.UseMiddleware<HttpApplicationMiddleware>();
142-
builder.UseHttpApplicationEvent(ApplicationEvent.BeginRequest);
143-
}
144-
145149
next(builder);
146150
};
147151
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
#if NET7_0_OR_GREATER
5+
6+
using System;
7+
using System.Configuration;
8+
using System.Net.Http;
9+
using System.Threading.Tasks;
10+
using System.Web;
11+
using Microsoft.AspNetCore.Builder;
12+
using Microsoft.AspNetCore.Hosting;
13+
using Microsoft.AspNetCore.Http;
14+
using Microsoft.AspNetCore.Http.HttpResults;
15+
using Microsoft.AspNetCore.OutputCaching;
16+
using Microsoft.AspNetCore.TestHost;
17+
using Microsoft.Extensions.DependencyInjection;
18+
using Microsoft.Extensions.Hosting;
19+
using Xunit;
20+
21+
namespace Microsoft.AspNetCore.SystemWebAdapters.CoreServices.Tests;
22+
23+
[Collection(nameof(SelfHostedTests))]
24+
public class OutputCachingTests
25+
{
26+
[Fact]
27+
public async Task OutputCachingWorksWithHttpApplication()
28+
{
29+
// Arrange
30+
using var host = await new HostBuilder()
31+
.ConfigureWebHost(webBuilder =>
32+
{
33+
webBuilder
34+
.UseTestServer(options =>
35+
{
36+
options.AllowSynchronousIO = true;
37+
})
38+
.ConfigureServices(services =>
39+
{
40+
services.AddRouting();
41+
services.AddSystemWebAdapters()
42+
.AddHttpApplication<MyApp>();
43+
services.AddOutputCache();
44+
})
45+
.Configure(app =>
46+
{
47+
app.UseRouting();
48+
app.UseSystemWebAdapters();
49+
app.UseOutputCache();
50+
app.UseEndpoints(endpoints =>
51+
{
52+
var count = 0;
53+
endpoints.Map("/", () => Results.Ok(count++))
54+
.CacheOutput(builder =>
55+
{
56+
builder.AddHttpApplicationVaryByCustom(MyApp.VaryBy);
57+
});
58+
});
59+
});
60+
})
61+
.StartAsync();
62+
63+
using var client = host.GetTestClient();
64+
65+
// Act
66+
var result1 = await GetResponseAsync(client, "test");
67+
var result2 = await GetResponseAsync(client, "other");
68+
var result3 = await GetResponseAsync(client, "test");
69+
70+
// Assert
71+
Assert.Equal("0", result1);
72+
Assert.Equal("1", result2);
73+
Assert.Equal("0", result3);
74+
75+
static async Task<string> GetResponseAsync(HttpClient client, string value)
76+
{
77+
using var message = new HttpRequestMessage(HttpMethod.Get, new Uri("/", UriKind.Relative))
78+
{
79+
Headers =
80+
{
81+
{ MyApp.Header, value }
82+
}
83+
};
84+
85+
using var response = await client.SendAsync(message);
86+
87+
return await response.Content.ReadAsStringAsync();
88+
}
89+
}
90+
91+
private sealed class MyApp : HttpApplication
92+
{
93+
public const string VaryBy = "myValue";
94+
public const string Header = "X-TEST-HEADER";
95+
96+
public override string? GetVaryByCustomString(HttpContext context, string custom)
97+
{
98+
if (custom == VaryBy)
99+
{
100+
return context.Request.Headers[Header];
101+
}
102+
103+
return base.GetVaryByCustomString(context, custom);
104+
}
105+
}
106+
}
107+
#endif

0 commit comments

Comments
 (0)