question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Resolve routing RegEx constraint dependency size issue

See original GitHub issue

Routing has a feature named “Route Constraints”. One of the options to make a constraint is to add a regular expression to the route, for example: app.MapGet("/posts/{id:regex(^[a-z0-9]+$)}", …). Because these route constraints are inline in the route string, the Regex code needs to always be in the application, in case any of the routes happen to use a regex constraint.

In .NET 7, we added a new feature to Regex: NonBacktracking. This added a considerable amount of code. Depending on the Regex constructor overload used (the one that takes RegexOptions, which ASP.NET Routing uses), this new feature’s code will be left in the app, even if the NonBacktracking engine isn’t being used.

ASP.NET Routing uses the CultureInvariant and IgnoreCase options when constructing Regex route constraints.

Testing locally, being able to remove the NonBacktracking engine can cut about .8 MB of the 1.0 MB of Regex code out of the app size.

UPDATE 11/30/2022

With the latest NativeAOT compiler changes, here are updated numbers for linux-x64 NativeAOT:

Hello World 3.22 MB (3,381,112 bytes)
new Regex(“”).IsMatch 3.50 MB (3,680,200 bytes)
new Regex(“”, RegexOptions).IsMatch 4.33 MB (4,545,960 bytes)

UPDATE 1/18/2023

With the latest NativeAOT compiler changes, here are updated numbers for linux-x64 NativeAOT:

Hello World 2.79 MB (2,925,616 bytes)
new Regex(“”).IsMatch 3.04 MB (3,193,344 bytes)
new Regex(“”, RegexOptions).IsMatch 3.82 MB (4,008,288 bytes)

Options

  1. Add new Regex construction APIs that allow for some RegexOptions to be used, but also allows for the NonBacktracking engine to be trimmed. For example: Regex.CreateCompiled(pattern, RegexOptions). This API would throw an exception if RegexOptions.NonBacktracking was passed.
  2. Remove the use of RegexOptions. The IgnoreCase option can be specified as part of the pattern as a Pattern Modifier: (?i). However, CultureInvariant cannot be specified this way.
    • One option is to drop support for CultureInvariant from regex route constraints. This affects the Turkish ‘i’ handling.
    • Another option could be to add a CultureInvariant Pattern Modifier to .NET Regex, so this could be specified without using RegexOptions.
  3. When using the new “slim” hosting API (See https://github.com/dotnet/aspnetcore/issues/32485), we could remove the Regex route constraints feature by default and have an API that adds it back. Apps using the inline regex route constraints and the slim hosting API, would call this new API to opt-in to the feature.
  4. Add a feature to the linker/NativeAOT compiler that can see which RegexOptions values are used in the app. And for the enum values that aren’t used, it can trim the code branches behind those values (i.e. the NonBacktracking code). This would accrue more size savings elsewhere as well.

Issue Analytics

  • State:closed
  • Created 8 months ago
  • Comments:57 (57 by maintainers)

github_iconTop GitHub Comments

1reaction
eerhardtcommented, Feb 22, 2023

The Regex engine still isn’t being trimmed with the latest code. This is due to the refactoring that was done in #46323.

The reason is because the new Regex code has been moved out of the constructor, and instead is lazily instantiated in the Constraint property: https://github.com/dotnet/aspnetcore/blob/86e3a4bc2d85794b6470539ddd29b9d3e194f546/src/Http/Routing/src/Constraints/RegexRouteConstraint.cs#L49-L62

And that property can’t be trimmed because it is used in the Match and MatchesLiteral methods. And the whole class can’t be trimmed because it is still used by AlphaRouteConstraint.

1reaction
eerhardtcommented, Feb 17, 2023

@mitchdenny - unfortunately https://github.com/dotnet/aspnetcore/pull/46227 didn’t fully address this size issue. RegexRouteConstraint still gets pulled into this app with this path:

image

See this code:

https://github.com/dotnet/aspnetcore/blob/bb3f0d626627d399695a9fa0741e4803c0c23eb8/src/Http/Routing/src/Patterns/RoutePatternFactory.cs#L938-L955

Read more comments on GitHub >

github_iconTop Results From Across the Web

The constraint reference 'string' could not be resolved to a ...
This was documented in the Microsoft documentation. It could be a blank space between the param name and the type.
Read more >
Routing in ASP.NET Core
This has the nice effect that route matching time is dependent only on the length of the path to match and not the...
Read more >
How to use attribute routing in ASP.NET Core
Use attribute route constraints in an action method. Route constraints are used to thwart invalid requests to controller actions. For example, ...
Read more >
Resolve template validation or template format errors in ...
For "Unresolved resource dependencies [XXXXXXXX] in the Resources block of the template" errors, see the Validate logical IDs and parameters section.
Read more >
Learn ASP.NET Core Route Constraint in details with lots ...
ASP.NET Core Routing Constraints restricts route matching to a set of URLs. This is done by applying different types of constraints or rules ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found