getContext method

RouterContext getContext (String path, [ String method = DEFAULT_METHOD ])

根据一个路径,获取路由上下文

Implementation

RouterContext getContext(String path, [String method = DEFAULT_METHOD]) {
  assert(path != '');
  final Uri uri = Uri.parse(path);
  // 使用 / 拆分路径
  Stack<String> pathParts = Stack(uri.pathSegments);

  String pathPart;
  Stack<MatchResult> matchedResults = Stack([MatchResult(root)]);
  MatchResult lastMatchResult;
  bool hasEnded = false;
  while (pathParts.isNotEmpty && !hasEnded) {
    pathPart = pathParts.pop();

    if (pathPart == '') {
      //忽略空的部分路径
      continue;
    }

    lastMatchResult = matchedResults.top;
    RouteNode currentNode = lastMatchResult.node;

    MatchResult matchResult;

    if (!lastMatchResult.partChildrenHadMatch) {
      // 1. 在partChildren中匹配
      matchResult = currentNode.matchPartChildren(pathPart);
      lastMatchResult.partChildrenHadMatch = true;
    }

    // 2. 在paramChildren中匹配
    if (matchResult == null) {
      matchResult = currentNode.matchParamChildren(
          pathPart, lastMatchResult.paramChildIndex);
    }
    // 3. 在wildChildren中匹配
    if (matchResult == null) {
      matchResult = currentNode.matchWildcardChild(pathPart);
    }

    if (matchResult != null) {
      // 匹配到了路由节点

      // 将匹配上的结果入栈
      matchedResults.push(matchResult);

      // 该情况是当前段已匹配上了一个节点,接下来继续匹配下一个节点
      if (matchResult.node.type == NodeType.param) {
        lastMatchResult.paramChildIndex++;
      }

      if (matchResult.node.type == NodeType.wildcard) {
        pathParts.push(pathPart);
        hasEnded = true;
        // 匹配到通配节点,结束匹配
        break;
      }

      if (pathParts.isEmpty && matchResult.node.getHandler(method) == null) {
        // 已经匹配到路径最后了,但是没有找到对应的处理器函数,则需要检查回滚
        if (matchResult.node.isHandleNode) {
          // 匹配到了已绑定的路由,但是方法未能匹配,匹配已结束
          hasEnded = true;
        } else {
          pathParts.push(pathPart);
          matchedResults.pop();
          switch (_backtrackingCheck(pathParts, matchedResults)) {
            case _BacktrackingState.cant:
              // 回溯之前需要判断层级,需要判断是不是每一层都已经回溯完了,如果都回溯完了的话,就表明当前路径是 404 的情况
              // 不可回溯,如果可回溯的话,两个栈的状态都会回溯到正确位置
              // 完全不可回溯了,也就是整个匹配过程已结束,但并未匹配上带当前方法的处理器的路由
              return null;
              break;
            case _BacktrackingState.yes:
              // ignore this do next loop
              break;
            case _BacktrackingState.stop:
              hasEnded = true;
              break;
          }
        }
      }
    } else {
      // 当前这帧没有匹配上,则加回到栈中,然后再检查回溯条件
      pathParts.push(pathPart);
      switch (_backtrackingCheck(pathParts, matchedResults)) {
        case _BacktrackingState.cant:
          // 回溯之前需要判断层级,需要判断是不是每一层都已经回溯完了,如果都回溯完了的话,就表明当前路径是 404 的情况
          // 不可回溯,如果可回溯的话,两个栈的状态都会回溯到正确位置
          // 完全不可回溯了,也就是整个匹配过程已结束,但并未匹配上路由
          return null;
        case _BacktrackingState.yes:
          // ignore this do next loop
          break;
        case _BacktrackingState.stop:
          hasEnded = true;
          break;
      }
    }
  }

  if (matchedResults.isEmpty) {
    // 匹配完成之后,并未匹配到记录
    return null;
  }

  // 已经匹配上了,根据匹配结果集构造路由上下文
  RouterContext context =
      _generateRouterContext(pathParts, matchedResults, method);
  context.path = path;
  context.queries = uri.queryParametersAll.map(
      (String key, List<String> value) =>
          MapEntry(key, value.length == 1 ? value[0] : value));

  return context;
}