HttpRoute constructor

HttpRoute(
  1. String route,
  2. FutureOr callback(
    1. HttpRequest req,
    2. HttpResponse res
    ),
  3. ServerUniverseMethodType method, {
  4. List<FutureOr Function(HttpRequest req, HttpResponse res)> middleware = const [],
})

Implementation

HttpRoute(this.route, this.callback, this.method, {this.middleware = const []}) : usesWildcardMatcher = route.contains('*') {
  // Split route path into segments

  /// Because in dart 2.18 uri parsing is more permissive, using a \ in regex
  /// is being counted as a /, so we need to add an r and join them together
  /// VERY happy for a more elegant solution here than some random escape
  /// sequence.
  const escapeChar = '@@@^';
  var escapedPath = route.normalizePath.replaceAll('\\', escapeChar);
  var segments = Uri.tryParse('/${escapedPath}')?.pathSegments ?? [route.normalizePath];
  segments = segments.map((e) => e.replaceAll(escapeChar, '\\')).toList();

  var pattern = '^';
  for (var segment in segments) {
    if (segment == '*' && segment != segments.first && segment == segments.last) {
      // Generously match path if last segment is wildcard (*)
      // Example: 'some/path/*' => should match 'some/path', 'some/path/', 'some/path/with/children'
      //                           but not 'some/pathological'
      pattern += r'(?:/.*|)';
      break;
    } else if (segment != segments.first) {
      // Add path separators
      pattern += '/';
    }

    // parse parameter if any
    final param = HttpRouteParam.tryParse(segment);
    if (param != null) {
      if (_params.containsKey(param.name)) {
        throw DuplicateParameterException(param.name);
      }
      _params[param.name] = param;
      // ignore: prefer_interpolation_to_compose_strings
      segment = r'(?<' + param.name + r'>' + param.pattern + ')';
    } else {
      // escape period character
      segment = segment.replaceAll('.', r'\.');
      // wildcard ('*') to anything
      segment = segment.replaceAll('*', '.*?');
    }

    pattern += segment;
  }

  pattern += r'$';
  matcher = RegExp(pattern, caseSensitive: false);
}