/*
Break apart a url into the path matching regular expression and the
optional method prefix.
760178
function splitURL(url) {
    var method, path, match = /^([A-Z]+)(?:\s+|$)/.exec(url);
    if (match) {
        method = match[1];
        path = /^[A-Z]+\s+(.*)$/.exec(url);
        url = path ? path[1]: '';
    }
    return {url: url, method: method};
}
46022
def urlsplit(url):
    
    proto, rest = url.split(':', 1)
    host = ''
    if rest[:2] == '//':
        host, rest = rest[2:].split('/', 1)
        rest = '/' + rest
    return proto, host, rest
8402
function resolveURL(url, path) {
  if (typeof url !== 'string' || typeof path !== 'string') {
    return new Error('url-and-path-required');
  }

  /* Remove leading and duplicate slashes */
  url = url.replace(/\/{2,}/g, '/').replace(/^\//, '').replace(':/','://');

  let parsedUrl = urlModule.parse(url);
  if (protocols.indexOf(parsedUrl.protocol) < 0 || !parsedUrl.host) {
    return new Error('invalid-url');
  }

  let resolvedUrl = urlModule.resolve(parsedUrl.href, path);
  return resolvedUrl;
}
390474
function parse(uri) {
  var result = { baseUri: '', fragment: '#' };

  if (uri.slice(0, 4).toLowerCase() === 'urn:') {
    result.kind = 'urn';
    var parts = uri.match(URN_REGEX);
    if (parts) {
        result.baseUri = parts[1] + (parts[2] || '');
      result.host = parts[1];
      if (parts[2]) { result.pathname = parts[2]; }
      if (parts[3]) { result.fragment = parts[3]; }
    }
  } else {
    result.kind = 'url';
    var parsed = url.parse(uri);
    if (parsed.hash) {
      result.fragment = parsed.hash;
      delete parsed.hash;
    }
    result.absolute =
      (parsed.host && parsed.pathname && parsed.pathname[0] === '/') ?
      true : false;
    result.baseUri = url.format(parsed);
  }

  return result;
}
222859
function normalizePath(urlPath) {
  if (!urlPath) {
    return '';
  // make sure path starts with a /
  } else if (_.head(urlPath) !== '/') {
    urlPath = '/' + urlPath;
  }
  // make sure path does not end with a /
  return _.trimEnd(urlPath, '/');
}
509854
function normalizeSeparators (p) {
  p = p || "";

  if (path.sep === "\\") {
    // Replace backslashes with forward slashes
    return p.replace(/\\/g, "/");
  }
  else {
    // Return the path as-is, since it should already have proper URL separators.
    // If it DOES contain backslashes, then they are treated as normal characters,
    // NOT as separators
    return p;
  }
}
240892
function stringToRegexp(str, keys, options = {}) {
  let tokens = parse(str, options);
  let end = options.end !== false;
  let strict = options.strict;
  let delimiter = options.delimiter ? escapeString(options.delimiter) : '\\/';
  let delimiters = options.delimiters || './';
  let endsWith = [].concat(options.endsWith || []).map(escapeString).concat('$').join('|');
  let isEndDelimited = false;
  let route = '';

  // Iterate over the tokens and create our regexp string.
  for (let i = 0; i < tokens.length; i++) {
    let token = tokens[i];

    if (typeof token === 'string') {
      route += escapeString(token);
      isEndDelimited = i === tokens.length - 1 && delimiters.includes(token[token.length - 1]);
      continue;
    }

    let prefix = escapeString(token.prefix);
    let capture = token.repeat
      ? `(?:${token.pattern})(?:${prefix}(?:${token.pattern}))*`
      : token.pattern;

    if (keys) keys.push(token);

    if (token.optional) {
      if (token.partial) {
        route += prefix + `(${capture})?`;
      } else {
        route += `(?:${prefix}(${capture}))?`;
      }
    } else {
      route += `${prefix}(${capture})`;
    }
  }

  if (end) {
    if (!strict) route += `(?:${delimiter})?`;

    route += endsWith === '$' ? '$' : `(?=${endsWith})`;
  } else {
    if (!strict) route += `(?:${delimiter}(?=${endsWith}))?`;
    if (!isEndDelimited) route += `(?=${delimiter}|${endsWith})`;
  }

  return `^${route}`;
}
619369
def split_url(url)
      str = split_get_last(split_get_last(url, '/'), '?')
      str = split_get_last(str, '&', -1)
      str
    end
389561
function splitLocation(location) {
  var re = /([^\?#]*)?(\?[^#]*)?(#.*)?$/;
  var match = re.exec(location);
  return {
    path: match[1] || '',
    queryString: match[2] && match[2].substring(1) || '',
    hash: match[3] && match[3].substring(1) || ''
  }
}
613275
def _extractPathFromUrl(url):
        
        if url.netloc != '' and url.netloc != 'localhost':
            raise RuntimeError("The URL '%s' is invalid" % url.geturl())
        return url.netloc + url.path
569615
function(parts) {
        var urls = [];
        var start = '';

        // If the first part is empty
        // the original path begins with a slash so we
        // do that, too

        if( _.isEmpty(parts[0]) ) {
            start = '/';
            urls[0] = '/';      // would not be generated in reduce()
        }

        _.reduce(parts, function(acc, value){

            if( ! _.isString(value) || _.isEmpty(value) )
                return acc;

            acc += value;

            // Push w/out trailing slash
            urls.push(acc);

            return acc + '/';
        }, start );

        return urls;
    }
860481
function RouteRule_parseRequest(method, url) {

        var matches,
            route,
            key,
            result = [],
            escape = [],
            params = {},
            current;
        //match pathname
        matches = this.match(this.pattern, this.trim(url.pathname, '/'));


        if (!matches.length || !this.checkMethod(method)) {
            return false;
        }
        params = url.query;


        for (key in params) {
            current = this.find(matches, key);
            if (!current || current.value === '') {
                matches.push({
                    key: key,
                    value: params[key]
                });
            }
        }

        matches.forEach(function (item) {
            var current = this.find(this.routeParams, item.key);
            if (current) {
                escape.push({
                    key: '<' + current.key + '>',
                    value: item.value
                });
                delete params[item.name];
            } else if (this.find(this.paramRules, item.key)) {
                params[item.key] = item.value;
            }
        }.bind(this));


        if (this.routeParams.length) {
            route = this.escape(this.route, escape);
        } else {
            route = this.route;
        }

        result.push(route);
        result.push(params);

        return result;
    }
123501
def get_parts_of_url_path(url):
    
    parsed = urlparse(url)
    path = unquote(parsed.path).lstrip('/')
    parts = path.split('/')
    return parts
455166
function regexpPattern(pattern) {
  if (!pattern) {
    return pattern;
  }
  // A very simplified glob transform which allows passing legible strings like
  // "myPath/*.js" instead of a harder to read RegExp like /\/myPath\/.*\.js/.
  if (typeof pattern === 'string') {
    pattern = pattern.replace(/\./g, '\\.').replace(/\*/g, '.*');
    if (pattern[0] !== '/') {
      pattern = '/' + pattern;
    }
    return new RegExp(pattern);
  }
  if (typeof pattern.test === 'function') {
    return pattern;
  }
  throw new Error(
    'flow-remove-types: includes and excludes must be RegExp or path strings. Got: ' + pattern
  );
}
192108
function matchPath(a, b) {
        var regex = new RegExp('^' + a.join('~~'), 'i');
        return regex.test(b.join('~~'));
    }
747744
def join_url_parts(*args):
    
    # check for edge case
    if len(args) == 1:
        return args[0]

    return_val = clean_url_segment(args[0])

    for i in range(1, len(args)):
        arg = args[i]

        if i == len(args) - 1:
            # no need to remove a trailing slash if this is the last segment
            return_val += '/' + arg
        else:
            # remove a trailing slash so it won't be duplicated
            return_val += '/' + clean_url_segment(arg)

    return return_val
575219
function tokensToRegExp (tokens, options) {
	  options = options || {}
	
	  var strict = options.strict
	  var end = options.end !== false
	  var route = ''
	  var lastToken = tokens[tokens.length - 1]
	  var endsWithSlash = typeof lastToken === 'string' && /\/$/.test(lastToken)
	
	  // Iterate over the tokens and create our regexp string.
	  for (var i = 0; i < tokens.length; i++) {
	    var token = tokens[i]
	
	    if (typeof token === 'string') {
	      route += escapeString(token)
	    } else {
	      var prefix = escapeString(token.prefix)
	      var capture = '(?:' + token.pattern + ')'
	
	      if (token.repeat) {
	        capture += '(?:' + prefix + capture + ')*'
	      }
	
	      if (token.optional) {
	        if (!token.partial) {
	          capture = '(?:' + prefix + '(' + capture + '))?'
	        } else {
	          capture = prefix + '(' + capture + ')?'
	        }
	      } else {
	        capture = prefix + '(' + capture + ')'
	      }
	
	      route += capture
	    }
	  }
	
	  // In non-strict mode we allow a slash at the end of match. If the path to
	  // match already ends with a slash, we remove it for consistency. The slash
	  // is valid at the end of a path match, not in the middle. This is important
	  // in non-ending mode, where "/test/" shouldn't match "/test//route".
	  if (!strict) {
	    route = (endsWithSlash ? route.slice(0, -2) : route) + '(?:\\/(?=$))?'
	  }
	
	  if (end) {
	    route += '$'
	  } else {
	    // In non-ending mode, we need the capturing groups to match as much as
	    // possible by using a positive lookahead to the end or next path segment.
	    route += strict && endsWithSlash ? '' : '(?=\\/|$)'
	  }
	
	  return new RegExp('^' + route, flags(options))
	}