From 4f8b8b3415e09223555d09d7467e80062eff494e Mon Sep 17 00:00:00 2001 From: Nuklon Date: Thu, 16 Feb 2023 23:09:26 +0100 Subject: [PATCH] Fixes #13732 - IsBackOfficeRequest is extremely inefficient (#13743) * Update UmbracoRequestPaths.cs * Update UmbracoRequestPaths.cs * remove redundant check --------- Co-authored-by: Michael (cherry picked from commit de27eb697ee5554258793edbba4404c4725a898e) # Conflicts: # src/Umbraco.Core/Routing/UmbracoRequestPaths.cs --- .../Routing/UmbracoRequestPaths.cs | 76 +++++++++++-------- 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/src/Umbraco.Core/Routing/UmbracoRequestPaths.cs b/src/Umbraco.Core/Routing/UmbracoRequestPaths.cs index fe1e83d254..ac1328daaa 100644 --- a/src/Umbraco.Core/Routing/UmbracoRequestPaths.cs +++ b/src/Umbraco.Core/Routing/UmbracoRequestPaths.cs @@ -14,9 +14,9 @@ public class UmbracoRequestPaths private readonly string _appPath; private readonly string _backOfficeMvcPath; private readonly string _backOfficePath; - private readonly List _defaultUmbPaths; + private readonly string _defaultUmbPath; + private readonly string _defaultUmbPathWithSlash; private readonly string _installPath; - private readonly string _mvcArea; private readonly string _previewMvcPath; private readonly string _surfaceMvcPath; @@ -25,18 +25,19 @@ public class UmbracoRequestPaths /// public UmbracoRequestPaths(IOptions globalSettings, IHostingEnvironment hostingEnvironment) { - var applicationPath = hostingEnvironment.ApplicationVirtualPath; - _appPath = applicationPath.TrimStart(Constants.CharArrays.ForwardSlash); + _appPath = hostingEnvironment.ApplicationVirtualPath; _backOfficePath = globalSettings.Value.GetBackOfficePath(hostingEnvironment) - .EnsureStartsWith('/').TrimStart(_appPath.EnsureStartsWith('/')).EnsureStartsWith('/'); + .EnsureStartsWith('/').TrimStart(_appPath).EnsureStartsWith('/'); - _mvcArea = globalSettings.Value.GetUmbracoMvcArea(hostingEnvironment); - _defaultUmbPaths = new List { "/" + _mvcArea, "/" + _mvcArea + "/" }; - _backOfficeMvcPath = "/" + _mvcArea + "/BackOffice/"; - _previewMvcPath = "/" + _mvcArea + "/Preview/"; - _surfaceMvcPath = "/" + _mvcArea + "/Surface/"; - _apiMvcPath = "/" + _mvcArea + "/Api/"; + string mvcArea = globalSettings.Value.GetUmbracoMvcArea(hostingEnvironment); + + _defaultUmbPath = "/" + mvcArea; + _defaultUmbPathWithSlash = "/" + mvcArea + "/"; + _backOfficeMvcPath = "/" + mvcArea + "/BackOffice/"; + _previewMvcPath = "/" + mvcArea + "/Preview/"; + _surfaceMvcPath = "/" + mvcArea + "/Surface/"; + _apiMvcPath = "/" + mvcArea + "/Api/"; _installPath = hostingEnvironment.ToAbsolute(Constants.SystemDirectories.Install); } @@ -67,50 +68,65 @@ public class UmbracoRequestPaths /// public bool IsBackOfficeRequest(string absPath) { - var fullUrlPath = absPath.TrimStart(Constants.CharArrays.ForwardSlash); - var urlPath = fullUrlPath.TrimStart(_appPath).EnsureStartsWith('/'); + string urlPath = absPath.TrimStart(_appPath).EnsureStartsWith('/'); // check if this is in the umbraco back office - var isUmbracoPath = urlPath.InvariantStartsWith(_backOfficePath); - - // if not, then def not back office - if (isUmbracoPath == false) + if (!urlPath.InvariantStartsWith(_backOfficePath)) { return false; } // if its the normal /umbraco path - if (_defaultUmbPaths.Any(x => urlPath.InvariantEquals(x))) + if (urlPath.InvariantEquals(_defaultUmbPath) || urlPath.InvariantEquals(_defaultUmbPathWithSlash)) { return true; } // check for special back office paths - if (urlPath.InvariantStartsWith(_backOfficeMvcPath) - || urlPath.InvariantStartsWith(_previewMvcPath)) + if (urlPath.InvariantStartsWith(_backOfficeMvcPath) || urlPath.InvariantStartsWith(_previewMvcPath)) { return true; } // check for special front-end paths - if (urlPath.InvariantStartsWith(_surfaceMvcPath) - || urlPath.InvariantStartsWith(_apiMvcPath)) + if (urlPath.InvariantStartsWith(_surfaceMvcPath) || urlPath.InvariantStartsWith(_apiMvcPath)) { return false; } - // if its none of the above, we will have to try to detect if it's a PluginController route, we can detect this by - // checking how many parts the route has, for example, all PluginController routes will be routed like + // if its none of the above, we will have to try to detect if it's a PluginController route + return !IsPluginControllerRoute(urlPath); + } + + /// + /// Checks if the path is from a PluginController route. + /// + private static bool IsPluginControllerRoute(string path) + { + // Detect this by checking how many parts the route has, for example, all PluginController routes will be routed like // Umbraco/MYPLUGINAREA/MYCONTROLLERNAME/{action}/{id} - // so if the path contains at a minimum 3 parts: Umbraco + MYPLUGINAREA + MYCONTROLLERNAME then we will have to assume it is a - // plugin controller for the front-end. - if (urlPath.Split(Constants.CharArrays.ForwardSlash, StringSplitOptions.RemoveEmptyEntries).Length >= 3) + // so if the path contains at a minimum 3 parts: Umbraco + MYPLUGINAREA + MYCONTROLLERNAME then we will have to assume it is a plugin controller for the front-end. + + int count = 0; + + for (int i = 0; i < path.Length; i++) { - return false; + char chr = path[i]; + + if (chr == '/') + { + count++; + continue; + } + + // Check last char so we can properly determine the number of parts, e.g. /url/path/ has two parts, /url/path/test has three. + if (count == 3) + { + return true; + } } - // if its anything else we can assume it's back office - return true; + return false; } ///