internal static IReadOnlyCollection <BasicUrlHandler> ResolveUrl(string baseUrlString, string appRelativeUrl)
        {
            var handlers = new List <BasicUrlHandler>();

            var urlComponents  = parseAppRelativeUrl(appRelativeUrl);
            var pathComponents = parsePath(urlComponents.path);

            var baseUrlComponents = BaseUrl.GetComponents(baseUrlString);
            var baseUrl           = new DecodingBaseUrl(
                baseUrlComponents.secure,
                baseUrlComponents.host,
                baseUrlComponents.port,
                baseUrlComponents.path,
                new DecodingUrlParameterCollection(
                    parseSegmentParameters(pathComponents.baseUrlParameters),
                    pathComponents.segments.Any() ? Enumerable.Empty <(string, string)>() : parseQuery(urlComponents.query)));
            UrlDecoder decoder = null;

            foreach (var i in EwfApp.Instance.GetBaseUrlPatterns())
            {
                decoder = i.Parser(baseUrl);
                if (decoder != null)
                {
                    break;
                }
                baseUrl.Parameters.ResetState();
            }
            if (decoder == null)
            {
                return(null);
            }
            var basicHandler = decoder.GetUrlHandler(baseUrl.Parameters);

            handlers.Add(basicHandler);

            for (var segmentIndex = 0; segmentIndex < pathComponents.segments.Count; segmentIndex += 1)
            {
                if (!(basicHandler is UrlHandler handler))
                {
                    return(null);
                }

                var segmentComponents = parseSegment(pathComponents.segments[segmentIndex]);
                if (segmentComponents.segment.Length == 0)
                {
                    return(null);
                }
                var segment = new DecodingUrlSegment(
                    segmentComponents.segment,
                    new DecodingUrlParameterCollection(
                        parseSegmentParameters(segmentComponents.parameters),
                        segmentIndex < pathComponents.segments.Count - 1 ? Enumerable.Empty <(string, string)>() : parseQuery(urlComponents.query)));
                decoder = null;
                foreach (var i in handler.GetChildPatterns())
                {
                    decoder = i.Parser(segment);
                    if (decoder != null)
                    {
                        break;
                    }
                    segment.Parameters.ResetState();
                }
                if (decoder == null)
                {
                    return(null);
                }
                basicHandler = decoder.GetUrlHandler(segment.Parameters);
                handlers.Add(basicHandler);
            }

            if (basicHandler is UrlHandler lastHandler)
            {
                handlers.AddRange(lastHandler.GetRequestHandlingDescendants());
            }

            return(handlers);
        }