1
1
// Licensed to the .NET Foundation under one or more agreements.
2
2
// The .NET Foundation licenses this file to you under the MIT license.
3
3
4
+ using System . Diagnostics ;
4
5
using System . Diagnostics . CodeAnalysis ;
5
6
using System . Globalization ;
6
7
using System . Text . RegularExpressions ;
@@ -15,7 +16,7 @@ namespace Microsoft.AspNetCore.Routing.Constraints;
15
16
public class RegexRouteConstraint : IRouteConstraint , IParameterLiteralNodeMatchingPolicy
16
17
{
17
18
private static readonly TimeSpan RegexMatchTimeout = TimeSpan . FromSeconds ( 10 ) ;
18
- private readonly string _regexPattern ;
19
+ private readonly Func < Regex > ? _regexFactory ;
19
20
private Regex ? _constraint ;
20
21
21
22
/// <summary>
@@ -27,20 +28,24 @@ public RegexRouteConstraint(Regex regex)
27
28
ArgumentNullException . ThrowIfNull ( regex ) ;
28
29
29
30
_constraint = regex ;
30
- _regexPattern = regex . ToString ( ) ;
31
31
}
32
32
33
33
/// <summary>
34
34
/// Constructor for a <see cref="RegexRouteConstraint"/> given a <paramref name="regexPattern"/>.
35
35
/// </summary>
36
36
/// <param name="regexPattern">A string containing the regex pattern.</param>
37
37
public RegexRouteConstraint (
38
- [ StringSyntax ( StringSyntaxAttribute . Regex , RegexOptions . CultureInvariant | RegexOptions . IgnoreCase ) ]
38
+ [ StringSyntax ( StringSyntaxAttribute . Regex , RegexOptions . CultureInvariant | RegexOptions . Compiled | RegexOptions . IgnoreCase ) ]
39
39
string regexPattern )
40
40
{
41
41
ArgumentNullException . ThrowIfNull ( regexPattern ) ;
42
42
43
- _regexPattern = regexPattern ;
43
+ // Create regex instance lazily to avoid compiling regexes at app startup. Delay creation until Constraint is first evaluated.
44
+ // The regex instance is created by a delegate here to allow the regex engine to be trimmed when this constructor is trimmed.
45
+ _regexFactory = ( ) => new Regex (
46
+ regexPattern ,
47
+ RegexOptions . CultureInvariant | RegexOptions . Compiled | RegexOptions . IgnoreCase ,
48
+ RegexMatchTimeout ) ;
44
49
}
45
50
46
51
/// <summary>
@@ -50,12 +55,13 @@ public Regex Constraint
50
55
{
51
56
get
52
57
{
53
- // Create regex instance lazily to avoid compiling regexes at app startup. Delay creation until constraint is first evaluated.
54
- // This is not thread safe. No side effect but multiple instances of a regex instance could be created from a burst of requests.
55
- _constraint ??= new Regex (
56
- _regexPattern ,
57
- RegexOptions . CultureInvariant | RegexOptions . Compiled | RegexOptions . IgnoreCase ,
58
- RegexMatchTimeout ) ;
58
+ if ( _constraint is null )
59
+ {
60
+ Debug . Assert ( _regexFactory is not null ) ;
61
+
62
+ // This is not thread-safe. No side effect, but multiple instances of a regex instance could be created from a burst of requests.
63
+ _constraint = _regexFactory ( ) ;
64
+ }
59
65
60
66
return _constraint ;
61
67
}
0 commit comments