-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Regex improvements #1348
base: develop
Are you sure you want to change the base?
Regex improvements #1348
Changes from all commits
6aa1d1a
05289ff
d35906a
f23420f
f17c7da
2760946
8d18bf3
4b9516c
bbe471c
040613a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,14 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text.RegularExpressions; | ||
using System.Threading.Tasks; | ||
|
||
using Ocelot.Errors; | ||
|
||
using Ocelot.Configuration.File; | ||
|
||
using FluentValidation; | ||
|
||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
using Ocelot.Responses; | ||
|
||
using Ocelot.ServiceDiscovery; | ||
using FluentValidation; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Ocelot.Configuration.File; | ||
using Ocelot.Errors; | ||
using Ocelot.Responses; | ||
using Ocelot.ServiceDiscovery; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text.RegularExpressions; | ||
using System.Threading.Tasks; | ||
|
||
namespace Ocelot.Configuration.Validator | ||
{ | ||
|
@@ -23,6 +17,9 @@ public class FileConfigurationFluentValidator : AbstractValidator<FileConfigurat | |
private const string Servicefabric = "servicefabric"; | ||
private readonly List<ServiceDiscoveryFinderDelegate> _serviceDiscoveryFinderDelegates; | ||
|
||
private static readonly Regex _regExPlaceholder = | ||
new Regex("{[^}]+}", RegexOptions.Compiled, TimeSpan.FromMilliseconds(100)); | ||
|
||
public FileConfigurationFluentValidator(IServiceProvider provider, RouteFluentValidator routeFluentValidator, FileGlobalConfigurationFluentValidator fileGlobalConfigurationFluentValidator) | ||
{ | ||
_serviceDiscoveryFinderDelegates = provider | ||
|
@@ -107,8 +104,7 @@ private static bool AllRoutesForAggregateExist(FileAggregateRoute fileAggregateR | |
|
||
private static bool IsPlaceholderNotDuplicatedIn(string upstreamPathTemplate) | ||
{ | ||
var regExPlaceholder = new Regex("{[^}]+}"); | ||
var matches = regExPlaceholder.Matches(upstreamPathTemplate); | ||
var matches = _regExPlaceholder.Matches(upstreamPathTemplate); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No catching and processing of the Will it result to unhandled exception by app domain? |
||
var upstreamPathPlaceholders = matches.Select(m => m.Value); | ||
return upstreamPathPlaceholders.Count() == upstreamPathPlaceholders.Distinct().Count(); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,21 @@ | ||
using System.Linq; | ||
using System.Text.RegularExpressions; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
using Ocelot.Configuration.File; | ||
|
||
using FluentValidation; | ||
|
||
using FluentValidation; | ||
using Microsoft.AspNetCore.Authentication; | ||
using Ocelot.Configuration.File; | ||
using System; | ||
using System.Linq; | ||
using System.Text.RegularExpressions; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace Ocelot.Configuration.Validator | ||
{ | ||
public class RouteFluentValidator : AbstractValidator<FileRoute> | ||
{ | ||
private readonly IAuthenticationSchemeProvider _authenticationSchemeProvider; | ||
private static readonly Regex _secondsRegEx = new Regex("^[0-9]+s", RegexOptions.Compiled, TimeSpan.FromMilliseconds(100)); | ||
private static readonly Regex _minutesRegEx = new Regex("^[0-9]+m", RegexOptions.Compiled, TimeSpan.FromMilliseconds(100)); | ||
private static readonly Regex _hoursRegEx = new Regex("^[0-9]+h", RegexOptions.Compiled, TimeSpan.FromMilliseconds(100)); | ||
private static readonly Regex _daysRegEx = new Regex("^[0-9]+d", RegexOptions.Compiled, TimeSpan.FromMilliseconds(100)); | ||
Comment on lines
+15
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hardcode has detected! |
||
|
||
public RouteFluentValidator(IAuthenticationSchemeProvider authenticationSchemeProvider, HostAndPortValidator hostAndPortValidator, FileQoSOptionsFluentValidator fileQoSOptionsFluentValidator) | ||
{ | ||
|
@@ -116,15 +118,10 @@ private static bool IsValidPeriod(FileRateLimitRule rateLimitOptions) | |
|
||
var period = rateLimitOptions.Period; | ||
|
||
var secondsRegEx = new Regex("^[0-9]+s"); | ||
var minutesRegEx = new Regex("^[0-9]+m"); | ||
var hoursRegEx = new Regex("^[0-9]+h"); | ||
var daysRegEx = new Regex("^[0-9]+d"); | ||
|
||
return secondsRegEx.Match(period).Success | ||
|| minutesRegEx.Match(period).Success | ||
|| hoursRegEx.Match(period).Success | ||
|| daysRegEx.Match(period).Success; | ||
return _secondsRegEx.Match(period).Success | ||
|| _minutesRegEx.Match(period).Success | ||
|| _hoursRegEx.Match(period).Success | ||
|| _daysRegEx.Match(period).Success; | ||
Comment on lines
+121
to
+124
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No catching and processing of the Will it result to unhandled exception by app domain? |
||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,25 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Text.RegularExpressions; | ||
|
||
using Ocelot.Configuration.File; | ||
|
||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.Configuration.Memory; | ||
|
||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.Configuration.Memory; | ||
using Newtonsoft.Json; | ||
using Ocelot.Configuration.File; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Text.RegularExpressions; | ||
|
||
namespace Ocelot.DependencyInjection | ||
{ | ||
public static class ConfigurationBuilderExtensions | ||
{ | ||
private static readonly Regex _reg = new Regex(@"^ocelot\.(.*?)\.json$", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled, TimeSpan.FromMilliseconds(100)); | ||
|
||
[Obsolete("Please set BaseUrl in ocelot.json GlobalConfiguration.BaseUrl")] | ||
public static IConfigurationBuilder AddOcelotBaseUrl(this IConfigurationBuilder builder, string baseUrl) | ||
{ | ||
Regex.CacheSize += 100; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the default, current value of the cache in runtime? |
||
|
||
var memorySource = new MemoryConfigurationSource | ||
{ | ||
InitialData = new List<KeyValuePair<string, string>> | ||
|
@@ -39,19 +40,17 @@ public static IConfigurationBuilder AddOcelot(this IConfigurationBuilder builder | |
|
||
public static IConfigurationBuilder AddOcelot(this IConfigurationBuilder builder, string folder, IWebHostEnvironment env) | ||
{ | ||
Regex.CacheSize += 100; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you consider the |
||
|
||
const string primaryConfigFile = "ocelot.json"; | ||
|
||
const string globalConfigFile = "ocelot.global.json"; | ||
|
||
const string subConfigPattern = @"^ocelot\.(.*?)\.json$"; | ||
|
||
var excludeConfigName = env?.EnvironmentName != null ? $"ocelot.{env.EnvironmentName}.json" : string.Empty; | ||
|
||
var reg = new Regex(subConfigPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline); | ||
|
||
var files = new DirectoryInfo(folder) | ||
.EnumerateFiles() | ||
.Where(fi => reg.IsMatch(fi.Name) && (fi.Name != excludeConfigName)) | ||
.Where(fi => _reg.IsMatch(fi.Name) && (fi.Name != excludeConfigName)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No catching and processing of the |
||
.ToArray(); | ||
|
||
var fileConfiguration = new FileConfiguration(); | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,37 +1,31 @@ | ||||||||||||||||||
using System; | ||||||||||||||||||
using System.Collections.Generic; | ||||||||||||||||||
using System.Text.RegularExpressions; | ||||||||||||||||||
using System.Threading.Tasks; | ||||||||||||||||||
|
||||||||||||||||||
using Ocelot.Configuration; | ||||||||||||||||||
|
||||||||||||||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher; | ||||||||||||||||||
|
||||||||||||||||||
using Ocelot.Logging; | ||||||||||||||||||
|
||||||||||||||||||
using Microsoft.AspNetCore.Http; | ||||||||||||||||||
|
||||||||||||||||||
using Ocelot.Middleware; | ||||||||||||||||||
using Ocelot.Request.Middleware; | ||||||||||||||||||
|
||||||||||||||||||
using Ocelot.Responses; | ||||||||||||||||||
|
||||||||||||||||||
using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer; | ||||||||||||||||||
|
||||||||||||||||||
using Microsoft.AspNetCore.Http; | ||||||||||||||||||
using Ocelot.Configuration; | ||||||||||||||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher; | ||||||||||||||||||
using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer; | ||||||||||||||||||
using Ocelot.Logging; | ||||||||||||||||||
using Ocelot.Middleware; | ||||||||||||||||||
using Ocelot.Request.Middleware; | ||||||||||||||||||
using Ocelot.Responses; | ||||||||||||||||||
using Ocelot.Values; | ||||||||||||||||||
using System; | ||||||||||||||||||
using System.Collections.Concurrent; | ||||||||||||||||||
using System.Collections.Generic; | ||||||||||||||||||
using System.Text.RegularExpressions; | ||||||||||||||||||
using System.Threading.Tasks; | ||||||||||||||||||
|
||||||||||||||||||
namespace Ocelot.DownstreamUrlCreator.Middleware | ||||||||||||||||||
{ | ||||||||||||||||||
{ | ||||||||||||||||||
public class DownstreamUrlCreatorMiddleware : OcelotMiddleware | ||||||||||||||||||
{ | ||||||||||||||||||
private readonly RequestDelegate _next; | ||||||||||||||||||
private readonly IDownstreamPathPlaceholderReplacer _replacer; | ||||||||||||||||||
private static ConcurrentDictionary<string, Regex> _regex = new ConcurrentDictionary<string, Regex>(); | ||||||||||||||||||
|
||||||||||||||||||
public DownstreamUrlCreatorMiddleware(RequestDelegate next, | ||||||||||||||||||
IOcelotLoggerFactory loggerFactory, | ||||||||||||||||||
IDownstreamPathPlaceholderReplacer replacer | ||||||||||||||||||
) | ||||||||||||||||||
: base(loggerFactory.CreateLogger<DownstreamUrlCreatorMiddleware>()) | ||||||||||||||||||
) | ||||||||||||||||||
: base(loggerFactory.CreateLogger<DownstreamUrlCreatorMiddleware>()) | ||||||||||||||||||
{ | ||||||||||||||||||
_next = next; | ||||||||||||||||||
_replacer = replacer; | ||||||||||||||||||
|
@@ -66,11 +60,12 @@ public async Task Invoke(HttpContext httpContext) | |||||||||||||||||
|
||||||||||||||||||
if (ServiceFabricRequest(internalConfiguration, downstreamRoute)) | ||||||||||||||||||
{ | ||||||||||||||||||
var pathAndQuery = CreateServiceFabricUri(downstreamRequest, downstreamRoute, templatePlaceholderNameAndValues, response); | ||||||||||||||||||
var pathAndQuery = CreateServiceFabricUri(downstreamRequest, downstreamRoute, | ||||||||||||||||||
templatePlaceholderNameAndValues, response); | ||||||||||||||||||
|
||||||||||||||||||
//todo check this works again hope there is a test.. | ||||||||||||||||||
downstreamRequest.AbsolutePath = pathAndQuery.Path; | ||||||||||||||||||
downstreamRequest.Query = pathAndQuery.Query; | ||||||||||||||||||
downstreamRequest.AbsolutePath = pathAndQuery.Path; | ||||||||||||||||||
downstreamRequest.Query = pathAndQuery.Query; | ||||||||||||||||||
Comment on lines
+63
to
+68
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Zero changes! |
||||||||||||||||||
} | ||||||||||||||||||
else | ||||||||||||||||||
{ | ||||||||||||||||||
|
@@ -91,7 +86,8 @@ public async Task Invoke(HttpContext httpContext) | |||||||||||||||||
} | ||||||||||||||||||
else | ||||||||||||||||||
{ | ||||||||||||||||||
RemoveQueryStringParametersThatHaveBeenUsedInTemplate(downstreamRequest, templatePlaceholderNameAndValues); | ||||||||||||||||||
RemoveQueryStringParametersThatHaveBeenUsedInTemplate(downstreamRequest, | ||||||||||||||||||
templatePlaceholderNameAndValues); | ||||||||||||||||||
Comment on lines
+89
to
+90
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Revert this! |
||||||||||||||||||
|
||||||||||||||||||
downstreamRequest.AbsolutePath = dsPath.Value; | ||||||||||||||||||
} | ||||||||||||||||||
|
@@ -102,20 +98,25 @@ public async Task Invoke(HttpContext httpContext) | |||||||||||||||||
await _next.Invoke(httpContext); | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
private static void RemoveQueryStringParametersThatHaveBeenUsedInTemplate(DownstreamRequest downstreamRequest, List<PlaceholderNameAndValue> templatePlaceholderNameAndValues) | ||||||||||||||||||
private static void RemoveQueryStringParametersThatHaveBeenUsedInTemplate( | ||||||||||||||||||
DownstreamRequest downstreamRequest, List<PlaceholderNameAndValue> templatePlaceholderNameAndValues) | ||||||||||||||||||
Comment on lines
+101
to
+102
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why was that changed? 😉 |
||||||||||||||||||
{ | ||||||||||||||||||
foreach (var nAndV in templatePlaceholderNameAndValues) | ||||||||||||||||||
{ | ||||||||||||||||||
var name = nAndV.Name.Replace("{", string.Empty).Replace("}", string.Empty); | ||||||||||||||||||
var name = nAndV.Name.Replace("{", string.Empty).Replace("}", string.Empty); | ||||||||||||||||||
|
||||||||||||||||||
if (downstreamRequest.Query.Contains(name) && | ||||||||||||||||||
downstreamRequest.Query.Contains(nAndV.Value)) | ||||||||||||||||||
{ | ||||||||||||||||||
var questionMarkOrAmpersand = downstreamRequest.Query.IndexOf(name, StringComparison.Ordinal); | ||||||||||||||||||
downstreamRequest.Query = downstreamRequest.Query.Remove(questionMarkOrAmpersand - 1, 1); | ||||||||||||||||||
|
||||||||||||||||||
var rgx = new Regex($@"\b{name}={nAndV.Value}\b"); | ||||||||||||||||||
downstreamRequest.Query = rgx.Replace(downstreamRequest.Query, string.Empty); | ||||||||||||||||||
var pattern = $@"\b{name}={nAndV.Value}\b"; | ||||||||||||||||||
var regex = _regex.AddOrUpdate(pattern, | ||||||||||||||||||
new Regex(pattern, RegexOptions.Compiled, TimeSpan.FromMilliseconds(100)), | ||||||||||||||||||
(key, oldValue) => oldValue); | ||||||||||||||||||
Comment on lines
+115
to
+117
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No catching and processing of the |
||||||||||||||||||
|
||||||||||||||||||
downstreamRequest.Query = regex.Replace(downstreamRequest.Query, string.Empty); | ||||||||||||||||||
|
||||||||||||||||||
if (!string.IsNullOrEmpty(downstreamRequest.Query)) | ||||||||||||||||||
{ | ||||||||||||||||||
|
@@ -125,22 +126,24 @@ private static void RemoveQueryStringParametersThatHaveBeenUsedInTemplate(Downst | |||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
private static string GetPath(DownstreamPath dsPath) | ||||||||||||||||||
private static string GetPath(DownstreamPath dsPath) | ||||||||||||||||||
{ | ||||||||||||||||||
return dsPath.Value.Substring(0, dsPath.Value.IndexOf('?', StringComparison.Ordinal)); | ||||||||||||||||||
return dsPath.Value.Substring(0, dsPath.Value.IndexOf('?', StringComparison.Ordinal)); | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
private static string GetQueryString(DownstreamPath dsPath) | ||||||||||||||||||
private static string GetQueryString(DownstreamPath dsPath) | ||||||||||||||||||
{ | ||||||||||||||||||
return dsPath.Value.Substring(dsPath.Value.IndexOf('?', StringComparison.Ordinal)); | ||||||||||||||||||
return dsPath.Value.Substring(dsPath.Value.IndexOf('?', StringComparison.Ordinal)); | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
private static bool ContainsQueryString(DownstreamPath dsPath) | ||||||||||||||||||
private static bool ContainsQueryString(DownstreamPath dsPath) | ||||||||||||||||||
{ | ||||||||||||||||||
return dsPath.Value.Contains('?'); | ||||||||||||||||||
return dsPath.Value.Contains('?'); | ||||||||||||||||||
} | ||||||||||||||||||
Comment on lines
+129
to
142
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Still wonder... |
||||||||||||||||||
|
||||||||||||||||||
private (string Path, string Query) CreateServiceFabricUri(DownstreamRequest downstreamRequest, DownstreamRoute downstreamRoute, List<PlaceholderNameAndValue> templatePlaceholderNameAndValues, Response<DownstreamPath> dsPath) | ||||||||||||||||||
private (string Path, string Query) CreateServiceFabricUri(DownstreamRequest downstreamRequest, | ||||||||||||||||||
DownstreamRoute downstreamRoute, List<PlaceholderNameAndValue> templatePlaceholderNameAndValues, | ||||||||||||||||||
Response<DownstreamPath> dsPath) | ||||||||||||||||||
Comment on lines
+144
to
+146
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see zero changes in the method signature!
Suggested change
|
||||||||||||||||||
{ | ||||||||||||||||||
var query = downstreamRequest.Query; | ||||||||||||||||||
var serviceName = _replacer.Replace(downstreamRoute.ServiceName, templatePlaceholderNameAndValues); | ||||||||||||||||||
|
@@ -150,7 +153,8 @@ private static bool ContainsQueryString(DownstreamPath dsPath) | |||||||||||||||||
|
||||||||||||||||||
private static bool ServiceFabricRequest(IInternalConfiguration config, DownstreamRoute downstreamRoute) | ||||||||||||||||||
{ | ||||||||||||||||||
return config.ServiceProviderConfiguration.Type?.ToLower() == "servicefabric" && downstreamRoute.UseServiceDiscovery; | ||||||||||||||||||
return config.ServiceProviderConfiguration.Type?.ToLower() == "servicefabric" && | ||||||||||||||||||
downstreamRoute.UseServiceDiscovery; | ||||||||||||||||||
Comment on lines
+156
to
+157
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Zero changes! |
||||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No catching and processing of the
RegexMatchTimeoutException
exception.Will it result to unhandled exception by app domain?
Will it be caught by upper context?