Search code examples
c#asp.net-mvcasp.net-core.net-coreddos

How to set match timeout of regex in route attribute of asp.net core


MSDN recommends setting a time-out value in all regular expression pattern-matching operations.
How we can set match timeout in route attribute of asp.net core projects

[Route("[controller]/[action]/{test:regex(^(\\w+$)}")]
public string Get(string test)
{
    //...
}

Solution

  • You could refer to the following sample to create a custom route constraint, then, set the Timeout.

    Public class MyCustomConstraint : IRouteConstraint
    {
        private Regex _regex;
    
        public MyCustomConstraint()
        {
            _regex = new Regex(@"^[1-9]*$",
                                RegexOptions.CultureInvariant | RegexOptions.IgnoreCase,
                                TimeSpan.FromMilliseconds(100));
        }
        public bool Match(HttpContext httpContext, IRouter route, string routeKey,
                          RouteValueDictionary values, RouteDirection routeDirection)
        {
            if (values.TryGetValue(routeKey, out object value))
            {
                var parameterValueString = Convert.ToString(value,
                                                            CultureInfo.InvariantCulture);
                if (parameterValueString == null)
                {
                    return false;
                }
    
                return _regex.IsMatch(parameterValueString);
            }
    
            return false;
        }
    }
    

    Then, register the above constraint in the Startup.ConfigureServices method:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    
        services.AddRouting(options =>
        {
            options.ConstraintMap.Add("customName", typeof(MyCustomConstraint));
        });
    }
    

    Then, apply the constrain in the action method, like this:

    // GET /api/test/my/3
    [HttpGet("my/{id:customName}")]
    public IActionResult Get(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
    

    The debug screenshot like this:

    enter image description here

    Besides, you can also set the timeout value for all Regex matching operations in an application domain by calling the AppDomain.SetData method, code in the Program.cs file:

        public static void Main(string[] args)
        {
            AppDomain domain = AppDomain.CurrentDomain;
            // Set a timeout interval of 200 milliseconds.
            domain.SetData("REGEX_DEFAULT_MATCH_TIMEOUT", TimeSpan.FromMilliseconds(200));
    
            CreateHostBuilder(args).Build().Run();
        }
    

    Then, there is no need to set the timeout in the custom route constraint, check this screenshot:

    enter image description here