Skip to content

Commit 38a7c59

Browse files
pranavkmdougbuJamesNK
authored
Annotate Microsoft.AspNetCore.Routing for trimming (#40974)
Co-authored-by: Doug Bunting <[email protected]> Co-authored-by: James Newton-King <[email protected]>
1 parent 4880fee commit 38a7c59

21 files changed

+760
-55
lines changed

eng/TrimmableProjects.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<TrimmableProject Include="Microsoft.AspNetCore.Http" />
2020
<TrimmableProject Include="Microsoft.AspNetCore.Metadata" />
2121
<TrimmableProject Include="Microsoft.AspNetCore.Routing.Abstractions" />
22+
<TrimmableProject Include="Microsoft.AspNetCore.Routing" />
2223
<TrimmableProject Include="Microsoft.AspNetCore.WebUtilities" />
2324
<TrimmableProject Include="Microsoft.AspNetCore.Connections.Abstractions" />
2425
<TrimmableProject Include="Microsoft.AspNetCore.Server.HttpSys" />

src/Http/Http/src/Microsoft.AspNetCore.Http.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
<GenerateDocumentationFile>true</GenerateDocumentationFile>
99
<PackageTags>aspnetcore</PackageTags>
1010
<IsPackable>false</IsPackable>
11-
<Nullable>enable</Nullable>
1211
<IsTrimmable>true</IsTrimmable>
1312
</PropertyGroup>
1413

src/Http/Routing/src/Builder/EndpointRouteBuilderExtensions.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Diagnostics.CodeAnalysis;
45
using System.Linq;
56
using System.Reflection;
67
using System.Runtime.CompilerServices;
@@ -18,6 +19,8 @@ namespace Microsoft.AspNetCore.Builder;
1819
/// </summary>
1920
public static class EndpointRouteBuilderExtensions
2021
{
22+
internal const string MapEndpointTrimmerWarning = "This API may perform reflection on the supplied delegate and its parameters. These types may be trimmed if not directly referenced.";
23+
2124
// Avoid creating a new array every call
2225
private static readonly string[] GetVerb = new[] { HttpMethods.Get };
2326
private static readonly string[] PostVerb = new[] { HttpMethods.Post };
@@ -33,6 +36,7 @@ public static class EndpointRouteBuilderExtensions
3336
/// <param name="pattern">The route pattern.</param>
3437
/// <param name="requestDelegate">The delegate executed when the endpoint is matched.</param>
3538
/// <returns>A <see cref="IEndpointConventionBuilder"/> that can be used to further customize the endpoint.</returns>
39+
[RequiresUnreferencedCode(EndpointRouteBuilderExtensions.MapEndpointTrimmerWarning)]
3640
public static IEndpointConventionBuilder MapGet(
3741
this IEndpointRouteBuilder endpoints,
3842
string pattern,
@@ -220,6 +224,7 @@ public static IEndpointConventionBuilder Map(
220224
/// <param name="pattern">The route pattern.</param>
221225
/// <param name="handler">The delegate executed when the endpoint is matched.</param>
222226
/// <returns>A <see cref="RouteHandlerBuilder"/> that can be used to further customize the endpoint.</returns>
227+
[RequiresUnreferencedCode(MapEndpointTrimmerWarning)]
223228
public static RouteHandlerBuilder MapGet(
224229
this IEndpointRouteBuilder endpoints,
225230
string pattern,
@@ -236,6 +241,7 @@ public static RouteHandlerBuilder MapGet(
236241
/// <param name="pattern">The route pattern.</param>
237242
/// <param name="handler">The delegate executed when the endpoint is matched.</param>
238243
/// <returns>A <see cref="RouteHandlerBuilder"/> that can be used to further customize the endpoint.</returns>
244+
[RequiresUnreferencedCode(MapEndpointTrimmerWarning)]
239245
public static RouteHandlerBuilder MapPost(
240246
this IEndpointRouteBuilder endpoints,
241247
string pattern,
@@ -252,6 +258,7 @@ public static RouteHandlerBuilder MapPost(
252258
/// <param name="pattern">The route pattern.</param>
253259
/// <param name="handler">The delegate executed when the endpoint is matched.</param>
254260
/// <returns>A <see cref="RouteHandlerBuilder"/> that can be used to further customize the endpoint.</returns>
261+
[RequiresUnreferencedCode(MapEndpointTrimmerWarning)]
255262
public static RouteHandlerBuilder MapPut(
256263
this IEndpointRouteBuilder endpoints,
257264
string pattern,
@@ -268,6 +275,7 @@ public static RouteHandlerBuilder MapPut(
268275
/// <param name="pattern">The route pattern.</param>
269276
/// <param name="handler">The delegate executed when the endpoint is matched.</param>
270277
/// <returns>A <see cref="RouteHandlerBuilder"/> that can be used to further customize the endpoint.</returns>
278+
[RequiresUnreferencedCode(MapEndpointTrimmerWarning)]
271279
public static RouteHandlerBuilder MapDelete(
272280
this IEndpointRouteBuilder endpoints,
273281
string pattern,
@@ -284,6 +292,7 @@ public static RouteHandlerBuilder MapDelete(
284292
/// <param name="pattern">The route pattern.</param>
285293
/// <param name="handler">The <see cref="Delegate" /> executed when the endpoint is matched.</param>
286294
/// <returns>A <see cref="RouteHandlerBuilder"/> that can be used to further customize the endpoint.</returns>
295+
[RequiresUnreferencedCode(MapEndpointTrimmerWarning)]
287296
public static RouteHandlerBuilder MapPatch(
288297
this IEndpointRouteBuilder endpoints,
289298
string pattern,
@@ -301,6 +310,7 @@ public static RouteHandlerBuilder MapPatch(
301310
/// <param name="handler">The delegate executed when the endpoint is matched.</param>
302311
/// <param name="httpMethods">HTTP methods that the endpoint will match.</param>
303312
/// <returns>A <see cref="RouteHandlerBuilder"/> that can be used to further customize the endpoint.</returns>
313+
[RequiresUnreferencedCode(MapEndpointTrimmerWarning)]
304314
public static RouteHandlerBuilder MapMethods(
305315
this IEndpointRouteBuilder endpoints,
306316
string pattern,
@@ -348,6 +358,7 @@ static bool ShouldDisableInferredBody(string method)
348358
/// <param name="pattern">The route pattern.</param>
349359
/// <param name="handler">The delegate executed when the endpoint is matched.</param>
350360
/// <returns>A <see cref="RouteHandlerBuilder"/> that can be used to further customize the endpoint.</returns>
361+
[RequiresUnreferencedCode(MapEndpointTrimmerWarning)]
351362
public static RouteHandlerBuilder Map(
352363
this IEndpointRouteBuilder endpoints,
353364
string pattern,
@@ -364,6 +375,7 @@ public static RouteHandlerBuilder Map(
364375
/// <param name="pattern">The route pattern.</param>
365376
/// <param name="handler">The delegate executed when the endpoint is matched.</param>
366377
/// <returns>A <see cref="RouteHandlerBuilder"/> that can be used to further customize the endpoint.</returns>
378+
[RequiresUnreferencedCode(MapEndpointTrimmerWarning)]
367379
public static RouteHandlerBuilder Map(
368380
this IEndpointRouteBuilder endpoints,
369381
RoutePattern pattern,
@@ -391,6 +403,7 @@ public static RouteHandlerBuilder Map(
391403
/// <c>{*path:nonfile}</c>. The order of the registered endpoint will be <c>int.MaxValue</c>.
392404
/// </para>
393405
/// </remarks>
406+
[RequiresUnreferencedCode(MapEndpointTrimmerWarning)]
394407
public static RouteHandlerBuilder MapFallback(this IEndpointRouteBuilder endpoints, Delegate handler)
395408
{
396409
if (endpoints == null)
@@ -427,6 +440,7 @@ public static RouteHandlerBuilder MapFallback(this IEndpointRouteBuilder endpoin
427440
/// to exclude requests for static files.
428441
/// </para>
429442
/// </remarks>
443+
[RequiresUnreferencedCode(MapEndpointTrimmerWarning)]
430444
public static RouteHandlerBuilder MapFallback(
431445
this IEndpointRouteBuilder endpoints,
432446
string pattern,
@@ -453,6 +467,7 @@ public static RouteHandlerBuilder MapFallback(
453467
return conventionBuilder;
454468
}
455469

470+
[RequiresUnreferencedCode(MapEndpointTrimmerWarning)]
456471
private static RouteHandlerBuilder Map(
457472
this IEndpointRouteBuilder endpoints,
458473
RoutePattern pattern,
@@ -515,7 +530,11 @@ private static RouteHandlerBuilder Map(
515530
}
516531

517532
var routeHandlerBuilder = new RouteHandlerBuilder(dataSource.AddEndpointBuilder(builder));
518-
routeHandlerBuilder.Add(endpointBuilder =>
533+
routeHandlerBuilder.Add(RouteHandlerBuilderConvention);
534+
535+
[UnconditionalSuppressMessage("Trimmer", "IL2026", Justification = "We surface a RequireUnreferencedCode in the call to enclosing Map method. " +
536+
"The trimmer is unable to infer this on the nested lambda.")]
537+
void RouteHandlerBuilderConvention(EndpointBuilder endpointBuilder)
519538
{
520539
var options = new RequestDelegateFactoryOptions
521540
{
@@ -545,7 +564,7 @@ private static RouteHandlerBuilder Map(
545564
}
546565
}
547566
endpointBuilder.RequestDelegate = filteredRequestDelegateResult.RequestDelegate;
548-
});
567+
}
549568

550569
return routeHandlerBuilder;
551570
}

src/Http/Routing/src/DefaultInlineConstraintResolver.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public DefaultInlineConstraintResolver(IOptions<RouteOptions> routeOptions, ISer
3434
throw new ArgumentNullException(nameof(serviceProvider));
3535
}
3636

37-
_inlineConstraintMap = routeOptions.Value.ConstraintMap;
37+
_inlineConstraintMap = routeOptions.Value.TrimmerSafeConstraintMap;
3838
_serviceProvider = serviceProvider;
3939
}
4040

src/Http/Routing/src/DefaultParameterPolicyFactory.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,17 @@ public override IParameterPolicy Create(RoutePatternParameterPart? parameter, st
4343
}
4444

4545
var parameterPolicy = ParameterPolicyActivator.ResolveParameterPolicy<IParameterPolicy>(
46-
_options.ConstraintMap,
46+
_options.TrimmerSafeConstraintMap,
4747
_serviceProvider,
4848
inlineText,
4949
out var parameterPolicyKey);
5050

5151
if (parameterPolicy == null)
5252
{
5353
throw new InvalidOperationException(Resources.FormatRoutePattern_ConstraintReferenceNotFound(
54-
parameterPolicyKey,
55-
typeof(RouteOptions),
56-
nameof(RouteOptions.ConstraintMap)));
54+
parameterPolicyKey,
55+
typeof(RouteOptions),
56+
nameof(RouteOptions.ConstraintMap)));
5757
}
5858

5959
if (parameterPolicy is IRouteConstraint constraint)

src/Http/Routing/src/EndpointRoutingMiddleware.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Diagnostics;
5+
using System.Diagnostics.CodeAnalysis;
56
using System.Runtime.CompilerServices;
67
using Microsoft.AspNetCore.Http;
78
using Microsoft.AspNetCore.Routing.Matching;
@@ -96,14 +97,21 @@ private Task SetRoutingAndContinue(HttpContext httpContext)
9697
// Raise an event if the route matched
9798
if (_diagnosticListener.IsEnabled() && _diagnosticListener.IsEnabled(DiagnosticsEndpointMatchedKey))
9899
{
99-
// We're just going to send the HttpContext since it has all of the relevant information
100-
_diagnosticListener.Write(DiagnosticsEndpointMatchedKey, httpContext);
100+
Write(_diagnosticListener, httpContext);
101101
}
102102

103103
Log.MatchSuccess(_logger, endpoint);
104104
}
105105

106106
return _next(httpContext);
107+
108+
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern",
109+
Justification = "The values being passed into Write are being consumed by the application already.")]
110+
static void Write(DiagnosticListener diagnosticListener, HttpContext httpContext)
111+
{
112+
// We're just going to send the HttpContext since it has all of the relevant information
113+
diagnosticListener.Write(DiagnosticsEndpointMatchedKey, httpContext);
114+
}
107115
}
108116

109117
// Initialization is async to avoid blocking threads while reflection and things

0 commit comments

Comments
 (0)